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