Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2fb4e4f authored by Stuart Menefy's avatar Stuart Menefy Committed by Paul Mundt
Browse files

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: default avatarStuart Menefy <stuart.menefy@st.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 068f5914
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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:
+8 −4
Original line number Diff line number Diff line
@@ -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..