diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 14 |
2 files changed, 18 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index caa404556b9c..266e4649b1da 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1093,11 +1093,13 @@ unsigned long kernel_eflags; | |||
1093 | DEFINE_PER_CPU(struct orig_ist, orig_ist); | 1093 | DEFINE_PER_CPU(struct orig_ist, orig_ist); |
1094 | 1094 | ||
1095 | static DEFINE_PER_CPU(unsigned long, debug_stack_addr); | 1095 | static DEFINE_PER_CPU(unsigned long, debug_stack_addr); |
1096 | DEFINE_PER_CPU(int, debug_stack_usage); | ||
1096 | 1097 | ||
1097 | int is_debug_stack(unsigned long addr) | 1098 | int is_debug_stack(unsigned long addr) |
1098 | { | 1099 | { |
1099 | return addr <= __get_cpu_var(debug_stack_addr) && | 1100 | return __get_cpu_var(debug_stack_usage) || |
1100 | addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ); | 1101 | (addr <= __get_cpu_var(debug_stack_addr) && |
1102 | addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ)); | ||
1101 | } | 1103 | } |
1102 | 1104 | ||
1103 | void debug_stack_set_zero(void) | 1105 | void debug_stack_set_zero(void) |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a93c5cabc36a..0072b38e3ea1 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -316,9 +316,15 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) | |||
316 | return; | 316 | return; |
317 | #endif | 317 | #endif |
318 | 318 | ||
319 | /* | ||
320 | * Let others (NMI) know that the debug stack is in use | ||
321 | * as we may switch to the interrupt stack. | ||
322 | */ | ||
323 | debug_stack_usage_inc(); | ||
319 | preempt_conditional_sti(regs); | 324 | preempt_conditional_sti(regs); |
320 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | 325 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); |
321 | preempt_conditional_cli(regs); | 326 | preempt_conditional_cli(regs); |
327 | debug_stack_usage_dec(); | ||
322 | } | 328 | } |
323 | 329 | ||
324 | #ifdef CONFIG_X86_64 | 330 | #ifdef CONFIG_X86_64 |
@@ -411,6 +417,12 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
411 | SIGTRAP) == NOTIFY_STOP) | 417 | SIGTRAP) == NOTIFY_STOP) |
412 | return; | 418 | return; |
413 | 419 | ||
420 | /* | ||
421 | * Let others (NMI) know that the debug stack is in use | ||
422 | * as we may switch to the interrupt stack. | ||
423 | */ | ||
424 | debug_stack_usage_inc(); | ||
425 | |||
414 | /* It's safe to allow irq's after DR6 has been saved */ | 426 | /* It's safe to allow irq's after DR6 has been saved */ |
415 | preempt_conditional_sti(regs); | 427 | preempt_conditional_sti(regs); |
416 | 428 | ||
@@ -418,6 +430,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
418 | handle_vm86_trap((struct kernel_vm86_regs *) regs, | 430 | handle_vm86_trap((struct kernel_vm86_regs *) regs, |
419 | error_code, 1); | 431 | error_code, 1); |
420 | preempt_conditional_cli(regs); | 432 | preempt_conditional_cli(regs); |
433 | debug_stack_usage_dec(); | ||
421 | return; | 434 | return; |
422 | } | 435 | } |
423 | 436 | ||
@@ -437,6 +450,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
437 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) | 450 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) |
438 | send_sigtrap(tsk, regs, error_code, si_code); | 451 | send_sigtrap(tsk, regs, error_code, si_code); |
439 | preempt_conditional_cli(regs); | 452 | preempt_conditional_cli(regs); |
453 | debug_stack_usage_dec(); | ||
440 | 454 | ||
441 | return; | 455 | return; |
442 | } | 456 | } |