[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: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
fad7906d16
commit
40e59a6166
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue