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