2 * Copyright (c) 2014 The FreeBSD Foundation
4 * This software was developed by Semihalf under
5 * the sponsorship of the FreeBSD Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/types.h>
40 #include <sys/systm.h>
41 #include <sys/sysent.h>
43 #include <machine/armreg.h>
44 #include <machine/cpu.h>
45 #include <machine/debug_monitor.h>
46 #include <machine/kdb.h>
47 #include <machine/pcb.h>
51 #include <ddb/db_sym.h>
55 DBG_TYPE_BREAKPOINT = 0,
56 DBG_TYPE_WATCHPOINT = 1,
59 static int dbg_watchpoint_num;
60 static int dbg_breakpoint_num;
61 static struct debug_monitor_state kernel_monitor = {
62 .dbg_flags = DBGMON_KERNEL
65 static int dbg_setup_watchpoint(struct debug_monitor_state *, vm_offset_t,
66 vm_size_t, enum dbg_access_t);
67 static int dbg_remove_watchpoint(struct debug_monitor_state *, vm_offset_t,
70 /* Called from the exception handlers */
71 void dbg_monitor_enter(struct thread *);
72 void dbg_monitor_exit(struct thread *, struct trapframe *);
74 /* Watchpoints/breakpoints control register bitfields */
75 #define DBG_WATCH_CTRL_LEN_1 (0x1 << 5)
76 #define DBG_WATCH_CTRL_LEN_2 (0x3 << 5)
77 #define DBG_WATCH_CTRL_LEN_4 (0xf << 5)
78 #define DBG_WATCH_CTRL_LEN_8 (0xff << 5)
79 #define DBG_WATCH_CTRL_LEN_MASK(x) ((x) & (0xff << 5))
80 #define DBG_WATCH_CTRL_EXEC (0x0 << 3)
81 #define DBG_WATCH_CTRL_LOAD (0x1 << 3)
82 #define DBG_WATCH_CTRL_STORE (0x2 << 3)
83 #define DBG_WATCH_CTRL_ACCESS_MASK(x) ((x) & (0x3 << 3))
85 /* Common for breakpoint and watchpoint */
86 #define DBG_WB_CTRL_EL1 (0x1 << 1)
87 #define DBG_WB_CTRL_EL0 (0x2 << 1)
88 #define DBG_WB_CTRL_ELX_MASK(x) ((x) & (0x3 << 1))
89 #define DBG_WB_CTRL_E (0x1 << 0)
91 #define DBG_REG_BASE_BVR 0
92 #define DBG_REG_BASE_BCR (DBG_REG_BASE_BVR + 16)
93 #define DBG_REG_BASE_WVR (DBG_REG_BASE_BCR + 16)
94 #define DBG_REG_BASE_WCR (DBG_REG_BASE_WVR + 16)
96 /* Watchpoint/breakpoint helpers */
97 #define DBG_WB_WVR "wvr"
98 #define DBG_WB_WCR "wcr"
99 #define DBG_WB_BVR "bvr"
100 #define DBG_WB_BCR "bcr"
102 #define DBG_WB_READ(reg, num, val) do { \
103 __asm __volatile("mrs %0, dbg" reg #num "_el1" : "=r" (val)); \
106 #define DBG_WB_WRITE(reg, num, val) do { \
107 __asm __volatile("msr dbg" reg #num "_el1, %0" :: "r" (val)); \
110 #define READ_WB_REG_CASE(reg, num, offset, val) \
111 case (num + offset): \
112 DBG_WB_READ(reg, num, val); \
115 #define WRITE_WB_REG_CASE(reg, num, offset, val) \
116 case (num + offset): \
117 DBG_WB_WRITE(reg, num, val); \
120 #define SWITCH_CASES_READ_WB_REG(reg, offset, val) \
121 READ_WB_REG_CASE(reg, 0, offset, val); \
122 READ_WB_REG_CASE(reg, 1, offset, val); \
123 READ_WB_REG_CASE(reg, 2, offset, val); \
124 READ_WB_REG_CASE(reg, 3, offset, val); \
125 READ_WB_REG_CASE(reg, 4, offset, val); \
126 READ_WB_REG_CASE(reg, 5, offset, val); \
127 READ_WB_REG_CASE(reg, 6, offset, val); \
128 READ_WB_REG_CASE(reg, 7, offset, val); \
129 READ_WB_REG_CASE(reg, 8, offset, val); \
130 READ_WB_REG_CASE(reg, 9, offset, val); \
131 READ_WB_REG_CASE(reg, 10, offset, val); \
132 READ_WB_REG_CASE(reg, 11, offset, val); \
133 READ_WB_REG_CASE(reg, 12, offset, val); \
134 READ_WB_REG_CASE(reg, 13, offset, val); \
135 READ_WB_REG_CASE(reg, 14, offset, val); \
136 READ_WB_REG_CASE(reg, 15, offset, val)
138 #define SWITCH_CASES_WRITE_WB_REG(reg, offset, val) \
139 WRITE_WB_REG_CASE(reg, 0, offset, val); \
140 WRITE_WB_REG_CASE(reg, 1, offset, val); \
141 WRITE_WB_REG_CASE(reg, 2, offset, val); \
142 WRITE_WB_REG_CASE(reg, 3, offset, val); \
143 WRITE_WB_REG_CASE(reg, 4, offset, val); \
144 WRITE_WB_REG_CASE(reg, 5, offset, val); \
145 WRITE_WB_REG_CASE(reg, 6, offset, val); \
146 WRITE_WB_REG_CASE(reg, 7, offset, val); \
147 WRITE_WB_REG_CASE(reg, 8, offset, val); \
148 WRITE_WB_REG_CASE(reg, 9, offset, val); \
149 WRITE_WB_REG_CASE(reg, 10, offset, val); \
150 WRITE_WB_REG_CASE(reg, 11, offset, val); \
151 WRITE_WB_REG_CASE(reg, 12, offset, val); \
152 WRITE_WB_REG_CASE(reg, 13, offset, val); \
153 WRITE_WB_REG_CASE(reg, 14, offset, val); \
154 WRITE_WB_REG_CASE(reg, 15, offset, val)
158 dbg_wb_read_reg(int reg, int n)
163 SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
164 SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
165 SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
166 SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
168 printf("trying to read from wrong debug register %d\n", n);
176 dbg_wb_write_reg(int reg, int n, uint64_t val)
179 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
180 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
181 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
182 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
184 printf("trying to write to wrong debug register %d\n", n);
190 #if defined(DDB) || defined(GDB)
192 kdb_cpu_set_singlestep(void)
195 KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
196 ("%s: debug exceptions are not masked", __func__));
198 kdb_frame->tf_spsr |= PSR_SS;
199 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) |
200 MDSCR_SS | MDSCR_KDE);
203 * Disable breakpoints and watchpoints, e.g. stepping
204 * over watched instruction will trigger break exception instead of
205 * single-step exception and locks CPU on that instruction for ever.
207 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
208 WRITE_SPECIALREG(mdscr_el1,
209 READ_SPECIALREG(mdscr_el1) & ~MDSCR_MDE);
214 kdb_cpu_clear_singlestep(void)
217 KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
218 ("%s: debug exceptions are not masked", __func__));
220 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) &
221 ~(MDSCR_SS | MDSCR_KDE));
223 /* Restore breakpoints and watchpoints */
224 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
225 WRITE_SPECIALREG(mdscr_el1,
226 READ_SPECIALREG(mdscr_el1) | MDSCR_MDE);
228 if ((kernel_monitor.dbg_flags & DBGMON_KERNEL) != 0) {
229 WRITE_SPECIALREG(mdscr_el1,
230 READ_SPECIALREG(mdscr_el1) | MDSCR_KDE);
236 kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access)
238 enum dbg_access_t dbg_access;
241 case KDB_DBG_ACCESS_R:
242 dbg_access = HW_BREAKPOINT_R;
244 case KDB_DBG_ACCESS_W:
245 dbg_access = HW_BREAKPOINT_W;
247 case KDB_DBG_ACCESS_RW:
248 dbg_access = HW_BREAKPOINT_RW;
254 return (dbg_setup_watchpoint(NULL, addr, size, dbg_access));
258 kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size)
261 return (dbg_remove_watchpoint(NULL, addr, size));
263 #endif /* DDB || GDB */
267 dbg_watchtype_str(uint32_t type)
270 case DBG_WATCH_CTRL_EXEC:
272 case DBG_WATCH_CTRL_STORE:
274 case DBG_WATCH_CTRL_LOAD:
276 case DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE:
277 return ("read/write");
284 dbg_watchtype_len(uint32_t len)
287 case DBG_WATCH_CTRL_LEN_1:
289 case DBG_WATCH_CTRL_LEN_2:
291 case DBG_WATCH_CTRL_LEN_4:
293 case DBG_WATCH_CTRL_LEN_8:
301 dbg_show_watchpoint(void)
303 uint32_t wcr, len, type;
307 db_printf("\nhardware watchpoints:\n");
308 db_printf(" watch status type len address symbol\n");
309 db_printf(" ----- -------- ---------- --- ------------------ ------------------\n");
310 for (i = 0; i < dbg_watchpoint_num; i++) {
311 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
312 if ((wcr & DBG_WB_CTRL_E) != 0) {
313 type = DBG_WATCH_CTRL_ACCESS_MASK(wcr);
314 len = DBG_WATCH_CTRL_LEN_MASK(wcr);
315 addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i);
316 db_printf(" %-5d %-8s %10s %3d 0x%16lx ",
317 i, "enabled", dbg_watchtype_str(type),
318 dbg_watchtype_len(len), addr);
319 db_printsym((db_addr_t)addr, DB_STGY_ANY);
322 db_printf(" %-5d disabled\n", i);
329 dbg_find_free_slot(struct debug_monitor_state *monitor, enum dbg_t type)
335 case DBG_TYPE_BREAKPOINT:
336 max = dbg_breakpoint_num;
337 reg = monitor->dbg_bcr;
339 case DBG_TYPE_WATCHPOINT:
340 max = dbg_watchpoint_num;
341 reg = monitor->dbg_wcr;
344 printf("Unsupported debug type\n");
348 for (i = 0; i < max; i++) {
349 if ((reg[i] & DBG_WB_CTRL_E) == 0)
357 dbg_find_slot(struct debug_monitor_state *monitor, enum dbg_t type,
360 uint64_t *reg_addr, *reg_ctrl;
364 case DBG_TYPE_BREAKPOINT:
365 max = dbg_breakpoint_num;
366 reg_addr = monitor->dbg_bvr;
367 reg_ctrl = monitor->dbg_bcr;
369 case DBG_TYPE_WATCHPOINT:
370 max = dbg_watchpoint_num;
371 reg_addr = monitor->dbg_wvr;
372 reg_ctrl = monitor->dbg_wcr;
375 printf("Unsupported debug type\n");
379 for (i = 0; i < max; i++) {
380 if (reg_addr[i] == addr &&
381 (reg_ctrl[i] & DBG_WB_CTRL_E) != 0)
389 dbg_setup_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
390 vm_size_t size, enum dbg_access_t access)
392 uint64_t wcr_size, wcr_priv, wcr_access;
396 monitor = &kernel_monitor;
398 i = dbg_find_free_slot(monitor, DBG_TYPE_WATCHPOINT);
400 printf("Can not find slot for watchpoint, max %d"
401 " watchpoints supported\n", dbg_watchpoint_num);
407 wcr_size = DBG_WATCH_CTRL_LEN_1;
410 wcr_size = DBG_WATCH_CTRL_LEN_2;
413 wcr_size = DBG_WATCH_CTRL_LEN_4;
416 wcr_size = DBG_WATCH_CTRL_LEN_8;
419 printf("Unsupported address size for watchpoint: %zu\n", size);
423 if ((monitor->dbg_flags & DBGMON_KERNEL) == 0)
424 wcr_priv = DBG_WB_CTRL_EL0;
426 wcr_priv = DBG_WB_CTRL_EL1;
429 case HW_BREAKPOINT_X:
430 wcr_access = DBG_WATCH_CTRL_EXEC;
432 case HW_BREAKPOINT_R:
433 wcr_access = DBG_WATCH_CTRL_LOAD;
435 case HW_BREAKPOINT_W:
436 wcr_access = DBG_WATCH_CTRL_STORE;
438 case HW_BREAKPOINT_RW:
439 wcr_access = DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE;
442 printf("Unsupported access type for watchpoint: %d\n", access);
446 monitor->dbg_wvr[i] = addr;
447 monitor->dbg_wcr[i] = wcr_size | wcr_access | wcr_priv | DBG_WB_CTRL_E;
448 monitor->dbg_enable_count++;
449 monitor->dbg_flags |= DBGMON_ENABLED;
451 dbg_register_sync(monitor);
456 dbg_remove_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
462 monitor = &kernel_monitor;
464 i = dbg_find_slot(monitor, DBG_TYPE_WATCHPOINT, addr);
466 printf("Can not find watchpoint for address 0%lx\n", addr);
470 monitor->dbg_wvr[i] = 0;
471 monitor->dbg_wcr[i] = 0;
472 monitor->dbg_enable_count--;
473 if (monitor->dbg_enable_count == 0)
474 monitor->dbg_flags &= ~DBGMON_ENABLED;
476 dbg_register_sync(monitor);
481 dbg_register_sync(struct debug_monitor_state *monitor)
487 monitor = &kernel_monitor;
489 mdscr = READ_SPECIALREG(mdscr_el1);
490 if ((monitor->dbg_flags & DBGMON_ENABLED) == 0) {
491 mdscr &= ~(MDSCR_MDE | MDSCR_KDE);
493 for (i = 0; i < dbg_breakpoint_num; i++) {
494 dbg_wb_write_reg(DBG_REG_BASE_BCR, i,
495 monitor->dbg_bcr[i]);
496 dbg_wb_write_reg(DBG_REG_BASE_BVR, i,
497 monitor->dbg_bvr[i]);
500 for (i = 0; i < dbg_watchpoint_num; i++) {
501 dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
502 monitor->dbg_wcr[i]);
503 dbg_wb_write_reg(DBG_REG_BASE_WVR, i,
504 monitor->dbg_wvr[i]);
507 if ((monitor->dbg_flags & DBGMON_KERNEL) == DBGMON_KERNEL)
510 WRITE_SPECIALREG(mdscr_el1, mdscr);
515 dbg_monitor_init(void)
520 /* Find out many breakpoints and watchpoints we can use */
521 aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
522 dbg_watchpoint_num = ID_AA64DFR0_WRPs_VAL(aa64dfr0);
523 dbg_breakpoint_num = ID_AA64DFR0_BRPs_VAL(aa64dfr0);
525 if (bootverbose && PCPU_GET(cpuid) == 0) {
526 printf("%d watchpoints and %d breakpoints supported\n",
527 dbg_watchpoint_num, dbg_breakpoint_num);
531 * We have limited number of {watch,break}points, each consists of
533 * - wcr/bcr regsiter configurates corresponding {watch,break}point
535 * - wvr/bvr register keeps address we are hunting for
537 * Reset all breakpoints and watchpoints.
539 for (i = 0; i < dbg_watchpoint_num; i++) {
540 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
541 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
544 for (i = 0; i < dbg_breakpoint_num; i++) {
545 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
546 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
553 dbg_monitor_enter(struct thread *thread)
557 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
558 /* Install the kernel version of the registers */
559 dbg_register_sync(&kernel_monitor);
560 } else if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
561 /* Disable the user breakpoints until we return to userspace */
562 for (i = 0; i < dbg_watchpoint_num; i++) {
563 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
564 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
567 for (i = 0; i < dbg_breakpoint_num; ++i) {
568 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
569 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
571 WRITE_SPECIALREG(mdscr_el1,
572 READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));
578 dbg_monitor_exit(struct thread *thread, struct trapframe *frame)
583 * PSR_D is an aarch64-only flag. On aarch32, it switches
584 * the processor to big-endian, so avoid setting it for
587 if (!(SV_PROC_FLAG(thread->td_proc, SV_ILP32)))
588 frame->tf_spsr |= PSR_D;
589 if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
590 /* Install the thread's version of the registers */
591 dbg_register_sync(&thread->td_pcb->pcb_dbg_regs);
592 frame->tf_spsr &= ~PSR_D;
593 } else if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
594 /* Disable the kernel breakpoints until we re-enter */
595 for (i = 0; i < dbg_watchpoint_num; i++) {
596 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
597 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
600 for (i = 0; i < dbg_breakpoint_num; ++i) {
601 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
602 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
604 WRITE_SPECIALREG(mdscr_el1,
605 READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));