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