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