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
This commit is contained in:
Brian S. Dean 2001-06-28 02:08:13 +00:00
parent ffabd15013
commit 6eda157eaa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78903
7 changed files with 240 additions and 50 deletions

View File

@ -44,28 +44,45 @@
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -44,28 +44,45 @@
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
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)

View File

@ -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

View File

@ -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