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