aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r--arch/x86/kernel/traps.c22
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
91static inline void preempt_conditional_sti(struct pt_regs *regs) 91static 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
104static inline void preempt_conditional_cli(struct pt_regs *regs) 105static 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
240dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) 242dotraplinkage 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}