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