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