diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-02-04 11:43:17 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2013-02-04 11:44:41 +0100 |
commit | 39376ba840a8682082eee9175b6951d4a7ae41f2 (patch) | |
tree | 09d99578313db44ba159bf14d33a38b577231711 | |
parent | 43042e6f6cc483b22694619861eab183364f08f5 (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.c | 13 | ||||
-rw-r--r-- | i386/i386/db_interface.c | 43 | ||||
-rw-r--r-- | i386/i386/db_interface.h | 12 | ||||
-rw-r--r-- | i386/i386/db_machdep.h | 1 |
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> |