Commit ba773f7c authored by Jason Wessel's avatar Jason Wessel

x86,kgdb: Fix hw breakpoint regression

HW breakpoints events stopped working correctly with kgdb
as a result of commit: 018cbffe
(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: default avatarJason Wessel <jason.wessel@windriver.com>
Acked-by: default avatarDongdong Deng <dongdong.deng@windriver.com>
Acked-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent fc0f5ac8
...@@ -572,7 +572,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) ...@@ -572,7 +572,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
return NOTIFY_STOP; return NOTIFY_STOP;
} }
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
int kgdb_ll_trap(int cmd, const char *str, int kgdb_ll_trap(int cmd, const char *str,
struct pt_regs *regs, long err, int trap, int sig) struct pt_regs *regs, long err, int trap, int sig)
{ {
...@@ -590,7 +589,6 @@ int kgdb_ll_trap(int cmd, const char *str, ...@@ -590,7 +589,6 @@ int kgdb_ll_trap(int cmd, const char *str,
return __kgdb_notify(&args, cmd); return __kgdb_notify(&args, cmd);
} }
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
static int static int
kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
...@@ -625,6 +623,12 @@ int kgdb_arch_init(void) ...@@ -625,6 +623,12 @@ int kgdb_arch_init(void)
return register_die_notifier(&kgdb_notifier); return register_die_notifier(&kgdb_notifier);
} }
static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
struct perf_sample_data *data, struct pt_regs *regs)
{
kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
}
void kgdb_arch_late(void) void kgdb_arch_late(void)
{ {
int i, cpu; int i, cpu;
...@@ -655,6 +659,7 @@ void kgdb_arch_late(void) ...@@ -655,6 +659,7 @@ void kgdb_arch_late(void)
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
pevent = per_cpu_ptr(breakinfo[i].pev, cpu); pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
pevent[0]->hw.sample_period = 1; pevent[0]->hw.sample_period = 1;
pevent[0]->overflow_handler = kgdb_hw_overflow_handler;
if (pevent[0]->destroy != NULL) { if (pevent[0]->destroy != NULL) {
pevent[0]->destroy = NULL; pevent[0]->destroy = NULL;
release_bp_slot(*pevent); release_bp_slot(*pevent);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment