1 1.61 andvar /* $NetBSD: db_interface.c,v 1.61 2024/09/08 10:09:48 andvar Exp $ */ 2 1.1 sakamoto /* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */ 3 1.29 lukem 4 1.29 lukem #include <sys/cdefs.h> 5 1.61 andvar __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.61 2024/09/08 10:09:48 andvar Exp $"); 6 1.3 jonathan 7 1.10 simonb #define USERACC 8 1.10 simonb 9 1.54 rin #ifdef _KERNEL_OPT 10 1.3 jonathan #include "opt_ddb.h" 11 1.17 dbj #include "opt_kgdb.h" 12 1.53 nonaka #include "opt_multiprocessor.h" 13 1.10 simonb #include "opt_ppcarch.h" 14 1.54 rin #endif 15 1.1 sakamoto 16 1.1 sakamoto #include <sys/param.h> 17 1.1 sakamoto #include <sys/proc.h> 18 1.4 tsubai #include <sys/systm.h> 19 1.46 matt #include <sys/cpu.h> 20 1.53 nonaka #include <sys/atomic.h> 21 1.6 kleink 22 1.11 simonb #include <dev/cons.h> 23 1.11 simonb 24 1.47 matt #include <powerpc/db_machdep.h> 25 1.47 matt #include <powerpc/frame.h> 26 1.43 phx #include <powerpc/spr.h> 27 1.43 phx #include <powerpc/pte.h> 28 1.47 matt #include <powerpc/psl.h> 29 1.43 phx 30 1.44 matt #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 31 1.44 matt #include <powerpc/oea/spr.h> 32 1.46 matt #include <powerpc/oea/bat.h> 33 1.49 matt #include <powerpc/oea/cpufeat.h> 34 1.44 matt #endif 35 1.44 matt 36 1.10 simonb #ifdef PPC_IBM4XX 37 1.46 matt #include <powerpc/ibm4xx/cpu.h> 38 1.44 matt #include <powerpc/ibm4xx/spr.h> 39 1.56 rin #include <powerpc/ibm4xx/tlb.h> 40 1.10 simonb #include <uvm/uvm_extern.h> 41 1.10 simonb #endif 42 1.7 tsubai 43 1.44 matt #ifdef PPC_BOOKE 44 1.45 matt #include <powerpc/booke/cpuvar.h> 45 1.44 matt #include <powerpc/booke/spr.h> 46 1.44 matt #endif 47 1.44 matt 48 1.17 dbj #ifdef DDB 49 1.60 riastrad #include <ddb/db_active.h> 50 1.6 kleink #include <ddb/db_sym.h> 51 1.6 kleink #include <ddb/db_command.h> 52 1.6 kleink #include <ddb/db_extern.h> 53 1.6 kleink #include <ddb/db_access.h> 54 1.22 scw #include <ddb/db_lex.h> 55 1.6 kleink #include <ddb/db_output.h> 56 1.53 nonaka #include <ddb/db_run.h> /* for db_continue_cmd() proto */ 57 1.6 kleink #include <ddb/ddbvar.h> 58 1.17 dbj #endif 59 1.17 dbj 60 1.17 dbj #ifdef KGDB 61 1.17 dbj #include <sys/kgdb.h> 62 1.39 garbled #define db_printf printf 63 1.17 dbj #endif 64 1.17 dbj 65 1.17 dbj #include <dev/ofw/openfirm.h> 66 1.1 sakamoto 67 1.53 nonaka #define NOCPU ~0 68 1.53 nonaka volatile u_int ddb_cpu = NOCPU; 69 1.53 nonaka 70 1.11 simonb int db_active = 0; 71 1.11 simonb 72 1.19 matt db_regs_t ddb_regs; 73 1.8 tsubai 74 1.10 simonb void ddb_trap(void); /* Call into trap_subr.S */ 75 1.10 simonb int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */ 76 1.61 andvar #ifdef DDB 77 1.43 phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 78 1.43 phx static void db_show_bat(db_expr_t, bool, db_expr_t, const char *); 79 1.43 phx static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *); 80 1.43 phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */ 81 1.10 simonb #ifdef PPC_IBM4XX 82 1.37 matt static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *); 83 1.37 matt static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *); 84 1.37 matt static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *); 85 1.37 matt static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *); 86 1.37 matt static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *); 87 1.37 matt static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *); 88 1.22 scw static db_expr_t db_ppc4xx_mfdcr(db_expr_t); 89 1.22 scw static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t); 90 1.10 simonb #ifdef USERACC 91 1.37 matt static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *); 92 1.10 simonb #endif 93 1.10 simonb #endif /* PPC_IBM4XX */ 94 1.9 briggs 95 1.45 matt #ifdef PPC_BOOKE 96 1.45 matt static void db_ppcbooke_reset(db_expr_t, bool, db_expr_t, const char *); 97 1.51 matt static void db_ppcbooke_splhist(db_expr_t, bool, db_expr_t, const char *); 98 1.45 matt static void db_ppcbooke_tf(db_expr_t, bool, db_expr_t, const char *); 99 1.45 matt static void db_ppcbooke_dumptlb(db_expr_t, bool, db_expr_t, const char *); 100 1.45 matt #endif 101 1.45 matt 102 1.53 nonaka #ifdef MULTIPROCESSOR 103 1.53 nonaka static void db_mach_cpu(db_expr_t, bool, db_expr_t, const char *); 104 1.53 nonaka #endif /* MULTIPROCESSOR */ 105 1.53 nonaka 106 1.43 phx const struct db_command db_machine_command_table[] = { 107 1.43 phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 108 1.43 phx { DDB_ADD_CMD("bat", db_show_bat, 0, 109 1.43 phx "Print BAT register translations", NULL,NULL) }, 110 1.43 phx { DDB_ADD_CMD("mmu", db_show_mmu, 0, 111 1.43 phx "Print MMU registers", NULL,NULL) }, 112 1.43 phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */ 113 1.43 phx #ifdef PPC_IBM4XX 114 1.43 phx { DDB_ADD_CMD("ctx", db_ppc4xx_ctx, 0, 115 1.43 phx "Print process MMU context information", NULL,NULL) }, 116 1.43 phx { DDB_ADD_CMD("pv", db_ppc4xx_pv, 0, 117 1.43 phx "Print PA->VA mapping information", 118 1.43 phx "address", 119 1.43 phx " address:\tphysical address to look up") }, 120 1.43 phx { DDB_ADD_CMD("reset", db_ppc4xx_reset, 0, 121 1.43 phx "Reset the system ", NULL,NULL) }, 122 1.43 phx { DDB_ADD_CMD("tf", db_ppc4xx_tf, 0, 123 1.43 phx "Display the contents of the trapframe", 124 1.43 phx "address", 125 1.43 phx " address:\tthe struct trapframe to print") }, 126 1.43 phx { DDB_ADD_CMD("tlb", db_ppc4xx_dumptlb, 0, 127 1.43 phx "Display instruction translation storage buffer information.", 128 1.43 phx NULL,NULL) }, 129 1.43 phx { DDB_ADD_CMD("dcr", db_ppc4xx_dcr, CS_MORE|CS_SET_DOT, 130 1.43 phx "Set the DCR register", 131 1.43 phx "dcr", 132 1.43 phx " dcr:\tNew DCR value (between 0x0 and 0x3ff)") }, 133 1.43 phx #ifdef USERACC 134 1.43 phx { DDB_ADD_CMD("user", db_ppc4xx_useracc, 0, 135 1.43 phx "Display user memory.", "[address][,count]", 136 1.43 phx " address:\tuserspace address to start\n" 137 1.43 phx " count:\tnumber of bytes to display") }, 138 1.43 phx #endif 139 1.43 phx #endif /* PPC_IBM4XX */ 140 1.45 matt #ifdef PPC_BOOKE 141 1.45 matt { DDB_ADD_CMD("reset", db_ppcbooke_reset, 0, 142 1.45 matt "Reset the system ", NULL,NULL) }, 143 1.45 matt { DDB_ADD_CMD("tf", db_ppcbooke_tf, 0, 144 1.45 matt "Display the contents of the trapframe", 145 1.45 matt "address", 146 1.45 matt " address:\tthe struct trapframe to print") }, 147 1.51 matt { DDB_ADD_CMD("splhist", db_ppcbooke_splhist, 0, 148 1.51 matt "Display the splraise/splx splx", 149 1.51 matt NULL, NULL) }, 150 1.45 matt { DDB_ADD_CMD("tlb", db_ppcbooke_dumptlb, 0, 151 1.45 matt "Display instruction translation storage buffer information.", 152 1.45 matt NULL,NULL) }, 153 1.45 matt #endif /* PPC_BOOKE */ 154 1.53 nonaka 155 1.53 nonaka #ifdef MULTIPROCESSOR 156 1.53 nonaka { DDB_ADD_CMD("cpu", db_mach_cpu, 0, 157 1.53 nonaka "switch to another cpu", "cpu-no", NULL) }, 158 1.53 nonaka #endif /* MULTIPROCESSOR */ 159 1.53 nonaka 160 1.55 mrg { DDB_END_CMD }, 161 1.43 phx }; 162 1.43 phx 163 1.1 sakamoto void 164 1.31 matt cpu_Debugger(void) 165 1.1 sakamoto { 166 1.45 matt #ifdef PPC_BOOKE 167 1.45 matt const register_t msr = mfmsr(); 168 1.45 matt __asm volatile("wrteei 0\n\ttweq\t1,1"); 169 1.45 matt mtmsr(msr); 170 1.45 matt __asm volatile("isync"); 171 1.45 matt #else 172 1.1 sakamoto ddb_trap(); 173 1.45 matt #endif 174 1.1 sakamoto } 175 1.45 matt #endif /* DDB */ 176 1.1 sakamoto 177 1.1 sakamoto int 178 1.45 matt ddb_trap_glue(struct trapframe *tf) 179 1.1 sakamoto { 180 1.45 matt #if defined(PPC_IBM4XX) || defined(PPC_BOOKE) 181 1.45 matt if ((tf->tf_srr1 & PSL_PR) == 0) 182 1.45 matt return kdb_trap(tf->tf_exc, tf); 183 1.28 matt #else /* PPC_OEA */ 184 1.45 matt if ((tf->tf_srr1 & PSL_PR) == 0 && 185 1.45 matt (tf->tf_exc == EXC_TRC || 186 1.45 matt tf->tf_exc == EXC_RUNMODETRC || 187 1.45 matt (tf->tf_exc == EXC_PGM && (tf->tf_srr1 & 0x20000)) || 188 1.45 matt tf->tf_exc == EXC_BPT || 189 1.45 matt tf->tf_exc == EXC_DSI)) { 190 1.45 matt int type = tf->tf_exc; 191 1.45 matt if (type == EXC_PGM && (tf->tf_srr1 & 0x20000)) { 192 1.17 dbj type = T_BREAKPOINT; 193 1.17 dbj } 194 1.45 matt return kdb_trap(type, tf); 195 1.1 sakamoto } 196 1.25 thorpej #endif 197 1.1 sakamoto return 0; 198 1.8 tsubai } 199 1.8 tsubai 200 1.8 tsubai int 201 1.31 matt kdb_trap(int type, void *v) 202 1.8 tsubai { 203 1.45 matt struct trapframe *tf = v; 204 1.53 nonaka int rv = 1; 205 1.53 nonaka int s; 206 1.8 tsubai 207 1.17 dbj #ifdef DDB 208 1.30 matt if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) { 209 1.30 matt db_error("Faulted in DDB; continuing...\n"); 210 1.30 matt /* NOTREACHED */ 211 1.8 tsubai } 212 1.17 dbj #endif 213 1.8 tsubai 214 1.8 tsubai /* XXX Should switch to kdb's own stack here. */ 215 1.8 tsubai 216 1.53 nonaka #ifdef MULTIPROCESSOR 217 1.53 nonaka bool first_in_ddb = false; 218 1.53 nonaka const u_int cpu_me = cpu_number(); 219 1.53 nonaka const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me); 220 1.53 nonaka if (old_ddb_cpu == NOCPU) { 221 1.53 nonaka first_in_ddb = true; 222 1.53 nonaka cpu_pause_others(); 223 1.53 nonaka } else { 224 1.53 nonaka if (old_ddb_cpu != cpu_me) { 225 1.53 nonaka KASSERT(cpu_is_paused(cpu_me)); 226 1.53 nonaka cpu_pause(tf); 227 1.53 nonaka return 1; 228 1.53 nonaka } 229 1.53 nonaka } 230 1.53 nonaka KASSERT(!cpu_is_paused(cpu_me)); 231 1.53 nonaka #endif /* MULTIPROCESSOR */ 232 1.53 nonaka 233 1.53 nonaka s = splhigh(); 234 1.45 matt memcpy(DDB_REGS->r, tf->tf_fixreg, 32 * sizeof(u_int32_t)); 235 1.45 matt DDB_REGS->iar = tf->tf_srr0; 236 1.45 matt DDB_REGS->msr = tf->tf_srr1; 237 1.45 matt DDB_REGS->lr = tf->tf_lr; 238 1.45 matt DDB_REGS->ctr = tf->tf_ctr; 239 1.45 matt DDB_REGS->cr = tf->tf_cr; 240 1.45 matt DDB_REGS->xer = tf->tf_xer; 241 1.28 matt #ifdef PPC_OEA 242 1.45 matt DDB_REGS->mq = tf->tf_mq; 243 1.45 matt #elif defined(PPC_IBM4XX) || defined(PPC_BOOKE) 244 1.45 matt DDB_REGS->dear = tf->tf_dear; 245 1.45 matt DDB_REGS->esr = tf->tf_esr; 246 1.45 matt DDB_REGS->pid = tf->tf_pid; 247 1.10 simonb #endif 248 1.8 tsubai 249 1.17 dbj #ifdef DDB 250 1.11 simonb db_active++; 251 1.11 simonb cnpollc(1); 252 1.15 dbj db_trap(type, 0); 253 1.11 simonb cnpollc(0); 254 1.11 simonb db_active--; 255 1.61 andvar #endif 256 1.61 andvar #ifdef KGDB 257 1.53 nonaka if (!kgdb_trap(type, DDB_REGS)) { 258 1.53 nonaka rv = 0; 259 1.53 nonaka goto out; 260 1.53 nonaka } 261 1.17 dbj #endif 262 1.17 dbj 263 1.17 dbj /* KGDB isn't smart about advancing PC if we 264 1.17 dbj * take a breakpoint trap after kgdb_active is set. 265 1.17 dbj * Therefore, we help out here. 266 1.17 dbj */ 267 1.17 dbj if (IS_BREAKPOINT_TRAP(type, 0)) { 268 1.17 dbj int bkpt; 269 1.17 dbj db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt); 270 1.17 dbj if (bkpt== BKPT_INST) { 271 1.17 dbj PC_REGS(DDB_REGS) += BKPT_SIZE; 272 1.17 dbj } 273 1.17 dbj } 274 1.8 tsubai 275 1.45 matt memcpy(tf->tf_fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t)); 276 1.45 matt tf->tf_srr0 = DDB_REGS->iar; 277 1.45 matt tf->tf_srr1 = DDB_REGS->msr; 278 1.45 matt tf->tf_lr = DDB_REGS->lr; 279 1.45 matt tf->tf_ctr = DDB_REGS->ctr; 280 1.45 matt tf->tf_cr = DDB_REGS->cr; 281 1.45 matt tf->tf_xer = DDB_REGS->xer; 282 1.28 matt #ifdef PPC_OEA 283 1.45 matt tf->tf_mq = DDB_REGS->mq; 284 1.27 matt #endif 285 1.45 matt #if defined(PPC_IBM4XX) || defined(PPC_BOOKE) 286 1.45 matt tf->tf_dear = DDB_REGS->dear; 287 1.45 matt tf->tf_esr = DDB_REGS->esr; 288 1.45 matt tf->tf_pid = DDB_REGS->pid; 289 1.10 simonb #endif 290 1.53 nonaka #ifdef KGDB 291 1.53 nonaka out: 292 1.53 nonaka #endif /* KGDB */ 293 1.53 nonaka splx(s); 294 1.53 nonaka 295 1.53 nonaka #ifdef MULTIPROCESSOR 296 1.53 nonaka if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) { 297 1.53 nonaka cpu_resume_others(); 298 1.53 nonaka } else { 299 1.53 nonaka cpu_resume(ddb_cpu); 300 1.53 nonaka if (first_in_ddb) 301 1.53 nonaka cpu_pause(tf); 302 1.53 nonaka } 303 1.53 nonaka #endif /* MULTIPROCESSOR */ 304 1.8 tsubai 305 1.53 nonaka return rv; 306 1.1 sakamoto } 307 1.10 simonb 308 1.61 andvar #ifdef DDB 309 1.43 phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 310 1.43 phx static void 311 1.43 phx print_battranslation(struct bat *bat, unsigned int blidx) 312 1.43 phx { 313 1.52 joerg static const char batsizes[][6] = { 314 1.49 matt "128KB", 315 1.49 matt "256KB", 316 1.49 matt "512KB", 317 1.43 phx "1MB", 318 1.43 phx "2MB", 319 1.43 phx "4MB", 320 1.43 phx "8MB", 321 1.43 phx "16MB", 322 1.43 phx "32MB", 323 1.43 phx "64MB", 324 1.43 phx "128MB", 325 1.49 matt "256MB", 326 1.49 matt "512MB", 327 1.49 matt "1GB", 328 1.49 matt "2GB", 329 1.49 matt "4GB", 330 1.43 phx }; 331 1.43 phx vsize_t len; 332 1.43 phx 333 1.43 phx len = (0x20000L << blidx) - 1; 334 1.43 phx db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n", 335 1.43 phx bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len, 336 1.43 phx (bat->batu & ~len) + len, bat->batl & ~len); 337 1.43 phx } 338 1.43 phx 339 1.43 phx static void 340 1.43 phx print_batmodes(register_t super, register_t user, register_t pp) 341 1.43 phx { 342 1.43 phx static const char *const accessmodes[] = { 343 1.43 phx "none", 344 1.43 phx "ro soft", 345 1.43 phx "read/write", 346 1.43 phx "read only" 347 1.43 phx }; 348 1.43 phx 349 1.43 phx db_printf("\tvalid: %c%c access: %-10s memory:", 350 1.43 phx super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]); 351 1.43 phx } 352 1.43 phx 353 1.43 phx static void 354 1.43 phx print_wimg(register_t wimg) 355 1.43 phx { 356 1.43 phx if (wimg & BAT_W) 357 1.43 phx db_printf(" wrthrough"); 358 1.43 phx if (wimg & BAT_I) 359 1.43 phx db_printf(" nocache"); 360 1.43 phx if (wimg & BAT_M) 361 1.43 phx db_printf(" coherent"); 362 1.43 phx if (wimg & BAT_G) 363 1.43 phx db_printf(" guard"); 364 1.43 phx } 365 1.43 phx 366 1.43 phx static void 367 1.43 phx print_bat(struct bat *bat) 368 1.43 phx { 369 1.43 phx if ((bat->batu & BAT_V) == 0) { 370 1.43 phx db_printf("\tdisabled\n\n"); 371 1.43 phx return; 372 1.43 phx } 373 1.49 matt print_battranslation(bat, 374 1.49 matt 30 - __builtin_clz((bat->batu & (BAT_XBL|BAT_BL))|2)); 375 1.43 phx print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu, 376 1.43 phx bat->batl & BAT_PP); 377 1.43 phx print_wimg(bat->batl & BAT_WIMG); 378 1.43 phx db_printf("\n"); 379 1.43 phx } 380 1.43 phx 381 1.43 phx #ifdef PPC_OEA601 382 1.43 phx static void 383 1.43 phx print_bat601(struct bat *bat) 384 1.43 phx { 385 1.43 phx if ((bat->batl & BAT601_V) == 0) { 386 1.43 phx db_printf("\tdisabled\n\n"); 387 1.43 phx return; 388 1.43 phx } 389 1.43 phx print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM)); 390 1.43 phx print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku, 391 1.43 phx bat->batu & BAT601_PP); 392 1.43 phx print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M)); 393 1.43 phx db_printf("\n"); 394 1.43 phx } 395 1.43 phx #endif 396 1.43 phx 397 1.43 phx static void 398 1.43 phx db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 399 1.43 phx { 400 1.49 matt struct bat ibat[8]; 401 1.49 matt struct bat dbat[8]; 402 1.43 phx unsigned int cpuvers; 403 1.49 matt u_int i; 404 1.49 matt u_int maxbat = (oeacpufeat & OEACPU_HIGHBAT) ? 8 : 4; 405 1.43 phx 406 1.50 matt if (oeacpufeat & OEACPU_NOBAT) 407 1.50 matt return; 408 1.50 matt 409 1.43 phx cpuvers = mfpvr() >> 16; 410 1.43 phx 411 1.49 matt ibat[0].batu = mfspr(SPR_IBAT0U); 412 1.49 matt ibat[0].batl = mfspr(SPR_IBAT0L); 413 1.49 matt ibat[1].batu = mfspr(SPR_IBAT1U); 414 1.49 matt ibat[1].batl = mfspr(SPR_IBAT1L); 415 1.49 matt ibat[2].batu = mfspr(SPR_IBAT2U); 416 1.49 matt ibat[2].batl = mfspr(SPR_IBAT2L); 417 1.49 matt ibat[3].batu = mfspr(SPR_IBAT3U); 418 1.49 matt ibat[3].batl = mfspr(SPR_IBAT3L); 419 1.49 matt if (maxbat == 8) { 420 1.49 matt ibat[4].batu = mfspr(SPR_IBAT4U); 421 1.49 matt ibat[4].batl = mfspr(SPR_IBAT4L); 422 1.49 matt ibat[5].batu = mfspr(SPR_IBAT5U); 423 1.49 matt ibat[5].batl = mfspr(SPR_IBAT5L); 424 1.49 matt ibat[6].batu = mfspr(SPR_IBAT6U); 425 1.49 matt ibat[6].batl = mfspr(SPR_IBAT6L); 426 1.49 matt ibat[7].batu = mfspr(SPR_IBAT7U); 427 1.49 matt ibat[7].batl = mfspr(SPR_IBAT7L); 428 1.49 matt } 429 1.43 phx 430 1.43 phx if (cpuvers != MPC601) { 431 1.43 phx /* The 601 has only four unified BATs */ 432 1.49 matt dbat[0].batu = mfspr(SPR_DBAT0U); 433 1.49 matt dbat[0].batl = mfspr(SPR_DBAT0L); 434 1.49 matt dbat[1].batu = mfspr(SPR_DBAT1U); 435 1.49 matt dbat[1].batl = mfspr(SPR_DBAT1L); 436 1.49 matt dbat[2].batu = mfspr(SPR_DBAT2U); 437 1.49 matt dbat[2].batl = mfspr(SPR_DBAT2L); 438 1.49 matt dbat[3].batu = mfspr(SPR_DBAT3U); 439 1.49 matt dbat[3].batl = mfspr(SPR_DBAT3L); 440 1.49 matt if (maxbat == 8) { 441 1.49 matt dbat[4].batu = mfspr(SPR_DBAT4U); 442 1.49 matt dbat[4].batl = mfspr(SPR_DBAT4L); 443 1.49 matt dbat[5].batu = mfspr(SPR_DBAT5U); 444 1.49 matt dbat[5].batl = mfspr(SPR_DBAT5L); 445 1.49 matt dbat[6].batu = mfspr(SPR_DBAT6U); 446 1.49 matt dbat[6].batl = mfspr(SPR_DBAT6L); 447 1.49 matt dbat[7].batu = mfspr(SPR_DBAT7U); 448 1.49 matt dbat[7].batl = mfspr(SPR_DBAT7L); 449 1.49 matt } 450 1.43 phx } 451 1.43 phx 452 1.49 matt for (i = 0; i < maxbat; i++) { 453 1.43 phx #ifdef PPC_OEA601 454 1.43 phx if (cpuvers == MPC601) { 455 1.49 matt db_printf("bat[%u]:\n", i); 456 1.43 phx print_bat601(&ibat[i]); 457 1.43 phx } else 458 1.43 phx #endif 459 1.43 phx { 460 1.49 matt db_printf("ibat[%u]:\n", i); 461 1.43 phx print_bat(&ibat[i]); 462 1.49 matt db_printf("dbat[%u]:\n", i); 463 1.43 phx print_bat(&dbat[i]); 464 1.43 phx } 465 1.43 phx } 466 1.43 phx } 467 1.43 phx 468 1.43 phx static void 469 1.43 phx db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 470 1.43 phx { 471 1.43 phx paddr_t sdr1; 472 1.43 phx 473 1.43 phx __asm volatile ("mfsdr1 %0" : "=r"(sdr1)); 474 1.43 phx db_printf("sdr1\t\t0x%08lx\n", sdr1); 475 1.43 phx 476 1.43 phx #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE) 477 1.50 matt if (oeacpufeat & (OEACPU_64|OEACPU_64_BRIDGE)) { 478 1.50 matt __asm volatile ("mfasr %0" : "=r"(sdr1)); 479 1.50 matt db_printf("asr\t\t0x%08lx\n", sdr1); 480 1.50 matt } 481 1.50 matt #endif 482 1.50 matt #if defined(PPC_OEA) || defined(PPC_OEA64_BRIDGE) 483 1.50 matt if ((oeacpufeat & OEACPU_64) == 0) { 484 1.50 matt vaddr_t saddr = 0; 485 1.50 matt for (u_int i = 0; i <= 0xf; i++) { 486 1.50 matt register_t sr; 487 1.50 matt if ((i & 3) == 0) 488 1.50 matt db_printf("sr%d-%d\t\t", i, i+3); 489 1.50 matt __asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr)); 490 1.50 matt db_printf("0x%08lx %c", sr, (i&3) == 3 ? '\n' : ' '); 491 1.50 matt saddr += 1 << ADDR_SR_SHFT; 492 1.50 matt } 493 1.43 phx } 494 1.43 phx #endif 495 1.43 phx } 496 1.43 phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */ 497 1.61 andvar #endif /* DDB */ 498 1.43 phx 499 1.45 matt #if defined(PPC_IBM4XX) || defined(PPC_BOOKE) 500 1.24 scw db_addr_t 501 1.24 scw branch_taken(int inst, db_addr_t pc, db_regs_t *regs) 502 1.24 scw { 503 1.24 scw 504 1.24 scw if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) { 505 1.24 scw db_expr_t off; 506 1.24 scw off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6; 507 1.24 scw return (((inst & 0x2) ? 0 : pc) + off); 508 1.24 scw } 509 1.24 scw 510 1.24 scw if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) { 511 1.24 scw db_expr_t off; 512 1.24 scw off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16; 513 1.24 scw return (((inst & 0x2) ? 0 : pc) + off); 514 1.24 scw } 515 1.24 scw 516 1.24 scw if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL) 517 1.24 scw return (regs->lr); 518 1.24 scw 519 1.24 scw if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL) 520 1.24 scw return (regs->ctr); 521 1.24 scw 522 1.24 scw db_printf("branch_taken: can't figure out branch target for 0x%x!\n", 523 1.24 scw inst); 524 1.24 scw return (0); 525 1.24 scw } 526 1.45 matt #endif /* PPC_IBM4XX || PPC_BOOKE */ 527 1.24 scw 528 1.61 andvar #ifdef DDB 529 1.45 matt #ifdef PPC_IBM4XX 530 1.10 simonb static void 531 1.37 matt db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 532 1.10 simonb { 533 1.10 simonb struct proc *p; 534 1.10 simonb 535 1.10 simonb /* XXX LOCKING XXX */ 536 1.10 simonb for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 537 1.10 simonb if (p->p_stat) { 538 1.10 simonb db_printf("process %p:", p); 539 1.10 simonb db_printf("pid:%d pmap:%p ctx:%d %s\n", 540 1.10 simonb p->p_pid, p->p_vmspace->vm_map.pmap, 541 1.10 simonb p->p_vmspace->vm_map.pmap->pm_ctx, 542 1.10 simonb p->p_comm); 543 1.10 simonb } 544 1.10 simonb } 545 1.10 simonb return; 546 1.10 simonb } 547 1.10 simonb 548 1.10 simonb static void 549 1.37 matt db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 550 1.10 simonb { 551 1.10 simonb struct pv_entry { 552 1.10 simonb struct pv_entry *pv_next; /* Linked list of mappings */ 553 1.10 simonb vaddr_t pv_va; /* virtual address of mapping */ 554 1.10 simonb struct pmap *pv_pm; 555 1.10 simonb }; 556 1.10 simonb struct pv_entry *pa_to_pv(paddr_t); 557 1.10 simonb struct pv_entry *pv; 558 1.10 simonb 559 1.10 simonb if (!have_addr) { 560 1.10 simonb db_printf("pv: <pa>\n"); 561 1.10 simonb return; 562 1.10 simonb } 563 1.10 simonb pv = pa_to_pv(addr); 564 1.10 simonb db_printf("pv at %p\n", pv); 565 1.10 simonb while (pv && pv->pv_pm) { 566 1.48 kiyohara db_printf("next %p va %p pmap %p\n", pv->pv_next, 567 1.10 simonb (void *)pv->pv_va, pv->pv_pm); 568 1.10 simonb pv = pv->pv_next; 569 1.10 simonb } 570 1.10 simonb } 571 1.10 simonb 572 1.10 simonb static void 573 1.37 matt db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count, 574 1.34 scw const char *modif) 575 1.10 simonb { 576 1.57 andvar printf("Resetting...\n"); 577 1.10 simonb ppc4xx_reset(); 578 1.10 simonb } 579 1.10 simonb 580 1.10 simonb static void 581 1.37 matt db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 582 1.10 simonb { 583 1.45 matt struct trapframe *tf; 584 1.10 simonb 585 1.10 simonb 586 1.10 simonb if (have_addr) { 587 1.45 matt tf = (struct trapframe *)addr; 588 1.10 simonb 589 1.48 kiyohara db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n", 590 1.45 matt tf->tf_fixreg[0], tf->tf_fixreg[1], 591 1.45 matt tf->tf_fixreg[2], tf->tf_fixreg[3]); 592 1.27 matt db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n", 593 1.45 matt tf->tf_fixreg[4], tf->tf_fixreg[5], 594 1.45 matt tf->tf_fixreg[6], tf->tf_fixreg[7]); 595 1.27 matt db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n", 596 1.45 matt tf->tf_fixreg[8], tf->tf_fixreg[9], 597 1.45 matt tf->tf_fixreg[10], tf->tf_fixreg[11]); 598 1.27 matt db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n", 599 1.45 matt tf->tf_fixreg[12], tf->tf_fixreg[13], 600 1.45 matt tf->tf_fixreg[14], tf->tf_fixreg[15]); 601 1.27 matt db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n", 602 1.45 matt tf->tf_fixreg[16], tf->tf_fixreg[17], 603 1.45 matt tf->tf_fixreg[18], tf->tf_fixreg[19]); 604 1.27 matt db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n", 605 1.45 matt tf->tf_fixreg[20], tf->tf_fixreg[21], 606 1.45 matt tf->tf_fixreg[22], tf->tf_fixreg[23]); 607 1.27 matt db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n", 608 1.45 matt tf->tf_fixreg[24], tf->tf_fixreg[25], 609 1.45 matt tf->tf_fixreg[26], tf->tf_fixreg[27]); 610 1.27 matt db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n", 611 1.45 matt tf->tf_fixreg[28], tf->tf_fixreg[29], 612 1.45 matt tf->tf_fixreg[30], tf->tf_fixreg[31]); 613 1.10 simonb 614 1.27 matt db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n", 615 1.45 matt tf->tf_lr, tf->tf_cr, tf->tf_xer, tf->tf_ctr); 616 1.27 matt db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx " 617 1.27 matt "dear: %8.8lx esr: %8.8x\n", 618 1.45 matt tf->tf_srr0, tf->tf_srr1, tf->tf_dear, tf->tf_esr); 619 1.10 simonb db_printf("exc: %8.8x pid: %8.8x\n", 620 1.45 matt tf->tf_exc, tf->tf_pid); 621 1.10 simonb } 622 1.10 simonb return; 623 1.10 simonb } 624 1.10 simonb 625 1.10 simonb static const char *const tlbsizes[] = { 626 1.10 simonb "1kB", 627 1.10 simonb "4kB", 628 1.10 simonb "16kB", 629 1.10 simonb "64kB", 630 1.10 simonb "256kB", 631 1.10 simonb "1MB", 632 1.10 simonb "4MB", 633 1.10 simonb "16MB" 634 1.10 simonb }; 635 1.10 simonb 636 1.10 simonb static void 637 1.37 matt db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count, 638 1.34 scw const char *modif) 639 1.10 simonb { 640 1.10 simonb int i, zone, tlbsize; 641 1.10 simonb u_int zpr, pid, opid, msr; 642 1.10 simonb u_long tlblo, tlbhi, tlbmask; 643 1.10 simonb 644 1.10 simonb zpr = mfspr(SPR_ZPR); 645 1.10 simonb for (i = 0; i < NTLB; i++) { 646 1.36 perry __asm volatile("mfmsr %3;" 647 1.59 rin MFPID(%4) 648 1.10 simonb "li %0,0;" 649 1.10 simonb "mtmsr %0;" 650 1.10 simonb "sync; isync;" 651 1.21 thorpej "tlbrelo %0,%5;" 652 1.21 thorpej "tlbrehi %1,%5;" 653 1.59 rin MFPID(%2) 654 1.59 rin MTPID(%4) 655 1.10 simonb "mtmsr %3;" 656 1.10 simonb "sync; isync" 657 1.48 kiyohara : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid), 658 1.10 simonb "=&r" (msr), "=&r" (opid) : "r" (i)); 659 1.10 simonb 660 1.10 simonb if (strchr(modif, 'v') && !(tlbhi & TLB_VALID)) 661 1.10 simonb continue; 662 1.10 simonb 663 1.10 simonb tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT; 664 1.10 simonb /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */ 665 1.10 simonb tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1; 666 1.10 simonb 667 1.10 simonb if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask))) 668 1.10 simonb continue; 669 1.10 simonb 670 1.10 simonb zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT; 671 1.10 simonb db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i); 672 1.10 simonb db_printf(" PID %3d EPN 0x%08lx %-5s", 673 1.10 simonb pid, 674 1.10 simonb tlbhi & tlbmask, 675 1.10 simonb tlbsizes[tlbsize]); 676 1.10 simonb db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s", 677 1.10 simonb tlblo & tlbmask, 678 1.10 simonb zone, 679 1.10 simonb "NTTA"[(zpr >> ((15 - zone) * 2)) & 3], 680 1.10 simonb tlblo & TLB_EX ? "EX" : " ", 681 1.10 simonb tlblo & TLB_WR ? "WR" : " ", 682 1.10 simonb tlblo & TLB_W ? 'W' : ' ', 683 1.10 simonb tlblo & TLB_I ? 'I' : ' ', 684 1.10 simonb tlblo & TLB_M ? 'M' : ' ', 685 1.10 simonb tlblo & TLB_G ? 'G' : ' ', 686 1.10 simonb tlbhi & TLB_ENDIAN ? 'E' : ' ', 687 1.10 simonb tlbhi & TLB_U0 ? "U0" : " "); 688 1.10 simonb db_printf("\n"); 689 1.10 simonb } 690 1.22 scw } 691 1.22 scw 692 1.22 scw static void 693 1.37 matt db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count, 694 1.34 scw const char *modif) 695 1.22 scw { 696 1.22 scw db_expr_t new_value; 697 1.22 scw db_expr_t addr; 698 1.23 scw 699 1.23 scw if (address < 0 || address > 0x3ff) 700 1.23 scw db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n"); 701 1.22 scw 702 1.22 scw addr = address; 703 1.22 scw 704 1.22 scw while (db_expression(&new_value)) { 705 1.22 scw db_printf("dcr 0x%lx\t\t%s = ", addr, 706 1.22 scw db_num_to_str(db_ppc4xx_mfdcr(addr))); 707 1.22 scw db_ppc4xx_mtdcr(addr, new_value); 708 1.22 scw db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr))); 709 1.22 scw addr += 1; 710 1.22 scw } 711 1.22 scw 712 1.22 scw if (addr == address) { 713 1.22 scw db_next = (db_addr_t)addr + 1; 714 1.22 scw db_prev = (db_addr_t)addr; 715 1.22 scw db_printf("dcr 0x%lx\t\t%s\n", addr, 716 1.22 scw db_num_to_str(db_ppc4xx_mfdcr(addr))); 717 1.22 scw } else { 718 1.22 scw db_next = (db_addr_t)addr; 719 1.22 scw db_prev = (db_addr_t)addr - 1; 720 1.22 scw } 721 1.22 scw 722 1.22 scw db_skip_to_eol(); 723 1.22 scw } 724 1.22 scw 725 1.22 scw /* 726 1.22 scw * XXX Grossness Alert! XXX 727 1.22 scw * 728 1.22 scw * Please look away now if you don't like self-modifying code 729 1.22 scw */ 730 1.22 scw static u_int32_t db_ppc4xx_dcrfunc[4]; 731 1.22 scw 732 1.22 scw static db_expr_t 733 1.22 scw db_ppc4xx_mfdcr(db_expr_t reg) 734 1.22 scw { 735 1.22 scw db_expr_t (*func)(void); 736 1.22 scw 737 1.22 scw reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11; 738 1.22 scw db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */ 739 1.22 scw db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */ 740 1.22 scw db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */ 741 1.22 scw db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */ 742 1.22 scw 743 1.22 scw __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc)); 744 1.22 scw func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc; 745 1.22 scw 746 1.22 scw return ((*func)()); 747 1.22 scw } 748 1.22 scw 749 1.22 scw static void 750 1.22 scw db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val) 751 1.22 scw { 752 1.22 scw db_expr_t (*func)(db_expr_t); 753 1.22 scw 754 1.22 scw reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11; 755 1.22 scw db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */ 756 1.22 scw db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */ 757 1.22 scw db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */ 758 1.22 scw db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */ 759 1.22 scw 760 1.22 scw __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc)); 761 1.22 scw func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc; 762 1.22 scw 763 1.22 scw (*func)(val); 764 1.10 simonb } 765 1.10 simonb 766 1.10 simonb #ifdef USERACC 767 1.10 simonb static void 768 1.37 matt db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count, 769 1.34 scw const char *modif) 770 1.10 simonb { 771 1.10 simonb static paddr_t oldaddr = -1; 772 1.10 simonb int instr = 0; 773 1.10 simonb int data; 774 1.10 simonb extern vaddr_t opc_disasm(vaddr_t loc, int); 775 1.10 simonb 776 1.10 simonb 777 1.10 simonb if (!have_addr) { 778 1.10 simonb addr = oldaddr; 779 1.10 simonb } 780 1.10 simonb if (addr == -1) { 781 1.10 simonb db_printf("no address\n"); 782 1.10 simonb return; 783 1.10 simonb } 784 1.10 simonb addr &= ~0x3; /* align */ 785 1.10 simonb { 786 1.34 scw const char *cp = modif; 787 1.34 scw char c; 788 1.10 simonb while ((c = *cp++) != 0) 789 1.10 simonb if (c == 'i') 790 1.10 simonb instr = 1; 791 1.10 simonb } 792 1.10 simonb while (count--) { 793 1.10 simonb if (db_print_position() == 0) { 794 1.10 simonb /* Always print the address. */ 795 1.10 simonb db_printf("%8.4lx:\t", addr); 796 1.10 simonb } 797 1.10 simonb oldaddr=addr; 798 1.10 simonb copyin((void *)addr, &data, sizeof(data)); 799 1.10 simonb if (instr) { 800 1.10 simonb opc_disasm(addr, data); 801 1.10 simonb } else { 802 1.10 simonb db_printf("%4.4x\n", data); 803 1.10 simonb } 804 1.10 simonb addr += 4; 805 1.10 simonb db_end_line(); 806 1.10 simonb } 807 1.10 simonb 808 1.10 simonb } 809 1.10 simonb #endif 810 1.10 simonb 811 1.10 simonb #endif /* PPC_IBM4XX */ 812 1.45 matt 813 1.45 matt #ifdef PPC_BOOKE 814 1.45 matt static void 815 1.45 matt db_ppcbooke_reset(db_expr_t addr, bool have_addr, db_expr_t count, 816 1.45 matt const char *modif) 817 1.45 matt { 818 1.58 msaitoh printf("Resetting...\n"); 819 1.45 matt (*cpu_md_ops.md_cpu_reset)(); 820 1.45 matt } 821 1.45 matt 822 1.45 matt static void 823 1.51 matt db_ppcbooke_splhist(db_expr_t addr, bool have_addr, db_expr_t count, 824 1.51 matt const char *modif) 825 1.51 matt { 826 1.51 matt dump_splhist(curcpu(), db_printf); 827 1.51 matt } 828 1.51 matt 829 1.51 matt static void 830 1.51 matt db_ppcbooke_tf(db_expr_t addr, bool have_addr, db_expr_t count, 831 1.51 matt const char *modif) 832 1.45 matt { 833 1.45 matt if (!have_addr) 834 1.45 matt return; 835 1.45 matt 836 1.51 matt dump_trapframe((const struct trapframe *)addr, db_printf); 837 1.45 matt } 838 1.45 matt 839 1.45 matt static void 840 1.45 matt db_ppcbooke_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count, 841 1.45 matt const char *modif) 842 1.45 matt { 843 1.45 matt tlb_dump(db_printf); 844 1.45 matt } 845 1.45 matt #endif /* PPC_BOOKE */ 846 1.53 nonaka 847 1.53 nonaka #ifdef MULTIPROCESSOR 848 1.53 nonaka bool 849 1.53 nonaka ddb_running_on_this_cpu_p(void) 850 1.53 nonaka { 851 1.53 nonaka 852 1.53 nonaka return ddb_cpu == cpu_number(); 853 1.53 nonaka } 854 1.53 nonaka 855 1.53 nonaka bool 856 1.53 nonaka ddb_running_on_any_cpu_p(void) 857 1.53 nonaka { 858 1.53 nonaka 859 1.53 nonaka return ddb_cpu != NOCPU; 860 1.53 nonaka } 861 1.53 nonaka 862 1.53 nonaka void 863 1.53 nonaka db_resume_others(void) 864 1.53 nonaka { 865 1.53 nonaka u_int cpu_me = cpu_number(); 866 1.53 nonaka 867 1.53 nonaka if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) 868 1.53 nonaka cpu_resume_others(); 869 1.53 nonaka } 870 1.53 nonaka 871 1.53 nonaka static void 872 1.53 nonaka db_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 873 1.53 nonaka { 874 1.53 nonaka CPU_INFO_ITERATOR cii; 875 1.53 nonaka struct cpu_info *ci; 876 1.53 nonaka bool found = false; 877 1.53 nonaka 878 1.53 nonaka if (!have_addr) { 879 1.53 nonaka cpu_debug_dump(); 880 1.53 nonaka return; 881 1.53 nonaka } 882 1.53 nonaka 883 1.53 nonaka if (addr < 0) { 884 1.53 nonaka db_printf("%ld: CPU out of range\n", addr); 885 1.53 nonaka return; 886 1.53 nonaka } 887 1.53 nonaka for (CPU_INFO_FOREACH(cii, ci)) { 888 1.53 nonaka if (cpu_index(ci) == addr) { 889 1.53 nonaka found = true; 890 1.53 nonaka break; 891 1.53 nonaka } 892 1.53 nonaka } 893 1.53 nonaka if (!found) { 894 1.53 nonaka db_printf("CPU %ld not configured\n", addr); 895 1.53 nonaka return; 896 1.53 nonaka } 897 1.53 nonaka if (ci != curcpu()) { 898 1.53 nonaka if (!cpu_is_paused(cpu_index(ci))) { 899 1.53 nonaka db_printf("CPU %ld not paused\n", (long)addr); 900 1.53 nonaka return; 901 1.53 nonaka } 902 1.53 nonaka (void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci)); 903 1.53 nonaka db_continue_cmd(0, false, 0, ""); 904 1.53 nonaka } 905 1.53 nonaka } 906 1.53 nonaka #endif /* MULTIPROCESSOR */ 907 1.61 andvar #endif /* DDB */ 908