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