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