forked from luck/tmp_suning_uos_patched
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: Jason Wessel <jason.wessel@windriver.com>
This commit is contained in:
parent
0b4b3827db
commit
031acd8c42
|
@ -199,6 +199,8 @@ static struct hw_breakpoint {
|
|||
struct perf_event **pev;
|
||||
} breakinfo[4];
|
||||
|
||||
static unsigned long early_dr7;
|
||||
|
||||
static void kgdb_correct_hw_break(void)
|
||||
{
|
||||
int breakno;
|
||||
|
@ -210,6 +212,14 @@ static void kgdb_correct_hw_break(void)
|
|||
int cpu = raw_smp_processor_id();
|
||||
if (!breakinfo[breakno].enabled)
|
||||
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);
|
||||
info = counter_arch_bp(bp);
|
||||
if (bp->attr.disabled != 1)
|
||||
|
@ -224,7 +234,8 @@ static void kgdb_correct_hw_break(void)
|
|||
if (!val)
|
||||
bp->attr.disabled = 0;
|
||||
}
|
||||
hw_breakpoint_restore();
|
||||
if (!dbg_is_early)
|
||||
hw_breakpoint_restore();
|
||||
}
|
||||
|
||||
static int hw_break_reserve_slot(int breakno)
|
||||
|
@ -233,6 +244,9 @@ static int hw_break_reserve_slot(int breakno)
|
|||
int cnt = 0;
|
||||
struct perf_event **pevent;
|
||||
|
||||
if (dbg_is_early)
|
||||
return 0;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
cnt++;
|
||||
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
|
||||
|
@ -258,6 +272,9 @@ static int hw_break_release_slot(int breakno)
|
|||
struct perf_event **pevent;
|
||||
int cpu;
|
||||
|
||||
if (dbg_is_early)
|
||||
return 0;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
|
||||
if (dbg_release_bp_slot(*pevent))
|
||||
|
@ -302,7 +319,11 @@ static void kgdb_remove_all_hw_break(void)
|
|||
bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
|
||||
if (bp->attr.disabled == 1)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -379,6 +400,11 @@ void kgdb_disable_hw_debug(struct pt_regs *regs)
|
|||
for (i = 0; i < 4; i++) {
|
||||
if (!breakinfo[i].enabled)
|
||||
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);
|
||||
if (bp->attr.disabled == 1)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue
Block a user