xref: /f-stack/freebsd/arm/arm/debug_monitor.c (revision 22ce4aff)
1 /*
2  * Copyright (c) 2015 Juniper Networks Inc.
3  * All rights reserved.
4  *
5  * Developed by Semihalf.
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 <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include "opt_ddb.h"
33 
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/kdb.h>
37 #include <sys/pcpu.h>
38 #include <sys/smp.h>
39 #include <sys/systm.h>
40 
41 #include <machine/atomic.h>
42 #include <machine/armreg.h>
43 #include <machine/cpu.h>
44 #include <machine/debug_monitor.h>
45 #include <machine/kdb.h>
46 #include <machine/pcb.h>
47 #include <machine/reg.h>
48 
49 #include <ddb/ddb.h>
50 #include <ddb/db_access.h>
51 #include <ddb/db_sym.h>
52 
53 enum dbg_t {
54 	DBG_TYPE_BREAKPOINT = 0,
55 	DBG_TYPE_WATCHPOINT = 1,
56 };
57 
58 struct dbg_wb_conf {
59 	enum dbg_t		type;
60 	enum dbg_access_t	access;
61 	db_addr_t		address;
62 	db_expr_t		size;
63 	u_int			slot;
64 };
65 
66 static int dbg_reset_state(void);
67 static int dbg_setup_breakpoint(db_expr_t, db_expr_t, u_int);
68 static int dbg_remove_breakpoint(u_int);
69 static u_int dbg_find_slot(enum dbg_t, db_expr_t);
70 static boolean_t dbg_check_slot_free(enum dbg_t, u_int);
71 
72 static int dbg_remove_xpoint(struct dbg_wb_conf *);
73 static int dbg_setup_xpoint(struct dbg_wb_conf *);
74 
75 static int dbg_capable_var;	/* Indicates that machine is capable of using
76 				   HW watchpoints/breakpoints */
77 
78 static uint32_t dbg_model;	/* Debug Arch. Model */
79 static boolean_t dbg_ossr;	/* OS Save and Restore implemented */
80 
81 static uint32_t dbg_watchpoint_num;
82 static uint32_t dbg_breakpoint_num;
83 
84 /* ID_DFR0 - Debug Feature Register 0 */
85 #define	ID_DFR0_CP_DEBUG_M_SHIFT	0
86 #define	ID_DFR0_CP_DEBUG_M_MASK		(0xF << ID_DFR0_CP_DEBUG_M_SHIFT)
87 #define	ID_DFR0_CP_DEBUG_M_NS		(0x0) /* Not supported */
88 #define	ID_DFR0_CP_DEBUG_M_V6		(0x2) /* v6 Debug arch. CP14 access */
89 #define	ID_DFR0_CP_DEBUG_M_V6_1		(0x3) /* v6.1 Debug arch. CP14 access */
90 #define	ID_DFR0_CP_DEBUG_M_V7		(0x4) /* v7 Debug arch. CP14 access */
91 #define	ID_DFR0_CP_DEBUG_M_V7_1		(0x5) /* v7.1 Debug arch. CP14 access */
92 
93 /* DBGDIDR - Debug ID Register */
94 #define	DBGDIDR_WRPS_SHIFT		28
95 #define	DBGDIDR_WRPS_MASK		(0xF << DBGDIDR_WRPS_SHIFT)
96 #define	DBGDIDR_WRPS_NUM(reg)		\
97     ((((reg) & DBGDIDR_WRPS_MASK) >> DBGDIDR_WRPS_SHIFT) + 1)
98 
99 #define	DBGDIDR_BRPS_SHIFT		24
100 #define	DBGDIDR_BRPS_MASK		(0xF << DBGDIDR_BRPS_SHIFT)
101 #define	DBGDIDR_BRPS_NUM(reg)		\
102     ((((reg) & DBGDIDR_BRPS_MASK) >> DBGDIDR_BRPS_SHIFT) + 1)
103 
104 /* DBGPRSR - Device Powerdown and Reset Status Register */
105 #define	DBGPRSR_PU			(1 << 0) /* Powerup status */
106 
107 /* DBGOSLSR - OS Lock Status Register */
108 #define	DBGOSLSR_OSLM0			(1 << 0)
109 
110 /* DBGOSDLR - OS Double Lock Register */
111 #define	DBGPRSR_DLK			(1 << 0) /* OS Double Lock set */
112 
113 /* DBGDSCR - Debug Status and Control Register */
114 #define	DBGSCR_MDBG_EN			(1 << 15) /* Monitor debug-mode enable */
115 
116 /* DBGWVR - Watchpoint Value Register */
117 #define	DBGWVR_ADDR_MASK		(~0x3U)
118 
119 /* Watchpoints/breakpoints control register bitfields */
120 #define	DBG_WB_CTRL_LEN_1		(0x1 << 5)
121 #define	DBG_WB_CTRL_LEN_2		(0x3 << 5)
122 #define	DBG_WB_CTRL_LEN_4		(0xf << 5)
123 #define	DBG_WB_CTRL_LEN_8		(0xff << 5)
124 #define	DBG_WB_CTRL_LEN_MASK(x)	((x) & (0xff << 5))
125 #define	DBG_WB_CTRL_EXEC		(0x0 << 3)
126 #define	DBG_WB_CTRL_LOAD		(0x1 << 3)
127 #define	DBG_WB_CTRL_STORE		(0x2 << 3)
128 #define	DBG_WB_CTRL_ACCESS_MASK(x)	((x) & (0x3 << 3))
129 
130 /* Common for breakpoint and watchpoint */
131 #define	DBG_WB_CTRL_PL1		(0x1 << 1)
132 #define	DBG_WB_CTRL_PL0		(0x2 << 1)
133 #define	DBG_WB_CTRL_PLX_MASK(x)	((x) & (0x3 << 1))
134 #define	DBG_WB_CTRL_E		(0x1 << 0)
135 
136 /*
137  * Watchpoint/breakpoint helpers
138  */
139 #define	DBG_BKPT_BT_SLOT	0	/* Slot for branch taken */
140 #define	DBG_BKPT_BNT_SLOT	1	/* Slot for branch not taken */
141 
142 #define	OP2_SHIFT		4
143 
144 /* Opc2 numbers for coprocessor instructions */
145 #define	DBG_WB_BVR	4
146 #define	DBG_WB_BCR	5
147 #define	DBG_WB_WVR	6
148 #define	DBG_WB_WCR	7
149 
150 #define	DBG_REG_BASE_BVR	(DBG_WB_BVR << OP2_SHIFT)
151 #define	DBG_REG_BASE_BCR	(DBG_WB_BCR << OP2_SHIFT)
152 #define	DBG_REG_BASE_WVR	(DBG_WB_WVR << OP2_SHIFT)
153 #define	DBG_REG_BASE_WCR	(DBG_WB_WCR << OP2_SHIFT)
154 
155 #define	DBG_WB_READ(cn, cm, op2, val) do {					\
156 	__asm __volatile("mrc p14, 0, %0, " #cn "," #cm "," #op2 : "=r" (val));	\
157 } while (0)
158 
159 #define	DBG_WB_WRITE(cn, cm, op2, val) do {					\
160 	__asm __volatile("mcr p14, 0, %0, " #cn "," #cm "," #op2 :: "r" (val));	\
161 } while (0)
162 
163 #define	READ_WB_REG_CASE(op2, m, val)			\
164 	case (((op2) << OP2_SHIFT) + m):		\
165 		DBG_WB_READ(c0, c ## m, op2, val);	\
166 		break
167 
168 #define	WRITE_WB_REG_CASE(op2, m, val)			\
169 	case (((op2) << OP2_SHIFT) + m):		\
170 		DBG_WB_WRITE(c0, c ## m, op2, val);	\
171 		break
172 
173 #define	SWITCH_CASES_READ_WB_REG(op2, val)	\
174 	READ_WB_REG_CASE(op2,  0, val);		\
175 	READ_WB_REG_CASE(op2,  1, val);		\
176 	READ_WB_REG_CASE(op2,  2, val);		\
177 	READ_WB_REG_CASE(op2,  3, val);		\
178 	READ_WB_REG_CASE(op2,  4, val);		\
179 	READ_WB_REG_CASE(op2,  5, val);		\
180 	READ_WB_REG_CASE(op2,  6, val);		\
181 	READ_WB_REG_CASE(op2,  7, val);		\
182 	READ_WB_REG_CASE(op2,  8, val);		\
183 	READ_WB_REG_CASE(op2,  9, val);		\
184 	READ_WB_REG_CASE(op2, 10, val);		\
185 	READ_WB_REG_CASE(op2, 11, val);		\
186 	READ_WB_REG_CASE(op2, 12, val);		\
187 	READ_WB_REG_CASE(op2, 13, val);		\
188 	READ_WB_REG_CASE(op2, 14, val);		\
189 	READ_WB_REG_CASE(op2, 15, val)
190 
191 #define	SWITCH_CASES_WRITE_WB_REG(op2, val)	\
192 	WRITE_WB_REG_CASE(op2,  0, val);	\
193 	WRITE_WB_REG_CASE(op2,  1, val);	\
194 	WRITE_WB_REG_CASE(op2,  2, val);	\
195 	WRITE_WB_REG_CASE(op2,  3, val);	\
196 	WRITE_WB_REG_CASE(op2,  4, val);	\
197 	WRITE_WB_REG_CASE(op2,  5, val);	\
198 	WRITE_WB_REG_CASE(op2,  6, val);	\
199 	WRITE_WB_REG_CASE(op2,  7, val);	\
200 	WRITE_WB_REG_CASE(op2,  8, val);	\
201 	WRITE_WB_REG_CASE(op2,  9, val);	\
202 	WRITE_WB_REG_CASE(op2, 10, val);	\
203 	WRITE_WB_REG_CASE(op2, 11, val);	\
204 	WRITE_WB_REG_CASE(op2, 12, val);	\
205 	WRITE_WB_REG_CASE(op2, 13, val);	\
206 	WRITE_WB_REG_CASE(op2, 14, val);	\
207 	WRITE_WB_REG_CASE(op2, 15, val)
208 
209 static uint32_t
dbg_wb_read_reg(int reg,int n)210 dbg_wb_read_reg(int reg, int n)
211 {
212 	uint32_t val;
213 
214 	val = 0;
215 
216 	switch (reg + n) {
217 	SWITCH_CASES_READ_WB_REG(DBG_WB_WVR, val);
218 	SWITCH_CASES_READ_WB_REG(DBG_WB_WCR, val);
219 	SWITCH_CASES_READ_WB_REG(DBG_WB_BVR, val);
220 	SWITCH_CASES_READ_WB_REG(DBG_WB_BCR, val);
221 	default:
222 		db_printf(
223 		    "trying to read from CP14 reg. using wrong opc2 %d\n",
224 		    reg >> OP2_SHIFT);
225 	}
226 
227 	return (val);
228 }
229 
230 static void
dbg_wb_write_reg(int reg,int n,uint32_t val)231 dbg_wb_write_reg(int reg, int n, uint32_t val)
232 {
233 
234 	switch (reg + n) {
235 	SWITCH_CASES_WRITE_WB_REG(DBG_WB_WVR, val);
236 	SWITCH_CASES_WRITE_WB_REG(DBG_WB_WCR, val);
237 	SWITCH_CASES_WRITE_WB_REG(DBG_WB_BVR, val);
238 	SWITCH_CASES_WRITE_WB_REG(DBG_WB_BCR, val);
239 	default:
240 		db_printf(
241 		    "trying to write to CP14 reg. using wrong opc2 %d\n",
242 		    reg >> OP2_SHIFT);
243 	}
244 	isb();
245 }
246 
247 static __inline boolean_t
dbg_capable(void)248 dbg_capable(void)
249 {
250 
251 	return (atomic_cmpset_int(&dbg_capable_var, 0, 0) == 0);
252 }
253 
254 boolean_t
kdb_cpu_pc_is_singlestep(db_addr_t pc)255 kdb_cpu_pc_is_singlestep(db_addr_t pc)
256 {
257 	/*
258 	 * XXX: If the platform fails to enable its debug arch.
259 	 *      there will be no stepping capabilities
260 	 */
261 	if (!dbg_capable())
262 		return (FALSE);
263 
264 	if (dbg_find_slot(DBG_TYPE_BREAKPOINT, pc) != ~0U)
265 		return (TRUE);
266 
267 	return (FALSE);
268 }
269 
270 void
kdb_cpu_set_singlestep(void)271 kdb_cpu_set_singlestep(void)
272 {
273 	db_expr_t inst;
274 	db_addr_t pc, brpc;
275 	uint32_t wcr;
276 	u_int i;
277 
278 	if (!dbg_capable())
279 		return;
280 
281 	/*
282 	 * Disable watchpoints, e.g. stepping over watched instruction will
283 	 * trigger break exception instead of single-step exception and locks
284 	 * CPU on that instruction for ever.
285 	 */
286 	for (i = 0; i < dbg_watchpoint_num; i++) {
287 		wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
288 		if ((wcr & DBG_WB_CTRL_E) != 0) {
289 			dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
290 			    (wcr & ~DBG_WB_CTRL_E));
291 		}
292 	}
293 
294 	pc = PC_REGS();
295 
296 	inst = db_get_value(pc, sizeof(pc), FALSE);
297 	if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
298 		brpc = branch_taken(inst, pc);
299 		dbg_setup_breakpoint(brpc, INSN_SIZE, DBG_BKPT_BT_SLOT);
300 	}
301 	pc = next_instr_address(pc, 0);
302 	dbg_setup_breakpoint(pc, INSN_SIZE, DBG_BKPT_BNT_SLOT);
303 }
304 
305 void
kdb_cpu_clear_singlestep(void)306 kdb_cpu_clear_singlestep(void)
307 {
308 	uint32_t wvr, wcr;
309 	u_int i;
310 
311 	if (!dbg_capable())
312 		return;
313 
314 	dbg_remove_breakpoint(DBG_BKPT_BT_SLOT);
315 	dbg_remove_breakpoint(DBG_BKPT_BNT_SLOT);
316 
317 	/* Restore all watchpoints */
318 	for (i = 0; i < dbg_watchpoint_num; i++) {
319 		wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
320 		wvr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i);
321 		/* Watchpoint considered not empty if address value is not 0 */
322 		if ((wvr & DBGWVR_ADDR_MASK) != 0) {
323 			dbg_wb_write_reg(DBG_REG_BASE_WCR, i,
324 			    (wcr | DBG_WB_CTRL_E));
325 		}
326 	}
327 }
328 
329 int
dbg_setup_watchpoint(db_expr_t addr,db_expr_t size,enum dbg_access_t access)330 dbg_setup_watchpoint(db_expr_t addr, db_expr_t size, enum dbg_access_t access)
331 {
332 	struct dbg_wb_conf conf;
333 
334 	if (access == HW_BREAKPOINT_X) {
335 		db_printf("Invalid access type for watchpoint: %d\n", access);
336 		return (EINVAL);
337 	}
338 
339 	conf.address = addr;
340 	conf.size = size;
341 	conf.access = access;
342 	conf.type = DBG_TYPE_WATCHPOINT;
343 
344 	return (dbg_setup_xpoint(&conf));
345 }
346 
347 int
dbg_remove_watchpoint(db_expr_t addr,db_expr_t size __unused)348 dbg_remove_watchpoint(db_expr_t addr, db_expr_t size __unused)
349 {
350 	struct dbg_wb_conf conf;
351 
352 	conf.address = addr;
353 	conf.type = DBG_TYPE_WATCHPOINT;
354 
355 	return (dbg_remove_xpoint(&conf));
356 }
357 
358 static int
dbg_setup_breakpoint(db_expr_t addr,db_expr_t size,u_int slot)359 dbg_setup_breakpoint(db_expr_t addr, db_expr_t size, u_int slot)
360 {
361 	struct dbg_wb_conf conf;
362 
363 	conf.address = addr;
364 	conf.size = size;
365 	conf.access = HW_BREAKPOINT_X;
366 	conf.type = DBG_TYPE_BREAKPOINT;
367 	conf.slot = slot;
368 
369 	return (dbg_setup_xpoint(&conf));
370 }
371 
372 static int
dbg_remove_breakpoint(u_int slot)373 dbg_remove_breakpoint(u_int slot)
374 {
375 	struct dbg_wb_conf conf;
376 
377 	/* Slot already cleared. Don't recurse */
378 	if (dbg_check_slot_free(DBG_TYPE_BREAKPOINT, slot))
379 		return (0);
380 
381 	conf.slot = slot;
382 	conf.type = DBG_TYPE_BREAKPOINT;
383 
384 	return (dbg_remove_xpoint(&conf));
385 }
386 
387 static const char *
dbg_watchtype_str(uint32_t type)388 dbg_watchtype_str(uint32_t type)
389 {
390 
391 	switch (type) {
392 		case DBG_WB_CTRL_EXEC:
393 			return ("execute");
394 		case DBG_WB_CTRL_STORE:
395 			return ("write");
396 		case DBG_WB_CTRL_LOAD:
397 			return ("read");
398 		case DBG_WB_CTRL_LOAD | DBG_WB_CTRL_STORE:
399 			return ("read/write");
400 		default:
401 			return ("invalid");
402 	}
403 }
404 
405 static int
dbg_watchtype_len(uint32_t len)406 dbg_watchtype_len(uint32_t len)
407 {
408 
409 	switch (len) {
410 	case DBG_WB_CTRL_LEN_1:
411 		return (1);
412 	case DBG_WB_CTRL_LEN_2:
413 		return (2);
414 	case DBG_WB_CTRL_LEN_4:
415 		return (4);
416 	case DBG_WB_CTRL_LEN_8:
417 		return (8);
418 	default:
419 		return (0);
420 	}
421 }
422 
423 void
dbg_show_watchpoint(void)424 dbg_show_watchpoint(void)
425 {
426 	uint32_t wcr, len, type;
427 	uint32_t addr;
428 	boolean_t is_enabled;
429 	int i;
430 
431 	if (!dbg_capable()) {
432 		db_printf("Architecture does not support HW "
433 		    "breakpoints/watchpoints\n");
434 		return;
435 	}
436 
437 	db_printf("\nhardware watchpoints:\n");
438 	db_printf("  watch    status        type  len     address              symbol\n");
439 	db_printf("  -----  --------  ----------  ---  ----------  ------------------\n");
440 	for (i = 0; i < dbg_watchpoint_num; i++) {
441 		wcr = dbg_wb_read_reg(DBG_REG_BASE_WCR, i);
442 		if ((wcr & DBG_WB_CTRL_E) != 0)
443 			is_enabled = TRUE;
444 		else
445 			is_enabled = FALSE;
446 
447 		type = DBG_WB_CTRL_ACCESS_MASK(wcr);
448 		len = DBG_WB_CTRL_LEN_MASK(wcr);
449 		addr = dbg_wb_read_reg(DBG_REG_BASE_WVR, i) & DBGWVR_ADDR_MASK;
450 		db_printf("  %-5d  %-8s  %10s  %3d  0x%08x  ", i,
451 		    is_enabled ? "enabled" : "disabled",
452 		    is_enabled ? dbg_watchtype_str(type) : "",
453 		    is_enabled ? dbg_watchtype_len(len) : 0,
454 		    addr);
455 		db_printsym((db_addr_t)addr, DB_STGY_ANY);
456 		db_printf("\n");
457 	}
458 }
459 
460 static boolean_t
dbg_check_slot_free(enum dbg_t type,u_int slot)461 dbg_check_slot_free(enum dbg_t type, u_int slot)
462 {
463 	uint32_t cr, vr;
464 	uint32_t max;
465 
466 	switch(type) {
467 	case DBG_TYPE_BREAKPOINT:
468 		max = dbg_breakpoint_num;
469 		cr = DBG_REG_BASE_BCR;
470 		vr = DBG_REG_BASE_BVR;
471 		break;
472 	case DBG_TYPE_WATCHPOINT:
473 		max = dbg_watchpoint_num;
474 		cr = DBG_REG_BASE_WCR;
475 		vr = DBG_REG_BASE_WVR;
476 		break;
477 	default:
478 		db_printf("%s: Unsupported event type %d\n", __func__, type);
479 		return (FALSE);
480 	}
481 
482 	if (slot >= max) {
483 		db_printf("%s: Invalid slot number %d, max %d\n",
484 		    __func__, slot, max - 1);
485 		return (FALSE);
486 	}
487 
488 	if ((dbg_wb_read_reg(cr, slot) & DBG_WB_CTRL_E) == 0 &&
489 	    (dbg_wb_read_reg(vr, slot) & DBGWVR_ADDR_MASK) == 0)
490 		return (TRUE);
491 
492 	return (FALSE);
493 }
494 
495 static u_int
dbg_find_free_slot(enum dbg_t type)496 dbg_find_free_slot(enum dbg_t type)
497 {
498 	u_int max, i;
499 
500 	switch(type) {
501 	case DBG_TYPE_BREAKPOINT:
502 		max = dbg_breakpoint_num;
503 		break;
504 	case DBG_TYPE_WATCHPOINT:
505 		max = dbg_watchpoint_num;
506 		break;
507 	default:
508 		db_printf("Unsupported debug type\n");
509 		return (~0U);
510 	}
511 
512 	for (i = 0; i < max; i++) {
513 		if (dbg_check_slot_free(type, i))
514 			return (i);
515 	}
516 
517 	return (~0U);
518 }
519 
520 static u_int
dbg_find_slot(enum dbg_t type,db_expr_t addr)521 dbg_find_slot(enum dbg_t type, db_expr_t addr)
522 {
523 	uint32_t reg_addr, reg_ctrl;
524 	u_int max, i;
525 
526 	switch(type) {
527 	case DBG_TYPE_BREAKPOINT:
528 		max = dbg_breakpoint_num;
529 		reg_addr = DBG_REG_BASE_BVR;
530 		reg_ctrl = DBG_REG_BASE_BCR;
531 		break;
532 	case DBG_TYPE_WATCHPOINT:
533 		max = dbg_watchpoint_num;
534 		reg_addr = DBG_REG_BASE_WVR;
535 		reg_ctrl = DBG_REG_BASE_WCR;
536 		break;
537 	default:
538 		db_printf("Unsupported debug type\n");
539 		return (~0U);
540 	}
541 
542 	for (i = 0; i < max; i++) {
543 		if ((dbg_wb_read_reg(reg_addr, i) == addr) &&
544 		    ((dbg_wb_read_reg(reg_ctrl, i) & DBG_WB_CTRL_E) != 0))
545 			return (i);
546 	}
547 
548 	return (~0U);
549 }
550 
551 static __inline boolean_t
dbg_monitor_is_enabled(void)552 dbg_monitor_is_enabled(void)
553 {
554 
555 	return ((cp14_dbgdscrint_get() & DBGSCR_MDBG_EN) != 0);
556 }
557 
558 static int
dbg_enable_monitor(void)559 dbg_enable_monitor(void)
560 {
561 	uint32_t dbg_dscr;
562 
563 	/* Already enabled? Just return */
564 	if (dbg_monitor_is_enabled())
565 		return (0);
566 
567 	dbg_dscr = cp14_dbgdscrint_get();
568 
569 	switch (dbg_model) {
570 	case ID_DFR0_CP_DEBUG_M_V6:
571 	case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
572 		cp14_dbgdscr_v6_set(dbg_dscr | DBGSCR_MDBG_EN);
573 		break;
574 	case ID_DFR0_CP_DEBUG_M_V7: /* fall through */
575 	case ID_DFR0_CP_DEBUG_M_V7_1:
576 		cp14_dbgdscr_v7_set(dbg_dscr | DBGSCR_MDBG_EN);
577 		break;
578 	default:
579 		break;
580 	}
581 	isb();
582 
583 	/* Verify that Monitor mode is set */
584 	if (dbg_monitor_is_enabled())
585 		return (0);
586 
587 	return (ENXIO);
588 }
589 
590 static int
dbg_setup_xpoint(struct dbg_wb_conf * conf)591 dbg_setup_xpoint(struct dbg_wb_conf *conf)
592 {
593 	struct pcpu *pcpu;
594 	struct dbreg *d;
595 	const char *typestr;
596 	uint32_t cr_size, cr_priv, cr_access;
597 	uint32_t reg_ctrl, reg_addr, ctrl, addr;
598 	boolean_t is_bkpt;
599 	u_int cpu;
600 	u_int i;
601 
602 	if (!dbg_capable())
603 		return (ENXIO);
604 
605 	is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
606 	typestr = is_bkpt ? "breakpoint" : "watchpoint";
607 
608 	if (is_bkpt) {
609 		if (dbg_breakpoint_num == 0) {
610 			db_printf("Breakpoints not supported on this architecture\n");
611 			return (ENXIO);
612 		}
613 		i = conf->slot;
614 		if (!dbg_check_slot_free(DBG_TYPE_BREAKPOINT, i)) {
615 			/*
616 			 * This should never happen. If it does it means that
617 			 * there is an erroneus scenario somewhere. Still, it can
618 			 * be done but let's inform the user.
619 			 */
620 			db_printf("ERROR: Breakpoint already set. Replacing...\n");
621 		}
622 	} else {
623 		i = dbg_find_free_slot(DBG_TYPE_WATCHPOINT);
624 		if (i == ~0U) {
625 			db_printf("Can not find slot for %s, max %d slots supported\n",
626 			    typestr, dbg_watchpoint_num);
627 			return (ENXIO);
628 		}
629 	}
630 
631 	/* Kernel access only */
632 	cr_priv = DBG_WB_CTRL_PL1;
633 
634 	switch(conf->size) {
635 	case 1:
636 		cr_size = DBG_WB_CTRL_LEN_1;
637 		break;
638 	case 2:
639 		cr_size = DBG_WB_CTRL_LEN_2;
640 		break;
641 	case 4:
642 		cr_size = DBG_WB_CTRL_LEN_4;
643 		break;
644 	case 8:
645 		cr_size = DBG_WB_CTRL_LEN_8;
646 		break;
647 	default:
648 		db_printf("Unsupported address size for %s\n", typestr);
649 		return (EINVAL);
650 	}
651 
652 	if (is_bkpt) {
653 		cr_access = DBG_WB_CTRL_EXEC;
654 		reg_ctrl = DBG_REG_BASE_BCR;
655 		reg_addr = DBG_REG_BASE_BVR;
656 		/* Always unlinked BKPT */
657 		ctrl = (cr_size | cr_access | cr_priv | DBG_WB_CTRL_E);
658 	} else {
659 		switch(conf->access) {
660 		case HW_WATCHPOINT_R:
661 			cr_access = DBG_WB_CTRL_LOAD;
662 			break;
663 		case HW_WATCHPOINT_W:
664 			cr_access = DBG_WB_CTRL_STORE;
665 			break;
666 		case HW_WATCHPOINT_RW:
667 			cr_access = DBG_WB_CTRL_LOAD | DBG_WB_CTRL_STORE;
668 			break;
669 		default:
670 			db_printf("Unsupported exception level for %s\n", typestr);
671 			return (EINVAL);
672 		}
673 
674 		reg_ctrl = DBG_REG_BASE_WCR;
675 		reg_addr = DBG_REG_BASE_WVR;
676 		ctrl = (cr_size | cr_access | cr_priv | DBG_WB_CTRL_E);
677 	}
678 
679 	addr = conf->address;
680 
681 	dbg_wb_write_reg(reg_addr, i, addr);
682 	dbg_wb_write_reg(reg_ctrl, i, ctrl);
683 
684 	/*
685 	 * Save watchpoint settings for all CPUs.
686 	 * We don't need to do the same with breakpoints since HW breakpoints
687 	 * are only used to perform single stepping.
688 	 */
689 	if (!is_bkpt) {
690 		CPU_FOREACH(cpu) {
691 			pcpu = pcpu_find(cpu);
692 			/* Fill out the settings for watchpoint */
693 			d = (struct dbreg *)pcpu->pc_dbreg;
694 			d->dbg_wvr[i] = addr;
695 			d->dbg_wcr[i] = ctrl;
696 			/* Skip update command for the current CPU */
697 			if (cpu != PCPU_GET(cpuid))
698 				pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
699 		}
700 	}
701 	/* Ensure all data is written before waking other CPUs */
702 	atomic_thread_fence_rel();
703 
704 	return (0);
705 }
706 
707 static int
dbg_remove_xpoint(struct dbg_wb_conf * conf)708 dbg_remove_xpoint(struct dbg_wb_conf *conf)
709 {
710 	struct pcpu *pcpu;
711 	struct dbreg *d;
712 	uint32_t reg_ctrl, reg_addr, addr;
713 	boolean_t is_bkpt;
714 	u_int cpu;
715 	u_int i;
716 
717 	if (!dbg_capable())
718 		return (ENXIO);
719 
720 	is_bkpt = (conf->type == DBG_TYPE_BREAKPOINT);
721 	addr = conf->address;
722 
723 	if (is_bkpt) {
724 		i = conf->slot;
725 		reg_ctrl = DBG_REG_BASE_BCR;
726 		reg_addr = DBG_REG_BASE_BVR;
727 	} else {
728 		i = dbg_find_slot(DBG_TYPE_WATCHPOINT, addr);
729 		if (i == ~0U) {
730 			db_printf("Can not find watchpoint for address 0%x\n", addr);
731 			return (EINVAL);
732 		}
733 		reg_ctrl = DBG_REG_BASE_WCR;
734 		reg_addr = DBG_REG_BASE_WVR;
735 	}
736 
737 	dbg_wb_write_reg(reg_ctrl, i, 0);
738 	dbg_wb_write_reg(reg_addr, i, 0);
739 
740 	/*
741 	 * Save watchpoint settings for all CPUs.
742 	 * We don't need to do the same with breakpoints since HW breakpoints
743 	 * are only used to perform single stepping.
744 	 */
745 	if (!is_bkpt) {
746 		CPU_FOREACH(cpu) {
747 			pcpu = pcpu_find(cpu);
748 			/* Fill out the settings for watchpoint */
749 			d = (struct dbreg *)pcpu->pc_dbreg;
750 			d->dbg_wvr[i] = 0;
751 			d->dbg_wcr[i] = 0;
752 			/* Skip update command for the current CPU */
753 			if (cpu != PCPU_GET(cpuid))
754 				pcpu->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
755 		}
756 		/* Ensure all data is written before waking other CPUs */
757 		atomic_thread_fence_rel();
758 	}
759 
760 	return (0);
761 }
762 
763 static __inline uint32_t
dbg_get_debug_model(void)764 dbg_get_debug_model(void)
765 {
766 	uint32_t dbg_m;
767 
768 	dbg_m = ((cpuinfo.id_dfr0 & ID_DFR0_CP_DEBUG_M_MASK) >>
769 	    ID_DFR0_CP_DEBUG_M_SHIFT);
770 
771 	return (dbg_m);
772 }
773 
774 static __inline boolean_t
dbg_get_ossr(void)775 dbg_get_ossr(void)
776 {
777 
778 	switch (dbg_model) {
779 	case ID_DFR0_CP_DEBUG_M_V7:
780 		if ((cp14_dbgoslsr_get() & DBGOSLSR_OSLM0) != 0)
781 			return (TRUE);
782 
783 		return (FALSE);
784 	case ID_DFR0_CP_DEBUG_M_V7_1:
785 		return (TRUE);
786 	default:
787 		return (FALSE);
788 	}
789 }
790 
791 static __inline boolean_t
dbg_arch_supported(void)792 dbg_arch_supported(void)
793 {
794 	uint32_t dbg_didr;
795 
796 	switch (dbg_model) {
797 	case ID_DFR0_CP_DEBUG_M_V6:
798 	case ID_DFR0_CP_DEBUG_M_V6_1:
799 		dbg_didr = cp14_dbgdidr_get();
800 		/*
801 		 * read-all-zeroes is used by QEMU
802 		 * to indicate that ARMv6 debug support
803 		 * is not implemented. Real hardware has at
804 		 * least version bits set
805 		 */
806 		if (dbg_didr == 0)
807 			return (FALSE);
808 		return (TRUE);
809 	case ID_DFR0_CP_DEBUG_M_V7:
810 	case ID_DFR0_CP_DEBUG_M_V7_1:	/* fall through */
811 		return (TRUE);
812 	default:
813 		/* We only support valid v6.x/v7.x modes through CP14 */
814 		return (FALSE);
815 	}
816 }
817 
818 static __inline uint32_t
dbg_get_wrp_num(void)819 dbg_get_wrp_num(void)
820 {
821 	uint32_t dbg_didr;
822 
823 	dbg_didr = cp14_dbgdidr_get();
824 
825 	return (DBGDIDR_WRPS_NUM(dbg_didr));
826 }
827 
828 static __inline uint32_t
dgb_get_brp_num(void)829 dgb_get_brp_num(void)
830 {
831 	uint32_t dbg_didr;
832 
833 	dbg_didr = cp14_dbgdidr_get();
834 
835 	return (DBGDIDR_BRPS_NUM(dbg_didr));
836 }
837 
838 static int
dbg_reset_state(void)839 dbg_reset_state(void)
840 {
841 	u_int cpuid;
842 	size_t i;
843 	int err;
844 
845 	cpuid = PCPU_GET(cpuid);
846 	err = 0;
847 
848 	switch (dbg_model) {
849 	case ID_DFR0_CP_DEBUG_M_V6:
850 	case ID_DFR0_CP_DEBUG_M_V6_1: /* fall through */
851 		/*
852 		 * Arch needs monitor mode selected and enabled
853 		 * to be able to access breakpoint/watchpoint registers.
854 		 */
855 		err = dbg_enable_monitor();
856 		if (err != 0)
857 			return (err);
858 		goto vectr_clr;
859 	case ID_DFR0_CP_DEBUG_M_V7:
860 		/* Is core power domain powered up? */
861 		if ((cp14_dbgprsr_get() & DBGPRSR_PU) == 0)
862 			err = ENXIO;
863 
864 		if (err != 0)
865 			break;
866 
867 		if (dbg_ossr)
868 			goto vectr_clr;
869 		break;
870 	case ID_DFR0_CP_DEBUG_M_V7_1:
871 		/* Is double lock set? */
872 		if ((cp14_dbgosdlr_get() & DBGPRSR_DLK) != 0)
873 			err = ENXIO;
874 
875 		break;
876 	default:
877 		break;
878 	}
879 
880 	if (err != 0) {
881 		db_printf("Debug facility locked (CPU%d)\n", cpuid);
882 		return (err);
883 	}
884 
885 	/*
886 	 * DBGOSLAR is always implemented for v7.1 Debug Arch. however is
887 	 * optional for v7 (depends on OS save and restore support).
888 	 */
889 	if (((dbg_model & ID_DFR0_CP_DEBUG_M_V7_1) != 0) || dbg_ossr) {
890 		/*
891 		 * Clear OS lock.
892 		 * Writing any other value than 0xC5ACCESS will unlock.
893 		 */
894 		cp14_dbgoslar_set(0);
895 		isb();
896 	}
897 
898 vectr_clr:
899 	/*
900 	 * After reset we must ensure that DBGVCR has a defined value.
901 	 * Disable all vector catch events. Safe to use - required in all
902 	 * implementations.
903 	 */
904 	cp14_dbgvcr_set(0);
905 	isb();
906 
907 	/*
908 	 * We have limited number of {watch,break}points, each consists of
909 	 * two registers:
910 	 * - wcr/bcr regsiter configurates corresponding {watch,break}point
911 	 *   behaviour
912 	 * - wvr/bvr register keeps address we are hunting for
913 	 *
914 	 * Reset all breakpoints and watchpoints.
915 	 */
916 	for (i = 0; i < dbg_watchpoint_num; ++i) {
917 		dbg_wb_write_reg(DBG_REG_BASE_WCR, i, 0);
918 		dbg_wb_write_reg(DBG_REG_BASE_WVR, i, 0);
919 	}
920 
921 	for (i = 0; i < dbg_breakpoint_num; ++i) {
922 		dbg_wb_write_reg(DBG_REG_BASE_BCR, i, 0);
923 		dbg_wb_write_reg(DBG_REG_BASE_BVR, i, 0);
924 	}
925 
926 	return (0);
927 }
928 
929 void
dbg_monitor_init(void)930 dbg_monitor_init(void)
931 {
932 	int err;
933 
934 	/* Fetch ARM Debug Architecture model */
935 	dbg_model = dbg_get_debug_model();
936 
937 	if (!dbg_arch_supported()) {
938 		db_printf("ARM Debug Architecture not supported\n");
939 		return;
940 	}
941 
942 	if (bootverbose) {
943 		db_printf("ARM Debug Architecture %s\n",
944 		    (dbg_model == ID_DFR0_CP_DEBUG_M_V6) ? "v6" :
945 		    (dbg_model == ID_DFR0_CP_DEBUG_M_V6_1) ? "v6.1" :
946 		    (dbg_model == ID_DFR0_CP_DEBUG_M_V7) ? "v7" :
947 		    (dbg_model == ID_DFR0_CP_DEBUG_M_V7_1) ? "v7.1" : "unknown");
948 	}
949 
950 	/* Do we have OS Save and Restore mechanism? */
951 	dbg_ossr = dbg_get_ossr();
952 
953 	/* Find out many breakpoints and watchpoints we can use */
954 	dbg_watchpoint_num = dbg_get_wrp_num();
955 	dbg_breakpoint_num = dgb_get_brp_num();
956 
957 	if (bootverbose) {
958 		db_printf("%d watchpoints and %d breakpoints supported\n",
959 		    dbg_watchpoint_num, dbg_breakpoint_num);
960 	}
961 
962 	err = dbg_reset_state();
963 	if (err == 0) {
964 		err = dbg_enable_monitor();
965 		if (err == 0) {
966 			atomic_set_int(&dbg_capable_var, 1);
967 			return;
968 		}
969 	}
970 
971 	db_printf("HW Breakpoints/Watchpoints not enabled on CPU%d\n",
972 	    PCPU_GET(cpuid));
973 }
974 
975 CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
976 
977 void
dbg_monitor_init_secondary(void)978 dbg_monitor_init_secondary(void)
979 {
980 	u_int cpuid;
981 	int err;
982 	/*
983 	 * This flag is set on the primary CPU
984 	 * and its meaning is valid for other CPUs too.
985 	 */
986 	if (!dbg_capable())
987 		return;
988 
989 	cpuid = PCPU_GET(cpuid);
990 
991 	err = dbg_reset_state();
992 	if (err != 0) {
993 		/*
994 		 * Something is very wrong.
995 		 * WPs/BPs will not work correctly on this CPU.
996 		 */
997 		KASSERT(0, ("%s: Failed to reset Debug Architecture "
998 		    "state on CPU%d", __func__, cpuid));
999 		/* Disable HW debug capabilities for all CPUs */
1000 		atomic_set_int(&dbg_capable_var, 0);
1001 		return;
1002 	}
1003 	err = dbg_enable_monitor();
1004 	if (err != 0) {
1005 		KASSERT(0, ("%s: Failed to enable Debug Monitor"
1006 		    " on CPU%d", __func__, cpuid));
1007 		atomic_set_int(&dbg_capable_var, 0);
1008 	}
1009 }
1010 
1011 void
dbg_resume_dbreg(void)1012 dbg_resume_dbreg(void)
1013 {
1014 	struct dbreg *d;
1015 	u_int i;
1016 
1017 	/*
1018 	 * This flag is set on the primary CPU
1019 	 * and its meaning is valid for other CPUs too.
1020 	 */
1021 	if (!dbg_capable())
1022 		return;
1023 
1024 	atomic_thread_fence_acq();
1025 
1026 	switch (PCPU_GET(dbreg_cmd)) {
1027 	case PC_DBREG_CMD_LOAD:
1028 		d = (struct dbreg *)PCPU_PTR(dbreg);
1029 
1030 		/* Restore watchpoints */
1031 		for (i = 0; i < dbg_watchpoint_num; i++) {
1032 			dbg_wb_write_reg(DBG_REG_BASE_WVR, i, d->dbg_wvr[i]);
1033 			dbg_wb_write_reg(DBG_REG_BASE_WCR, i, d->dbg_wcr[i]);
1034 		}
1035 
1036 		PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
1037 		break;
1038 	}
1039 }
1040