summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/alpha/alpha/db_trace.c33
-rw-r--r--sys/amd64/amd64/db_trace.c202
-rw-r--r--sys/amd64/amd64/machdep.c160
-rw-r--r--sys/ddb/db_command.c2
-rw-r--r--sys/ddb/db_watch.c45
-rw-r--r--sys/ddb/ddb.h2
-rw-r--r--sys/i386/i386/db_trace.c202
-rw-r--r--sys/i386/i386/machdep.c160
-rw-r--r--sys/ia64/ia64/db_trace.c33
9 files changed, 699 insertions, 140 deletions
diff --git a/sys/alpha/alpha/db_trace.c b/sys/alpha/alpha/db_trace.c
index c522379..c743926 100644
--- a/sys/alpha/alpha/db_trace.c
+++ b/sys/alpha/alpha/db_trace.c
@@ -96,6 +96,12 @@ static struct special_symbol {
{ NULL }
};
+
+int db_md_set_watchpoint __P((db_expr_t addr, db_expr_t size));
+int db_md_clr_watchpoint __P((db_expr_t addr, db_expr_t size));
+void db_md_list_watchpoints __P((void));
+
+
/*
* Decode the function prologue for the function we're in, and note
* which registers are stored where, and how large the stack frame is.
@@ -367,3 +373,30 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
frame += pi.pi_frame_size;
}
}
+
+
+
+int
+db_md_set_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ return (-1);
+}
+
+
+int
+db_md_clr_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ return (-1);
+}
+
+
+void
+db_md_list_watchpoints()
+{
+ return;
+}
+
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index a861d16..dc1e2f0 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -34,6 +34,8 @@
#include <sys/user.h>
#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/reg.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -107,6 +109,16 @@ static int db_numargs __P((struct i386_frame *));
static void db_print_stack_entry __P((const char *, int, char **, int *, db_addr_t));
static void decode_syscall __P((int, struct proc *));
+
+static char * watchtype_str __P((int type));
+int i386_set_watch __P((int watchnum, unsigned int watchaddr,
+ int size, int access, struct dbreg * d));
+int i386_clr_watch __P((int watchnum, struct dbreg * d));
+int db_md_set_watchpoint __P((db_expr_t addr, db_expr_t size));
+int db_md_clr_watchpoint __P((db_expr_t addr, db_expr_t size));
+void db_md_list_watchpoints __P((void));
+
+
/*
* Figure out how many arguments were passed into the frame at "fp".
*/
@@ -427,7 +439,7 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
}
}
-#define DB_DRX_FUNC(reg) \
+#define DB_DRX_FUNC(reg) \
int \
db_ ## reg (vp, valuep, op) \
struct db_variable *vp; \
@@ -450,3 +462,191 @@ DB_DRX_FUNC(dr4)
DB_DRX_FUNC(dr5)
DB_DRX_FUNC(dr6)
DB_DRX_FUNC(dr7)
+
+
+
+int
+i386_set_watch(watchnum, watchaddr, size, access, d)
+ int watchnum;
+ unsigned int watchaddr;
+ int size;
+ int access;
+ struct dbreg * d;
+{
+ int i;
+ unsigned int mask;
+
+ if (watchnum == -1) {
+ for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
+ if ((d->dr7 & mask) == 0)
+ break;
+ if (i < 4)
+ watchnum = i;
+ else
+ return (-1);
+ }
+
+ switch (access) {
+ case DBREG_DR7_EXEC:
+ size = 1; /* size must be 1 for an execution breakpoint */
+ /* fall through */
+ case DBREG_DR7_WRONLY:
+ case DBREG_DR7_RDWR:
+ break;
+ default : return (-1); break;
+ }
+
+ /*
+ * we can watch a 1, 2, or 4 byte sized location
+ */
+ switch (size) {
+ case 1 : mask = 0x00; break;
+ case 2 : mask = 0x01 << 2; break;
+ case 4 : mask = 0x03 << 2; break;
+ default : return (-1); break;
+ }
+
+ mask |= access;
+
+ /* clear the bits we are about to affect */
+ d->dr7 &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+
+ /* set drN register to the address, N=watchnum */
+ DBREG_DRX(d,watchnum) = watchaddr;
+
+ /* enable the watchpoint */
+ d->dr7 |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
+
+ return (watchnum);
+}
+
+
+int
+i386_clr_watch(watchnum, d)
+ int watchnum;
+ struct dbreg * d;
+{
+
+ if (watchnum < 0 || watchnum >= 4)
+ return (-1);
+
+ d->dr7 = d->dr7 & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+ DBREG_DRX(d,watchnum) = 0;
+
+ return (0);
+}
+
+
+int
+db_md_set_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ int avail, wsize;
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ avail = 0;
+ for(i=0; i<4; i++) {
+ if ((d.dr7 & (3 << (i*2))) == 0)
+ avail++;
+ }
+
+ if (avail*4 < size)
+ return (-1);
+
+ for (i=0; i<4 && (size != 0); i++) {
+ if ((d.dr7 & (3<<(i*2))) == 0) {
+ if (size > 4)
+ wsize = 4;
+ else
+ wsize = size;
+ if (wsize == 3)
+ wsize++;
+ i386_set_watch(i, addr, wsize,
+ DBREG_DR7_WRONLY, &d);
+ addr += wsize;
+ size -= wsize;
+ }
+ }
+
+ set_dbregs(NULL, &d);
+
+ return(0);
+}
+
+
+int
+db_md_clr_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ for(i=0; i<4; i++) {
+ if (d.dr7 & (3 << (i*2))) {
+ if ((DBREG_DRX((&d), i) >= addr) &&
+ (DBREG_DRX((&d), i) < addr+size))
+ i386_clr_watch(i, &d);
+
+ }
+ }
+
+ set_dbregs(NULL, &d);
+
+ return(0);
+}
+
+
+static
+char *
+watchtype_str(type)
+ int type;
+{
+ switch (type) {
+ case DBREG_DR7_EXEC : return "execute"; break;
+ case DBREG_DR7_RDWR : return "read/write"; break;
+ case DBREG_DR7_WRONLY : return "write"; break;
+ default : return "invalid"; break;
+ }
+}
+
+
+void
+db_md_list_watchpoints()
+{
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ db_printf("\nhardware watchpoints:\n");
+ db_printf(" watch status type len address\n"
+ " ----- -------- ---------- --- ----------\n");
+ for (i=0; i<4; i++) {
+ if (d.dr7 & (0x03 << (i*2))) {
+ unsigned type, len;
+ type = (d.dr7 >> (16+(i*4))) & 3;
+ len = (d.dr7 >> (16+(i*4)+2)) & 3;
+ db_printf(" %-5d %-8s %10s %3d 0x%08x\n",
+ i, "enabled", watchtype_str(type),
+ len+1, DBREG_DRX((&d),i));
+ }
+ else {
+ db_printf(" %-5d disabled\n", i);
+ }
+ }
+
+ db_printf("\ndebug register values:\n");
+ for (i=0; i<8; i++) {
+ db_printf(" dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
+ }
+ db_printf("\n");
+}
+
+
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 9ee7bfc..544aff5 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -2186,15 +2186,27 @@ fill_dbregs(p, dbregs)
{
struct pcb *pcb;
- pcb = &p->p_addr->u_pcb;
- dbregs->dr0 = pcb->pcb_dr0;
- dbregs->dr1 = pcb->pcb_dr1;
- dbregs->dr2 = pcb->pcb_dr2;
- dbregs->dr3 = pcb->pcb_dr3;
- dbregs->dr4 = 0;
- dbregs->dr5 = 0;
- dbregs->dr6 = pcb->pcb_dr6;
- dbregs->dr7 = pcb->pcb_dr7;
+ if (p == NULL) {
+ dbregs->dr0 = rdr0();
+ dbregs->dr1 = rdr1();
+ dbregs->dr2 = rdr2();
+ dbregs->dr3 = rdr3();
+ dbregs->dr4 = rdr4();
+ dbregs->dr5 = rdr5();
+ dbregs->dr6 = rdr6();
+ dbregs->dr7 = rdr7();
+ }
+ else {
+ pcb = &p->p_addr->u_pcb;
+ dbregs->dr0 = pcb->pcb_dr0;
+ dbregs->dr1 = pcb->pcb_dr1;
+ dbregs->dr2 = pcb->pcb_dr2;
+ dbregs->dr3 = pcb->pcb_dr3;
+ dbregs->dr4 = 0;
+ dbregs->dr5 = 0;
+ dbregs->dr6 = pcb->pcb_dr6;
+ dbregs->dr7 = pcb->pcb_dr7;
+ }
return (0);
}
@@ -2207,74 +2219,84 @@ set_dbregs(p, dbregs)
int i;
u_int32_t mask1, mask2;
- /*
- * Don't let an illegal value for dr7 get set. Specifically,
- * check for undefined settings. Setting these bit patterns
- * result in undefined behaviour and can lead to an unexpected
- * TRCTRAP.
- */
- for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
- i++, mask1 <<= 2, mask2 <<= 2)
- if ((dbregs->dr7 & mask1) == mask2)
+ if (p == NULL) {
+ load_dr0(dbregs->dr0);
+ load_dr1(dbregs->dr1);
+ load_dr2(dbregs->dr2);
+ load_dr3(dbregs->dr3);
+ load_dr4(dbregs->dr4);
+ load_dr5(dbregs->dr5);
+ load_dr6(dbregs->dr6);
+ load_dr7(dbregs->dr7);
+ }
+ else {
+ /*
+ * Don't let an illegal value for dr7 get set. Specifically,
+ * check for undefined settings. Setting these bit patterns
+ * result in undefined behaviour and can lead to an unexpected
+ * TRCTRAP.
+ */
+ for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
+ i++, mask1 <<= 2, mask2 <<= 2)
+ if ((dbregs->dr7 & mask1) == mask2)
+ return (EINVAL);
+
+ if (dbregs->dr7 & 0x0000fc00)
return (EINVAL);
- if (dbregs->dr7 & 0x0000fc00)
- return (EINVAL);
-
-
-
- pcb = &p->p_addr->u_pcb;
-
- /*
- * Don't let a process set a breakpoint that is not within the
- * process's address space. If a process could do this, it
- * could halt the system by setting a breakpoint in the kernel
- * (if ddb was enabled). Thus, we need to check to make sure
- * that no breakpoints are being enabled for addresses outside
- * process's address space, unless, perhaps, we were called by
- * uid 0.
- *
- * XXX - what about when the watched area of the user's
- * address space is written into from within the kernel
- * ... wouldn't that still cause a breakpoint to be generated
- * from within kernel mode?
- */
-
- if (suser(p) != 0) {
- if (dbregs->dr7 & 0x3) {
- /* dr0 is enabled */
- if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb = &p->p_addr->u_pcb;
+
+ /*
+ * Don't let a process set a breakpoint that is not within the
+ * process's address space. If a process could do this, it
+ * could halt the system by setting a breakpoint in the kernel
+ * (if ddb was enabled). Thus, we need to check to make sure
+ * that no breakpoints are being enabled for addresses outside
+ * process's address space, unless, perhaps, we were called by
+ * uid 0.
+ *
+ * XXX - what about when the watched area of the user's
+ * address space is written into from within the kernel
+ * ... wouldn't that still cause a breakpoint to be generated
+ * from within kernel mode?
+ */
- if (dbregs->dr7 & (0x3<<2)) {
- /* dr1 is enabled */
- if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
+ if (suser(p) != 0) {
+ if (dbregs->dr7 & 0x3) {
+ /* dr0 is enabled */
+ if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<2)) {
+ /* dr1 is enabled */
+ if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<4)) {
+ /* dr2 is enabled */
+ if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<6)) {
+ /* dr3 is enabled */
+ if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
}
- if (dbregs->dr7 & (0x3<<4)) {
- /* dr2 is enabled */
- if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb->pcb_dr0 = dbregs->dr0;
+ pcb->pcb_dr1 = dbregs->dr1;
+ pcb->pcb_dr2 = dbregs->dr2;
+ pcb->pcb_dr3 = dbregs->dr3;
+ pcb->pcb_dr6 = dbregs->dr6;
+ pcb->pcb_dr7 = dbregs->dr7;
- if (dbregs->dr7 & (0x3<<6)) {
- /* dr3 is enabled */
- if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb->pcb_flags |= PCB_DBREGS;
}
- pcb->pcb_dr0 = dbregs->dr0;
- pcb->pcb_dr1 = dbregs->dr1;
- pcb->pcb_dr2 = dbregs->dr2;
- pcb->pcb_dr3 = dbregs->dr3;
- pcb->pcb_dr6 = dbregs->dr6;
- pcb->pcb_dr7 = dbregs->dr7;
-
- pcb->pcb_flags |= PCB_DBREGS;
-
return (0);
}
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index 64cad7e..dfcc9c3 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -401,6 +401,8 @@ static struct command db_command_table[] = {
{ "break", db_breakpoint_cmd, 0, 0 },
{ "dwatch", db_deletewatch_cmd, 0, 0 },
{ "watch", db_watchpoint_cmd, CS_MORE,0 },
+ { "dhwatch", db_deletehwatch_cmd, 0, 0 },
+ { "hwatch", db_hwatchpoint_cmd, 0, 0 },
{ "step", db_single_step_cmd, 0, 0 },
{ "s", db_single_step_cmd, 0, 0 },
{ "continue", db_continue_cmd, 0, 0 },
diff --git a/sys/ddb/db_watch.c b/sys/ddb/db_watch.c
index 079013a..abfb853 100644
--- a/sys/ddb/db_watch.c
+++ b/sys/ddb/db_watch.c
@@ -67,6 +67,10 @@ static void db_list_watchpoints __P((void));
static void db_set_watchpoint __P((vm_map_t map, db_addr_t addr,
vm_size_t size));
+int db_md_set_watchpoint __P((db_expr_t addr, db_expr_t size));
+int db_md_clr_watchpoint __P((db_expr_t addr, db_expr_t size));
+void db_md_list_watchpoints __P((void));
+
db_watchpoint_t
db_watchpoint_alloc()
@@ -220,6 +224,7 @@ db_watchpoint_cmd(addr, have_addr, count, modif)
DB_SHOW_COMMAND(watches, db_listwatch_cmd)
{
db_list_watchpoints();
+ db_md_list_watchpoints();
}
void
@@ -282,3 +287,43 @@ db_find_watchpoint(map, addr, regs)
return (FALSE);
}
#endif
+
+
+
+/* Delete hardware watchpoint */
+/*ARGSUSED*/
+void
+db_deletehwatch_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char * modif;
+{
+ int rc;
+
+ if (count < 0)
+ count = 4;
+
+ rc = db_md_clr_watchpoint(addr, count);
+ if (rc < 0)
+ db_printf("hardware watchpoint could not be deleted\n");
+}
+
+/* Set hardware watchpoint */
+/*ARGSUSED*/
+void
+db_hwatchpoint_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char * modif;
+{
+ int rc;
+
+ if (count < 0)
+ count = 4;
+
+ rc = db_md_set_watchpoint(addr, count);
+ if (rc < 0)
+ db_printf("hardware watchpoint could not be set\n");
+}
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index 972772f..df602d0 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -109,8 +109,10 @@ void kdb_init __P((void));
db_cmdfcn_t db_breakpoint_cmd;
db_cmdfcn_t db_continue_cmd;
db_cmdfcn_t db_delete_cmd;
+db_cmdfcn_t db_deletehwatch_cmd;
db_cmdfcn_t db_deletewatch_cmd;
db_cmdfcn_t db_examine_cmd;
+db_cmdfcn_t db_hwatchpoint_cmd;
db_cmdfcn_t db_listbreak_cmd;
db_cmdfcn_t db_print_cmd;
db_cmdfcn_t db_ps;
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index a861d16..dc1e2f0 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -34,6 +34,8 @@
#include <sys/user.h>
#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/reg.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -107,6 +109,16 @@ static int db_numargs __P((struct i386_frame *));
static void db_print_stack_entry __P((const char *, int, char **, int *, db_addr_t));
static void decode_syscall __P((int, struct proc *));
+
+static char * watchtype_str __P((int type));
+int i386_set_watch __P((int watchnum, unsigned int watchaddr,
+ int size, int access, struct dbreg * d));
+int i386_clr_watch __P((int watchnum, struct dbreg * d));
+int db_md_set_watchpoint __P((db_expr_t addr, db_expr_t size));
+int db_md_clr_watchpoint __P((db_expr_t addr, db_expr_t size));
+void db_md_list_watchpoints __P((void));
+
+
/*
* Figure out how many arguments were passed into the frame at "fp".
*/
@@ -427,7 +439,7 @@ db_stack_trace_cmd(addr, have_addr, count, modif)
}
}
-#define DB_DRX_FUNC(reg) \
+#define DB_DRX_FUNC(reg) \
int \
db_ ## reg (vp, valuep, op) \
struct db_variable *vp; \
@@ -450,3 +462,191 @@ DB_DRX_FUNC(dr4)
DB_DRX_FUNC(dr5)
DB_DRX_FUNC(dr6)
DB_DRX_FUNC(dr7)
+
+
+
+int
+i386_set_watch(watchnum, watchaddr, size, access, d)
+ int watchnum;
+ unsigned int watchaddr;
+ int size;
+ int access;
+ struct dbreg * d;
+{
+ int i;
+ unsigned int mask;
+
+ if (watchnum == -1) {
+ for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
+ if ((d->dr7 & mask) == 0)
+ break;
+ if (i < 4)
+ watchnum = i;
+ else
+ return (-1);
+ }
+
+ switch (access) {
+ case DBREG_DR7_EXEC:
+ size = 1; /* size must be 1 for an execution breakpoint */
+ /* fall through */
+ case DBREG_DR7_WRONLY:
+ case DBREG_DR7_RDWR:
+ break;
+ default : return (-1); break;
+ }
+
+ /*
+ * we can watch a 1, 2, or 4 byte sized location
+ */
+ switch (size) {
+ case 1 : mask = 0x00; break;
+ case 2 : mask = 0x01 << 2; break;
+ case 4 : mask = 0x03 << 2; break;
+ default : return (-1); break;
+ }
+
+ mask |= access;
+
+ /* clear the bits we are about to affect */
+ d->dr7 &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+
+ /* set drN register to the address, N=watchnum */
+ DBREG_DRX(d,watchnum) = watchaddr;
+
+ /* enable the watchpoint */
+ d->dr7 |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
+
+ return (watchnum);
+}
+
+
+int
+i386_clr_watch(watchnum, d)
+ int watchnum;
+ struct dbreg * d;
+{
+
+ if (watchnum < 0 || watchnum >= 4)
+ return (-1);
+
+ d->dr7 = d->dr7 & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+ DBREG_DRX(d,watchnum) = 0;
+
+ return (0);
+}
+
+
+int
+db_md_set_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ int avail, wsize;
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ avail = 0;
+ for(i=0; i<4; i++) {
+ if ((d.dr7 & (3 << (i*2))) == 0)
+ avail++;
+ }
+
+ if (avail*4 < size)
+ return (-1);
+
+ for (i=0; i<4 && (size != 0); i++) {
+ if ((d.dr7 & (3<<(i*2))) == 0) {
+ if (size > 4)
+ wsize = 4;
+ else
+ wsize = size;
+ if (wsize == 3)
+ wsize++;
+ i386_set_watch(i, addr, wsize,
+ DBREG_DR7_WRONLY, &d);
+ addr += wsize;
+ size -= wsize;
+ }
+ }
+
+ set_dbregs(NULL, &d);
+
+ return(0);
+}
+
+
+int
+db_md_clr_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ for(i=0; i<4; i++) {
+ if (d.dr7 & (3 << (i*2))) {
+ if ((DBREG_DRX((&d), i) >= addr) &&
+ (DBREG_DRX((&d), i) < addr+size))
+ i386_clr_watch(i, &d);
+
+ }
+ }
+
+ set_dbregs(NULL, &d);
+
+ return(0);
+}
+
+
+static
+char *
+watchtype_str(type)
+ int type;
+{
+ switch (type) {
+ case DBREG_DR7_EXEC : return "execute"; break;
+ case DBREG_DR7_RDWR : return "read/write"; break;
+ case DBREG_DR7_WRONLY : return "write"; break;
+ default : return "invalid"; break;
+ }
+}
+
+
+void
+db_md_list_watchpoints()
+{
+ int i;
+ struct dbreg d;
+
+ fill_dbregs(NULL, &d);
+
+ db_printf("\nhardware watchpoints:\n");
+ db_printf(" watch status type len address\n"
+ " ----- -------- ---------- --- ----------\n");
+ for (i=0; i<4; i++) {
+ if (d.dr7 & (0x03 << (i*2))) {
+ unsigned type, len;
+ type = (d.dr7 >> (16+(i*4))) & 3;
+ len = (d.dr7 >> (16+(i*4)+2)) & 3;
+ db_printf(" %-5d %-8s %10s %3d 0x%08x\n",
+ i, "enabled", watchtype_str(type),
+ len+1, DBREG_DRX((&d),i));
+ }
+ else {
+ db_printf(" %-5d disabled\n", i);
+ }
+ }
+
+ db_printf("\ndebug register values:\n");
+ for (i=0; i<8; i++) {
+ db_printf(" dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
+ }
+ db_printf("\n");
+}
+
+
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 9ee7bfc..544aff5 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -2186,15 +2186,27 @@ fill_dbregs(p, dbregs)
{
struct pcb *pcb;
- pcb = &p->p_addr->u_pcb;
- dbregs->dr0 = pcb->pcb_dr0;
- dbregs->dr1 = pcb->pcb_dr1;
- dbregs->dr2 = pcb->pcb_dr2;
- dbregs->dr3 = pcb->pcb_dr3;
- dbregs->dr4 = 0;
- dbregs->dr5 = 0;
- dbregs->dr6 = pcb->pcb_dr6;
- dbregs->dr7 = pcb->pcb_dr7;
+ if (p == NULL) {
+ dbregs->dr0 = rdr0();
+ dbregs->dr1 = rdr1();
+ dbregs->dr2 = rdr2();
+ dbregs->dr3 = rdr3();
+ dbregs->dr4 = rdr4();
+ dbregs->dr5 = rdr5();
+ dbregs->dr6 = rdr6();
+ dbregs->dr7 = rdr7();
+ }
+ else {
+ pcb = &p->p_addr->u_pcb;
+ dbregs->dr0 = pcb->pcb_dr0;
+ dbregs->dr1 = pcb->pcb_dr1;
+ dbregs->dr2 = pcb->pcb_dr2;
+ dbregs->dr3 = pcb->pcb_dr3;
+ dbregs->dr4 = 0;
+ dbregs->dr5 = 0;
+ dbregs->dr6 = pcb->pcb_dr6;
+ dbregs->dr7 = pcb->pcb_dr7;
+ }
return (0);
}
@@ -2207,74 +2219,84 @@ set_dbregs(p, dbregs)
int i;
u_int32_t mask1, mask2;
- /*
- * Don't let an illegal value for dr7 get set. Specifically,
- * check for undefined settings. Setting these bit patterns
- * result in undefined behaviour and can lead to an unexpected
- * TRCTRAP.
- */
- for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
- i++, mask1 <<= 2, mask2 <<= 2)
- if ((dbregs->dr7 & mask1) == mask2)
+ if (p == NULL) {
+ load_dr0(dbregs->dr0);
+ load_dr1(dbregs->dr1);
+ load_dr2(dbregs->dr2);
+ load_dr3(dbregs->dr3);
+ load_dr4(dbregs->dr4);
+ load_dr5(dbregs->dr5);
+ load_dr6(dbregs->dr6);
+ load_dr7(dbregs->dr7);
+ }
+ else {
+ /*
+ * Don't let an illegal value for dr7 get set. Specifically,
+ * check for undefined settings. Setting these bit patterns
+ * result in undefined behaviour and can lead to an unexpected
+ * TRCTRAP.
+ */
+ for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8;
+ i++, mask1 <<= 2, mask2 <<= 2)
+ if ((dbregs->dr7 & mask1) == mask2)
+ return (EINVAL);
+
+ if (dbregs->dr7 & 0x0000fc00)
return (EINVAL);
- if (dbregs->dr7 & 0x0000fc00)
- return (EINVAL);
-
-
-
- pcb = &p->p_addr->u_pcb;
-
- /*
- * Don't let a process set a breakpoint that is not within the
- * process's address space. If a process could do this, it
- * could halt the system by setting a breakpoint in the kernel
- * (if ddb was enabled). Thus, we need to check to make sure
- * that no breakpoints are being enabled for addresses outside
- * process's address space, unless, perhaps, we were called by
- * uid 0.
- *
- * XXX - what about when the watched area of the user's
- * address space is written into from within the kernel
- * ... wouldn't that still cause a breakpoint to be generated
- * from within kernel mode?
- */
-
- if (suser(p) != 0) {
- if (dbregs->dr7 & 0x3) {
- /* dr0 is enabled */
- if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb = &p->p_addr->u_pcb;
+
+ /*
+ * Don't let a process set a breakpoint that is not within the
+ * process's address space. If a process could do this, it
+ * could halt the system by setting a breakpoint in the kernel
+ * (if ddb was enabled). Thus, we need to check to make sure
+ * that no breakpoints are being enabled for addresses outside
+ * process's address space, unless, perhaps, we were called by
+ * uid 0.
+ *
+ * XXX - what about when the watched area of the user's
+ * address space is written into from within the kernel
+ * ... wouldn't that still cause a breakpoint to be generated
+ * from within kernel mode?
+ */
- if (dbregs->dr7 & (0x3<<2)) {
- /* dr1 is enabled */
- if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
+ if (suser(p) != 0) {
+ if (dbregs->dr7 & 0x3) {
+ /* dr0 is enabled */
+ if (dbregs->dr0 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<2)) {
+ /* dr1 is enabled */
+ if (dbregs->dr1 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<4)) {
+ /* dr2 is enabled */
+ if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
+
+ if (dbregs->dr7 & (0x3<<6)) {
+ /* dr3 is enabled */
+ if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+ }
}
- if (dbregs->dr7 & (0x3<<4)) {
- /* dr2 is enabled */
- if (dbregs->dr2 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb->pcb_dr0 = dbregs->dr0;
+ pcb->pcb_dr1 = dbregs->dr1;
+ pcb->pcb_dr2 = dbregs->dr2;
+ pcb->pcb_dr3 = dbregs->dr3;
+ pcb->pcb_dr6 = dbregs->dr6;
+ pcb->pcb_dr7 = dbregs->dr7;
- if (dbregs->dr7 & (0x3<<6)) {
- /* dr3 is enabled */
- if (dbregs->dr3 >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
+ pcb->pcb_flags |= PCB_DBREGS;
}
- pcb->pcb_dr0 = dbregs->dr0;
- pcb->pcb_dr1 = dbregs->dr1;
- pcb->pcb_dr2 = dbregs->dr2;
- pcb->pcb_dr3 = dbregs->dr3;
- pcb->pcb_dr6 = dbregs->dr6;
- pcb->pcb_dr7 = dbregs->dr7;
-
- pcb->pcb_flags |= PCB_DBREGS;
-
return (0);
}
diff --git a/sys/ia64/ia64/db_trace.c b/sys/ia64/ia64/db_trace.c
index e30e340..3fc7909 100644
--- a/sys/ia64/ia64/db_trace.c
+++ b/sys/ia64/ia64/db_trace.c
@@ -36,6 +36,12 @@
#include <ddb/db_variables.h>
#include <ddb/db_output.h>
+
+int db_md_set_watchpoint __P((db_expr_t addr, db_expr_t size));
+int db_md_clr_watchpoint __P((db_expr_t addr, db_expr_t size));
+void db_md_list_watchpoints __P((void));
+
+
void
db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif)
{
@@ -99,3 +105,30 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *m
break;
}
}
+
+
+
+int
+db_md_set_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ return (-1);
+}
+
+
+int
+db_md_clr_watchpoint(addr, size)
+ db_expr_t addr;
+ db_expr_t size;
+{
+ return (-1);
+}
+
+
+void
+db_md_list_watchpoints()
+{
+ return;
+}
+
OpenPOWER on IntegriCloud