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.
This commit is contained in:
John Baldwin 2006-11-17 20:27:01 +00:00
parent 4fca587ae7
commit 81efc3d94c
3 changed files with 17 additions and 5 deletions

View File

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

View File

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

View File

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