diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r-- | arch/x86/kernel/traps.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 33399176512a..9288ccfcf6db 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -88,9 +88,10 @@ static inline void conditional_sti(struct pt_regs *regs) | |||
88 | local_irq_enable(); | 88 | local_irq_enable(); |
89 | } | 89 | } |
90 | 90 | ||
91 | static inline void preempt_conditional_sti(struct pt_regs *regs) | 91 | static inline void preempt_conditional_sti(struct pt_regs *regs, int stack) |
92 | { | 92 | { |
93 | inc_preempt_count(); | 93 | if (stack) |
94 | inc_preempt_count(); | ||
94 | if (regs->flags & X86_EFLAGS_IF) | 95 | if (regs->flags & X86_EFLAGS_IF) |
95 | local_irq_enable(); | 96 | local_irq_enable(); |
96 | } | 97 | } |
@@ -101,11 +102,12 @@ static inline void conditional_cli(struct pt_regs *regs) | |||
101 | local_irq_disable(); | 102 | local_irq_disable(); |
102 | } | 103 | } |
103 | 104 | ||
104 | static inline void preempt_conditional_cli(struct pt_regs *regs) | 105 | static inline void preempt_conditional_cli(struct pt_regs *regs, int stack) |
105 | { | 106 | { |
106 | if (regs->flags & X86_EFLAGS_IF) | 107 | if (regs->flags & X86_EFLAGS_IF) |
107 | local_irq_disable(); | 108 | local_irq_disable(); |
108 | dec_preempt_count(); | 109 | if (stack) |
110 | dec_preempt_count(); | ||
109 | } | 111 | } |
110 | 112 | ||
111 | #ifdef CONFIG_X86_32 | 113 | #ifdef CONFIG_X86_32 |
@@ -232,9 +234,9 @@ dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) | |||
232 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | 234 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, |
233 | 12, SIGBUS) == NOTIFY_STOP) | 235 | 12, SIGBUS) == NOTIFY_STOP) |
234 | return; | 236 | return; |
235 | preempt_conditional_sti(regs); | 237 | preempt_conditional_sti(regs, STACKFAULT_STACK); |
236 | do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); | 238 | do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); |
237 | preempt_conditional_cli(regs); | 239 | preempt_conditional_cli(regs, STACKFAULT_STACK); |
238 | } | 240 | } |
239 | 241 | ||
240 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | 242 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) |
@@ -470,9 +472,9 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) | |||
470 | return; | 472 | return; |
471 | #endif | 473 | #endif |
472 | 474 | ||
473 | preempt_conditional_sti(regs); | 475 | preempt_conditional_sti(regs, DEBUG_STACK); |
474 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | 476 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); |
475 | preempt_conditional_cli(regs); | 477 | preempt_conditional_cli(regs, DEBUG_STACK); |
476 | } | 478 | } |
477 | 479 | ||
478 | #ifdef CONFIG_X86_64 | 480 | #ifdef CONFIG_X86_64 |
@@ -554,7 +556,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
554 | return; | 556 | return; |
555 | 557 | ||
556 | /* It's safe to allow irq's after DR6 has been saved */ | 558 | /* It's safe to allow irq's after DR6 has been saved */ |
557 | preempt_conditional_sti(regs); | 559 | preempt_conditional_sti(regs, DEBUG_STACK); |
558 | 560 | ||
559 | if (regs->flags & X86_VM_MASK) { | 561 | if (regs->flags & X86_VM_MASK) { |
560 | handle_vm86_trap((struct kernel_vm86_regs *) regs, | 562 | handle_vm86_trap((struct kernel_vm86_regs *) regs, |
@@ -577,7 +579,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
577 | si_code = get_si_code(tsk->thread.debugreg6); | 579 | si_code = get_si_code(tsk->thread.debugreg6); |
578 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) | 580 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) |
579 | send_sigtrap(tsk, regs, error_code, si_code); | 581 | send_sigtrap(tsk, regs, error_code, si_code); |
580 | preempt_conditional_cli(regs); | 582 | preempt_conditional_cli(regs, DEBUG_STACK); |
581 | 583 | ||
582 | return; | 584 | return; |
583 | } | 585 | } |