36 #include <linux/string.h>
37 #include <linux/kernel.h>
38 #include <linux/ptrace.h>
39 #include <linux/sched.h>
45 #include <linux/hw_breakpoint.h>
117 memcpy(mem, ®s->orig_ax,
sizeof(regs->orig_ax));
130 if (!user_mode_vm(regs))
134 if (!user_mode_vm(regs))
139 *(
unsigned long *)mem = 0xFFFF;
160 #ifndef CONFIG_X86_32
161 u32 *gdb_regs32 = (
u32 *)gdb_regs;
177 gdb_regs[
GDB_FS] = 0xFFFF;
178 gdb_regs[
GDB_GS] = 0xFFFF;
180 gdb_regs32[
GDB_PS] = *(
unsigned long *)(p->
thread.sp + 8);
196 static struct hw_breakpoint {
204 static unsigned long early_dr7;
206 static void kgdb_correct_hw_break(
void)
210 for (breakno = 0; breakno <
HBP_NUM; breakno++) {
215 if (!breakinfo[breakno].
enabled)
218 set_debugreg(breakinfo[breakno].
addr, breakno);
220 breakinfo[breakno].
len,
221 breakinfo[breakno].
type);
222 set_debugreg(early_dr7, 7);
226 info = counter_arch_bp(bp);
227 if (bp->
attr.disabled != 1)
229 bp->
attr.bp_addr = breakinfo[breakno].addr;
230 bp->
attr.bp_len = breakinfo[breakno].len;
231 bp->
attr.bp_type = breakinfo[breakno].type;
232 info->
address = breakinfo[breakno].addr;
233 info->
len = breakinfo[breakno].len;
234 info->
type = breakinfo[breakno].type;
237 bp->
attr.disabled = 0;
243 static int hw_break_reserve_slot(
int breakno)
272 static int hw_break_release_slot(
int breakno)
293 kgdb_remove_hw_break(
unsigned long addr,
int len,
enum kgdb_bptype bptype)
298 if (breakinfo[i].addr == addr && breakinfo[i].enabled)
303 if (hw_break_release_slot(i)) {
307 breakinfo[
i].enabled = 0;
312 static void kgdb_remove_all_hw_break(
void)
318 for (i = 0; i <
HBP_NUM; i++) {
319 if (!breakinfo[i].enabled)
322 if (!bp->
attr.disabled) {
324 bp->
attr.disabled = 1;
330 else if (hw_break_release_slot(i))
333 breakinfo[
i].enabled = 0;
338 kgdb_set_hw_break(
unsigned long addr,
int len,
enum kgdb_bptype bptype)
343 if (!breakinfo[i].enabled)
349 case BP_HARDWARE_BREAKPOINT:
351 breakinfo[
i].type = X86_BREAKPOINT_EXECUTE;
353 case BP_WRITE_WATCHPOINT:
354 breakinfo[
i].type = X86_BREAKPOINT_WRITE;
356 case BP_ACCESS_WATCHPOINT:
357 breakinfo[
i].type = X86_BREAKPOINT_RW;
364 breakinfo[
i].len = X86_BREAKPOINT_LEN_1;
367 breakinfo[
i].len = X86_BREAKPOINT_LEN_2;
370 breakinfo[
i].len = X86_BREAKPOINT_LEN_4;
374 breakinfo[
i].len = X86_BREAKPOINT_LEN_8;
380 breakinfo[
i].addr =
addr;
381 if (hw_break_reserve_slot(i)) {
382 breakinfo[
i].addr = 0;
385 breakinfo[
i].enabled = 1;
398 static void kgdb_disable_hw_debug(
struct pt_regs *
regs)
405 set_debugreg(0
UL, 7);
406 for (i = 0; i <
HBP_NUM; i++) {
407 if (!breakinfo[i].enabled)
415 if (bp->
attr.disabled == 1)
418 bp->
attr.disabled = 1;
462 char *remcomInBuffer,
char *remcomOutBuffer,
468 switch (remcomInBuffer[0]) {
472 ptr = &remcomInBuffer[1];
474 linux_regs->ip =
addr;
482 if (remcomInBuffer[0] ==
's') {
505 args->
err,
"c",
"", regs);
510 (*(
unsigned long *)ERR_PTR(args->
err)) &= ~
DR_STEP;
515 static int was_in_debug_nmi[
NR_CPUS];
517 static int kgdb_nmi_handler(
unsigned int cmd,
struct pt_regs *regs)
543 static int __kgdb_notify(
struct die_args *args,
unsigned long cmd)
551 return single_step_cont(regs, args);
587 return __kgdb_notify(&args, cmd);
597 ret = __kgdb_notify(ptr, cmd);
604 .notifier_call = kgdb_notify,
643 struct perf_sample_data *
data,
struct pt_regs *regs)
648 for (i = 0; i < 4; i++)
649 if (breakinfo[i].enabled)
664 hw_breakpoint_init(&attr);
669 for (i = 0; i <
HBP_NUM; i++) {
670 if (breakinfo[i].pev)
673 if (IS_ERR((
void *
__force)breakinfo[i].pev)) {
675 "breakpoints\nDisabling the kernel debugger\n");
676 breakinfo[
i].pev =
NULL;
682 pevent[0]->hw.sample_period = 1;
683 pevent[0]->overflow_handler = kgdb_hw_overflow_handler;
685 pevent[0]->destroy =
NULL;
701 for (i = 0; i < 4; i++) {
702 if (breakinfo[i].pev) {
704 breakinfo[
i].pev =
NULL;
749 #ifdef CONFIG_DEBUG_RODATA
753 bpt->type = BP_BREAKPOINT;
760 #ifdef CONFIG_DEBUG_RODATA
776 bpt->type = BP_POKE_BREAKPOINT;
783 #ifdef CONFIG_DEBUG_RODATA
787 if (bpt->type != BP_POKE_BREAKPOINT)
808 .gdb_bpt_instr = { 0xcc },
809 .flags = KGDB_HW_BREAKPOINT,
810 .set_hw_breakpoint = kgdb_set_hw_break,
811 .remove_hw_breakpoint = kgdb_remove_hw_break,
812 .disable_hw_break = kgdb_disable_hw_debug,
813 .remove_all_hw_break = kgdb_remove_all_hw_break,
814 .correct_hw_break = kgdb_correct_hw_break,