aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-07-28 20:10:30 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-07-28 20:10:30 -0400
commitba773f7c510c0b252145933926c636c439889207 (patch)
tree97983dc7a149487a7926f1efc2619fafcc8cc93c
parentfc0f5ac8fe693d1b05f5a928cc48135d1c8b7f2e (diff)
x86,kgdb: Fix hw breakpoint regression
HW breakpoints events stopped working correctly with kgdb as a result of commit: 018cbffe6819f6f8db20a0a3acd9bab9bfd667e4 (Merge commit 'v2.6.33' into perf/core). The regression occurred because the behavior changed for setting NOTIFY_STOP as the return value to the die notifier if the breakpoint was known to the HW breakpoint API. Because kgdb is using the HW breakpoint API to register HW breakpoints slots, it must also now implement the overflow_handler call back else kgdb does not get to see the events from the die notifier. The kgdb_ll_trap function will be changed to be general purpose code which can allow an easy way to implement the hw_breakpoint API overflow call back. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Acked-by: Dongdong Deng <dongdong.deng@windriver.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r--arch/x86/kernel/kgdb.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 4f4af75b948..01ab17ae2ae 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -572,7 +572,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
572 return NOTIFY_STOP; 572 return NOTIFY_STOP;
573} 573}
574 574
575#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
576int kgdb_ll_trap(int cmd, const char *str, 575int kgdb_ll_trap(int cmd, const char *str,
577 struct pt_regs *regs, long err, int trap, int sig) 576 struct pt_regs *regs, long err, int trap, int sig)
578{ 577{
@@ -590,7 +589,6 @@ int kgdb_ll_trap(int cmd, const char *str,
590 589
591 return __kgdb_notify(&args, cmd); 590 return __kgdb_notify(&args, cmd);
592} 591}
593#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
594 592
595static int 593static int
596kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) 594kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
@@ -625,6 +623,12 @@ int kgdb_arch_init(void)
625 return register_die_notifier(&kgdb_notifier); 623 return register_die_notifier(&kgdb_notifier);
626} 624}
627 625
626static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
627 struct perf_sample_data *data, struct pt_regs *regs)
628{
629 kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
630}
631
628void kgdb_arch_late(void) 632void kgdb_arch_late(void)
629{ 633{
630 int i, cpu; 634 int i, cpu;
@@ -655,6 +659,7 @@ void kgdb_arch_late(void)
655 for_each_online_cpu(cpu) { 659 for_each_online_cpu(cpu) {
656 pevent = per_cpu_ptr(breakinfo[i].pev, cpu); 660 pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
657 pevent[0]->hw.sample_period = 1; 661 pevent[0]->hw.sample_period = 1;
662 pevent[0]->overflow_handler = kgdb_hw_overflow_handler;
658 if (pevent[0]->destroy != NULL) { 663 if (pevent[0]->destroy != NULL) {
659 pevent[0]->destroy = NULL; 664 pevent[0]->destroy = NULL;
660 release_bp_slot(*pevent); 665 release_bp_slot(*pevent);