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