From 47d3082050d220c6f4d161234ff7a3c4bc03b629 Mon Sep 17 00:00:00 2001 From: bsd Date: Thu, 28 Jun 2001 02:08:13 +0000 Subject: Provide access to the IA32 hardware debug registers from the ddb kernel debugger. Proper use of these registers allows setting hardware watchpoints for use in kernel debugging. MFC after: 2 weeks --- sys/amd64/amd64/db_trace.c | 71 +++++++++++++++++++++++++++++++++++---------- sys/amd64/amd64/support.S | 6 ---- sys/amd64/amd64/support.s | 6 ---- sys/amd64/include/cpufunc.h | 65 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 120 insertions(+), 28 deletions(-) (limited to 'sys/amd64') diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c index 64db559..a861d16 100644 --- a/sys/amd64/amd64/db_trace.c +++ b/sys/amd64/amd64/db_trace.c @@ -44,28 +44,45 @@ #include #include +db_varfcn_t db_dr0; +db_varfcn_t db_dr1; +db_varfcn_t db_dr2; +db_varfcn_t db_dr3; +db_varfcn_t db_dr4; +db_varfcn_t db_dr5; +db_varfcn_t db_dr6; +db_varfcn_t db_dr7; + /* * Machine register set. */ struct db_variable db_regs[] = { - { "cs", &ddb_regs.tf_cs, FCN_NULL }, - { "ds", &ddb_regs.tf_ds, FCN_NULL }, - { "es", &ddb_regs.tf_es, FCN_NULL }, - { "fs", &ddb_regs.tf_fs, FCN_NULL }, + { "cs", &ddb_regs.tf_cs, FCN_NULL }, + { "ds", &ddb_regs.tf_ds, FCN_NULL }, + { "es", &ddb_regs.tf_es, FCN_NULL }, + { "fs", &ddb_regs.tf_fs, FCN_NULL }, #if 0 - { "gs", &ddb_regs.tf_gs, FCN_NULL }, + { "gs", &ddb_regs.tf_gs, FCN_NULL }, #endif - { "ss", &ddb_regs.tf_ss, FCN_NULL }, - { "eax", &ddb_regs.tf_eax, FCN_NULL }, - { "ecx", &ddb_regs.tf_ecx, FCN_NULL }, - { "edx", &ddb_regs.tf_edx, FCN_NULL }, - { "ebx", &ddb_regs.tf_ebx, FCN_NULL }, - { "esp", &ddb_regs.tf_esp, FCN_NULL }, - { "ebp", &ddb_regs.tf_ebp, FCN_NULL }, - { "esi", &ddb_regs.tf_esi, FCN_NULL }, - { "edi", &ddb_regs.tf_edi, FCN_NULL }, - { "eip", &ddb_regs.tf_eip, FCN_NULL }, + { "ss", &ddb_regs.tf_ss, FCN_NULL }, + { "eax", &ddb_regs.tf_eax, FCN_NULL }, + { "ecx", &ddb_regs.tf_ecx, FCN_NULL }, + { "edx", &ddb_regs.tf_edx, FCN_NULL }, + { "ebx", &ddb_regs.tf_ebx, FCN_NULL }, + { "esp", &ddb_regs.tf_esp, FCN_NULL }, + { "ebp", &ddb_regs.tf_ebp, FCN_NULL }, + { "esi", &ddb_regs.tf_esi, FCN_NULL }, + { "edi", &ddb_regs.tf_edi, FCN_NULL }, + { "eip", &ddb_regs.tf_eip, FCN_NULL }, { "efl", &ddb_regs.tf_eflags, FCN_NULL }, + { "dr0", NULL, db_dr0 }, + { "dr1", NULL, db_dr1 }, + { "dr2", NULL, db_dr2 }, + { "dr3", NULL, db_dr3 }, + { "dr4", NULL, db_dr4 }, + { "dr5", NULL, db_dr5 }, + { "dr6", NULL, db_dr6 }, + { "dr7", NULL, db_dr7 }, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); @@ -409,3 +426,27 @@ db_stack_trace_cmd(addr, have_addr, count, modif) } } } + +#define DB_DRX_FUNC(reg) \ +int \ +db_ ## reg (vp, valuep, op) \ + struct db_variable *vp; \ + db_expr_t * valuep; \ + int op; \ +{ \ + if (op == DB_VAR_GET) \ + *valuep = r ## reg (); \ + else \ + load_ ## reg (*valuep); \ + \ + return(0); \ +} + +DB_DRX_FUNC(dr0) +DB_DRX_FUNC(dr1) +DB_DRX_FUNC(dr2) +DB_DRX_FUNC(dr3) +DB_DRX_FUNC(dr4) +DB_DRX_FUNC(dr5) +DB_DRX_FUNC(dr6) +DB_DRX_FUNC(dr7) diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 70cc144..3218774 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -1627,12 +1627,6 @@ ENTRY(load_cr4) movl %eax,%cr4 ret -/* void load_dr6(u_int dr6) */ -ENTRY(load_dr6) - movl 4(%esp),%eax - movl %eax,%dr6 - ret - /* void reset_dbregs() */ ENTRY(reset_dbregs) movl $0,%eax diff --git a/sys/amd64/amd64/support.s b/sys/amd64/amd64/support.s index 70cc144..3218774 100644 --- a/sys/amd64/amd64/support.s +++ b/sys/amd64/amd64/support.s @@ -1627,12 +1627,6 @@ ENTRY(load_cr4) movl %eax,%cr4 ret -/* void load_dr6(u_int dr6) */ -ENTRY(load_dr6) - movl 4(%esp),%eax - movl %eax,%dr6 - ret - /* void reset_dbregs() */ ENTRY(reset_dbregs) movl $0,%eax diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 40f5bb7..4a9300a 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -443,6 +443,12 @@ rdr0(void) return (data); } +static __inline void +load_dr0(u_int sel) +{ + __asm __volatile("movl %0,%%dr0" : : "r" (sel)); +} + static __inline u_int rdr1(void) { @@ -451,6 +457,12 @@ rdr1(void) return (data); } +static __inline void +load_dr1(u_int sel) +{ + __asm __volatile("movl %0,%%dr1" : : "r" (sel)); +} + static __inline u_int rdr2(void) { @@ -459,6 +471,12 @@ rdr2(void) return (data); } +static __inline void +load_dr2(u_int sel) +{ + __asm __volatile("movl %0,%%dr2" : : "r" (sel)); +} + static __inline u_int rdr3(void) { @@ -467,6 +485,40 @@ rdr3(void) return (data); } +static __inline void +load_dr3(u_int sel) +{ + __asm __volatile("movl %0,%%dr3" : : "r" (sel)); +} + +static __inline u_int +rdr4(void) +{ + u_int data; + __asm __volatile("movl %%dr4,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr4(u_int sel) +{ + __asm __volatile("movl %0,%%dr4" : : "r" (sel)); +} + +static __inline u_int +rdr5(void) +{ + u_int data; + __asm __volatile("movl %%dr5,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr5(u_int sel) +{ + __asm __volatile("movl %0,%%dr5" : : "r" (sel)); +} + static __inline u_int rdr6(void) { @@ -475,6 +527,12 @@ rdr6(void) return (data); } +static __inline void +load_dr6(u_int sel) +{ + __asm __volatile("movl %0,%%dr6" : : "r" (sel)); +} + static __inline u_int rdr7(void) { @@ -483,6 +541,12 @@ rdr7(void) return (data); } +static __inline void +load_dr7(u_int sel) +{ + __asm __volatile("movl %0,%%dr7" : : "r" (sel)); +} + static __inline critical_t critical_enter(void) { @@ -545,7 +609,6 @@ void ltr __P((u_short sel)); u_int rcr0 __P((void)); u_int rcr3 __P((void)); u_int rcr4 __P((void)); -void load_dr6 __P((u_int dr6)); void reset_dbregs __P((void)); __END_DECLS -- cgit v1.1