xref: /netbsd-src/sys/arch/mips/mips/db_interface.c (revision 69a26680a4246db70b60c1fd1a1279db964790d0)
1 /*	$NetBSD: db_interface.c,v 1.99 2023/02/19 11:19:51 simonb Exp $	*/
2 
3 /*
4  * Mach Operating System
5  * Copyright (c) 1991,1990 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.99 2023/02/19 11:19:51 simonb Exp $");
31 
32 #ifdef _KERNEL_OPT
33 #include "opt_multiprocessor.h"
34 #include "opt_cputype.h"	/* which mips CPUs do we support? */
35 #include "opt_ddb.h"
36 #include "opt_kgdb.h"
37 #endif
38 
39 #define __PMAP_PRIVATE
40 
41 #include <sys/types.h>
42 #include <sys/systm.h>
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/reboot.h>
46 #include <sys/atomic.h>
47 #include <sys/cpu.h>
48 
49 #include <uvm/uvm_extern.h>
50 
51 #include <mips/regnum.h>
52 #include <mips/cache.h>
53 #include <mips/pcb.h>
54 #include <mips/pte.h>
55 #include <mips/locore.h>
56 #include <mips/mips_opcode.h>
57 #include <dev/cons.h>
58 
59 #include <machine/int_fmtio.h>
60 #include <machine/db_machdep.h>
61 #include <ddb/db_access.h>
62 #include <ddb/db_active.h>
63 #include <ddb/db_user.h>
64 #ifndef KGDB
65 #include <ddb/db_command.h>
66 #include <ddb/db_output.h>
67 #include <ddb/db_sym.h>
68 #include <ddb/db_extern.h>
69 #include <ddb/db_interface.h>
70 #include <ddb/db_lex.h>
71 #include <ddb/db_run.h>	/* for db_continue_cmd() proto */
72 #endif
73 
74 #define NOCPU   ~0
75 volatile u_int ddb_cpu = NOCPU;
76 
77 int		db_active = 0;
78 #ifdef _KERNEL
79 db_regs_t	ddb_regs;
80 #endif
81 
82 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
83 static void db_watch_cmd(db_expr_t, bool, db_expr_t, const char *);
84 static void db_unwatch_cmd(db_expr_t, bool, db_expr_t, const char *);
85 #endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
86 
87 #ifdef MULTIPROCESSOR
88 static void db_mach_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
89 #endif
90 
91 void db_cp0dump_cmd(db_expr_t, bool, db_expr_t, const char *);
92 void db_cpuinfo_cmd(db_expr_t, bool, db_expr_t, const char *);
93 void db_kvtophys_cmd(db_expr_t, bool, db_expr_t, const char *);
94 void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *);
95 
96 #ifdef MIPS64_XLS
97 void db_mfcr_cmd(db_expr_t, bool, db_expr_t, const char *);
98 void db_mtcr_cmd(db_expr_t, bool, db_expr_t, const char *);
99 #endif
100 
101 paddr_t kvtophys(vaddr_t);
102 
103 #ifdef _KERNEL
104 CTASSERT(sizeof(ddb_regs) == sizeof(struct reg));
105 
106 #ifndef KGDB
107 int
kdb_trap(int type,struct reg * regs)108 kdb_trap(int type, struct reg *regs)
109 {
110 	int s;
111 
112 	switch (type) {
113 	case T_WATCH:		/* watchpoint */
114 	case T_BREAK:		/* breakpoint */
115 		printf("kernel: %s trap\n", trap_names[type & 0x1f]);
116 		break;
117 	case -1:		/* keyboard interrupt */
118 		printf("kernel: kdbint trap\n");
119 		break;
120 	default:
121 		printf("kernel: %s trap\n", trap_names[type & 0x1f]);
122 		if (db_recover != 0) {
123 			db_error("Faulted in DDB; continuing...\n");
124 			/*NOTREACHED*/
125 		}
126 		break;
127 	}
128 
129 	s = splhigh();
130 
131 #if defined(MULTIPROCESSOR)
132 	bool first_in_ddb = false;
133 	const u_int cpu_me = cpu_number();
134 	const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me);
135 	if (old_ddb_cpu == NOCPU) {
136 		first_in_ddb = true;
137 		cpu_pause_others();
138 	} else {
139 		if (old_ddb_cpu != cpu_me) {
140 			KASSERT(cpu_is_paused(cpu_me));
141 			cpu_pause(regs);
142 			splx(s);
143 			return 1;
144 		}
145 	}
146 	KASSERT(! cpu_is_paused(cpu_me));
147 #endif
148 
149 	ddb_regs = *regs;
150 	db_active++;
151 	cnpollc(1);
152 	db_trap(type & ~T_USER, 0 /*code*/);
153 	cnpollc(0);
154 	db_active--;
155 	*regs = ddb_regs;
156 
157 #if defined(MULTIPROCESSOR)
158 	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
159 		cpu_resume_others();
160 	} else {
161 		cpu_resume(ddb_cpu);
162 		if (first_in_ddb)
163 			cpu_pause(regs);
164 	}
165 #endif
166 
167 	splx(s);
168 	return 1;
169 }
170 
171 void
cpu_Debugger(void)172 cpu_Debugger(void)
173 {
174 
175 	__asm("break");
176 }
177 #endif	/* !KGDB */
178 
179 /*
180  * Read bytes from kernel address space for debugger.
181  */
182 void
db_read_bytes(vaddr_t addr,size_t size,char * data)183 db_read_bytes(vaddr_t addr, size_t size, char *data)
184 {
185 	const char *src = (char *)addr;
186 	int err;
187 
188 	/* If asked to fetch from userspace, do it safely */
189 	if (addr < VM_MAXUSER_ADDRESS) {
190 		err = copyin(src, data, size);
191 		if (err) {
192 #ifdef DDB
193 			db_printf("address %p is invalid\n", src);
194 #endif
195 			memset(data, 0, size);
196 		}
197 		return;
198 	}
199 
200 	if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0
201 	    && ((uintptr_t)data & (size-1)) == 0) {
202 		if (size == sizeof(uint8_t))
203 			*(uint8_t *)data = *(const uint8_t *)src;
204 		else if (size == sizeof(uint16_t))
205 			*(uint16_t *)data = *(const uint16_t *)src;
206 		else if (size == sizeof(uint32_t))
207 			*(uint32_t *)data = *(const uint32_t *)src;
208 		else
209 			*(uint64_t *)data = *(const uint64_t *)src;
210 		return;
211 	}
212 	while (size--)
213 		*data++ = *src++;
214 }
215 
216 /*
217  * Write bytes to kernel address space for debugger.
218  */
219 void
db_write_bytes(vaddr_t addr,size_t size,const char * data)220 db_write_bytes(vaddr_t addr, size_t size, const char *data)
221 {
222 	char *p = (char *)addr;
223 	size_t n = size;
224 	int err;
225 
226 	/* If asked to store to userspace, do it safely */
227 	if (addr < VM_MAXUSER_ADDRESS) {
228 		err = copyout(data, p, size);
229 		if (err) {
230 #ifdef DDB
231 			db_printf("address %p is invalid\n", p);
232 #endif
233 		}
234 		return;
235 	}
236 
237 	if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0
238 	    && ((uintptr_t)data & (size-1)) == 0) {
239 		if (size == sizeof(uint8_t))
240 			*(uint8_t *)p = *(const uint8_t *)data;
241 		else if (size == sizeof(uint16_t))
242 			*(uint16_t *)p = *(const uint16_t *)data;
243 		else if (size == sizeof(uint32_t))
244 			*(uint32_t *)p = *(const uint32_t *)data;
245 		else
246 			*(uint64_t *)p = *(const uint64_t *)data;
247 		return;
248 	}
249 	while (n--)
250 		*p++ = *data++;
251 
252 	wbflush();
253 	mips_icache_sync_range(addr, size);
254 }
255 
256 #ifndef KGDB
257 void
db_tlbdump_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)258 db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
259 	       const char *modif)
260 {
261 	struct tlbmask tlb;
262 	bool valid_only = false;
263 
264 	if (modif[0] == 'v')
265 		valid_only = true;
266 
267 #ifdef MIPS1
268 	if (!MIPS_HAS_R4K_MMU) {
269 		int i;
270 
271 		for (i = 0; i < mips_options.mips_num_tlb_entries; i++) {
272 			tlb_read_entry(i, &tlb);
273 			if (valid_only && !(tlb.tlb_lo1 & MIPS1_PG_V))
274 				continue;	/* skip invalid TLBs */
275 			db_printf("TLB%c%2d Hi 0x%08x Lo 0x%08x",
276 				(tlb.tlb_lo1 & MIPS1_PG_V) ? ' ' : '*',
277 				i, tlb.tlb_hi,
278 				tlb.tlb_lo1 & MIPS1_PG_FRAME);
279 			db_printf(" %c%c%c\n",
280 				(tlb.tlb_lo1 & MIPS1_PG_D) ? 'D' : ' ',
281 				(tlb.tlb_lo1 & MIPS1_PG_G) ? 'G' : ' ',
282 				(tlb.tlb_lo1 & MIPS1_PG_N) ? 'N' : ' ');
283 		}
284 	}
285 #endif
286 #ifdef MIPS3_PLUS
287 	if (MIPS_HAS_R4K_MMU) {
288 		int i;
289 		const int tlb_count_width =
290 		    mips_options.mips_num_tlb_entries > 100 ? 3 : 2;
291 
292 		for (i = 0; i < mips_options.mips_num_tlb_entries; i++) {
293 			tlb_read_entry(i, &tlb);
294 			if (valid_only &&
295 			    !((tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V))
296 				continue;	/* skip invalid TLBs */
297 
298 			db_printf("TLB%c%*d Hi 0x%08"PRIxVADDR" ",
299 			    (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
300 			    tlb_count_width, i, tlb.tlb_hi);
301 			db_printf("Lo0=0x%09" PRIx64 " %c%c attr %x ",
302 				(uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo0),
303 				(tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
304 				(tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
305 				(int)(tlb.tlb_lo0 >> 3) & 7);
306 			db_printf("Lo1=0x%09" PRIx64 " %c%c attr %x sz=%x\n",
307 				(uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo1),
308 				(tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
309 				(tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
310 				(int)(tlb.tlb_lo1 >> 3) & 7,
311 				tlb.tlb_mask);
312 		}
313 	}
314 #endif
315 }
316 
317 void
db_kvtophys_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)318 db_kvtophys_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
319 		const char *modif)
320 {
321 
322 	if (!have_addr)
323 		return;
324 	if (VM_MIN_KERNEL_ADDRESS <= addr && addr < VM_MAX_KERNEL_ADDRESS) {
325 		/*
326 		 * Cast the physical address -- some platforms, while
327 		 * being ILP32, may be using 64-bit paddr_t's.
328 		 */
329 		db_printf("0x%" DDB_EXPR_FMT "x -> 0x%" PRIx64 "\n", addr,
330 		    (uint64_t) kvtophys(addr));
331 	} else
332 		db_printf("not a kernel virtual address\n");
333 }
334 
335 #define	FLDWIDTH	10
336 
337 #define SHOW32(reg, name)	SHOW32SELECT(reg, 0, name)
338 #define SHOW64(reg, name)	SHOW64SELECT(reg, 0, name)
339 #define SHOW32SEL(reg, name)	SHOW32SELECT(reg, name)
340 #define SHOW64SEL(reg, name)	SHOW64SELECT(reg, name)
341 
342 #define	SHOW32SELECT(num, sel, name)					\
343 do {									\
344 	uint32_t __val;							\
345 									\
346 	__asm volatile(							\
347 		".set push			\n\t"			\
348 		".set mips32			\n\t"			\
349 		"mfc0 %0,$%1,%2			\n\t"			\
350 		".set pop			\n\t"			\
351 	    : "=r"(__val) : "n"(num), "n"(sel));			\
352 	db_printf("  %s:%*s %#x\n", name,				\
353 	    FLDWIDTH - (int) strlen(name), "", __val);			\
354 } while (0)
355 
356 /* XXX not 64-bit ABI safe! */
357 #define	SHOW64SELECT(num, sel, name)					\
358 do {									\
359 	uint64_t __val;							\
360 									\
361 	KASSERT (CPUIS64BITS);						\
362 	__asm volatile(							\
363 		".set push 			\n\t"			\
364 		".set mips64			\n\t"			\
365 		".set noat			\n\t"			\
366 		"dmfc0 %0,$%1,%2		\n\t"			\
367 		".set pop"						\
368 	    : "=r"(__val) : "n"(num), "n"(sel));			\
369 	db_printf("  %s:%*s %#"PRIx64"\n", name,			\
370 	    FLDWIDTH - (int) strlen(name), "", __val);			\
371 } while (0)
372 
373 #define	SET32(reg, name, val)						\
374 do {									\
375 									\
376 	__asm volatile("mtc0 %0,$" ___STRING(reg) :: "r"(val));		\
377 	if (name != NULL)						\
378 		db_printf("  %s =%*s %#x\n", name,			\
379 		    FLDWIDTH - (int) strlen(name), "", val);		\
380 } while (0)
381 
382 #define SET64(reg, name)	MIPS64_SET64(reg, 0, name)
383 
384 #define	MIPS64_SET32(num, sel, name, val)				\
385 do {									\
386 									\
387 	__asm volatile(							\
388 		".set push			\n\t"			\
389 		".set mips32			\n\t"			\
390 		"mtc0 %0,$%1,%2			\n\t"			\
391 		".set pop			\n\t"			\
392 	    :: "r"(val), "n"(num), "n"(sel));				\
393 	if (name != NULL)						\
394 		db_printf("  %s =%*s %#x\n", name,			\
395 		    FLDWIDTH - (int) strlen(name), "", val);		\
396 } while (0)
397 
398 /* XXX not 64-bit ABI safe! */
399 #define	MIPS64_SET64(num, sel, name, val)				\
400 do {									\
401 									\
402 	KASSERT (CPUIS64BITS);						\
403 	__asm volatile(							\
404 		".set push 			\n\t"			\
405 		".set mips64			\n\t"			\
406 		".set noat			\n\t"			\
407 		"dmtc0 %0,$%1,%2		\n\t"			\
408 		".set pop"						\
409 	    :: "r"(val), "n"(num), "n"(sel));				\
410 	if (name != NULL)						\
411 		db_printf("  %s =%*s %#"PRIx64"\n", name,		\
412 		    FLDWIDTH - (int) strlen(name), "", (uint64_t)val);	\
413 } while (0)
414 
415 void
db_cp0dump_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)416 db_cp0dump_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
417 	       const char *modif)
418 {
419 	u_int cp0flags = mips_options.mips_cpu->cpu_cp0flags;
420 
421 	SHOW32(MIPS_COP_0_TLB_INDEX, "index");
422 	SHOW32(MIPS_COP_0_TLB_RANDOM, "random");
423 
424 	if (!MIPS_HAS_R4K_MMU) {
425 		SHOW32(MIPS_COP_0_TLB_LOW, "entrylow");
426 	} else {
427 		if (CPUIS64BITS) {
428 			SHOW64(MIPS_COP_0_TLB_LO0, "entrylo0");
429 			SHOW64(MIPS_COP_0_TLB_LO1, "entrylo1");
430 		} else {
431 			SHOW32(MIPS_COP_0_TLB_LO0, "entrylo0");
432 			SHOW32(MIPS_COP_0_TLB_LO1, "entrylo1");
433 		}
434 	}
435 
436 	if (CPUIS64BITS) {
437 		SHOW64(MIPS_COP_0_TLB_CONTEXT, "context");
438 	} else {
439 		SHOW32(MIPS_COP_0_TLB_CONTEXT, "context");
440 	}
441 
442 	if (MIPS_HAS_R4K_MMU) {
443 		SHOW32(MIPS_COP_0_TLB_PG_MASK, "pagemask");
444 		SHOW32(MIPS_COP_0_TLB_WIRED, "wired");
445 	}
446 
447 	if (CPUIS64BITS) {
448 		SHOW64(MIPS_COP_0_BAD_VADDR, "badvaddr");
449 	} else {
450 		SHOW32(MIPS_COP_0_BAD_VADDR, "badvaddr");
451 	}
452 
453 	if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) {
454 		SHOW32(MIPS_COP_0_COUNT, "count");
455 	}
456 
457 	if ((cp0flags & MIPS_CP0FL_USE) != 0) {
458 		if ((cp0flags & MIPS_CP0FL_EIRR) != 0)
459 			SHOW64SEL(MIPS_COP_0_EIRR, "eirr");
460 		if ((cp0flags & MIPS_CP0FL_EIMR) != 0)
461 			SHOW64SEL(MIPS_COP_0_EIMR, "eimr");
462 	}
463 
464 	if (CPUIS64BITS) {
465 		SHOW64(MIPS_COP_0_TLB_HI, "entryhi");
466 	} else {
467 		SHOW32(MIPS_COP_0_TLB_HI, "entryhi");
468 	}
469 
470 	if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) {
471 		SHOW32(MIPS_COP_0_COMPARE, "compare");
472 	}
473 
474 	SHOW32(MIPS_COP_0_STATUS, "status");
475 	SHOW32(MIPS_COP_0_CAUSE, "cause");
476 
477 	if (CPUIS64BITS) {
478 		SHOW64(MIPS_COP_0_EXC_PC, "epc");
479 	} else {
480 		SHOW32(MIPS_COP_0_EXC_PC, "epc");
481 	}
482 
483 	SHOW32(MIPS_COP_0_PRID, "prid");
484 
485 	if ((cp0flags & MIPS_CP0FL_USE) != 0) {
486 		if ((cp0flags & MIPS_CP0FL_EBASE) != 0)
487 			SHOW32SEL(MIPS_COP_0_EBASE, "ebase");
488 		if ((cp0flags & MIPS_CP0FL_CONFIG) != 0)
489 			SHOW32(MIPS_COP_0_CONFIG, "config");
490 		if ((cp0flags & MIPS_CP0FL_CONFIG1) != 0)
491 			SHOW32SEL(MIPS_COP_0_CONFIG1, "config1");
492 		if ((cp0flags & MIPS_CP0FL_CONFIG2) != 0)
493 			SHOW32SEL(MIPS_COP_0_CONFIG2, "config2");
494 		if ((cp0flags & MIPS_CP0FL_CONFIG3) != 0)
495 			SHOW32SEL(MIPS_COP_0_CONFIG3, "config3");
496 		if ((cp0flags & MIPS_CP0FL_CONFIG4) != 0)
497 			SHOW32SEL(MIPS_COP_0_CONFIG4, "config4");
498 		if ((cp0flags & MIPS_CP0FL_CONFIG5) != 0)
499 			SHOW32SEL(MIPS_COP_0_CONFIG5, "config5");
500 		if ((cp0flags & MIPS_CP0FL_CONFIG6) != 0)
501 			SHOW32SEL(MIPS_COP_0_CONFIG6, "config6");
502 		if ((cp0flags & MIPS_CP0FL_CONFIG7) != 0)
503 			SHOW32SEL(MIPS_COP_0_CONFIG7, "config7");
504 		if (CPUISMIPSNNR2)
505 			SHOW32(MIPS_COP_0_HWRENA, "hwrena");
506 		if (MIPS_HAS_USERLOCAL)
507 			SHOW32SEL(MIPS_COP_0_USERLOCAL, "userlocal");
508 	} else {
509 		SHOW32(MIPS_COP_0_CONFIG, "config");
510 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
511 		if (CPUISMIPSNN) {
512 			uint32_t val;
513 
514 			val = mipsNN_cp0_config1_read();
515 			db_printf("  config1:    %#x\n", val);
516 		}
517 #endif
518 	}
519 
520 	if (MIPS_HAS_LLSC) {
521 		if (MIPS_HAS_LLADDR) {
522 			if (CPUIS64BITS)
523 				SHOW64(MIPS_COP_0_LLADDR, "lladdr");
524 			else
525 				SHOW32(MIPS_COP_0_LLADDR, "lladdr");
526 		}
527 	}
528 
529 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
530 	for (int i=0; i < curcpu()->ci_cpuwatch_count; i++) {
531 		const intptr_t lo = mipsNN_cp0_watchlo_read(i);
532 		const uint32_t hi = mipsNN_cp0_watchhi_read(i);
533 		db_printf("  %s%d:%*s %#" PRIxPTR "\t",
534 		    "watchlo", i, FLDWIDTH - 8, "", lo);
535 		db_printf("  %s%d:%*s %#" PRIx32 "\n",
536 		    "watchhi", i, FLDWIDTH - 8, "", hi);
537 	}
538 #endif
539 
540 	if (CPUIS64BITS) {
541 		SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext");
542 	}
543 
544 	if (CPUISMIPSNN) {
545 		if (CPUIS64BITS) {
546 			SHOW64(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl");
547 			SHOW64SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt");
548 		} else {
549 			SHOW32(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl");
550 			SHOW32SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt");
551 		}
552 	}
553 
554 	if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
555 	    ((cp0flags & MIPS_CP0FL_ECC) != 0))
556 		SHOW32(MIPS_COP_0_ECC, "ecc");
557 
558 	if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
559 	    ((cp0flags & MIPS_CP0FL_CACHE_ERR) != 0))
560 		SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr");
561 
562 	SHOW32(MIPS_COP_0_TAG_LO, "cachelo");
563 	SHOW32(MIPS_COP_0_TAG_HI, "cachehi");
564 
565 	if (CPUIS64BITS) {
566 		SHOW64(MIPS_COP_0_ERROR_PC, "errorpc");
567 	} else {
568 		SHOW32(MIPS_COP_0_ERROR_PC, "errorpc");
569 	}
570 }
571 
572 
573 static void
show_cpuinfo(struct cpu_info * kci)574 show_cpuinfo(struct cpu_info *kci)
575 {
576 	struct cpu_info cpuinfobuf;
577 	cpuid_t cpuid;
578 	int i;
579 
580 	db_read_bytes((db_addr_t)kci, sizeof(cpuinfobuf), (char *)&cpuinfobuf);
581 
582 	struct cpu_info *ci = &cpuinfobuf;
583 	cpuid = ci->ci_cpuid;
584 	db_printf("cpu_info=%p, cpu_name=%s\n", kci, ci->ci_cpuname);
585 	db_printf("%p cpu[%lu].ci_cpuid         = %lu\n",
586 	    &ci->ci_cpuid, cpuid, ci->ci_cpuid);
587 	db_printf("%p cpu[%lu].ci_curlwp        = %p\n",
588 	    &ci->ci_curlwp, cpuid, ci->ci_curlwp);
589 	for (i = 0; i < SOFTINT_COUNT; i++) {
590 		db_printf("%p cpu[%lu].ci_softlwps[%d]   = %p\n",
591 		    &ci->ci_softlwps[i], cpuid, i, ci->ci_softlwps[i]);
592 	}
593 	db_printf("%p cpu[%lu].ci_want_resched  = %d\n",
594 	    &ci->ci_want_resched, cpuid, ci->ci_want_resched);
595 	db_printf("%p cpu[%lu].ci_cpl           = %d\n",
596 	    &ci->ci_cpl, cpuid, ci->ci_cpl);
597 	db_printf("%p cpu[%lu].ci_softints      = 0x%08x\n",
598 	    &ci->ci_softints, cpuid, ci->ci_softints);
599 	db_printf("%p cpu[%lu].ci_idepth        = %u\n",
600 	    &ci->ci_idepth, cpuid, ci->ci_idepth);
601 }
602 
603 void
db_cpuinfo_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)604 db_cpuinfo_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
605     const char *modif)
606 {
607 #ifdef MULTIPROCESSOR
608 	CPU_INFO_ITERATOR cii;
609 	struct cpu_info *ci;
610 	bool showall = false;
611 
612 	if (modif != NULL) {
613 		for (; *modif != '\0'; modif++) {
614 			switch (*modif) {
615 			case 'a':
616 				showall = true;
617 				break;
618 			}
619 		}
620 	}
621 
622 	if (showall) {
623 		for (CPU_INFO_FOREACH(cii, ci)) {
624 			show_cpuinfo(ci);
625 		}
626 	} else
627 #endif /* MULTIPROCESSOR */
628 		show_cpuinfo(curcpu());
629 }
630 
631 
632 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
633 static void
db_watch_cmd(db_expr_t address,bool have_addr,db_expr_t count,const char * modif)634 db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
635 		 const char *modif)
636 {
637 	struct cpu_info * const ci = curcpu();
638 	cpu_watchpoint_t *cwp;
639 	register_t mask=0;
640 	uint32_t asid;
641 	uint32_t mode;
642 	db_expr_t value;
643 	char str[6];
644 
645 	if (!have_addr) {
646 		db_printf("%-3s %-5s %-16s %4s %4s\n",
647 			"#", "MODE", "ADDR", "MASK", "ASID");
648 		for (u_int i=0; i < ci->ci_cpuwatch_count; i++) {
649 			cwp = &ci->ci_cpuwatch_tab[i];
650 			mode = cwp->cw_mode;
651 			if ((mode & CPUWATCH_RWX) == 0)
652 				continue;	/* empty/disabled/invalid */
653 			str[0] = (mode & CPUWATCH_READ)  ?  'r' : '-';
654 			str[1] = (mode & CPUWATCH_WRITE) ?  'w' : '-';
655 			str[2] = (mode & CPUWATCH_EXEC)  ?  'x' : '-';
656 			str[3] = (mode & CPUWATCH_MASK)  ?  'm' : '-';
657 			str[4] = (mode & CPUWATCH_ASID)  ?  'a' : 'g';
658 			str[5] = '\0';
659 			db_printf("%2u: %s %16" PRIxREGISTER
660 			    " %4" PRIxREGISTER " %4x\n",
661 			    i, str, cwp->cw_addr, cwp->cw_mask, cwp->cw_asid);
662 		}
663 		db_flush_lex();
664 		return;
665 	}
666 
667 	cwp = cpuwatch_alloc();
668 	if (cwp == NULL) {
669 		db_printf("no watchpoint available\n");
670 		db_flush_lex();
671 		return;
672 	}
673 
674 	/*
675 	 * parse modif to define mode
676 	 */
677 	KASSERT(modif != NULL);
678 	mode = 0;
679 	for (int i=0; modif[i] != '\0'; i++) {
680 		switch(modif[i]) {
681 		case 'w':
682 			mode |= CPUWATCH_WRITE;
683 			break;
684 		case 'm':
685 			mode |= CPUWATCH_MASK;
686 			break;
687 		case 'r':
688 			mode |= CPUWATCH_READ;
689 			break;
690 		case 'x':
691 			mode |= CPUWATCH_EXEC;
692 			break;
693 		case 'a':
694 			mode |= CPUWATCH_ASID;
695 			break;
696 		}
697 	}
698 	if (mode == 0) {
699 		db_printf("mode modifier(s) missing\n");
700 		db_flush_lex();
701 		return;
702 	}
703 
704 	/*
705 	 * if mask mode is requested get the mask,
706 	 */
707 	if (mode & CPUWATCH_MASK) {
708 		if (! db_expression(&value)) {
709 			db_printf("mask missing\n");
710 			db_flush_lex();
711 			return;
712 		}
713 		mask = (register_t)(value & __BITS(11, 3));
714 	}
715 
716 	/*
717 	 * if asid mode is requested, get the asid;
718 	 * otherwise use global mode (and set asid=0)
719 	 */
720 	if (mode & CPUWATCH_ASID) {
721 		if (! db_expression(&value)) {
722 			db_printf("asid missing\n");
723 			db_flush_lex();
724 			return;
725 		}
726 		asid = (uint32_t)(value & __BITS(7,0));
727 	} else {
728 		asid = 0;
729 	}
730 
731 	if (mode & (CPUWATCH_MASK|CPUWATCH_ASID))
732 		db_skip_to_eol();
733 	else
734 		db_flush_lex();
735 
736 	/*
737 	 * store to the (volatile) table entry
738 	 * other CPUs can see this and load when resuming from pause
739 	 */
740 	cwp->cw_addr = (register_t)address;
741 	cwp->cw_mask = (register_t)mask;
742 	cwp->cw_asid = asid;
743 	cwp->cw_mode = mode;
744 
745 	/*
746 	 * program the CPU watchpoint regs
747 	 */
748 	cpuwatch_set(cwp);
749 }
750 
751 static void
db_unwatch_cmd(db_expr_t address,bool have_addr,db_expr_t count,const char * modif)752 db_unwatch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
753 		 const char *modif)
754 {
755 	struct cpu_info * const ci = curcpu();
756 	const bool unwatch_all = !have_addr;
757 	int n;
758 
759 	n = 0;
760 	for (u_int i=0; i < ci->ci_cpuwatch_count; i++) {
761 		cpu_watchpoint_t * const cwp = &ci->ci_cpuwatch_tab[i];
762 		if (unwatch_all || (cwp->cw_addr == (register_t)address)) {
763 			cpuwatch_free(cwp);
764 			n++;
765 		}
766 	}
767 	if (n == 0)
768 		db_printf("no watch found on address %#" PRIxREGISTER "\n",
769 		    (register_t)address);
770 }
771 #endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
772 
773 #ifdef MIPS64_XLS
774 void
db_mfcr_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)775 db_mfcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
776 		const char *modif)
777 {
778 	uint64_t value;
779 
780 	if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) {
781 		db_printf("mfcr not implemented on this CPU\n");
782 		return;
783 	}
784 
785 	if (!have_addr) {
786 		db_printf("Address missing\n");
787 		return;
788 	}
789 
790 	/* value = CR[addr] */
791 	__asm volatile(							\
792 		".set push 			\n\t"			\
793 		".set arch=xlr			\n\t"			\
794 		".set noat			\n\t"			\
795 		"mfcr %0,%1			\n\t"			\
796 		".set pop 			\n\t"			\
797 	    : "=r"(value) : "r"(addr));
798 
799 	db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" PRIx64 "\n",
800 	    addr, value);
801 }
802 
803 void
db_mtcr_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)804 db_mtcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
805 		const char *modif)
806 {
807 	db_expr_t value;
808 
809 	if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) {
810 		db_printf("mtcr not implemented on this CPU\n");
811 		return;
812 	}
813 
814 	if ((!have_addr) || (! db_expression(&value))) {
815 		db_printf("Address missing\n");
816 		db_flush_lex();
817 		return;
818         }
819 	db_skip_to_eol();
820 
821 	/* CR[addr] = value */
822 	__asm volatile(							\
823 		".set push 			\n\t"			\
824 		".set arch=xlr			\n\t"			\
825 		".set noat			\n\t"			\
826 		"mtcr %0,%1			\n\t"			\
827 		".set pop 			\n\t"			\
828 	    :: "r"(value), "r"(addr));
829 
830 	db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" DDB_EXPR_FMT "x\n",
831 	    addr, value);
832 }
833 #endif /* MIPS64_XLS */
834 
835 #ifdef MIPS64_OCTEON
836 #include <mips/cavium/dev/octeon_ciureg.h>
837 
838 #ifdef MULTIPROCESSOR
839 static void
db_mach_nmi_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)840 db_mach_nmi_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
841 		const char *modif)
842 {
843 	CPU_INFO_ITERATOR cii;
844 	struct cpu_info *ci;
845 
846 	if (!have_addr) {
847 		db_printf("CPU not specific\n");
848 		return;
849 	}
850 	for (CPU_INFO_FOREACH(cii, ci)) {
851 		if (cpu_index(ci) == addr)
852 			break;
853 	}
854 	if (ci == NULL) {
855 		db_printf("CPU %ld not configured\n", (long)addr);
856 		return;
857 	}
858 	if (ci == curcpu()) {
859 		db_printf("CPU %ld is current cpu; request ignored\n",
860 		    (long)addr);
861 		return;
862 	}
863 	mips3_sd(MIPS_PHYS_TO_XKPHYS_UNCACHED(CIU_NMI), __BIT(ci->ci_cpuid));
864 }
865 #endif
866 #endif
867 
868 static void
db_mach_reset_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)869 db_mach_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
870 		const char *modif)
871 {
872 
873 	if (cpu_reset_address == NULL) {
874 		db_printf("cpu_reset_address is not set\n");
875 		return;
876 	}
877 
878 	cpu_reset_address();
879 }
880 
881 const struct db_command db_machine_command_table[] = {
882 #ifdef MULTIPROCESSOR
883 	{ DDB_ADD_CMD("cpu",	db_mach_cpu_cmd,	0,
884 	  "switch to another cpu", "cpu#", NULL) },
885 #endif
886 	{ DDB_ADD_CMD("cp0",	db_cp0dump_cmd,	0,
887 		"Dump CP0 registers.",
888 		NULL, NULL) },
889 	{ DDB_ADD_CMD("cpuinfo", db_cpuinfo_cmd,	0,
890 			"Displays the cpuinfo",
891 		    NULL, NULL)
892 	},
893 	{ DDB_ADD_CMD("kvtop",	db_kvtophys_cmd,	0,
894 		"Print the physical address for a given kernel virtual address",
895 		"address",
896 		"   address:\tvirtual address to look up") },
897 #ifdef MIPS64_XLS
898 	{ DDB_ADD_CMD("mfcr", 	db_mfcr_cmd,		CS_NOREPEAT,
899 		"Dump processor control register",
900 		NULL, NULL) },
901 	{ DDB_ADD_CMD("mtcr", 	db_mtcr_cmd,		CS_NOREPEAT|CS_MORE,
902 		"Set processor control register",
903 		NULL, NULL) },
904 #endif
905 #if defined(MIPS64_OCTEON) && defined(MULTIPROCESSOR)
906 	{ DDB_ADD_CMD("nmi", 	db_mach_nmi_cmd,	CS_NOREPEAT,
907 		"Send NMI to processor",
908 		"cpu#", NULL) },
909 #endif	/* OCTEON + MP */
910 	{ DDB_ADD_CMD("reset", 	db_mach_reset_cmd,	CS_NOREPEAT,
911 		"Initiate hardware reset",
912 		NULL, NULL) },
913 	{ DDB_ADD_CMD("tlb",	db_tlbdump_cmd,		0,
914 		"Print out TLB entries. (only works with options DEBUG)",
915 		NULL, NULL) },
916 #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
917 	{ DDB_ADD_CMD("watch",	db_watch_cmd,		CS_MORE,
918 		"set cp0 watchpoint",
919 		"address <mask> <asid> </rwxma>", NULL) },
920 	{ DDB_ADD_CMD("unwatch",db_unwatch_cmd,		0,
921 		"delete cp0 watchpoint",
922 		"address", NULL) },
923 #endif	/* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
924 	{ DDB_END_CMD },
925 };
926 #endif	/* !KGDB */
927 
928 /*
929  * Determine whether the instruction involves a delay slot.
930  */
931 bool
inst_branch(int inst)932 inst_branch(int inst)
933 {
934 	InstFmt i;
935 	int delslt;
936 
937 	i.word = inst;
938 	delslt = 0;
939 	switch (i.JType.op) {
940 	case OP_REGIMM:
941 	case OP_J:
942 	case OP_JAL:
943 #if MIPS64_OCTEON
944 	case OP_CVM_BBIT0:
945 	case OP_CVM_BBIT032:
946 	case OP_CVM_BBIT1:
947 	case OP_CVM_BBIT132:
948 #endif
949 	case OP_BEQ:
950 	case OP_BNE:
951 	case OP_BLEZ:
952 	case OP_BGTZ:
953 	case OP_BEQL:
954 	case OP_BNEL:
955 	case OP_BLEZL:
956 	case OP_BGTZL:
957 		delslt = 1;
958 		break;
959 
960 	case OP_COP0:
961 	case OP_COP1:
962 		switch (i.RType.rs) {
963 		case OP_BCx:
964 		case OP_BCy:
965 			delslt = 1;
966 		}
967 		break;
968 
969 	case OP_SPECIAL:
970 		if (i.RType.op == OP_JR || i.RType.op == OP_JALR)
971 			delslt = 1;
972 		break;
973 	}
974 	return delslt;
975 }
976 
977 /*
978  * Determine whether the instruction calls a function.
979  */
980 bool
inst_call(int inst)981 inst_call(int inst)
982 {
983 	bool call;
984 	InstFmt i;
985 
986 	i.word = inst;
987 	if (i.JType.op == OP_SPECIAL
988 	    && ((i.RType.func == OP_JR && i.RType.rs != 31) ||
989 		i.RType.func == OP_JALR))
990 		call = 1;
991 	else if (i.JType.op == OP_JAL)
992 		call = 1;
993 	else
994 		call = 0;
995 	return call;
996 }
997 
998 /*
999  * Determine whether the instruction returns from a function (j ra).  The
1000  * compiler can use this construct for other jumps, but usually will not.
1001  * This lets the ddb "next" command to work (also need inst_trap_return()).
1002  */
1003 bool
inst_return(int inst)1004 inst_return(int inst)
1005 {
1006 	InstFmt i;
1007 
1008 	i.word = inst;
1009 
1010 	return (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR &&
1011 		i.RType.rs == 31);
1012 }
1013 
1014 /*
1015  * Determine whether the instruction makes a jump.
1016  */
1017 bool
inst_unconditional_flow_transfer(int inst)1018 inst_unconditional_flow_transfer(int inst)
1019 {
1020 	InstFmt i;
1021 	bool jump;
1022 
1023 	i.word = inst;
1024 	jump = (i.JType.op == OP_J) ||
1025 	       (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR);
1026 	return jump;
1027 }
1028 
1029 /*
1030  * Determine whether the instruction is a load/store as appropriate.
1031  */
1032 bool
inst_load(int inst)1033 inst_load(int inst)
1034 {
1035 	InstFmt i = { .word = inst, };
1036 
1037 	/*
1038 	 * All loads are opcodes 04x or 06x.
1039 	 */
1040 	if ((i.JType.op & 050) != 040)
1041 		return false;
1042 
1043 	/*
1044 	 * Except these this opcode is not a load.
1045 	 */
1046 	return i.JType.op != OP_PREF;
1047 }
1048 
1049 bool
inst_store(int inst)1050 inst_store(int inst)
1051 {
1052 	InstFmt i = { .word = inst, };
1053 
1054 	/*
1055 	 * All stores are opcodes 05x or 07x.
1056 	 */
1057 	if ((i.JType.op & 050) != 050)
1058 		return false;
1059 
1060 	/*
1061 	 * Except these two opcodes are not stores.
1062 	 */
1063 	return i.JType.op != OP_RSVD073 && i.JType.op != OP_CACHE;
1064 }
1065 
1066 /*
1067  * Return the next pc if the given branch is taken.
1068  * mips_emul_branch() runs analysis for branch delay slot.
1069  */
1070 db_addr_t
branch_taken(int inst,db_addr_t pc,db_regs_t * regs)1071 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
1072 {
1073 	struct pcb * const pcb = lwp_getpcb(curlwp);
1074 	const uint32_t fpucsr = PCB_FSR(pcb);
1075 	vaddr_t ra;
1076 
1077 	ra = mips_emul_branch((struct trapframe *)regs, pc, fpucsr, false);
1078 	return ra;
1079 }
1080 
1081 /*
1082  * Return the next pc of an arbitrary instruction.
1083  */
1084 db_addr_t
next_instr_address(db_addr_t pc,bool bd)1085 next_instr_address(db_addr_t pc, bool bd)
1086 {
1087 	uint32_t ins;
1088 
1089 	if (bd == false)
1090 		return (pc + 4);
1091 
1092 	if (pc < MIPS_KSEG0_START)
1093 		ins = mips_ufetch32((void *)pc);
1094 	else
1095 		ins = *(uint32_t *)pc;
1096 
1097 	if (inst_branch(ins) || inst_call(ins) || inst_return(ins))
1098 		return (pc + 4);
1099 
1100 	return (pc);
1101 }
1102 
1103 #ifdef MULTIPROCESSOR
1104 
1105 bool
ddb_running_on_this_cpu_p(void)1106 ddb_running_on_this_cpu_p(void)
1107 {
1108 	return ddb_cpu == cpu_number();
1109 }
1110 
1111 bool
ddb_running_on_any_cpu_p(void)1112 ddb_running_on_any_cpu_p(void)
1113 {
1114 	return ddb_cpu != NOCPU;
1115 }
1116 
1117 void
db_resume_others(void)1118 db_resume_others(void)
1119 {
1120 	u_int cpu_me = cpu_number();
1121 
1122 	if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
1123 		cpu_resume_others();
1124 }
1125 
1126 static void
db_mach_cpu_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)1127 db_mach_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1128 {
1129 	CPU_INFO_ITERATOR cii;
1130 	struct cpu_info *ci;
1131 
1132 	if (!have_addr) {
1133 		cpu_debug_dump();
1134 		return;
1135 	}
1136 	for (CPU_INFO_FOREACH(cii, ci)) {
1137 		if (cpu_index(ci) == addr)
1138 			break;
1139 	}
1140 	if (ci == NULL) {
1141 		db_printf("CPU %ld not configured\n", (long)addr);
1142 		return;
1143 	}
1144 	if (ci != curcpu()) {
1145 		if (!cpu_is_paused(cpu_index(ci))) {
1146 			db_printf("CPU %ld not paused\n", (long)addr);
1147 			return;
1148 		}
1149 		(void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci));
1150 		db_continue_cmd(0, false, 0, "");
1151 	}
1152 }
1153 #endif	/* MULTIPROCESSOR */
1154 
1155 #endif	/* _KERNEL */
1156