Skip to content

Commit

Permalink
sh: Conditionally re-enable IRQs in fault path.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stuart Menefy authored and Paul Mundt committed Jul 28, 2008
1 parent 068f591 commit f2fb4e4
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 6 deletions.
3 changes: 1 addition & 2 deletions arch/sh/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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:
Expand Down
12 changes: 8 additions & 4 deletions arch/sh/mm/fault_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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..
Expand Down

0 comments on commit f2fb4e4

Please sign in to comment.