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>
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index eee2925..4bbbde8 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -373,6 +373,7 @@
 		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 @@
 	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:
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index d1fa275..0c776fd 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -37,16 +37,12 @@
 	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 @@
 		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..