diff options
author | Andi Kleen <ak@suse.de> | 2006-05-15 12:19:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-16 10:59:32 -0400 |
commit | 40e59a61669a3cab9e0bd24644e29155d6b00970 (patch) | |
tree | 25db313781596303562a1a316592ffb9ff96542b /arch/x86_64/kernel | |
parent | fad7906d16e8c4926aeb5b0f1756eb9f55b2837d (diff) |
[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>
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 6b87268c5c2e..cea335e8746c 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -102,6 +102,8 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) | |||
102 | { | 102 | { |
103 | if (regs->eflags & X86_EFLAGS_IF) | 103 | if (regs->eflags & X86_EFLAGS_IF) |
104 | local_irq_disable(); | 104 | local_irq_disable(); |
105 | /* Make sure to not schedule here because we could be running | ||
106 | on an exception stack. */ | ||
105 | preempt_enable_no_resched(); | 107 | preempt_enable_no_resched(); |
106 | } | 108 | } |
107 | 109 | ||
@@ -483,8 +485,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, | |||
483 | { | 485 | { |
484 | struct task_struct *tsk = current; | 486 | struct task_struct *tsk = current; |
485 | 487 | ||
486 | conditional_sti(regs); | ||
487 | |||
488 | tsk->thread.error_code = error_code; | 488 | tsk->thread.error_code = error_code; |
489 | tsk->thread.trap_no = trapnr; | 489 | tsk->thread.trap_no = trapnr; |
490 | 490 | ||
@@ -521,6 +521,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ | |||
521 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 521 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
522 | == NOTIFY_STOP) \ | 522 | == NOTIFY_STOP) \ |
523 | return; \ | 523 | return; \ |
524 | conditional_sti(regs); \ | ||
524 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | 525 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ |
525 | } | 526 | } |
526 | 527 | ||
@@ -535,6 +536,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ | |||
535 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 536 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
536 | == NOTIFY_STOP) \ | 537 | == NOTIFY_STOP) \ |
537 | return; \ | 538 | return; \ |
539 | conditional_sti(regs); \ | ||
538 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | 540 | do_trap(trapnr, signr, str, regs, error_code, &info); \ |
539 | } | 541 | } |
540 | 542 | ||
@@ -548,7 +550,17 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | |||
548 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 550 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
549 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) | 551 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) |
550 | DO_ERROR(18, SIGSEGV, "reserved", reserved) | 552 | DO_ERROR(18, SIGSEGV, "reserved", reserved) |
551 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | 553 | |
554 | /* Runs on IST stack */ | ||
555 | asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) | ||
556 | { | ||
557 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | ||
558 | 12, SIGBUS) == NOTIFY_STOP) | ||
559 | return; | ||
560 | preempt_conditional_sti(regs); | ||
561 | do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); | ||
562 | preempt_conditional_cli(regs); | ||
563 | } | ||
552 | 564 | ||
553 | asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) | 565 | asmlinkage void do_double_fault(struct pt_regs * regs, long error_code) |
554 | { | 566 | { |
@@ -682,8 +694,9 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) | |||
682 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { | 694 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { |
683 | return; | 695 | return; |
684 | } | 696 | } |
697 | preempt_conditional_sti(regs); | ||
685 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | 698 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); |
686 | return; | 699 | preempt_conditional_cli(regs); |
687 | } | 700 | } |
688 | 701 | ||
689 | /* Help handler running on IST stack to switch back to user stack | 702 | /* Help handler running on IST stack to switch back to user stack |