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