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