db_interface.c revision 1.43.2.1 1 /* $NetBSD: db_interface.c,v 1.43.2.1 2010/04/30 14:39:45 uebayasi Exp $ */
2 /* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */
3
4 #include <sys/cdefs.h>
5 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.43.2.1 2010/04/30 14:39:45 uebayasi Exp $");
6
7 #define USERACC
8
9 #include "opt_ddb.h"
10 #include "opt_kgdb.h"
11 #include "opt_ppcarch.h"
12
13 #include <sys/param.h>
14 #include <sys/proc.h>
15 #include <sys/systm.h>
16
17 #include <dev/cons.h>
18
19 #include <machine/db_machdep.h>
20 #include <machine/frame.h>
21 #include <powerpc/spr.h>
22 #include <powerpc/cpu.h>
23 #include <powerpc/bat.h>
24 #include <powerpc/pte.h>
25
26 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
27 #include <powerpc/oea/spr.h>
28 #endif
29
30 #ifdef PPC_IBM4XX
31 #include <powerpc/ibm4xx/spr.h>
32 #include <machine/tlb.h>
33 #include <uvm/uvm_extern.h>
34 #endif
35
36 #ifdef PPC_BOOKE
37 #include <powerpc/booke/spr.h>
38 #endif
39
40 #ifdef DDB
41 #include <ddb/db_sym.h>
42 #include <ddb/db_command.h>
43 #include <ddb/db_extern.h>
44 #include <ddb/db_access.h>
45 #include <ddb/db_lex.h>
46 #include <ddb/db_output.h>
47 #include <ddb/ddbvar.h>
48 #endif
49
50 #ifdef KGDB
51 #include <sys/kgdb.h>
52 #define db_printf printf
53 #endif
54
55 #include <dev/ofw/openfirm.h>
56
57 int db_active = 0;
58
59 db_regs_t ddb_regs;
60
61 void ddb_trap(void); /* Call into trap_subr.S */
62 int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */
63 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
64 static void db_show_bat(db_expr_t, bool, db_expr_t, const char *);
65 static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *);
66 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
67 #ifdef PPC_IBM4XX
68 static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *);
69 static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *);
70 static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *);
71 static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *);
72 static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *);
73 static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *);
74 static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
75 static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
76 #ifdef USERACC
77 static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *);
78 #endif
79 #endif /* PPC_IBM4XX */
80
81 #ifdef DDB
82 const struct db_command db_machine_command_table[] = {
83 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
84 { DDB_ADD_CMD("bat", db_show_bat, 0,
85 "Print BAT register translations", NULL,NULL) },
86 { DDB_ADD_CMD("mmu", db_show_mmu, 0,
87 "Print MMU registers", NULL,NULL) },
88 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
89 #ifdef PPC_IBM4XX
90 { DDB_ADD_CMD("ctx", db_ppc4xx_ctx, 0,
91 "Print process MMU context information", NULL,NULL) },
92 { DDB_ADD_CMD("pv", db_ppc4xx_pv, 0,
93 "Print PA->VA mapping information",
94 "address",
95 " address:\tphysical address to look up") },
96 { DDB_ADD_CMD("reset", db_ppc4xx_reset, 0,
97 "Reset the system ", NULL,NULL) },
98 { DDB_ADD_CMD("tf", db_ppc4xx_tf, 0,
99 "Display the contents of the trapframe",
100 "address",
101 " address:\tthe struct trapframe to print") },
102 { DDB_ADD_CMD("tlb", db_ppc4xx_dumptlb, 0,
103 "Display instruction translation storage buffer information.",
104 NULL,NULL) },
105 { DDB_ADD_CMD("dcr", db_ppc4xx_dcr, CS_MORE|CS_SET_DOT,
106 "Set the DCR register",
107 "dcr",
108 " dcr:\tNew DCR value (between 0x0 and 0x3ff)") },
109 #ifdef USERACC
110 { DDB_ADD_CMD("user", db_ppc4xx_useracc, 0,
111 "Display user memory.", "[address][,count]",
112 " address:\tuserspace address to start\n"
113 " count:\tnumber of bytes to display") },
114 #endif
115 #endif /* PPC_IBM4XX */
116 { DDB_ADD_CMD(NULL, NULL, 0,
117 NULL,NULL,NULL) }
118 };
119
120 void
121 cpu_Debugger(void)
122 {
123 ddb_trap();
124 }
125 #endif
126
127 int
128 ddb_trap_glue(struct trapframe *frame)
129 {
130 #ifdef PPC_IBM4XX
131 if ((frame->srr1 & PSL_PR) == 0)
132 return kdb_trap(frame->exc, frame);
133 #else /* PPC_OEA */
134 if ((frame->srr1 & PSL_PR) == 0 &&
135 (frame->exc == EXC_TRC ||
136 frame->exc == EXC_RUNMODETRC ||
137 (frame->exc == EXC_PGM && (frame->srr1 & 0x20000)) ||
138 frame->exc == EXC_BPT ||
139 frame->exc == EXC_DSI)) {
140 int type = frame->exc;
141 if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
142 type = T_BREAKPOINT;
143 }
144 return kdb_trap(type, frame);
145 }
146 #endif
147 return 0;
148 }
149
150 int
151 kdb_trap(int type, void *v)
152 {
153 struct trapframe *frame = v;
154
155 #ifdef DDB
156 if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) {
157 db_error("Faulted in DDB; continuing...\n");
158 /* NOTREACHED */
159 }
160 #endif
161
162 /* XXX Should switch to kdb's own stack here. */
163
164 memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
165 DDB_REGS->iar = frame->srr0;
166 DDB_REGS->msr = frame->srr1;
167 DDB_REGS->lr = frame->lr;
168 DDB_REGS->ctr = frame->ctr;
169 DDB_REGS->cr = frame->cr;
170 DDB_REGS->xer = frame->xer;
171 #ifdef PPC_OEA
172 DDB_REGS->mq = frame->tf_xtra[TF_MQ];
173 #endif
174 #ifdef PPC_IBM4XX
175 DDB_REGS->dear = frame->dar;
176 DDB_REGS->esr = frame->tf_xtra[TF_ESR];
177 DDB_REGS->pid = frame->tf_xtra[TF_PID];
178 #endif
179
180 #ifdef DDB
181 db_active++;
182 cnpollc(1);
183 db_trap(type, 0);
184 cnpollc(0);
185 db_active--;
186 #elif defined(KGDB)
187 if (!kgdb_trap(type, DDB_REGS))
188 return 0;
189 #endif
190
191 /* KGDB isn't smart about advancing PC if we
192 * take a breakpoint trap after kgdb_active is set.
193 * Therefore, we help out here.
194 */
195 if (IS_BREAKPOINT_TRAP(type, 0)) {
196 int bkpt;
197 db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
198 if (bkpt== BKPT_INST) {
199 PC_REGS(DDB_REGS) += BKPT_SIZE;
200 }
201 }
202
203 memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
204 frame->srr0 = DDB_REGS->iar;
205 frame->srr1 = DDB_REGS->msr;
206 frame->lr = DDB_REGS->lr;
207 frame->ctr = DDB_REGS->ctr;
208 frame->cr = DDB_REGS->cr;
209 frame->xer = DDB_REGS->xer;
210 #ifdef PPC_OEA
211 frame->tf_xtra[TF_MQ] = DDB_REGS->mq;
212 #endif
213 #ifdef PPC_IBM4XX
214 frame->dar = DDB_REGS->dear;
215 frame->tf_xtra[TF_ESR] = DDB_REGS->esr;
216 frame->tf_xtra[TF_PID] = DDB_REGS->pid;
217 #endif
218
219 return 1;
220 }
221
222 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
223 static void
224 print_battranslation(struct bat *bat, unsigned int blidx)
225 {
226 static const char *const batsizes[] = {
227 "128kB",
228 "256kB",
229 "512kB",
230 "1MB",
231 "2MB",
232 "4MB",
233 "8MB",
234 "16MB",
235 "32MB",
236 "64MB",
237 "128MB",
238 "256MB"
239 };
240 vsize_t len;
241
242 len = (0x20000L << blidx) - 1;
243 db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n",
244 bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len,
245 (bat->batu & ~len) + len, bat->batl & ~len);
246 }
247
248 static void
249 print_batmodes(register_t super, register_t user, register_t pp)
250 {
251 static const char *const accessmodes[] = {
252 "none",
253 "ro soft",
254 "read/write",
255 "read only"
256 };
257
258 db_printf("\tvalid: %c%c access: %-10s memory:",
259 super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]);
260 }
261
262 static void
263 print_wimg(register_t wimg)
264 {
265 if (wimg & BAT_W)
266 db_printf(" wrthrough");
267 if (wimg & BAT_I)
268 db_printf(" nocache");
269 if (wimg & BAT_M)
270 db_printf(" coherent");
271 if (wimg & BAT_G)
272 db_printf(" guard");
273 }
274
275 static void
276 print_bat(struct bat *bat)
277 {
278 if ((bat->batu & BAT_V) == 0) {
279 db_printf("\tdisabled\n\n");
280 return;
281 }
282 print_battranslation(bat, 30 - __builtin_clz((bat->batu & BAT_BL)|2));
283 print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
284 bat->batl & BAT_PP);
285 print_wimg(bat->batl & BAT_WIMG);
286 db_printf("\n");
287 }
288
289 #ifdef PPC_OEA601
290 static void
291 print_bat601(struct bat *bat)
292 {
293 if ((bat->batl & BAT601_V) == 0) {
294 db_printf("\tdisabled\n\n");
295 return;
296 }
297 print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM));
298 print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku,
299 bat->batu & BAT601_PP);
300 print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M));
301 db_printf("\n");
302 }
303 #endif
304
305 static void
306 db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
307 {
308 struct bat ibat[4];
309 struct bat dbat[4];
310 unsigned int cpuvers;
311 int i;
312
313 cpuvers = mfpvr() >> 16;
314
315 __asm volatile ("mfibatu %0,0" : "=r"(ibat[0].batu));
316 __asm volatile ("mfibatl %0,0" : "=r"(ibat[0].batl));
317 __asm volatile ("mfibatu %0,1" : "=r"(ibat[1].batu));
318 __asm volatile ("mfibatl %0,1" : "=r"(ibat[1].batl));
319 __asm volatile ("mfibatu %0,2" : "=r"(ibat[2].batu));
320 __asm volatile ("mfibatl %0,2" : "=r"(ibat[2].batl));
321 __asm volatile ("mfibatu %0,3" : "=r"(ibat[3].batu));
322 __asm volatile ("mfibatl %0,3" : "=r"(ibat[3].batl));
323
324 if (cpuvers != MPC601) {
325 /* The 601 has only four unified BATs */
326 __asm volatile ("mfdbatu %0,0" : "=r"(dbat[0].batu));
327 __asm volatile ("mfdbatl %0,0" : "=r"(dbat[0].batl));
328 __asm volatile ("mfdbatu %0,1" : "=r"(dbat[1].batu));
329 __asm volatile ("mfdbatl %0,1" : "=r"(dbat[1].batl));
330 __asm volatile ("mfdbatu %0,2" : "=r"(dbat[2].batu));
331 __asm volatile ("mfdbatl %0,2" : "=r"(dbat[2].batl));
332 __asm volatile ("mfdbatu %0,3" : "=r"(dbat[3].batu));
333 __asm volatile ("mfdbatl %0,3" : "=r"(dbat[3].batl));
334 }
335
336 for (i = 0; i < 4; i++) {
337 #ifdef PPC_OEA601
338 if (cpuvers == MPC601) {
339 db_printf("bat%d:", i);
340 print_bat601(&ibat[i]);
341 } else
342 #endif
343 {
344 db_printf("ibat%d:", i);
345 print_bat(&ibat[i]);
346 }
347 }
348 if (cpuvers != MPC601) {
349 for (i = 0; i < 4; i++) {
350 db_printf("dbat%d:", i);
351 print_bat(&dbat[i]);
352 }
353 }
354 }
355
356 static void
357 db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
358 {
359 paddr_t sdr1;
360 #if !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
361 register_t sr;
362 vaddr_t saddr;
363 int i;
364 #endif
365
366 __asm volatile ("mfsdr1 %0" : "=r"(sdr1));
367 db_printf("sdr1\t\t0x%08lx\n", sdr1);
368
369 #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
370 __asm volatile ("mfasr %0" : "=r"(sdr1));
371 db_printf("asr\t\t0x%08lx\n", sdr1);
372 #else
373 saddr = 0;
374 for (i = 0; i<= 0xf; i++) {
375 if ((i & 3) == 0)
376 db_printf("sr%d-%d\t\t", i, i+3);
377 __asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
378 db_printf("0x%08lx %c", sr, (i&3) == 3 ? '\n' : ' ');
379 saddr += 1 << ADDR_SR_SHFT;
380 }
381 #endif
382 }
383 #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
384
385 #ifdef PPC_IBM4XX
386 db_addr_t
387 branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
388 {
389
390 if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
391 db_expr_t off;
392 off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
393 return (((inst & 0x2) ? 0 : pc) + off);
394 }
395
396 if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
397 db_expr_t off;
398 off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
399 return (((inst & 0x2) ? 0 : pc) + off);
400 }
401
402 if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
403 return (regs->lr);
404
405 if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
406 return (regs->ctr);
407
408 db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
409 inst);
410 return (0);
411 }
412
413
414 #ifdef DDB
415 static void
416 db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
417 {
418 struct proc *p;
419
420 /* XXX LOCKING XXX */
421 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
422 if (p->p_stat) {
423 db_printf("process %p:", p);
424 db_printf("pid:%d pmap:%p ctx:%d %s\n",
425 p->p_pid, p->p_vmspace->vm_map.pmap,
426 p->p_vmspace->vm_map.pmap->pm_ctx,
427 p->p_comm);
428 }
429 }
430 return;
431 }
432
433 static void
434 db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
435 {
436 struct pv_entry {
437 struct pv_entry *pv_next; /* Linked list of mappings */
438 vaddr_t pv_va; /* virtual address of mapping */
439 struct pmap *pv_pm;
440 };
441 struct pv_entry *pa_to_pv(paddr_t);
442 struct pv_entry *pv;
443
444 if (!have_addr) {
445 db_printf("pv: <pa>\n");
446 return;
447 }
448 pv = pa_to_pv(addr);
449 db_printf("pv at %p\n", pv);
450 while (pv && pv->pv_pm) {
451 db_printf("next %p va %p pmap %p\n", pv->pv_next,
452 (void *)pv->pv_va, pv->pv_pm);
453 pv = pv->pv_next;
454 }
455 }
456
457 static void
458 db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
459 const char *modif)
460 {
461 printf("Reseting...\n");
462 ppc4xx_reset();
463 }
464
465 static void
466 db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
467 {
468 struct trapframe *f;
469
470
471 if (have_addr) {
472 f = (struct trapframe *)addr;
473
474 db_printf("r0-r3: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
475 f->fixreg[0], f->fixreg[1],
476 f->fixreg[2], f->fixreg[3]);
477 db_printf("r4-r7: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
478 f->fixreg[4], f->fixreg[5],
479 f->fixreg[6], f->fixreg[7]);
480 db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
481 f->fixreg[8], f->fixreg[9],
482 f->fixreg[10], f->fixreg[11]);
483 db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
484 f->fixreg[12], f->fixreg[13],
485 f->fixreg[14], f->fixreg[15]);
486 db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
487 f->fixreg[16], f->fixreg[17],
488 f->fixreg[18], f->fixreg[19]);
489 db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
490 f->fixreg[20], f->fixreg[21],
491 f->fixreg[22], f->fixreg[23]);
492 db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
493 f->fixreg[24], f->fixreg[25],
494 f->fixreg[26], f->fixreg[27]);
495 db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
496 f->fixreg[28], f->fixreg[29],
497 f->fixreg[30], f->fixreg[31]);
498
499 db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
500 f->lr, f->cr, f->xer, f->ctr);
501 db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
502 "dear: %8.8lx esr: %8.8x\n",
503 f->srr0, f->srr1, f->dar, f->tf_xtra[TF_ESR]);
504 db_printf("exc: %8.8x pid: %8.8x\n",
505 f->exc, f->tf_xtra[TF_PID]);
506 }
507 return;
508 }
509
510 static const char *const tlbsizes[] = {
511 "1kB",
512 "4kB",
513 "16kB",
514 "64kB",
515 "256kB",
516 "1MB",
517 "4MB",
518 "16MB"
519 };
520
521 static void
522 db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
523 const char *modif)
524 {
525 int i, zone, tlbsize;
526 u_int zpr, pid, opid, msr;
527 u_long tlblo, tlbhi, tlbmask;
528
529 zpr = mfspr(SPR_ZPR);
530 for (i = 0; i < NTLB; i++) {
531 __asm volatile("mfmsr %3;"
532 "mfpid %4;"
533 "li %0,0;"
534 "mtmsr %0;"
535 "sync; isync;"
536 "tlbrelo %0,%5;"
537 "tlbrehi %1,%5;"
538 "mfpid %2;"
539 "mtpid %4;"
540 "mtmsr %3;"
541 "sync; isync"
542 : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
543 "=&r" (msr), "=&r" (opid) : "r" (i));
544
545 if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
546 continue;
547
548 tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
549 /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
550 tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
551
552 if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
553 continue;
554
555 zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
556 db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
557 db_printf(" PID %3d EPN 0x%08lx %-5s",
558 pid,
559 tlbhi & tlbmask,
560 tlbsizes[tlbsize]);
561 db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
562 tlblo & tlbmask,
563 zone,
564 "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
565 tlblo & TLB_EX ? "EX" : " ",
566 tlblo & TLB_WR ? "WR" : " ",
567 tlblo & TLB_W ? 'W' : ' ',
568 tlblo & TLB_I ? 'I' : ' ',
569 tlblo & TLB_M ? 'M' : ' ',
570 tlblo & TLB_G ? 'G' : ' ',
571 tlbhi & TLB_ENDIAN ? 'E' : ' ',
572 tlbhi & TLB_U0 ? "U0" : " ");
573 db_printf("\n");
574 }
575 }
576
577 static void
578 db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
579 const char *modif)
580 {
581 db_expr_t new_value;
582 db_expr_t addr;
583
584 if (address < 0 || address > 0x3ff)
585 db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
586
587 addr = address;
588
589 while (db_expression(&new_value)) {
590 db_printf("dcr 0x%lx\t\t%s = ", addr,
591 db_num_to_str(db_ppc4xx_mfdcr(addr)));
592 db_ppc4xx_mtdcr(addr, new_value);
593 db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
594 addr += 1;
595 }
596
597 if (addr == address) {
598 db_next = (db_addr_t)addr + 1;
599 db_prev = (db_addr_t)addr;
600 db_printf("dcr 0x%lx\t\t%s\n", addr,
601 db_num_to_str(db_ppc4xx_mfdcr(addr)));
602 } else {
603 db_next = (db_addr_t)addr;
604 db_prev = (db_addr_t)addr - 1;
605 }
606
607 db_skip_to_eol();
608 }
609
610 /*
611 * XXX Grossness Alert! XXX
612 *
613 * Please look away now if you don't like self-modifying code
614 */
615 static u_int32_t db_ppc4xx_dcrfunc[4];
616
617 static db_expr_t
618 db_ppc4xx_mfdcr(db_expr_t reg)
619 {
620 db_expr_t (*func)(void);
621
622 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
623 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
624 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
625 db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
626 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
627
628 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
629 func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
630
631 return ((*func)());
632 }
633
634 static void
635 db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
636 {
637 db_expr_t (*func)(db_expr_t);
638
639 reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
640 db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
641 db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
642 db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
643 db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
644
645 __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
646 func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
647
648 (*func)(val);
649 }
650
651 #ifdef USERACC
652 static void
653 db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
654 const char *modif)
655 {
656 static paddr_t oldaddr = -1;
657 int instr = 0;
658 int data;
659 extern vaddr_t opc_disasm(vaddr_t loc, int);
660
661
662 if (!have_addr) {
663 addr = oldaddr;
664 }
665 if (addr == -1) {
666 db_printf("no address\n");
667 return;
668 }
669 addr &= ~0x3; /* align */
670 {
671 const char *cp = modif;
672 char c;
673 while ((c = *cp++) != 0)
674 if (c == 'i')
675 instr = 1;
676 }
677 while (count--) {
678 if (db_print_position() == 0) {
679 /* Always print the address. */
680 db_printf("%8.4lx:\t", addr);
681 }
682 oldaddr=addr;
683 copyin((void *)addr, &data, sizeof(data));
684 if (instr) {
685 opc_disasm(addr, data);
686 } else {
687 db_printf("%4.4x\n", data);
688 }
689 addr += 4;
690 db_end_line();
691 }
692
693 }
694 #endif
695
696 #endif /* DDB */
697
698 #endif /* PPC_IBM4XX */
699