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