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