aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorK.Prasad <prasad@linux.vnet.ibm.com>2009-06-01 14:17:06 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-06-02 16:47:00 -0400
commit62edab9056a6cf0c9207339c8892c923a5217e45 (patch)
tree2becd775fdc2a25df3daacf69d80685b251fbed9 /arch/x86
parent0722db015c246204044299eae3b02d18d3ca4faf (diff)
hw-breakpoints: reset bits in dr6 after the corresponding exception is handled
This patch resets the bit in dr6 after the corresponding exception is handled in code, so that we keep a clean track of the current virtual debug status register. [ Impact: keep track of breakpoints triggering completion ] Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/hw_breakpoint.c13
-rw-r--r--arch/x86/kernel/kgdb.c6
-rw-r--r--arch/x86/kernel/kprobes.c9
-rw-r--r--arch/x86/kernel/traps.c4
-rw-r--r--arch/x86/mm/kmmio.c8
5 files changed, 34 insertions, 6 deletions
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index 4867c9f3b5fb..69451473dbd2 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -314,8 +314,12 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
314{ 314{
315 int i, cpu, rc = NOTIFY_STOP; 315 int i, cpu, rc = NOTIFY_STOP;
316 struct hw_breakpoint *bp; 316 struct hw_breakpoint *bp;
317 /* The DR6 value is stored in args->err */ 317 unsigned long dr7, dr6;
318 unsigned long dr7, dr6 = args->err; 318 unsigned long *dr6_p;
319
320 /* The DR6 value is pointed by args->err */
321 dr6_p = (unsigned long *)ERR_PTR(args->err);
322 dr6 = *dr6_p;
319 323
320 /* Do an early return if no trap bits are set in DR6 */ 324 /* Do an early return if no trap bits are set in DR6 */
321 if ((dr6 & DR_TRAP_BITS) == 0) 325 if ((dr6 & DR_TRAP_BITS) == 0)
@@ -352,6 +356,11 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
352 rc = NOTIFY_DONE; 356 rc = NOTIFY_DONE;
353 } 357 }
354 /* 358 /*
359 * Reset the 'i'th TRAP bit in dr6 to denote completion of
360 * exception handling
361 */
362 (*dr6_p) &= ~(DR_TRAP0 << i);
363 /*
355 * bp can be NULL due to lazy debug register switching 364 * bp can be NULL due to lazy debug register switching
356 * or due to the delay between updates of hbp_kernel_pos 365 * or due to the delay between updates of hbp_kernel_pos
357 * and this_hbp_kernel. 366 * and this_hbp_kernel.
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index b1f4dffb919e..f820b73c7f28 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -43,6 +43,7 @@
43#include <linux/smp.h> 43#include <linux/smp.h>
44#include <linux/nmi.h> 44#include <linux/nmi.h>
45 45
46#include <asm/debugreg.h>
46#include <asm/apicdef.h> 47#include <asm/apicdef.h>
47#include <asm/system.h> 48#include <asm/system.h>
48 49
@@ -434,6 +435,11 @@ single_step_cont(struct pt_regs *regs, struct die_args *args)
434 "resuming...\n"); 435 "resuming...\n");
435 kgdb_arch_handle_exception(args->trapnr, args->signr, 436 kgdb_arch_handle_exception(args->trapnr, args->signr,
436 args->err, "c", "", regs); 437 args->err, "c", "", regs);
438 /*
439 * Reset the BS bit in dr6 (pointed by args->err) to
440 * denote completion of processing
441 */
442 (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
437 443
438 return NOTIFY_STOP; 444 return NOTIFY_STOP;
439} 445}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 7b5169d2b000..b5b1848c5336 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -54,6 +54,7 @@
54#include <asm/pgtable.h> 54#include <asm/pgtable.h>
55#include <asm/uaccess.h> 55#include <asm/uaccess.h>
56#include <asm/alternative.h> 56#include <asm/alternative.h>
57#include <asm/debugreg.h>
57 58
58void jprobe_return_end(void); 59void jprobe_return_end(void);
59 60
@@ -967,8 +968,14 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
967 ret = NOTIFY_STOP; 968 ret = NOTIFY_STOP;
968 break; 969 break;
969 case DIE_DEBUG: 970 case DIE_DEBUG:
970 if (post_kprobe_handler(args->regs)) 971 if (post_kprobe_handler(args->regs)) {
972 /*
973 * Reset the BS bit in dr6 (pointed by args->err) to
974 * denote completion of processing
975 */
976 (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP;
971 ret = NOTIFY_STOP; 977 ret = NOTIFY_STOP;
978 }
972 break; 979 break;
973 case DIE_GPF: 980 case DIE_GPF:
974 /* 981 /*
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index de9913247dd0..124a4d5a95b2 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -545,8 +545,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
545 /* Store the virtualized DR6 value */ 545 /* Store the virtualized DR6 value */
546 tsk->thread.debugreg6 = dr6; 546 tsk->thread.debugreg6 = dr6;
547 547
548 if (notify_die(DIE_DEBUG, "debug", regs, dr6, error_code, 548 if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
549 SIGTRAP) == NOTIFY_STOP) 549 SIGTRAP) == NOTIFY_STOP)
550 return; 550 return;
551 551
552 /* It's safe to allow irq's after DR6 has been saved */ 552 /* It's safe to allow irq's after DR6 has been saved */
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 16ccbd77917f..11a4ad4d6253 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -540,8 +540,14 @@ kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args)
540 struct die_args *arg = args; 540 struct die_args *arg = args;
541 541
542 if (val == DIE_DEBUG && (arg->err & DR_STEP)) 542 if (val == DIE_DEBUG && (arg->err & DR_STEP))
543 if (post_kmmio_handler(arg->err, arg->regs) == 1) 543 if (post_kmmio_handler(arg->err, arg->regs) == 1) {
544 /*
545 * Reset the BS bit in dr6 (pointed by args->err) to
546 * denote completion of processing
547 */
548 (*(unsigned long *)ERR_PTR(arg->err)) &= ~DR_STEP;
544 return NOTIFY_STOP; 549 return NOTIFY_STOP;
550 }
545 551
546 return NOTIFY_DONE; 552 return NOTIFY_DONE;
547} 553}