xref: /netbsd/sys/arch/aarch64/aarch64/db_machdep.c (revision e00aa033)
1 /* $NetBSD: db_machdep.c,v 1.45 2022/10/26 23:38:05 riastradh Exp $ */
2 
3 /*-
4  * Copyright (c) 2014 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Matt Thomas of 3am Software Foundry.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.45 2022/10/26 23:38:05 riastradh Exp $");
34 
35 #ifdef _KERNEL_OPT
36 #include "opt_compat_netbsd32.h"
37 #endif
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/atomic.h>
42 #include <sys/cpu.h>
43 #include <sys/lwp.h>
44 #include <sys/intr.h>
45 
46 #include <uvm/uvm.h>
47 
48 #include <arm/cpufunc.h>
49 
50 #include <aarch64/db_machdep.h>
51 #include <aarch64/armreg.h>
52 #include <aarch64/locore.h>
53 #include <aarch64/pmap.h>
54 
55 #include <arm/cpufunc.h>
56 
57 #include <ddb/db_access.h>
58 #include <ddb/db_active.h>
59 #include <ddb/db_command.h>
60 #include <ddb/db_output.h>
61 #include <ddb/db_proc.h>
62 #include <ddb/db_variables.h>
63 #include <ddb/db_run.h>
64 #include <ddb/db_sym.h>
65 #include <ddb/db_extern.h>
66 #include <ddb/db_interface.h>
67 #include <ddb/db_user.h>
68 
69 #include <dev/cons.h>
70 
71 void db_md_cpuinfo_cmd(db_expr_t, bool, db_expr_t, const char *);
72 void db_md_frame_cmd(db_expr_t, bool, db_expr_t, const char *);
73 void db_md_lwp_cmd(db_expr_t, bool, db_expr_t, const char *);
74 void db_md_pte_cmd(db_expr_t, bool, db_expr_t, const char *);
75 void db_md_reset_cmd(db_expr_t, bool, db_expr_t, const char *);
76 void db_md_tlbi_cmd(db_expr_t, bool, db_expr_t, const char *);
77 void db_md_ttbr_cmd(db_expr_t, bool, db_expr_t, const char *);
78 void db_md_sysreg_cmd(db_expr_t, bool, db_expr_t, const char *);
79 void db_md_break_cmd(db_expr_t, bool, db_expr_t, const char *);
80 void db_md_watch_cmd(db_expr_t, bool, db_expr_t, const char *);
81 #if defined(_KERNEL) && defined(MULTIPROCESSOR)
82 void db_md_switch_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
83 #endif
84 #if defined(_KERNEL)
85 static void db_md_meminfo_cmd(db_expr_t, bool, db_expr_t, const char *);
86 #endif
87 
88 #ifdef _KERNEL
89 #define MAX_BREAKPOINT	15
90 #define MAX_WATCHPOINT	15
91 /* The number varies depending on the CPU core (e.g. big.LITTLE) */
92 static int max_breakpoint = MAX_BREAKPOINT;
93 static int max_watchpoint = MAX_WATCHPOINT;
94 
95 struct breakpoint_info {
96 	db_addr_t addr;
97 };
98 static struct breakpoint_info breakpoint_buf[MAX_BREAKPOINT + 1];
99 
100 struct watchpoint_info {
101 	db_addr_t addr;
102 	int size;
103 	int accesstype;
104 };
105 static struct watchpoint_info watchpoint_buf[MAX_WATCHPOINT + 1];
106 #endif
107 
108 const struct db_command db_machine_command_table[] = {
109 #if defined(_KERNEL) && defined(MULTIPROCESSOR)
110 	{
111 		DDB_ADD_CMD(
112 		    "cpu", db_md_switch_cpu_cmd, 0,
113 		    "switch to a different cpu",
114 		    NULL, NULL)
115 	},
116 #endif
117 #if defined(_KERNEL)
118 	{
119 		DDB_ADD_CMD(
120 		    "break", db_md_break_cmd, 0,
121 		    "set or clear breakpoint",
122 		    "[address|#]",
123 		    "\taddress: breakpoint address to set\n"
124 		    "\t#: breakpoint number to remove\n")
125 	},
126 	{
127 		DDB_ADD_CMD(
128 		    "cpuinfo", db_md_cpuinfo_cmd, 0,
129 		    "Displays the current cpuinfo",
130 		    NULL, NULL)
131 	},
132 	{
133 		DDB_ADD_CMD(
134 		    "frame", db_md_frame_cmd, 0,
135 		    "Displays the contents of a trapframe",
136 		    "address",
137 		    "\taddress:\taddress of trapframe to display")
138 	},
139 	{
140 		DDB_ADD_CMD(
141 		    "lwp", db_md_lwp_cmd, 0,
142 		    "Displays the lwp",
143 		    "address",
144 		    "\taddress:\taddress of lwp to display")
145 	},
146 	{
147 		DDB_ADD_CMD(
148 		    "pte", db_md_pte_cmd, 0,
149 		    "Display information of pte",
150 		    "address",
151 		    "\taddress:\tvirtual address of page")
152 	},
153 	{
154 		DDB_ADD_CMD(
155 		    "reset", db_md_reset_cmd, 0,
156 		    "Reset the system",
157 		    NULL, NULL)
158 	},
159 	{
160 		DDB_ADD_CMD(
161 		    "sysreg", db_md_sysreg_cmd, 0,
162 		    "Displays system registers",
163 		    NULL, NULL)
164 	},
165 	{
166 		DDB_ADD_CMD(
167 		    "tlbi", db_md_tlbi_cmd, 0,
168 		    "flush tlb",
169 		    NULL, NULL)
170 	},
171 	{
172 		DDB_ADD_CMD(
173 		    "ttbr", db_md_ttbr_cmd, 0,
174 		    "Dump or count TTBR table",
175 		    "[/apc] address | pid",
176 		    "\taddress:\taddress of pmap to display\n"
177 		    "\tpid:\t\tpid of pmap to display")
178 	},
179 	{
180 		DDB_ADD_CMD(
181 		    "watch", db_md_watch_cmd, 0,
182 		    "set or clear watchpoint",
183 		    "[/rwbhlq] [address|#]",
184 		    "\taddress: watchpoint address to set\n"
185 		    "\t#: watchpoint number to remove\n"
186 		    "\t/rw: read or write access\n"
187 		    "\t/bhlq: size of access\n")
188 	},
189 	{
190 		DDB_ADD_CMD(
191 		    "meminfo", db_md_meminfo_cmd, 0,
192 		    "Dump info about memory ranges",
193 		    NULL, NULL)
194 	},
195 #endif
196 	{
197 		DDB_END_CMD
198 	},
199 };
200 
201 const struct db_variable db_regs[] = {
202 	{ "x0",    (long *) &ddb_regs.tf_reg[0],  FCN_NULL, NULL },
203 	{ "x1",    (long *) &ddb_regs.tf_reg[1],  FCN_NULL, NULL },
204 	{ "x2",    (long *) &ddb_regs.tf_reg[2],  FCN_NULL, NULL },
205 	{ "x3",    (long *) &ddb_regs.tf_reg[3],  FCN_NULL, NULL },
206 	{ "x4",    (long *) &ddb_regs.tf_reg[4],  FCN_NULL, NULL },
207 	{ "x5",    (long *) &ddb_regs.tf_reg[5],  FCN_NULL, NULL },
208 	{ "x6",    (long *) &ddb_regs.tf_reg[6],  FCN_NULL, NULL },
209 	{ "x7",    (long *) &ddb_regs.tf_reg[7],  FCN_NULL, NULL },
210 	{ "x8",    (long *) &ddb_regs.tf_reg[8],  FCN_NULL, NULL },
211 	{ "x9",    (long *) &ddb_regs.tf_reg[9],  FCN_NULL, NULL },
212 	{ "x10",   (long *) &ddb_regs.tf_reg[10], FCN_NULL, NULL },
213 	{ "x11",   (long *) &ddb_regs.tf_reg[11], FCN_NULL, NULL },
214 	{ "x12",   (long *) &ddb_regs.tf_reg[12], FCN_NULL, NULL },
215 	{ "x13",   (long *) &ddb_regs.tf_reg[13], FCN_NULL, NULL },
216 	{ "x14",   (long *) &ddb_regs.tf_reg[14], FCN_NULL, NULL },
217 	{ "x15",   (long *) &ddb_regs.tf_reg[15], FCN_NULL, NULL },
218 	{ "x16",   (long *) &ddb_regs.tf_reg[16], FCN_NULL, NULL },
219 	{ "x17",   (long *) &ddb_regs.tf_reg[17], FCN_NULL, NULL },
220 	{ "x18",   (long *) &ddb_regs.tf_reg[18], FCN_NULL, NULL },
221 	{ "x19",   (long *) &ddb_regs.tf_reg[19], FCN_NULL, NULL },
222 	{ "x20",   (long *) &ddb_regs.tf_reg[20], FCN_NULL, NULL },
223 	{ "x21",   (long *) &ddb_regs.tf_reg[21], FCN_NULL, NULL },
224 	{ "x22",   (long *) &ddb_regs.tf_reg[22], FCN_NULL, NULL },
225 	{ "x23",   (long *) &ddb_regs.tf_reg[23], FCN_NULL, NULL },
226 	{ "x24",   (long *) &ddb_regs.tf_reg[24], FCN_NULL, NULL },
227 	{ "x25",   (long *) &ddb_regs.tf_reg[25], FCN_NULL, NULL },
228 	{ "x26",   (long *) &ddb_regs.tf_reg[26], FCN_NULL, NULL },
229 	{ "x27",   (long *) &ddb_regs.tf_reg[27], FCN_NULL, NULL },
230 	{ "x28",   (long *) &ddb_regs.tf_reg[28], FCN_NULL, NULL },
231 	{ "x29",   (long *) &ddb_regs.tf_reg[29], FCN_NULL, NULL },
232 	{ "x30",   (long *) &ddb_regs.tf_reg[30], FCN_NULL, NULL },
233 	{ "sp",    (long *) &ddb_regs.tf_sp,      FCN_NULL, NULL },
234 	{ "pc",    (long *) &ddb_regs.tf_pc,      FCN_NULL, NULL },
235 	{ "spsr",  (long *) &ddb_regs.tf_spsr,    FCN_NULL, NULL }
236 };
237 
238 const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs);
239 int db_active;
240 
241 
242 void
dump_trapframe(struct trapframe * tf,void (* pr)(const char *,...))243 dump_trapframe(struct trapframe *tf, void (*pr)(const char *, ...))
244 {
245 	struct trapframe tf_buf;
246 
247 	db_read_bytes((db_addr_t)tf, sizeof(tf_buf), (char *)&tf_buf);
248 	tf = &tf_buf;
249 
250 #ifdef COMPAT_NETBSD32
251 	if (tf->tf_spsr & SPSR_A32) {
252 		(*pr)("    pc=%016"PRIxREGISTER",   spsr=%016"PRIxREGISTER
253 		    " (AArch32)\n", tf->tf_pc, tf->tf_spsr);
254 		(*pr)("   esr=%016"PRIxREGISTER",    far=%016"PRIxREGISTER"\n",
255 		    tf->tf_esr, tf->tf_far);
256 		(*pr)("    r0=%016"PRIxREGISTER",     r1=%016"PRIxREGISTER"\n",
257 		    tf->tf_reg[0], tf->tf_reg[1]);
258 		(*pr)("    r2=%016"PRIxREGISTER",     r3=%016"PRIxREGISTER"\n",
259 		    tf->tf_reg[2], tf->tf_reg[3]);
260 		(*pr)("    r4=%016"PRIxREGISTER",     r5=%016"PRIxREGISTER"\n",
261 		    tf->tf_reg[4], tf->tf_reg[5]);
262 		(*pr)("    r6=%016"PRIxREGISTER",     r7=%016"PRIxREGISTER"\n",
263 		    tf->tf_reg[6], tf->tf_reg[7]);
264 		(*pr)("    r8=%016"PRIxREGISTER",     r9=%016"PRIxREGISTER"\n",
265 		    tf->tf_reg[8], tf->tf_reg[9]);
266 		(*pr)("   r10=%016"PRIxREGISTER",    r11=%016"PRIxREGISTER"\n",
267 		    tf->tf_reg[10], tf->tf_reg[11]);
268 		(*pr)("   r12=%016"PRIxREGISTER", sp=r13=%016"PRIxREGISTER"\n",
269 		    tf->tf_reg[12], tf->tf_reg[13]);
270 		(*pr)("lr=r14=%016"PRIxREGISTER", pc=r15=%016"PRIxREGISTER"\n",
271 		    tf->tf_reg[14], tf->tf_pc);
272 		return;
273 	}
274 #endif
275 	(*pr)("    pc=%016"PRIxREGISTER",   spsr=%016"PRIxREGISTER"\n",
276 	    tf->tf_pc, tf->tf_spsr);
277 	(*pr)("   esr=%016"PRIxREGISTER",    far=%016"PRIxREGISTER"\n",
278 	    tf->tf_esr, tf->tf_far);
279 	(*pr)("    x0=%016"PRIxREGISTER",     x1=%016"PRIxREGISTER"\n",
280 	    tf->tf_reg[0], tf->tf_reg[1]);
281 	(*pr)("    x2=%016"PRIxREGISTER",     x3=%016"PRIxREGISTER"\n",
282 	    tf->tf_reg[2], tf->tf_reg[3]);
283 	(*pr)("    x4=%016"PRIxREGISTER",     x5=%016"PRIxREGISTER"\n",
284 	    tf->tf_reg[4], tf->tf_reg[5]);
285 	(*pr)("    x6=%016"PRIxREGISTER",     x7=%016"PRIxREGISTER"\n",
286 	    tf->tf_reg[6], tf->tf_reg[7]);
287 	(*pr)("    x8=%016"PRIxREGISTER",     x9=%016"PRIxREGISTER"\n",
288 	    tf->tf_reg[8], tf->tf_reg[9]);
289 	(*pr)("   x10=%016"PRIxREGISTER",    x11=%016"PRIxREGISTER"\n",
290 	    tf->tf_reg[10], tf->tf_reg[11]);
291 	(*pr)("   x12=%016"PRIxREGISTER",    x13=%016"PRIxREGISTER"\n",
292 	    tf->tf_reg[12], tf->tf_reg[13]);
293 	(*pr)("   x14=%016"PRIxREGISTER",    x15=%016"PRIxREGISTER"\n",
294 	    tf->tf_reg[14], tf->tf_reg[15]);
295 	(*pr)("   x16=%016"PRIxREGISTER",    x17=%016"PRIxREGISTER"\n",
296 	    tf->tf_reg[16], tf->tf_reg[17]);
297 	(*pr)("   x18=%016"PRIxREGISTER",    x19=%016"PRIxREGISTER"\n",
298 	    tf->tf_reg[18], tf->tf_reg[19]);
299 	(*pr)("   x20=%016"PRIxREGISTER",    x21=%016"PRIxREGISTER"\n",
300 	    tf->tf_reg[20], tf->tf_reg[21]);
301 	(*pr)("   x22=%016"PRIxREGISTER",    x23=%016"PRIxREGISTER"\n",
302 	    tf->tf_reg[22], tf->tf_reg[23]);
303 	(*pr)("   x24=%016"PRIxREGISTER",    x25=%016"PRIxREGISTER"\n",
304 	    tf->tf_reg[24], tf->tf_reg[25]);
305 	(*pr)("   x26=%016"PRIxREGISTER",    x27=%016"PRIxREGISTER"\n",
306 	    tf->tf_reg[26], tf->tf_reg[27]);
307 	(*pr)("   x28=%016"PRIxREGISTER", fp=x29=%016"PRIxREGISTER"\n",
308 	    tf->tf_reg[28], tf->tf_reg[29]);
309 	(*pr)("lr=x30=%016"PRIxREGISTER",     sp=%016"PRIxREGISTER"\n",
310 	    tf->tf_reg[30],  tf->tf_sp);
311 }
312 
313 void
dump_switchframe(struct trapframe * tf,void (* pr)(const char *,...))314 dump_switchframe(struct trapframe *tf, void (*pr)(const char *, ...))
315 {
316 	struct trapframe tf_buf;
317 
318 	db_read_bytes((db_addr_t)tf, sizeof(tf_buf), (char *)&tf_buf);
319 	tf = &tf_buf;
320 
321 	(*pr)("   x19=%016"PRIxREGISTER",    x20=%016"PRIxREGISTER"\n",
322 	    tf->tf_reg[19], tf->tf_reg[20]);
323 	(*pr)("   x21=%016"PRIxREGISTER",    x22=%016"PRIxREGISTER"\n",
324 	    tf->tf_reg[21], tf->tf_reg[22]);
325 	(*pr)("   x23=%016"PRIxREGISTER",    x24=%016"PRIxREGISTER"\n",
326 	    tf->tf_reg[23], tf->tf_reg[24]);
327 	(*pr)("   x25=%016"PRIxREGISTER",    x26=%016"PRIxREGISTER"\n",
328 	    tf->tf_reg[25], tf->tf_reg[26]);
329 	(*pr)("   x27=%016"PRIxREGISTER",    x28=%016"PRIxREGISTER"\n",
330 	    tf->tf_reg[27], tf->tf_reg[28]);
331 	(*pr)("fp=x29=%016"PRIxREGISTER", lr=x30=%016"PRIxREGISTER"\n",
332 	    tf->tf_reg[29], tf->tf_reg[30]);
333 }
334 
335 
336 #if defined(_KERNEL)
337 static void
show_cpuinfo(struct cpu_info * ci)338 show_cpuinfo(struct cpu_info *ci)
339 {
340 	struct cpu_info cpuinfobuf;
341 	u_int cpuidx;
342 	int i;
343 
344 	db_read_bytes((db_addr_t)ci, sizeof(cpuinfobuf), (char *)&cpuinfobuf);
345 
346 	cpuidx = cpu_index(&cpuinfobuf);
347 	db_printf("cpu_info=%p, cpu_name=%s\n", ci, cpuinfobuf.ci_cpuname);
348 	db_printf("%p cpu[%u].ci_cpuid         = 0x%lx\n",
349 	    &ci->ci_cpuid, cpuidx, cpuinfobuf.ci_cpuid);
350 	db_printf("%p cpu[%u].ci_curlwp        = %p\n",
351 	    &ci->ci_curlwp, cpuidx, cpuinfobuf.ci_curlwp);
352 	db_printf("%p cpu[%u].ci_onproc        = %p\n",
353 	    &ci->ci_onproc, cpuidx, cpuinfobuf.ci_onproc);
354 	for (i = 0; i < SOFTINT_COUNT; i++) {
355 		db_printf("%p cpu[%u].ci_softlwps[%d]   = %p\n",
356 		    &ci->ci_softlwps[i], cpuidx, i, cpuinfobuf.ci_softlwps[i]);
357 	}
358 	db_printf("%p cpu[%u].ci_lastintr      = %" PRIu64 "\n",
359 	    &ci->ci_lastintr, cpuidx, cpuinfobuf.ci_lastintr);
360 	db_printf("%p cpu[%u].ci_want_resched  = %d\n",
361 	    &ci->ci_want_resched, cpuidx, cpuinfobuf.ci_want_resched);
362 	db_printf("%p cpu[%u].ci_cpl           = %d\n",
363 	    &ci->ci_cpl, cpuidx, cpuinfobuf.ci_cpl);
364 	db_printf("%p cpu[%u].ci_softints      = 0x%08x\n",
365 	    &ci->ci_softints, cpuidx, cpuinfobuf.ci_softints);
366 	db_printf("%p cpu[%u].ci_intr_depth    = %u\n",
367 	    &ci->ci_intr_depth, cpuidx, cpuinfobuf.ci_intr_depth);
368 	db_printf("%p cpu[%u].ci_biglock_count = %u\n",
369 	    &ci->ci_biglock_count, cpuidx, cpuinfobuf.ci_biglock_count);
370 }
371 
372 void
db_md_cpuinfo_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)373 db_md_cpuinfo_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
374     const char *modif)
375 {
376 #ifdef MULTIPROCESSOR
377 	CPU_INFO_ITERATOR cii;
378 	struct cpu_info *ci;
379 	bool showall = false;
380 
381 	if (modif != NULL) {
382 		for (; *modif != '\0'; modif++) {
383 			switch (*modif) {
384 			case 'a':
385 				showall = true;
386 				break;
387 			}
388 		}
389 	}
390 
391 	if (showall) {
392 		for (CPU_INFO_FOREACH(cii, ci)) {
393 			show_cpuinfo(ci);
394 		}
395 	} else
396 #endif /* MULTIPROCESSOR */
397 		show_cpuinfo(curcpu());
398 }
399 
400 void
db_md_frame_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)401 db_md_frame_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
402     const char *modif)
403 {
404 	struct trapframe *tf;
405 
406 	if (!have_addr) {
407 		db_printf("frame address must be specified\n");
408 		return;
409 	}
410 
411 	tf = (struct trapframe *)addr;
412 	dump_trapframe(tf, db_printf);
413 }
414 
415 void
db_md_lwp_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)416 db_md_lwp_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
417     const char *modif)
418 {
419 	lwp_t *l, lwp_buf;
420 	struct pcb *pcb, pcb_buf;
421 
422 	if (!have_addr) {
423 		db_printf("lwp address must be specified\n");
424 		return;
425 	}
426 
427 	db_read_bytes(addr, sizeof(lwp_buf), (char *)&lwp_buf);
428 	l = &lwp_buf;
429 
430 #define SAFESTRPTR(p)	(((p) == NULL) ? "NULL" : (p))
431 
432 	db_printf("lwp=%p\n", (void *)addr);
433 
434 	db_printf("\tlwp_getpcb(l)     =%p\n", lwp_getpcb(l));
435 
436 	db_printf("\tl->l_md.md_onfault=%p\n", l->l_md.md_onfault);
437 	db_printf("\tl->l_md.md_utf    =%p\n", l->l_md.md_utf);
438 	dump_trapframe(l->l_md.md_utf, db_printf);
439 
440 	db_read_bytes((db_addr_t)l->l_addr, sizeof(pcb_buf), (char *)&pcb_buf);
441 	pcb = &pcb_buf;
442 
443 	db_printf("\tl->l_addr.pcb_tf    =%p\n", pcb->pcb_tf);
444 	if (pcb->pcb_tf != l->l_md.md_utf)
445 		dump_switchframe(pcb->pcb_tf, db_printf);
446 	db_printf("\tl->l_md.md_cpacr  =%016" PRIx64 "\n", l->l_md.md_cpacr);
447 	db_printf("\tl->l_md.md_flags  =%08x\n", l->l_md.md_flags);
448 
449 	db_printf("\tl->l_cpu          =%p\n", l->l_cpu);
450 	db_printf("\tl->l_proc         =%p\n", l->l_proc);
451 	db_printf("\tl->l_private      =%p\n", l->l_private);
452 	db_printf("\tl->l_name         =%s\n", SAFESTRPTR(l->l_name));
453 	db_printf("\tl->l_wmesg        =%s\n", SAFESTRPTR(l->l_wmesg));
454 }
455 
456 static void
db_par_print(uint64_t par,vaddr_t va)457 db_par_print(uint64_t par, vaddr_t va)
458 {
459 	paddr_t pa = (__SHIFTOUT(par, PAR_PA) << PAR_PA_SHIFT) +
460 	    (va & __BITS(PAR_PA_SHIFT - 1, 0));
461 
462 	if (__SHIFTOUT(par, PAR_F) == 0) {
463 		db_printf("%016" PRIx64
464 		    ": ATTR=0x%02" __PRIxBITS
465 		    ", NS=%" __PRIuBITS
466 		    ", SH=%" __PRIuBITS
467 		    ", PA=%016" PRIxPADDR
468 		    " (no fault)\n",
469 		    par,
470 		    __SHIFTOUT(par, PAR_ATTR),
471 		    __SHIFTOUT(par, PAR_NS),
472 		    __SHIFTOUT(par, PAR_SH),
473 		    pa);
474 	} else {
475 		db_printf("%016" PRIx64
476 		    ", S=%" __PRIuBITS
477 		    ", PTW=%" __PRIuBITS
478 		    ", FST=%" __PRIuBITS
479 		    " (fault)\n",
480 		    par,
481 		    __SHIFTOUT(par, PAR_S),
482 		    __SHIFTOUT(par, PAR_PTW),
483 		    __SHIFTOUT(par, PAR_FST));
484 	}
485 }
486 
487 void
db_md_pte_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)488 db_md_pte_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
489     const char *modif)
490 {
491 	uint64_t par;
492 
493 	if (!have_addr) {
494 		db_printf("pte address must be specified\n");
495 		return;
496 	}
497 
498 	reg_s1e0r_write(addr);
499 	isb();
500 	par = reg_par_el1_read();
501 	db_printf("Stage1 EL0 translation %016llx -> PAR_EL1 = ", addr);
502 	db_par_print(par, addr);
503 
504 	reg_s1e1r_write(addr);
505 	isb();
506 	par = reg_par_el1_read();
507 	db_printf("Stage1 EL1 translation %016llx -> PAR_EL1 = ", addr);
508 	db_par_print(par, addr);
509 
510 	db_pteinfo(addr, db_printf);
511 }
512 
513 void
db_md_reset_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)514 db_md_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
515     const char *modif)
516 {
517 	if (cpu_reset_address == NULL) {
518 		db_printf("cpu_reset_address is not set\n");
519 		return;
520 	}
521 
522 	cpu_reset_address();
523 }
524 
525 void
db_md_tlbi_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)526 db_md_tlbi_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
527     const char *modif)
528 {
529 	aarch64_tlbi_all();
530 }
531 
532 void
db_md_ttbr_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)533 db_md_ttbr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
534     const char *modif)
535 {
536 	bool countmode = false, by_pid = true;
537 
538 	if (!have_addr) {
539 		db_printf("usage: machine ttbr [/a] [/p] [/c] address|pid\n");
540 		db_printf("\t/a == argument is an address of any pmap_t\n");
541 		db_printf("\t/p == argument is a pid [default]\n");
542 		db_printf("\t/c == count TLB entries\n");
543 		return;
544 	}
545 
546 	if (modif != NULL) {
547 		for (; *modif != '\0'; modif++) {
548 			switch (*modif) {
549 			case 'c':
550 				countmode = true;
551 				break;
552 			case 'a':
553 				by_pid = false;
554 				break;
555 			case 'p':
556 				by_pid = true;
557 				break;
558 			}
559 		}
560 	}
561 
562 	if (by_pid) {
563 		proc_t *p = db_proc_find((pid_t)addr);
564 		if (p == NULL) {
565 			db_printf("bad address\n");
566 			return;
567 		}
568 		addr = (db_addr_t)p->p_vmspace->vm_map.pmap;
569 	}
570 
571 	db_ttbrdump(countmode, addr, db_printf);
572 }
573 
574 void
db_md_sysreg_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)575 db_md_sysreg_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
576     const char *modif)
577 {
578 #define SHOW_ARMREG(x)	\
579 	db_printf("%-16s = %016" PRIx64 "\n", #x, reg_ ## x ## _read())
580 
581 //	SHOW_ARMREG(cbar_el1);	/* Cortex */
582 	SHOW_ARMREG(ccsidr_el1);
583 	SHOW_ARMREG(clidr_el1);
584 	SHOW_ARMREG(cntfrq_el0);
585 	SHOW_ARMREG(cntkctl_el1);
586 	SHOW_ARMREG(cntp_ctl_el0);
587 	SHOW_ARMREG(cntp_cval_el0);
588 	SHOW_ARMREG(cntp_tval_el0);
589 	SHOW_ARMREG(cntpct_el0);
590 //	SHOW_ARMREG(cntps_ctl_el1);	/* need secure state */
591 //	SHOW_ARMREG(cntps_cval_el1);	/* need secure state */
592 //	SHOW_ARMREG(cntps_tval_el1);	/* need secure state */
593 	SHOW_ARMREG(cntv_ctl_el0);
594 	SHOW_ARMREG(cntv_ctl_el0);
595 	SHOW_ARMREG(cntv_cval_el0);
596 	SHOW_ARMREG(cntv_tval_el0);
597 	SHOW_ARMREG(cntv_tval_el0);
598 	SHOW_ARMREG(cntvct_el0);
599 	SHOW_ARMREG(cpacr_el1);
600 	SHOW_ARMREG(csselr_el1);
601 	SHOW_ARMREG(ctr_el0);
602 	SHOW_ARMREG(currentel);
603 	SHOW_ARMREG(daif);
604 	SHOW_ARMREG(dczid_el0);
605 	SHOW_ARMREG(elr_el1);
606 	SHOW_ARMREG(esr_el1);
607 	SHOW_ARMREG(far_el1);
608 //	SHOW_ARMREG(fpcr);	/* FP trap */
609 //	SHOW_ARMREG(fpsr);	/* FP trap */
610 	SHOW_ARMREG(id_aa64afr0_el1);
611 	SHOW_ARMREG(id_aa64afr1_el1);
612 	SHOW_ARMREG(id_aa64dfr0_el1);
613 	SHOW_ARMREG(id_aa64dfr1_el1);
614 	SHOW_ARMREG(id_aa64isar0_el1);
615 	SHOW_ARMREG(id_aa64isar1_el1);
616 	SHOW_ARMREG(id_aa64mmfr0_el1);
617 	SHOW_ARMREG(id_aa64mmfr1_el1);
618 	SHOW_ARMREG(id_aa64pfr0_el1);
619 	SHOW_ARMREG(id_aa64pfr1_el1);
620 	SHOW_ARMREG(isr_el1);
621 //	SHOW_ARMREG(l2ctlr_el1);	/* Cortex */
622 	SHOW_ARMREG(mair_el1);
623 	SHOW_ARMREG(mdscr_el1);
624 	SHOW_ARMREG(midr_el1);
625 	SHOW_ARMREG(mpidr_el1);
626 	SHOW_ARMREG(mvfr0_el1);
627 	SHOW_ARMREG(mvfr1_el1);
628 	SHOW_ARMREG(mvfr2_el1);
629 	SHOW_ARMREG(nzcv);
630 	SHOW_ARMREG(par_el1);
631 	SHOW_ARMREG(pmccfiltr_el0);
632 	SHOW_ARMREG(pmccntr_el0);
633 	SHOW_ARMREG(revidr_el1);
634 //	SHOW_ARMREG(rmr_el1);		/* unknown reason trap */
635 //	SHOW_ARMREG(rvbar_el1);
636 	SHOW_ARMREG(sctlr_el1);
637 	SHOW_ARMREG(spsel);
638 	SHOW_ARMREG(spsr_el1);
639 	SHOW_ARMREG(tcr_el1);
640 	SHOW_ARMREG(tpidr_el0);
641 	SHOW_ARMREG(tpidrro_el0);
642 	SHOW_ARMREG(tpidr_el1);
643 	SHOW_ARMREG(ttbr0_el1);
644 	SHOW_ARMREG(ttbr1_el1);
645 	SHOW_ARMREG(vbar_el1);
646 }
647 
648 /*
649  * hardware breakpoint/watchpoint command
650  */
651 static void
aarch64_set_bcr_bvr(int n,uint64_t bcr,uint64_t bvr)652 aarch64_set_bcr_bvr(int n, uint64_t bcr, uint64_t bvr)
653 {
654 #define DBG_BCR_BVR_SET(regno, bcr, bvr)			\
655 	do {							\
656 		reg_dbgbcr ## regno ## _el1_write(bcr);		\
657 		reg_dbgbvr ## regno ## _el1_write(bvr);		\
658 	} while (0 /* CONSTCOND */)
659 
660 	switch (n) {
661 	case 0:		DBG_BCR_BVR_SET(0,  bcr, bvr);	break;
662 	case 1:		DBG_BCR_BVR_SET(1,  bcr, bvr);	break;
663 	case 2:		DBG_BCR_BVR_SET(2,  bcr, bvr);	break;
664 	case 3:		DBG_BCR_BVR_SET(3,  bcr, bvr);	break;
665 	case 4:		DBG_BCR_BVR_SET(4,  bcr, bvr);	break;
666 	case 5:		DBG_BCR_BVR_SET(5,  bcr, bvr);	break;
667 	case 6:		DBG_BCR_BVR_SET(6,  bcr, bvr);	break;
668 	case 7:		DBG_BCR_BVR_SET(7,  bcr, bvr);	break;
669 	case 8:		DBG_BCR_BVR_SET(8,  bcr, bvr);	break;
670 	case 9:		DBG_BCR_BVR_SET(9,  bcr, bvr);	break;
671 	case 10:	DBG_BCR_BVR_SET(10, bcr, bvr);	break;
672 	case 11:	DBG_BCR_BVR_SET(11, bcr, bvr);	break;
673 	case 12:	DBG_BCR_BVR_SET(12, bcr, bvr);	break;
674 	case 13:	DBG_BCR_BVR_SET(13, bcr, bvr);	break;
675 	case 14:	DBG_BCR_BVR_SET(14, bcr, bvr);	break;
676 	case 15:	DBG_BCR_BVR_SET(15, bcr, bvr);	break;
677 	}
678 }
679 
680 static void
aarch64_set_wcr_wvr(int n,uint64_t wcr,uint64_t wvr)681 aarch64_set_wcr_wvr(int n, uint64_t wcr, uint64_t wvr)
682 {
683 #define DBG_WCR_WVR_SET(regno, wcr, wvr)			\
684 	do {							\
685 		reg_dbgwcr ## regno ## _el1_write(wcr);		\
686 		reg_dbgwvr ## regno ## _el1_write(wvr);		\
687 	} while (0 /* CONSTCOND */)
688 
689 	switch (n) {
690 	case 0:		DBG_WCR_WVR_SET(0,  wcr, wvr);	break;
691 	case 1:		DBG_WCR_WVR_SET(1,  wcr, wvr);	break;
692 	case 2:		DBG_WCR_WVR_SET(2,  wcr, wvr);	break;
693 	case 3:		DBG_WCR_WVR_SET(3,  wcr, wvr);	break;
694 	case 4:		DBG_WCR_WVR_SET(4,  wcr, wvr);	break;
695 	case 5:		DBG_WCR_WVR_SET(5,  wcr, wvr);	break;
696 	case 6:		DBG_WCR_WVR_SET(6,  wcr, wvr);	break;
697 	case 7:		DBG_WCR_WVR_SET(7,  wcr, wvr);	break;
698 	case 8:		DBG_WCR_WVR_SET(8,  wcr, wvr);	break;
699 	case 9:		DBG_WCR_WVR_SET(9,  wcr, wvr);	break;
700 	case 10:	DBG_WCR_WVR_SET(10, wcr, wvr);	break;
701 	case 11:	DBG_WCR_WVR_SET(11, wcr, wvr);	break;
702 	case 12:	DBG_WCR_WVR_SET(12, wcr, wvr);	break;
703 	case 13:	DBG_WCR_WVR_SET(13, wcr, wvr);	break;
704 	case 14:	DBG_WCR_WVR_SET(14, wcr, wvr);	break;
705 	case 15:	DBG_WCR_WVR_SET(15, wcr, wvr);	break;
706 	}
707 }
708 
709 void
aarch64_breakpoint_set(int n,vaddr_t addr)710 aarch64_breakpoint_set(int n, vaddr_t addr)
711 {
712 	uint64_t bcr, bvr;
713 
714 	if (addr == 0) {
715 		bvr = 0;
716 		bcr = 0;
717 	} else {
718 		bvr = addr & DBGBVR_MASK;
719 		bcr =
720 		    __SHIFTIN(0, DBGBCR_BT) |
721 		    __SHIFTIN(0, DBGBCR_LBN) |
722 		    __SHIFTIN(0, DBGBCR_SSC) |
723 		    __SHIFTIN(0, DBGBCR_HMC) |
724 		    __SHIFTIN(15, DBGBCR_BAS) |
725 		    __SHIFTIN(3, DBGBCR_PMC) |
726 		    __SHIFTIN(1, DBGBCR_E);
727 	}
728 
729 	aarch64_set_bcr_bvr(n, bcr, bvr);
730 }
731 
732 void
aarch64_watchpoint_set(int n,vaddr_t addr,u_int size,u_int accesstype)733 aarch64_watchpoint_set(int n, vaddr_t addr, u_int size, u_int accesstype)
734 {
735 	uint64_t wvr, wcr;
736 	uint32_t matchbytebit;
737 
738 	KASSERT(size <= 8);
739 	if (size > 8)
740 		size = 8;
741 
742 	/*
743 	 * It is always watched in 8byte units, and
744 	 * BAS is a bit field of byte offset in 8byte units.
745 	 */
746 	matchbytebit = 0xff >> (8 - size);
747 	matchbytebit <<= (addr & 7);
748 	addr &= ~7UL;
749 
750 	/* load, store, or both */
751 	accesstype &= WATCHPOINT_ACCESS_MASK;
752 	if (accesstype == 0)
753 		accesstype = WATCHPOINT_ACCESS_LOADSTORE;
754 
755 	if (addr == 0) {
756 		wvr = 0;
757 		wcr = 0;
758 	} else {
759 		wvr = addr;
760 		wcr =
761 		    __SHIFTIN(0, DBGWCR_MASK) |		/* MASK: no mask */
762 		    __SHIFTIN(0, DBGWCR_WT) |		/* WT: 0 */
763 		    __SHIFTIN(0, DBGWCR_LBN) |		/* LBN: 0 */
764 		    __SHIFTIN(0, DBGWCR_SSC) |		/* SSC: 00 */
765 		    __SHIFTIN(0, DBGWCR_HMC) |		/* HMC: 0 */
766 		    __SHIFTIN(matchbytebit, DBGWCR_BAS) | /* BAS: 0-8byte */
767 		    __SHIFTIN(accesstype, DBGWCR_LSC) |	/* LSC: Load/Store */
768 		    __SHIFTIN(3, DBGWCR_PAC) |		/* PAC: 11 */
769 		    __SHIFTIN(1, DBGWCR_E);		/* Enable */
770 	}
771 
772 	aarch64_set_wcr_wvr(n, wcr, wvr);
773 }
774 
775 static int
db_md_breakpoint_set(int n,vaddr_t addr)776 db_md_breakpoint_set(int n, vaddr_t addr)
777 {
778 	if (n >= __arraycount(breakpoint_buf))
779 		return -1;
780 
781 	if ((addr & 3) != 0) {
782 		db_printf("address must be 4bytes aligned\n");
783 		return -1;
784 	}
785 
786 	breakpoint_buf[n].addr = addr;
787 	return 0;
788 }
789 
790 static int
db_md_watchpoint_set(int n,vaddr_t addr,u_int size,u_int accesstype)791 db_md_watchpoint_set(int n, vaddr_t addr, u_int size, u_int accesstype)
792 {
793 	if (n >= __arraycount(watchpoint_buf))
794 		return -1;
795 
796 	if (size != 0 && ((addr) & ~7UL) != ((addr + size - 1) & ~7UL)) {
797 		db_printf(
798 		    "address and size must fit within a block of 8bytes\n");
799 		return -1;
800 	}
801 
802 	watchpoint_buf[n].addr = addr;
803 	watchpoint_buf[n].size = size;
804 	watchpoint_buf[n].accesstype = accesstype;
805 	return 0;
806 }
807 
808 static void
db_md_breakwatchpoints_clear(void)809 db_md_breakwatchpoints_clear(void)
810 {
811 	int i;
812 
813 	for (i = 0; i <= max_breakpoint; i++)
814 		aarch64_breakpoint_set(i, 0);
815 	for (i = 0; i <= max_watchpoint; i++)
816 		aarch64_watchpoint_set(i, 0, 0, 0);
817 }
818 
819 static void
db_md_breakwatchpoints_reload(void)820 db_md_breakwatchpoints_reload(void)
821 {
822 	int i;
823 
824 	for (i = 0; i <= max_breakpoint; i++) {
825 		aarch64_breakpoint_set(i,
826 		    breakpoint_buf[i].addr);
827 	}
828 	for (i = 0; i <= max_watchpoint; i++) {
829 		aarch64_watchpoint_set(i,
830 		    watchpoint_buf[i].addr,
831 		    watchpoint_buf[i].size,
832 		    watchpoint_buf[i].accesstype);
833 	}
834 }
835 
836 void
db_machdep_cpu_init(void)837 db_machdep_cpu_init(void)
838 {
839 	uint64_t dfr, mdscr;
840 	int i, cpu_max_breakpoint, cpu_max_watchpoint;
841 
842 	dfr = reg_id_aa64dfr0_el1_read();
843 	cpu_max_breakpoint = __SHIFTOUT(dfr, ID_AA64DFR0_EL1_BRPS);
844 	cpu_max_watchpoint = __SHIFTOUT(dfr, ID_AA64DFR0_EL1_WRPS);
845 
846 	for (i = 0; i <= cpu_max_breakpoint; i++) {
847 		/* clear all breakpoints */
848 		aarch64_breakpoint_set(i, 0);
849 	}
850 	for (i = 0; i <= cpu_max_watchpoint; i++) {
851 		/* clear all watchpoints */
852 		aarch64_watchpoint_set(i, 0, 0, 0);
853 	}
854 
855 	/* enable watchpoint and breakpoint */
856 	mdscr = reg_mdscr_el1_read();
857 	mdscr |= MDSCR_MDE | MDSCR_KDE;
858 	reg_mdscr_el1_write(mdscr);
859 	reg_oslar_el1_write(0);
860 }
861 
862 void
db_machdep_init(struct cpu_info * const ci)863 db_machdep_init(struct cpu_info * const ci)
864 {
865 	struct aarch64_sysctl_cpu_id * const id = &ci->ci_id;
866 	const uint64_t dfr = id->ac_aa64dfr0;
867 	const u_int cpu_max_breakpoint = __SHIFTOUT(dfr, ID_AA64DFR0_EL1_BRPS);
868 	const u_int cpu_max_watchpoint = __SHIFTOUT(dfr, ID_AA64DFR0_EL1_WRPS);
869 
870 	/*
871 	 * num of {watch,break}point may be different depending on the
872 	 * core.
873 	 */
874 	if (max_breakpoint > cpu_max_breakpoint)
875 		max_breakpoint = cpu_max_breakpoint;
876 	if (max_watchpoint > cpu_max_watchpoint)
877 		max_watchpoint = cpu_max_watchpoint;
878 }
879 
880 
881 static void
show_breakpoints(void)882 show_breakpoints(void)
883 {
884 	uint64_t addr;
885 	unsigned int i, nused;
886 
887 	for (nused = 0, i = 0; i <= max_breakpoint; i++) {
888 		addr = breakpoint_buf[i].addr;
889 		if (addr == 0) {
890 			db_printf("%d: disabled\n", i);
891 		} else {
892 			db_printf("%d: breakpoint %016" PRIx64 " (", i,
893 			    addr);
894 			db_printsym(addr, DB_STGY_ANY, db_printf);
895 			db_printf(")\n");
896 			nused++;
897 		}
898 	}
899 	db_printf("breakpoint used %d/%d\n", nused, max_breakpoint + 1);
900 }
901 
902 static void
show_watchpoints(void)903 show_watchpoints(void)
904 {
905 	uint64_t addr;
906 	unsigned int i, nused;
907 
908 	for (nused = 0, i = 0; i <= max_watchpoint; i++) {
909 		addr = watchpoint_buf[i].addr;
910 		if (addr == 0) {
911 			db_printf("%d: disabled\n", i);
912 		} else {
913 			db_printf("%d: watching %016" PRIx64 " (", i,
914 			    addr);
915 			db_printsym(addr, DB_STGY_ANY, db_printf);
916 			db_printf("), %d bytes", watchpoint_buf[i].size);
917 
918 			switch (watchpoint_buf[i].accesstype) {
919 			case WATCHPOINT_ACCESS_LOAD:
920 				db_printf(", load");
921 				break;
922 			case WATCHPOINT_ACCESS_STORE:
923 				db_printf(", store");
924 				break;
925 			case WATCHPOINT_ACCESS_LOADSTORE:
926 				db_printf(", load/store");
927 				break;
928 			}
929 			db_printf("\n");
930 			nused++;
931 		}
932 	}
933 	db_printf("watchpoint used %d/%d\n", nused, max_watchpoint + 1);
934 }
935 
936 void
db_md_break_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)937 db_md_break_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
938     const char *modif)
939 {
940 	int i, rc;
941 	int added, cleared;
942 
943 	if (!have_addr) {
944 		show_breakpoints();
945 		return;
946 	}
947 
948 	added = -1;
949 	cleared = -1;
950 	if (0 <= addr && addr <= max_breakpoint) {
951 		i = addr;
952 		if (breakpoint_buf[i].addr != 0) {
953 			db_md_breakpoint_set(i, 0);
954 			cleared = i;
955 		}
956 	} else {
957 		for (i = 0; i <= max_breakpoint; i++) {
958 			if (breakpoint_buf[i].addr == addr) {
959 				db_md_breakpoint_set(i, 0);
960 				cleared = i;
961 			}
962 		}
963 		if (cleared == -1) {
964 			for (i = 0; i <= max_breakpoint; i++) {
965 				if (breakpoint_buf[i].addr == 0) {
966 					rc = db_md_breakpoint_set(i, addr);
967 					if (rc != 0)
968 						return;
969 					added = i;
970 					break;
971 				}
972 			}
973 			if (i > max_breakpoint) {
974 				db_printf("no more available breakpoint\n");
975 			}
976 		}
977 	}
978 
979 	if (added >= 0)
980 		db_printf("add breakpoint %d as %016"DDB_EXPR_FMT"x\n",
981 		    added, addr);
982 	if (cleared >= 0)
983 		db_printf("clear breakpoint %d\n", cleared);
984 
985 	show_breakpoints();
986 }
987 
988 void
db_md_watch_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)989 db_md_watch_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
990     const char *modif)
991 {
992 	int i, rc;
993 	int added, cleared;
994 	u_int accesstype, watchsize;
995 
996 	if (!have_addr) {
997 		show_watchpoints();
998 		return;
999 	}
1000 
1001 	accesstype = watchsize = 0;
1002 	if ((modif != NULL) && (*modif != '\0')) {
1003 		int ch;
1004 		for (; *modif != '\0'; modif++) {
1005 			ch = *modif;
1006 
1007 			switch (ch) {
1008 			case 'b':
1009 				watchsize = 1;
1010 				break;
1011 			case 'h':
1012 				watchsize = 2;
1013 				break;
1014 			case 'l':
1015 				watchsize = 4;
1016 				break;
1017 			case 'q':
1018 				watchsize = 8;
1019 				break;
1020 			case 'r':
1021 				accesstype |= WATCHPOINT_ACCESS_LOAD;
1022 				break;
1023 			case 'w':
1024 				accesstype |= WATCHPOINT_ACCESS_STORE;
1025 				break;
1026 			}
1027 		}
1028 	}
1029 	if (watchsize == 0)
1030 		watchsize = 4;	/* default: 4byte */
1031 	if (accesstype == 0)
1032 		accesstype = WATCHPOINT_ACCESS_LOADSTORE; /* default */
1033 
1034 	added = -1;
1035 	cleared = -1;
1036 	if (0 <= addr && addr <= max_watchpoint) {
1037 		i = addr;
1038 		if (watchpoint_buf[i].addr != 0) {
1039 			db_md_watchpoint_set(i, 0, 0, 0);
1040 			cleared = i;
1041 		}
1042 	} else {
1043 		for (i = 0; i <= max_watchpoint; i++) {
1044 			if (watchpoint_buf[i].addr == addr) {
1045 				db_md_watchpoint_set(i, 0, 0, 0);
1046 				cleared = i;
1047 			}
1048 		}
1049 		if (cleared == -1) {
1050 			for (i = 0; i <= max_watchpoint; i++) {
1051 				if (watchpoint_buf[i].addr == 0) {
1052 					rc = db_md_watchpoint_set(i, addr,
1053 					    watchsize, accesstype);
1054 					if (rc != 0)
1055 						return;
1056 					added = i;
1057 					break;
1058 				}
1059 			}
1060 			if (i > max_watchpoint) {
1061 				db_printf("no more available watchpoint\n");
1062 			}
1063 		}
1064 	}
1065 
1066 	if (added >= 0)
1067 		db_printf("add watchpoint %d as %016"DDB_EXPR_FMT"x\n",
1068 		    added, addr);
1069 	if (cleared >= 0)
1070 		db_printf("clear watchpoint %d\n", cleared);
1071 
1072 	show_watchpoints();
1073 }
1074 #endif
1075 
1076 #ifdef MULTIPROCESSOR
1077 volatile struct cpu_info *db_trigger;
1078 volatile struct cpu_info *db_onproc;
1079 volatile struct cpu_info *db_newcpu;
1080 volatile struct trapframe *db_readytoswitch[MAXCPUS];
1081 
1082 #ifdef _KERNEL
1083 void
db_md_switch_cpu_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)1084 db_md_switch_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
1085     const char *modif)
1086 {
1087 	struct cpu_info *new_ci = NULL;
1088 	u_int cpuno = (u_int)addr;
1089 	int i;
1090 
1091 	membar_consumer();
1092 	if (!have_addr) {
1093 		for (i = 0; i < ncpu; i++) {
1094 			if (db_readytoswitch[i] != NULL) {
1095 				db_printf("cpu%d: ready. tf=%p, pc=%016lx ", i,
1096 				    db_readytoswitch[i],
1097 				    db_readytoswitch[i]->tf_pc);
1098 				db_printsym(db_readytoswitch[i]->tf_pc,
1099 				    DB_STGY_ANY, db_printf);
1100 				db_printf("\n");
1101 			} else {
1102 				db_printf("cpu%d: not responding\n", i);
1103 			}
1104 		}
1105 		return;
1106 	}
1107 
1108 	if (cpuno < ncpu)
1109 		new_ci = cpu_lookup(cpuno);
1110 	if (new_ci == NULL) {
1111 		db_printf("cpu %u does not exist", cpuno);
1112 		return;
1113 	}
1114 	if (db_readytoswitch[new_ci->ci_index] == 0) {
1115 		db_printf("cpu %u is not responding", cpuno);
1116 		return;
1117 	}
1118 
1119 	if (new_ci == curcpu())
1120 		return;
1121 
1122 	db_newcpu = new_ci;
1123 	db_continue_cmd(0, false, 0, "");
1124 }
1125 
1126 #endif /* _KERNEL */
1127 #endif /* MULTIPROCESSOR */
1128 
1129 #ifdef DDB
1130 int
kdb_trap(int type,struct trapframe * tf)1131 kdb_trap(int type, struct trapframe *tf)
1132 {
1133 #ifdef MULTIPROCESSOR
1134 	struct cpu_info * const ci = curcpu();
1135 	bool static_brk = false;
1136 #endif
1137 	int s;
1138 	bool restore_hw_watchpoints = true;
1139 
1140 	switch (type) {
1141 	case DB_TRAP_WATCHPOINT:
1142 	case DB_TRAP_BREAKPOINT:
1143 		/*
1144 		 * In the case of a hardware watchpoint or breakpoint,
1145 		 * even if cpu return from ddb as is, it will be trapped again,
1146 		 * so clear it all once.
1147 		 *
1148 		 * breakpoint and watchpoint will be restored at the end of
1149 		 * next DB_TRAP_BKPT_INSN (ddb's STEP_INVISIBLE mode).
1150 		 */
1151 		db_md_breakwatchpoints_clear();
1152 		restore_hw_watchpoints = false;
1153 		break;
1154 	case DB_TRAP_BKPT_INSN:
1155 #ifdef MULTIPROCESSOR
1156 		/* brk #0xffff in cpu_Debugger() ? */
1157 		if (__SHIFTOUT(tf->tf_esr, ESR_ISS) == 0xffff)
1158 			static_brk = true;
1159 		/* FALLTHRU */
1160 #endif
1161 	case DB_TRAP_SW_STEP:
1162 	case DB_TRAP_UNKNOWN:
1163 	case -1:	/* from pic_ipi_ddb() */
1164 		break;
1165 	default:
1166 		if (db_recover != 0) {
1167 			db_error("Faulted in DDB: continuing...\n");
1168 			/* NOTREACHED */
1169 		}
1170 		break;
1171 	}
1172 
1173 #ifdef MULTIPROCESSOR
1174 	if (ncpu > 1) {
1175 		/*
1176 		 * Try to take ownership of DDB.
1177 		 * If we do, tell all other CPUs to enter DDB too.
1178 		 */
1179 		if (atomic_cas_ptr(&db_onproc, NULL, ci) == NULL) {
1180 			intr_ipi_send(NULL, IPI_DDB);
1181 			db_trigger = ci;
1182 		} else {
1183 			/*
1184 			 * If multiple CPUs catch kdb_trap() that is not IPI_DDB
1185 			 * derived at the same time, only the CPU that was able
1186 			 * to get db_onproc first will execute db_trap.
1187 			 * The CPU that could not get db_onproc will be set to
1188 			 * type = -1 once, and kdb_trap will be called again
1189 			 * with the correct type after kdb_trap returns.
1190 			 */
1191 			type = -1;
1192 			restore_hw_watchpoints = true;
1193 		}
1194 	}
1195 	db_readytoswitch[ci->ci_index] = tf;
1196 #endif
1197 
1198 	for (;;) {
1199 #ifdef MULTIPROCESSOR
1200 		if (ncpu > 1) {
1201 			/* waiting my turn, or exit */
1202 			dsb(ishld);
1203 			while (db_onproc != ci) {
1204 				__asm __volatile ("wfe");
1205 
1206 				dsb(ishld);
1207 				if (db_onproc == NULL)
1208 					goto kdb_trap_done;
1209 			}
1210 			/* It's my turn! */
1211 		}
1212 #endif /* MULTIPROCESSOR */
1213 
1214 		/* Should switch to kdb`s own stack here. */
1215 		ddb_regs = *tf;
1216 
1217 		s = splhigh();
1218 		db_active++;
1219 		cnpollc(true);
1220 		db_trap(type, 0/*code*/);
1221 		cnpollc(false);
1222 		db_active--;
1223 		splx(s);
1224 
1225 		*tf = ddb_regs;
1226 
1227 #ifdef MULTIPROCESSOR
1228 		if (ncpu < 2)
1229 			break;
1230 
1231 		if (db_newcpu == NULL && db_onproc != db_trigger) {
1232 			/*
1233 			 * If the "machine cpu" switches CPUs after entering
1234 			 * ddb from a breakpoint or watchpoint, it will return
1235 			 * control to the CPU that triggered the ddb in the
1236 			 * first place in order to correctly reset the
1237 			 * breakpoint or watchpoint.
1238 			 * If db_trap() returns further from here,
1239 			 * watchpoints and breakpoints will be reset.
1240 			 * (db_run_mode = STEP_INVISIBLE)
1241 			 */
1242 			db_newcpu = db_trigger;
1243 		}
1244 
1245 		if (db_newcpu != NULL) {
1246 			/* XXX: override sys/ddb/db_run.c:db_run_mode */
1247 			db_continue_cmd(0, false, 0, "");
1248 
1249 			/*
1250 			 * When static BRK instruction (cpu_Debugger()),
1251 			 * db_trap() advance the $PC to the next instruction of
1252 			 * BRK. If db_trap() will be called twice by
1253 			 * "machine cpu" command, the $PC will be advanced to
1254 			 * the after the next instruction.
1255 			 * To avoid this, change 'type' so that the second call
1256 			 * to db_trap() will not change the PC.
1257 			 */
1258 			if (static_brk)
1259 				type = -1;
1260 
1261 			db_onproc = db_newcpu;
1262 			db_newcpu = NULL;
1263 			dsb(ishst);
1264 			/* waking up the CPU waiting for its turn to db_trap */
1265 			sev();
1266 
1267 			continue;	/* go to waiting my turn */
1268 		}
1269 #endif /* MULTIPROCESSOR */
1270 
1271 		break;
1272 	}
1273 
1274 #ifdef MULTIPROCESSOR
1275 	if (ncpu > 1 && db_onproc == ci) {
1276 		db_onproc = NULL;
1277 		dsb(ishst);
1278 		/* waking up the CPU waiting for its turn to exit */
1279 		sev();
1280 
1281 		db_readytoswitch[cpu_index(ci)] = NULL;
1282 		/* wait for all other CPUs are ready to exit */
1283 		for (;;) {
1284 			int i;
1285 			dsb(ishld);
1286 			for (i = 0; i < ncpu; i++) {
1287 				if (db_readytoswitch[i] != NULL)
1288 					break;
1289 			}
1290 			if (i == ncpu)
1291 				break;
1292 		}
1293 		db_trigger = NULL;
1294 		sev();
1295 	} else {
1296  kdb_trap_done:
1297 		db_readytoswitch[cpu_index(ci)] = NULL;
1298 		dsb(ishst);
1299 		__asm __volatile ("wfe");
1300 	}
1301 #endif
1302 	if (restore_hw_watchpoints)
1303 		db_md_breakwatchpoints_reload();
1304 
1305 	return 1;
1306 }
1307 #endif
1308 
1309 #if defined(_KERNEL)
1310 static void
db_md_meminfo_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)1311 db_md_meminfo_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
1312     const char *modif)
1313 {
1314 	unsigned blk;
1315 
1316 	for (blk = 0; blk < bootconfig.dramblocks; blk++) {
1317 		db_printf("blk[%u]: start %lx end %lx (pages %x)\n",
1318 		    blk, bootconfig.dram[blk].address,
1319 		    bootconfig.dram[blk].address +
1320 		    (uint64_t)bootconfig.dram[blk].pages * PAGE_SIZE,
1321 		    bootconfig.dram[blk].pages);
1322 	}
1323 }
1324 #endif
1325