提交 f2fb4e4f 编写于 作者: S Stuart Menefy 提交者: Paul Mundt

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: NStuart Menefy <stuart.menefy@st.com>
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 068f5914
......@@ -373,6 +373,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
err |= __put_user(OR_R0_R0, &frame->retcode[6]);
err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
regs->pr = (unsigned long) frame->retcode;
flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
}
if (err)
......@@ -398,8 +399,6 @@ static int setup_frame(int sig, struct k_sigaction *ka,
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
return 0;
give_sigsegv:
......
......@@ -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..
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册