Skip to content

Commit

Permalink
x86,kgdb: Implement early hardware breakpoint debugging
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jason Wessel committed May 21, 2010
1 parent 0b4b382 commit 031acd8
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions arch/x86/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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))
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 031acd8

Please sign in to comment.