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

Commit 40e59a61 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds
Browse files

[PATCH] x86_64: Don't schedule on exception stack on preemptive kernels



Extends an earlier patch from John Blackwood to more exception handlers
that also run on the exception stacks.

Expand the use of preempt_conditional_{sti,cli} to all cases where
interrupts are to be re-enabled during exception handling while running
on an IST stack.

Based on original patch from Jan Beulich.

Cc: John Blackwood <john.blackwood@ccur.com>
Cc: jbeulich@novell.com
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fad7906d
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -102,6 +102,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
{
	if (regs->eflags & X86_EFLAGS_IF)
		local_irq_disable();
	/* Make sure to not schedule here because we could be running
	   on an exception stack. */
	preempt_enable_no_resched();
}

@@ -483,8 +485,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
{
	struct task_struct *tsk = current;

	conditional_sti(regs);

	tsk->thread.error_code = error_code;
	tsk->thread.trap_no = trapnr;

@@ -521,6 +521,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
							== NOTIFY_STOP) \
		return; \
	conditional_sti(regs);						\
	do_trap(trapnr, signr, str, regs, error_code, NULL); \
}

@@ -535,6 +536,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
							== NOTIFY_STOP) \
		return; \
	conditional_sti(regs);						\
	do_trap(trapnr, signr, str, regs, error_code, &info); \
}

@@ -548,7 +550,17 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
DO_ERROR(18, SIGSEGV, "reserved", reserved)
DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)

/* Runs on IST stack */
asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
{
	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
			12, SIGBUS) == NOTIFY_STOP)
		return;
	preempt_conditional_sti(regs);
	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
	preempt_conditional_cli(regs);
}

asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
{
@@ -682,8 +694,9 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
		return;
	}
	preempt_conditional_sti(regs);
	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
	return;
	preempt_conditional_cli(regs);
}

/* Help handler running on IST stack to switch back to user stack