1 /*-
2 * Copyright (c) 2014 The FreeBSD Foundation
3 *
4 * This software was developed by Semihalf under
5 * the sponsorship of the FreeBSD Foundation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 *
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
26 * SUCH DAMAGE.
27 */
28
29 #include "opt_ddb.h"
30 #include "opt_gdb.h"
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/kdb.h>
35 #include <sys/pcpu.h>
36 #include <sys/proc.h>
37 #include <sys/systm.h>
38 #include <sys/sysent.h>
39
40 #include <machine/armreg.h>
41 #include <machine/cpu.h>
42 #include <machine/debug_monitor.h>
43 #include <machine/machdep.h>
44 #include <machine/kdb.h>
45 #include <machine/pcb.h>
46
47 #ifdef DDB
48 #include <vm/vm.h>
49 #include <ddb/ddb.h>
50 #include <ddb/db_break.h>
51 #include <ddb/db_sym.h>
52 #endif
53
54 enum dbg_t {
55 DBG_TYPE_BREAKPOINT = 0,
56 DBG_TYPE_WATCHPOINT = 1,
57 };
58
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
63 };
64
65 static int dbg_setup_breakpoint(struct debug_monitor_state *monitor,
66 vm_offset_t addr);
67 static int dbg_remove_breakpoint(struct debug_monitor_state *monitor,
68 vm_offset_t addr);
69 static int dbg_setup_watchpoint(struct debug_monitor_state *, vm_offset_t,
70 vm_size_t, enum dbg_access_t);
71 static int dbg_remove_watchpoint(struct debug_monitor_state *, vm_offset_t,
72 vm_size_t);
73
74 /* Called from the exception handlers */
75 void dbg_monitor_enter(struct thread *);
76 void dbg_monitor_exit(struct thread *, struct trapframe *);
77
78 /* Watchpoints/breakpoints control register bitfields */
79 #define DBG_WATCH_CTRL_LEN_1 (0x1 << 5)
80 #define DBG_WATCH_CTRL_LEN_2 (0x3 << 5)
81 #define DBG_WATCH_CTRL_LEN_4 (0xf << 5)
82 #define DBG_WATCH_CTRL_LEN_8 (0xff << 5)
83 #define DBG_WATCH_CTRL_LEN_MASK(x) ((x) & (0xff << 5))
84 #define DBG_WATCH_CTRL_EXEC (0x0 << 3)
85 #define DBG_WATCH_CTRL_LOAD (0x1 << 3)
86 #define DBG_WATCH_CTRL_STORE (0x2 << 3)
87 #define DBG_WATCH_CTRL_ACCESS_MASK(x) ((x) & (0x3 << 3))
88
89 /* Common for breakpoint and watchpoint */
90 #define DBG_WB_CTRL_HMC (0x1 << 13)
91 #define DBG_WB_CTRL_EL1 (0x1 << 1)
92 #define DBG_WB_CTRL_EL0 (0x2 << 1)
93 #define DBG_WB_CTRL_ELX_MASK(x) ((x) & (0x3 << 1))
94 #define DBG_WB_CTRL_E (0x1 << 0)
95
96 #define DBG_REG_BASE_BVR 0
97 #define DBG_REG_BASE_BCR (DBG_REG_BASE_BVR + 16)
98 #define DBG_REG_BASE_WVR (DBG_REG_BASE_BCR + 16)
99 #define DBG_REG_BASE_WCR (DBG_REG_BASE_WVR + 16)
100
101 /* Watchpoint/breakpoint helpers */
102 #define DBG_WB_WVR "wvr"
103 #define DBG_WB_WCR "wcr"
104 #define DBG_WB_BVR "bvr"
105 #define DBG_WB_BCR "bcr"
106
107 #define DBG_WB_READ(reg, num, val) do { \
108 __asm __volatile("mrs %0, dbg" reg #num "_el1" : "=r" (val)); \
109 } while (0)
110
111 #define DBG_WB_WRITE(reg, num, val) do { \
112 __asm __volatile("msr dbg" reg #num "_el1, %0" :: "r" (val)); \
113 } while (0)
114
115 #define READ_WB_REG_CASE(reg, num, offset, val) \
116 case (num + offset): \
117 DBG_WB_READ(reg, num, val); \
118 break
119
120 #define WRITE_WB_REG_CASE(reg, num, offset, val) \
121 case (num + offset): \
122 DBG_WB_WRITE(reg, num, val); \
123 break
124
125 #define SWITCH_CASES_READ_WB_REG(reg, offset, val) \
126 READ_WB_REG_CASE(reg, 0, offset, val); \
127 READ_WB_REG_CASE(reg, 1, offset, val); \
128 READ_WB_REG_CASE(reg, 2, offset, val); \
129 READ_WB_REG_CASE(reg, 3, offset, val); \
130 READ_WB_REG_CASE(reg, 4, offset, val); \
131 READ_WB_REG_CASE(reg, 5, offset, val); \
132 READ_WB_REG_CASE(reg, 6, offset, val); \
133 READ_WB_REG_CASE(reg, 7, offset, val); \
134 READ_WB_REG_CASE(reg, 8, offset, val); \
135 READ_WB_REG_CASE(reg, 9, offset, val); \
136 READ_WB_REG_CASE(reg, 10, offset, val); \
137 READ_WB_REG_CASE(reg, 11, offset, val); \
138 READ_WB_REG_CASE(reg, 12, offset, val); \
139 READ_WB_REG_CASE(reg, 13, offset, val); \
140 READ_WB_REG_CASE(reg, 14, offset, val); \
141 READ_WB_REG_CASE(reg, 15, offset, val)
142
143 #define SWITCH_CASES_WRITE_WB_REG(reg, offset, val) \
144 WRITE_WB_REG_CASE(reg, 0, offset, val); \
145 WRITE_WB_REG_CASE(reg, 1, offset, val); \
146 WRITE_WB_REG_CASE(reg, 2, offset, val); \
147 WRITE_WB_REG_CASE(reg, 3, offset, val); \
148 WRITE_WB_REG_CASE(reg, 4, offset, val); \
149 WRITE_WB_REG_CASE(reg, 5, offset, val); \
150 WRITE_WB_REG_CASE(reg, 6, offset, val); \
151 WRITE_WB_REG_CASE(reg, 7, offset, val); \
152 WRITE_WB_REG_CASE(reg, 8, offset, val); \
153 WRITE_WB_REG_CASE(reg, 9, offset, val); \
154 WRITE_WB_REG_CASE(reg, 10, offset, val); \
155 WRITE_WB_REG_CASE(reg, 11, offset, val); \
156 WRITE_WB_REG_CASE(reg, 12, offset, val); \
157 WRITE_WB_REG_CASE(reg, 13, offset, val); \
158 WRITE_WB_REG_CASE(reg, 14, offset, val); \
159 WRITE_WB_REG_CASE(reg, 15, offset, val)
160
161 #ifdef DDB
162 static uint64_t
dbg_wb_read_reg(int reg,int n)163 dbg_wb_read_reg(int reg, int n)
164 {
165 uint64_t val = 0;
166
167 switch (reg + n) {
168 SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
169 SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
170 SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
171 SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
172 default:
173 printf("trying to read from wrong debug register %d\n", n);
174 }
175
176 return val;
177 }
178 #endif /* DDB */
179
180 static void
dbg_wb_write_reg(int reg,int n,uint64_t val)181 dbg_wb_write_reg(int reg, int n, uint64_t val)
182 {
183 switch (reg + n) {
184 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, DBG_REG_BASE_WVR, val);
185 SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, DBG_REG_BASE_WCR, val);
186 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, DBG_REG_BASE_BVR, val);
187 SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, DBG_REG_BASE_BCR, val);
188 default:
189 printf("trying to write to wrong debug register %d\n", n);
190 return;
191 }
192 isb();
193 }
194
195 #if defined(DDB) || defined(GDB)
196 int
kdb_cpu_set_breakpoint(vm_offset_t addr)197 kdb_cpu_set_breakpoint(vm_offset_t addr)
198 {
199 return (dbg_setup_breakpoint(NULL, addr));
200 }
201
202 int
kdb_cpu_clr_breakpoint(vm_offset_t addr)203 kdb_cpu_clr_breakpoint(vm_offset_t addr)
204 {
205 return (dbg_remove_breakpoint(NULL, addr));
206 }
207
208 void
kdb_cpu_set_singlestep(void)209 kdb_cpu_set_singlestep(void)
210 {
211
212 KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
213 ("%s: debug exceptions are not masked", __func__));
214
215 kdb_frame->tf_spsr |= PSR_SS;
216
217 /*
218 * TODO: Handle single stepping over instructions that access
219 * the DAIF values. On a read the value will be incorrect.
220 */
221 kernel_monitor.dbg_flags &= ~PSR_DAIF;
222 kernel_monitor.dbg_flags |= kdb_frame->tf_spsr & PSR_DAIF;
223 kdb_frame->tf_spsr |= (PSR_A | PSR_I | PSR_F);
224
225 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) |
226 MDSCR_SS | MDSCR_KDE);
227
228 /*
229 * Disable breakpoints and watchpoints, e.g. stepping
230 * over watched instruction will trigger break exception instead of
231 * single-step exception and locks CPU on that instruction for ever.
232 */
233 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
234 WRITE_SPECIALREG(mdscr_el1,
235 READ_SPECIALREG(mdscr_el1) & ~MDSCR_MDE);
236 }
237 }
238
239 void
kdb_cpu_clear_singlestep(void)240 kdb_cpu_clear_singlestep(void)
241 {
242
243 KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
244 ("%s: debug exceptions are not masked", __func__));
245
246 kdb_frame->tf_spsr &= ~PSR_DAIF;
247 kdb_frame->tf_spsr |= kernel_monitor.dbg_flags & PSR_DAIF;
248
249 WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) &
250 ~(MDSCR_SS | MDSCR_KDE));
251
252 /* Restore breakpoints and watchpoints */
253 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
254 WRITE_SPECIALREG(mdscr_el1,
255 READ_SPECIALREG(mdscr_el1) | MDSCR_MDE);
256
257 if ((kernel_monitor.dbg_flags & DBGMON_KERNEL) != 0) {
258 WRITE_SPECIALREG(mdscr_el1,
259 READ_SPECIALREG(mdscr_el1) | MDSCR_KDE);
260 }
261 }
262 }
263
264 int
kdb_cpu_set_watchpoint(vm_offset_t addr,vm_size_t size,int access)265 kdb_cpu_set_watchpoint(vm_offset_t addr, vm_size_t size, int access)
266 {
267 enum dbg_access_t dbg_access;
268
269 switch (access) {
270 case KDB_DBG_ACCESS_R:
271 dbg_access = HW_BREAKPOINT_R;
272 break;
273 case KDB_DBG_ACCESS_W:
274 dbg_access = HW_BREAKPOINT_W;
275 break;
276 case KDB_DBG_ACCESS_RW:
277 dbg_access = HW_BREAKPOINT_RW;
278 break;
279 default:
280 return (EINVAL);
281 }
282
283 return (dbg_setup_watchpoint(NULL, addr, size, dbg_access));
284 }
285
286 int
kdb_cpu_clr_watchpoint(vm_offset_t addr,vm_size_t size)287 kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size)
288 {
289
290 return (dbg_remove_watchpoint(NULL, addr, size));
291 }
292 #endif /* DDB || GDB */
293
294 #ifdef DDB
295 void
dbg_show_breakpoint(void)296 dbg_show_breakpoint(void)
297 {
298 db_breakpoint_t bkpt;
299 uint32_t bcr;
300 uint64_t addr;
301 int i;
302
303 db_printf("\nhardware breakpoints:\n");
304 db_printf(" break status count address symbol\n");
305 db_printf(" ----- -------- ----- ------------------ ------------------\n");
306 for (i = 0; i < dbg_breakpoint_num; i++) {
307 bcr = dbg_wb_read_reg(DBG_REG_BASE_BCR, i);
308 if ((bcr & DBG_WB_CTRL_E) != 0) {
309 addr = dbg_wb_read_reg(DBG_REG_BASE_BVR, i);
310 bkpt = db_find_breakpoint_here(addr);
311 db_printf(" %-5d %-8s %-5d 0x%16lx ",
312 i, "enabled", bkpt == NULL ? -1 : bkpt->count,
313 addr);
314 db_printsym((db_addr_t)addr, DB_STGY_ANY);
315 db_printf("\n");
316 } else {
317 db_printf(" %-5d disabled\n", i);
318 }
319 }
320 }
321
322 static const char *
dbg_watchtype_str(uint32_t type)323 dbg_watchtype_str(uint32_t type)
324 {
325 switch (type) {
326 case DBG_WATCH_CTRL_EXEC:
327 return ("execute");
328 case DBG_WATCH_CTRL_STORE:
329 return ("write");
330 case DBG_WATCH_CTRL_LOAD:
331 return ("read");
332 case DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE:
333 return ("read/write");
334 default:
335 return ("invalid");
336 }
337 }
338
339 static int
dbg_watchtype_len(uint32_t len)340 dbg_watchtype_len(uint32_t len)
341 {
342 switch (len) {
343 case DBG_WATCH_CTRL_LEN_1:
344 return (1);
345 case DBG_WATCH_CTRL_LEN_2:
346 return (2);
347 case DBG_WATCH_CTRL_LEN_4:
348 return (4);
349 case DBG_WATCH_CTRL_LEN_8:
350 return (8);
351 default:
352 return (0);
353 }
354 }
355
356 void
dbg_show_watchpoint(void)357 dbg_show_watchpoint(void)
358 {
359 uint32_t wcr, len, type;
360 uint64_t addr;
361 int i;
362
363 db_printf("\nhardware watchpoints:\n");
364 db_printf(" watch status type len address symbol\n");
365 db_printf(" ----- -------- ---------- --- ------------------ ------------------\n");
366 for (i = 0; i < dbg_watchpoint_num; i++) {
367 wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
368 if ((wcr & DBG_WB_CTRL_E) != 0) {
369 type = DBG_WATCH_CTRL_ACCESS_MASK(wcr);
370 len = DBG_WATCH_CTRL_LEN_MASK(wcr);
371 addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i);
372 db_printf(" %-5d %-8s %10s %3d 0x%16lx ",
373 i, "enabled", dbg_watchtype_str(type),
374 dbg_watchtype_len(len), addr);
375 db_printsym((db_addr_t)addr, DB_STGY_ANY);
376 db_printf("\n");
377 } else {
378 db_printf(" %-5d disabled\n", i);
379 }
380 }
381 }
382 #endif /* DDB */
383
384 static int
dbg_find_free_slot(struct debug_monitor_state * monitor,enum dbg_t type)385 dbg_find_free_slot(struct debug_monitor_state *monitor, enum dbg_t type)
386 {
387 uint64_t *reg;
388 u_int max, i;
389
390 switch(type) {
391 case DBG_TYPE_BREAKPOINT:
392 max = dbg_breakpoint_num;
393 reg = monitor->dbg_bcr;
394 break;
395 case DBG_TYPE_WATCHPOINT:
396 max = dbg_watchpoint_num;
397 reg = monitor->dbg_wcr;
398 break;
399 default:
400 printf("Unsupported debug type\n");
401 return (i);
402 }
403
404 for (i = 0; i < max; i++) {
405 if ((reg[i] & DBG_WB_CTRL_E) == 0)
406 return (i);
407 }
408
409 return (-1);
410 }
411
412 static int
dbg_find_slot(struct debug_monitor_state * monitor,enum dbg_t type,vm_offset_t addr)413 dbg_find_slot(struct debug_monitor_state *monitor, enum dbg_t type,
414 vm_offset_t addr)
415 {
416 uint64_t *reg_addr, *reg_ctrl;
417 u_int max, i;
418
419 switch(type) {
420 case DBG_TYPE_BREAKPOINT:
421 max = dbg_breakpoint_num;
422 reg_addr = monitor->dbg_bvr;
423 reg_ctrl = monitor->dbg_bcr;
424 break;
425 case DBG_TYPE_WATCHPOINT:
426 max = dbg_watchpoint_num;
427 reg_addr = monitor->dbg_wvr;
428 reg_ctrl = monitor->dbg_wcr;
429 break;
430 default:
431 printf("Unsupported debug type\n");
432 return (i);
433 }
434
435 for (i = 0; i < max; i++) {
436 if (reg_addr[i] == addr &&
437 (reg_ctrl[i] & DBG_WB_CTRL_E) != 0)
438 return (i);
439 }
440
441 return (-1);
442 }
443
444 static int
dbg_setup_breakpoint(struct debug_monitor_state * monitor,vm_offset_t addr)445 dbg_setup_breakpoint(struct debug_monitor_state *monitor, vm_offset_t addr)
446 {
447 uint64_t bcr_priv;
448 u_int i;
449
450 if (monitor == NULL)
451 monitor = &kernel_monitor;
452
453 i = dbg_find_free_slot(monitor, DBG_TYPE_BREAKPOINT);
454 if (i == -1) {
455 printf("Can not find slot for breakpoint, max %d"
456 " breakpoints supported\n", dbg_breakpoint_num);
457 return (EBUSY);
458 }
459
460 if ((monitor->dbg_flags & DBGMON_KERNEL) == 0)
461 bcr_priv = DBG_WB_CTRL_EL0;
462 else if (in_vhe())
463 bcr_priv = DBG_WB_CTRL_EL1 | DBG_WB_CTRL_HMC;
464 else
465 bcr_priv = DBG_WB_CTRL_EL1;
466
467 monitor->dbg_bvr[i] = addr;
468 monitor->dbg_bcr[i] = (0xf << 5) | bcr_priv | DBG_WB_CTRL_E;
469 monitor->dbg_enable_count++;
470 monitor->dbg_flags |= DBGMON_ENABLED;
471 dbg_register_sync(monitor);
472
473 return (0);
474 }
475
476 static int
dbg_remove_breakpoint(struct debug_monitor_state * monitor,vm_offset_t addr)477 dbg_remove_breakpoint(struct debug_monitor_state *monitor, vm_offset_t addr)
478 {
479 u_int i;
480
481 if (monitor == NULL)
482 monitor = &kernel_monitor;
483
484 i = dbg_find_slot(monitor, DBG_TYPE_BREAKPOINT, addr);
485 if (i == -1) {
486 printf("Can not find breakpoint for address 0%lx\n", addr);
487 return (i);
488 }
489
490 monitor->dbg_bvr[i] = 0;
491 monitor->dbg_bcr[i] = 0;
492 monitor->dbg_enable_count--;
493 if (monitor->dbg_enable_count == 0)
494 monitor->dbg_flags &= ~DBGMON_ENABLED;
495 dbg_register_sync(monitor);
496
497 return (0);
498 }
499
500 static int
dbg_setup_watchpoint(struct debug_monitor_state * monitor,vm_offset_t addr,vm_size_t size,enum dbg_access_t access)501 dbg_setup_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
502 vm_size_t size, enum dbg_access_t access)
503 {
504 uint64_t wcr_size, wcr_priv, wcr_access;
505 u_int i;
506
507 if (monitor == NULL)
508 monitor = &kernel_monitor;
509
510 i = dbg_find_free_slot(monitor, DBG_TYPE_WATCHPOINT);
511 if (i == -1) {
512 printf("Can not find slot for watchpoint, max %d"
513 " watchpoints supported\n", dbg_watchpoint_num);
514 return (EBUSY);
515 }
516
517 switch(size) {
518 case 1:
519 wcr_size = DBG_WATCH_CTRL_LEN_1;
520 break;
521 case 2:
522 wcr_size = DBG_WATCH_CTRL_LEN_2;
523 break;
524 case 4:
525 wcr_size = DBG_WATCH_CTRL_LEN_4;
526 break;
527 case 8:
528 wcr_size = DBG_WATCH_CTRL_LEN_8;
529 break;
530 default:
531 printf("Unsupported address size for watchpoint: %zu\n", size);
532 return (EINVAL);
533 }
534
535 if ((monitor->dbg_flags & DBGMON_KERNEL) == 0)
536 wcr_priv = DBG_WB_CTRL_EL0;
537 else if (in_vhe())
538 wcr_priv = DBG_WB_CTRL_EL1 | DBG_WB_CTRL_HMC;
539 else
540 wcr_priv = DBG_WB_CTRL_EL1;
541
542 switch(access) {
543 case HW_BREAKPOINT_X:
544 wcr_access = DBG_WATCH_CTRL_EXEC;
545 break;
546 case HW_BREAKPOINT_R:
547 wcr_access = DBG_WATCH_CTRL_LOAD;
548 break;
549 case HW_BREAKPOINT_W:
550 wcr_access = DBG_WATCH_CTRL_STORE;
551 break;
552 case HW_BREAKPOINT_RW:
553 wcr_access = DBG_WATCH_CTRL_LOAD | DBG_WATCH_CTRL_STORE;
554 break;
555 default:
556 printf("Unsupported access type for watchpoint: %d\n", access);
557 return (EINVAL);
558 }
559
560 monitor->dbg_wvr[i] = addr;
561 monitor->dbg_wcr[i] = wcr_size | wcr_access | wcr_priv | DBG_WB_CTRL_E;
562 monitor->dbg_enable_count++;
563 monitor->dbg_flags |= DBGMON_ENABLED;
564
565 dbg_register_sync(monitor);
566 return (0);
567 }
568
569 static int
dbg_remove_watchpoint(struct debug_monitor_state * monitor,vm_offset_t addr,vm_size_t size)570 dbg_remove_watchpoint(struct debug_monitor_state *monitor, vm_offset_t addr,
571 vm_size_t size)
572 {
573 u_int i;
574
575 if (monitor == NULL)
576 monitor = &kernel_monitor;
577
578 i = dbg_find_slot(monitor, DBG_TYPE_WATCHPOINT, addr);
579 if (i == -1) {
580 printf("Can not find watchpoint for address 0%lx\n", addr);
581 return (EINVAL);
582 }
583
584 monitor->dbg_wvr[i] = 0;
585 monitor->dbg_wcr[i] = 0;
586 monitor->dbg_enable_count--;
587 if (monitor->dbg_enable_count == 0)
588 monitor->dbg_flags &= ~DBGMON_ENABLED;
589
590 dbg_register_sync(monitor);
591 return (0);
592 }
593
594 void
dbg_register_sync(struct debug_monitor_state * monitor)595 dbg_register_sync(struct debug_monitor_state *monitor)
596 {
597 uint64_t mdscr;
598 int i;
599
600 if (monitor == NULL)
601 monitor = &kernel_monitor;
602
603 for (i = 0; i < dbg_breakpoint_num; i++) {
604 dbg_wb_write_reg(DBG_REG_BASE_BCR, i,
605 monitor->dbg_bcr[i]);
606 dbg_wb_write_reg(DBG_REG_BASE_BVR, i,
607 monitor->dbg_bvr[i]);
608 }
609
610 for (i = 0; i < dbg_watchpoint_num; i++) {
611 dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
612 monitor->dbg_wcr[i]);
613 dbg_wb_write_reg(DBG_REG_BASE_WVR, i,
614 monitor->dbg_wvr[i]);
615 }
616
617 mdscr = READ_SPECIALREG(mdscr_el1);
618 if ((monitor->dbg_flags & DBGMON_ENABLED) == 0) {
619 mdscr &= ~(MDSCR_MDE | MDSCR_KDE);
620 } else {
621 mdscr |= MDSCR_MDE;
622 if ((monitor->dbg_flags & DBGMON_KERNEL) == DBGMON_KERNEL)
623 mdscr |= MDSCR_KDE;
624 }
625 WRITE_SPECIALREG(mdscr_el1, mdscr);
626 isb();
627 }
628
629 void
dbg_monitor_init(void)630 dbg_monitor_init(void)
631 {
632 uint64_t aa64dfr0;
633 u_int i;
634
635 /* Find out many breakpoints and watchpoints we can use */
636 aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
637 dbg_watchpoint_num = ID_AA64DFR0_WRPs_VAL(aa64dfr0);
638 dbg_breakpoint_num = ID_AA64DFR0_BRPs_VAL(aa64dfr0);
639
640 if (bootverbose && PCPU_GET(cpuid) == 0) {
641 printf("%d watchpoints and %d breakpoints supported\n",
642 dbg_watchpoint_num, dbg_breakpoint_num);
643 }
644
645 /*
646 * We have limited number of {watch,break}points, each consists of
647 * two registers:
648 * - wcr/bcr regsiter configurates corresponding {watch,break}point
649 * behaviour
650 * - wvr/bvr register keeps address we are hunting for
651 *
652 * Reset all breakpoints and watchpoints.
653 */
654 for (i = 0; i < dbg_watchpoint_num; i++) {
655 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
656 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
657 }
658
659 for (i = 0; i < dbg_breakpoint_num; i++) {
660 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
661 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
662 }
663
664 dbg_enable();
665 }
666
667 void
dbg_monitor_enter(struct thread * thread)668 dbg_monitor_enter(struct thread *thread)
669 {
670 int i;
671
672 if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
673 /* Install the kernel version of the registers */
674 dbg_register_sync(&kernel_monitor);
675 } else if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
676 /* Disable the user breakpoints until we return to userspace */
677 for (i = 0; i < dbg_watchpoint_num; i++) {
678 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
679 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
680 }
681
682 for (i = 0; i < dbg_breakpoint_num; ++i) {
683 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
684 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
685 }
686 WRITE_SPECIALREG(mdscr_el1,
687 READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));
688 isb();
689 }
690 }
691
692 void
dbg_monitor_exit(struct thread * thread,struct trapframe * frame)693 dbg_monitor_exit(struct thread *thread, struct trapframe *frame)
694 {
695 int i;
696
697 /*
698 * PSR_D is an aarch64-only flag. On aarch32, it switches
699 * the processor to big-endian, so avoid setting it for
700 * 32bits binaries.
701 */
702 if (!(SV_PROC_FLAG(thread->td_proc, SV_ILP32)))
703 frame->tf_spsr |= PSR_D;
704 if ((thread->td_pcb->pcb_dbg_regs.dbg_flags & DBGMON_ENABLED) != 0) {
705 /* Install the thread's version of the registers */
706 dbg_register_sync(&thread->td_pcb->pcb_dbg_regs);
707 frame->tf_spsr &= ~PSR_D;
708 } else if ((kernel_monitor.dbg_flags & DBGMON_ENABLED) != 0) {
709 /* Disable the kernel breakpoints until we re-enter */
710 for (i = 0; i < dbg_watchpoint_num; i++) {
711 dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
712 dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
713 }
714
715 for (i = 0; i < dbg_breakpoint_num; ++i) {
716 dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
717 dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
718 }
719 WRITE_SPECIALREG(mdscr_el1,
720 READ_SPECIALREG(mdscr_el1) & ~(MDSCR_MDE | MDSCR_KDE));
721 isb();
722 }
723 }
724