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