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