diff options
author | Stuart Menefy <stuart.menefy@st.com> | 2008-07-02 17:51:23 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-07-28 18:10:33 +0900 |
commit | f2fb4e4f647dabf1177d3ce164988e73482d76b1 (patch) | |
tree | 5288184d2d8535c826c8b3c33d79b2529c83542b /arch/sh/mm/fault_32.c | |
parent | 068f59143d821553e7a55cdbd69142b05e245d47 (diff) |
sh: Conditionally re-enable IRQs in fault path.
The current kernel behaviour is to reenable interrupts unconditionally
when taking a page fault. This patch changes this to only enable them
if interrupts were previously enabled.
It also fixes a problem seen with this fix in place: the kernel previously
flushed the vsyscall page when handling a signal, which is not only
unncessary, but caused a possible sleep with interrupts disabled.
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/fault_32.c')
-rw-r--r-- | arch/sh/mm/fault_32.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index d1fa27594c6e..0c776fdfbdda 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -37,16 +37,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, int fault; siginfo_t info; - trace_hardirqs_on(); - local_irq_enable(); - #ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) kgdb_bus_err_hook(); #endif tsk = current; - mm = tsk->mm; si_code = SEGV_MAPERR; if (unlikely(address >= TASK_SIZE)) { @@ -88,6 +84,14 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, return; } + /* Only enable interrupts if they were on before the fault */ + if ((regs->sr & SR_IMASK) != SR_IMASK) { + trace_hardirqs_on(); + local_irq_enable(); + } + + mm = tsk->mm; + /* * If we're in an interrupt or have no user * context, we must not take the fault.. |