提交 031acd8c 编写于 作者: J Jason Wessel

x86,kgdb: Implement early hardware breakpoint debugging

It is not possible to use the hw_breakpoint.c API prior to mm_init(),
but it is possible to use hardware breakpoints with the kernel
debugger.

Prior to smp_init() it is possible to simply write to the dr registers
of the boot cpu directly.  This can be used up until the
kgdb_arch_late() is invoked, at which point the standard hw_breakpoint.c
API will get used.

CC: Frederic Weisbecker <fweisbec@gmail.com>
CC: Ingo Molnar <mingo@elte.hu>
Signed-off-by: NJason Wessel <jason.wessel@windriver.com>
上级 0b4b3827
...@@ -199,6 +199,8 @@ static struct hw_breakpoint { ...@@ -199,6 +199,8 @@ static struct hw_breakpoint {
struct perf_event **pev; struct perf_event **pev;
} breakinfo[4]; } breakinfo[4];
static unsigned long early_dr7;
static void kgdb_correct_hw_break(void) static void kgdb_correct_hw_break(void)
{ {
int breakno; int breakno;
...@@ -210,6 +212,14 @@ static void kgdb_correct_hw_break(void) ...@@ -210,6 +212,14 @@ static void kgdb_correct_hw_break(void)
int cpu = raw_smp_processor_id(); int cpu = raw_smp_processor_id();
if (!breakinfo[breakno].enabled) if (!breakinfo[breakno].enabled)
continue; continue;
if (dbg_is_early) {
set_debugreg(breakinfo[breakno].addr, breakno);
early_dr7 |= encode_dr7(breakno,
breakinfo[breakno].len,
breakinfo[breakno].type);
set_debugreg(early_dr7, 7);
continue;
}
bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu); bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu);
info = counter_arch_bp(bp); info = counter_arch_bp(bp);
if (bp->attr.disabled != 1) if (bp->attr.disabled != 1)
...@@ -224,7 +234,8 @@ static void kgdb_correct_hw_break(void) ...@@ -224,7 +234,8 @@ static void kgdb_correct_hw_break(void)
if (!val) if (!val)
bp->attr.disabled = 0; bp->attr.disabled = 0;
} }
hw_breakpoint_restore(); if (!dbg_is_early)
hw_breakpoint_restore();
} }
static int hw_break_reserve_slot(int breakno) static int hw_break_reserve_slot(int breakno)
...@@ -233,6 +244,9 @@ static int hw_break_reserve_slot(int breakno) ...@@ -233,6 +244,9 @@ static int hw_break_reserve_slot(int breakno)
int cnt = 0; int cnt = 0;
struct perf_event **pevent; struct perf_event **pevent;
if (dbg_is_early)
return 0;
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
cnt++; cnt++;
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
...@@ -258,6 +272,9 @@ static int hw_break_release_slot(int breakno) ...@@ -258,6 +272,9 @@ static int hw_break_release_slot(int breakno)
struct perf_event **pevent; struct perf_event **pevent;
int cpu; int cpu;
if (dbg_is_early)
return 0;
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
if (dbg_release_bp_slot(*pevent)) if (dbg_release_bp_slot(*pevent))
...@@ -302,7 +319,11 @@ static void kgdb_remove_all_hw_break(void) ...@@ -302,7 +319,11 @@ static void kgdb_remove_all_hw_break(void)
bp = *per_cpu_ptr(breakinfo[i].pev, cpu); bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
if (bp->attr.disabled == 1) if (bp->attr.disabled == 1)
continue; continue;
arch_uninstall_hw_breakpoint(bp); if (dbg_is_early)
early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
breakinfo[i].type);
else
arch_uninstall_hw_breakpoint(bp);
bp->attr.disabled = 1; bp->attr.disabled = 1;
} }
} }
...@@ -379,6 +400,11 @@ void kgdb_disable_hw_debug(struct pt_regs *regs) ...@@ -379,6 +400,11 @@ void kgdb_disable_hw_debug(struct pt_regs *regs)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (!breakinfo[i].enabled) if (!breakinfo[i].enabled)
continue; continue;
if (dbg_is_early) {
early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
breakinfo[i].type);
continue;
}
bp = *per_cpu_ptr(breakinfo[i].pev, cpu); bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
if (bp->attr.disabled == 1) if (bp->attr.disabled == 1)
continue; continue;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册