summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2013-02-04 11:43:17 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2013-02-04 11:44:41 +0100
commit39376ba840a8682082eee9175b6951d4a7ae41f2 (patch)
tree09d99578313db44ba159bf14d33a38b577231711
parent43042e6f6cc483b22694619861eab183364f08f5 (diff)
Plug hw debug register support into kdb
Make the `watch' command use hw debug registers whenever possible. * ddb/db_watch.c (db_set_hw_watchpoint, db_clear_hw_watchpoint): Add functions prototypes. (db_set_watchpoints): Try to call db_set_hw_watchpoint. (db_clear_watchpoints): Call db_clear_hw_watchpoint. * i386/i386/db_interface.c: Include <ddb/db_watch.h> (db_set_hw_watchpoint): Take a db_watchpoint_t WATCH parameter instead of its content. Remove support for clearing a debug register. (db_clear_hw_watchpoint): Add function. * i386/i386/db_interface.h: Include <ddb/db_watch.h>. (db_set_hw_watchpoint): Fix function prototype. (db_clear_hw_watchpoint): Add function prototype. * i386/i386/db_machdep.h: Do not include <machine/db_interface.h>
-rw-r--r--ddb/db_watch.c13
-rw-r--r--i386/i386/db_interface.c43
-rw-r--r--i386/i386/db_interface.h12
-rw-r--r--i386/i386/db_machdep.h1
4 files changed, 47 insertions, 22 deletions
diff --git a/ddb/db_watch.c b/ddb/db_watch.c
index 072f474..7eb9995 100644
--- a/ddb/db_watch.c
+++ b/ddb/db_watch.c
@@ -55,6 +55,9 @@
boolean_t db_watchpoints_inserted = TRUE;
+extern boolean_t db_set_hw_watchpoint(db_watchpoint_t watch, unsigned hw_idx);
+extern boolean_t db_clear_hw_watchpoint(unsigned hw_idx);
+
#define NWATCHPOINTS 100
struct db_watchpoint db_watch_table[NWATCHPOINTS];
db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
@@ -264,9 +267,14 @@ db_set_watchpoints(void)
{
register db_watchpoint_t watch;
vm_map_t map;
+ unsigned hw_idx = 0;
if (!db_watchpoints_inserted) {
for (watch = db_watchpoint_list; watch != 0; watch = watch->link) {
+ if (db_set_hw_watchpoint(watch, hw_idx)) {
+ hw_idx++;
+ continue;
+ }
map = (watch->task)? watch->task->map: kernel_map;
pmap_protect(map->pmap,
trunc_page(watch->loaddr),
@@ -280,6 +288,11 @@ db_set_watchpoints(void)
void
db_clear_watchpoints(void)
{
+ unsigned hw_idx = 0;
+
+ while (db_clear_hw_watchpoint(hw_idx))
+ hw_idx++;
+
db_watchpoints_inserted = FALSE;
}
diff --git a/i386/i386/db_interface.c b/i386/i386/db_interface.c
index c6d7fb4..90ca22d 100644
--- a/i386/i386/db_interface.c
+++ b/i386/i386/db_interface.c
@@ -53,6 +53,7 @@
#include <ddb/db_run.h>
#include <ddb/db_task_thread.h>
#include <ddb/db_trap.h>
+#include <ddb/db_watch.h>
#include <machine/db_interface.h>
#include <machine/machspl.h>
@@ -167,29 +168,27 @@ void db_dr (
splx(s);
}
-void db_set_hw_watchpoint(
- int num,
- task_t task,
- db_addr_t addr,
- vm_size_t size)
+boolean_t
+db_set_hw_watchpoint(
+ db_watchpoint_t watch,
+ unsigned num)
{
+ vm_size_t size = watch->hiaddr - watch->loaddr;
+ db_addr_t addr = watch->loaddr;
unsigned int kern_addr;
+ if (num >= 4)
+ return FALSE;
if (size != 1 && size != 2 && size != 4)
- return;
+ return FALSE;
if (addr & (size-1))
/* Unaligned */
- return;
-
- if (!addr) {
- db_dr (num, 0, 0, 0, 0);
- db_printf("Hardware watchpoint %d deleted\n", num);
- }
+ return FALSE;
- if (task) {
- if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
- return;
+ if (watch->task) {
+ if (db_user_to_kernel_address(watch->task, addr, &kern_addr, 1) < 0)
+ return FALSE;
addr = kern_addr;
}
addr = kvtolin(addr);
@@ -197,6 +196,18 @@ void db_set_hw_watchpoint(
db_dr (num, addr, I386_DB_TYPE_W, size-1, I386_DB_LOCAL|I386_DB_GLOBAL);
db_printf("Hardware watchpoint %d set for %x\n", num, addr);
+ return TRUE;
+}
+
+boolean_t
+db_clear_hw_watchpoint(
+ unsigned num)
+{
+ if (num >= 4)
+ return FALSE;
+
+ db_dr (num, 0, 0, 0, 0);
+ return TRUE;
}
/*
@@ -577,7 +588,7 @@ db_check_access(
register int size,
task_t task)
{
- register n;
+ int n;
vm_offset_t kern_addr;
if (addr >= VM_MIN_KERNEL_ADDRESS) {
diff --git a/i386/i386/db_interface.h b/i386/i386/db_interface.h
index a8dfdce..e1b2dff 100644
--- a/i386/i386/db_interface.h
+++ b/i386/i386/db_interface.h
@@ -24,6 +24,7 @@
#include <sys/types.h>
#include <kern/task.h>
#include <machine/thread.h>
+#include <ddb/db_watch.h>
extern boolean_t kdb_trap (
int type,
@@ -73,11 +74,12 @@ extern void db_task_name (task_t task);
#define I386_DB_LOCAL 1
#define I386_DB_GLOBAL 2
-extern void db_set_hw_watchpoint(
- int num,
- task_t task,
- vm_offset_t addr,
- vm_size_t size);
+extern boolean_t db_set_hw_watchpoint(
+ db_watchpoint_t watch,
+ unsigned num);
+
+extern boolean_t db_clear_hw_watchpoint(
+ unsigned num);
extern void db_dr (
int num,
diff --git a/i386/i386/db_machdep.h b/i386/i386/db_machdep.h
index 1dba2cd..c6ea3ca 100644
--- a/i386/i386/db_machdep.h
+++ b/i386/i386/db_machdep.h
@@ -34,7 +34,6 @@
#include <mach/machine/vm_types.h>
#include <mach/machine/vm_param.h>
#include <mach/machine/eflags.h>
-#include <machine/db_interface.h>
#include <i386/thread.h> /* for thread_status */
#include <i386/trap.h>