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