summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-11-17 20:27:01 +0000
committerjhb <jhb@FreeBSD.org>2006-11-17 20:27:01 +0000
commit500c68689fe5387192dc5847af52413cf40bc4e3 (patch)
tree63928ef6e7214e0703d43d428f3319ff1640bd02
parent13fc897c39d908dee24d44cc0765ca966b4a385e (diff)
downloadFreeBSD-src-500c68689fe5387192dc5847af52413cf40bc4e3.zip
FreeBSD-src-500c68689fe5387192dc5847af52413cf40bc4e3.tar.gz
Add support for 8 byte hardware watches in long mode. Kernel hardware
watches support 8 byte watches. For userland, we disallow 8 byte watches for 32-bit tasks.
-rw-r--r--sys/amd64/amd64/db_trace.c18
-rw-r--r--sys/amd64/amd64/machdep.c3
-rw-r--r--sys/amd64/include/reg.h1
3 files changed, 17 insertions, 5 deletions
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index bd737dd..880be61 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -562,7 +562,7 @@ amd64_set_watch(watchnum, watchaddr, size, access, d)
}
/*
- * we can watch a 1, 2, or 4 byte sized location
+ * we can watch a 1, 2, 4, or 8 byte sized location
*/
switch (size) {
case 1:
@@ -574,6 +574,9 @@ amd64_set_watch(watchnum, watchaddr, size, access, d)
case 4:
len = DBREG_DR7_LEN_4;
break;
+ case 8:
+ len = DBREG_DR7_LEN_8;
+ break;
default:
return (-1);
}
@@ -624,12 +627,14 @@ db_md_set_watchpoint(addr, size)
avail++;
}
- if (avail * 4 < size)
+ if (avail * 8 < size)
return (-1);
for (i = 0; i < 4 && (size > 0); i++) {
if (!DBREG_DR7_ENABLED(d.dr[7], i)) {
- if (size > 2)
+ if (size >= 8 || (avail == 1 && size > 4))
+ wsize = 8;
+ else if (size > 2)
wsize = 4;
else
wsize = size;
@@ -637,6 +642,7 @@ db_md_set_watchpoint(addr, size)
DBREG_DR7_WRONLY, &d);
addr += wsize;
size -= wsize;
+ avail--;
}
}
@@ -699,8 +705,12 @@ db_md_list_watchpoints()
if (DBREG_DR7_ENABLED(d.dr[7], i)) {
type = DBREG_DR7_ACCESS(d.dr[7], i);
len = DBREG_DR7_LEN(d.dr[7], i);
+ if (len == DBREG_DR7_LEN_8)
+ len = 8;
+ else
+ len++;
db_printf(" %-5d %-8s %10s %3d ",
- i, "enabled", watchtype_str(type), len + 1);
+ i, "enabled", watchtype_str(type), len);
db_printsym((db_addr_t)DBREG_DRX((&d), i), DB_STGY_ANY);
db_printf("\n");
} else {
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 6c98010..67469e0 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1711,7 +1711,8 @@ set_dbregs(struct thread *td, struct dbreg *dbregs)
for (i = 0; i < 4; i++) {
if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02)
return (EINVAL);
- if (DBREG_DR7_LEN(dbregs->dr[7], i) == 0x02)
+ if (td->td_frame->tf_cs == _ucode32sel &&
+ DBREG_DR7_LEN(dbregs->dr[7], i) == DBREG_DR7_LEN_8)
return (EINVAL);
}
if ((dbregs->dr[6] & 0xffffffff00000000ul) != 0 ||
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 9358f05..9ca092f 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -97,6 +97,7 @@ struct dbreg {
#define DBREG_DR7_LEN_1 0x00 /* 1 byte length */
#define DBREG_DR7_LEN_2 0x01
#define DBREG_DR7_LEN_4 0x03
+#define DBREG_DR7_LEN_8 0x02
#define DBREG_DR7_EXEC 0x00 /* break on execute */
#define DBREG_DR7_WRONLY 0x01 /* break on write */
#define DBREG_DR7_RDWR 0x03 /* break on read or write */
OpenPOWER on IntegriCloud