db_interface.c revision 1.12.6.8 1 1.12.6.8 thorpej /* $NetBSD: db_interface.c,v 1.12.6.8 2003/01/04 23:51:18 thorpej Exp $ */
2 1.12.6.2 nathanw /* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */
3 1.12.6.2 nathanw
4 1.12.6.2 nathanw #define USERACC
5 1.12.6.2 nathanw
6 1.12.6.2 nathanw #include "opt_ddb.h"
7 1.12.6.3 nathanw #include "opt_kgdb.h"
8 1.12.6.2 nathanw #include "opt_ppcarch.h"
9 1.12.6.2 nathanw
10 1.12.6.2 nathanw #include <sys/param.h>
11 1.12.6.2 nathanw #include <sys/proc.h>
12 1.12.6.2 nathanw #include <sys/systm.h>
13 1.12.6.2 nathanw
14 1.12.6.2 nathanw #include <dev/cons.h>
15 1.12.6.2 nathanw
16 1.12.6.2 nathanw #include <machine/db_machdep.h>
17 1.12.6.2 nathanw #include <machine/frame.h>
18 1.12.6.2 nathanw #ifdef PPC_IBM4XX
19 1.12.6.2 nathanw #include <machine/tlb.h>
20 1.12.6.2 nathanw #include <powerpc/spr.h>
21 1.12.6.2 nathanw #include <uvm/uvm_extern.h>
22 1.12.6.2 nathanw #endif
23 1.12.6.2 nathanw
24 1.12.6.3 nathanw #ifdef DDB
25 1.12.6.2 nathanw #include <ddb/db_sym.h>
26 1.12.6.2 nathanw #include <ddb/db_command.h>
27 1.12.6.2 nathanw #include <ddb/db_extern.h>
28 1.12.6.2 nathanw #include <ddb/db_access.h>
29 1.12.6.7 thorpej #include <ddb/db_lex.h>
30 1.12.6.2 nathanw #include <ddb/db_output.h>
31 1.12.6.2 nathanw #include <ddb/ddbvar.h>
32 1.12.6.3 nathanw #endif
33 1.12.6.3 nathanw
34 1.12.6.3 nathanw #ifdef KGDB
35 1.12.6.3 nathanw #include <sys/kgdb.h>
36 1.12.6.3 nathanw #endif
37 1.12.6.3 nathanw
38 1.12.6.3 nathanw #include <dev/ofw/openfirm.h>
39 1.12.6.2 nathanw
40 1.12.6.2 nathanw int db_active = 0;
41 1.12.6.2 nathanw
42 1.12.6.5 nathanw db_regs_t ddb_regs;
43 1.12.6.2 nathanw
44 1.12.6.2 nathanw void ddb_trap(void); /* Call into trap_subr.S */
45 1.12.6.2 nathanw int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */
46 1.12.6.2 nathanw #ifdef PPC_IBM4XX
47 1.12.6.2 nathanw static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
48 1.12.6.2 nathanw static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
49 1.12.6.2 nathanw static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
50 1.12.6.2 nathanw static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
51 1.12.6.2 nathanw static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
52 1.12.6.7 thorpej static void db_ppc4xx_dcr(db_expr_t, int, db_expr_t, char *);
53 1.12.6.7 thorpej static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
54 1.12.6.7 thorpej static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
55 1.12.6.2 nathanw #ifdef USERACC
56 1.12.6.2 nathanw static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
57 1.12.6.2 nathanw #endif
58 1.12.6.2 nathanw #endif /* PPC_IBM4XX */
59 1.12.6.2 nathanw
60 1.12.6.3 nathanw #ifdef DDB
61 1.12.6.2 nathanw void
62 1.12.6.2 nathanw cpu_Debugger()
63 1.12.6.2 nathanw {
64 1.12.6.2 nathanw ddb_trap();
65 1.12.6.2 nathanw }
66 1.12.6.3 nathanw #endif
67 1.12.6.2 nathanw
68 1.12.6.2 nathanw int
69 1.12.6.2 nathanw ddb_trap_glue(frame)
70 1.12.6.2 nathanw struct trapframe *frame;
71 1.12.6.2 nathanw {
72 1.12.6.8 thorpej #ifdef PPC_IBM4XX
73 1.12.6.8 thorpej if ((frame->srr1 & PSL_PR) == 0)
74 1.12.6.8 thorpej return kdb_trap(frame->exc, frame);
75 1.12.6.8 thorpej #else /* PPC_MPC6XX */
76 1.12.6.8 thorpej if ((frame->srr1 & PSL_PR) == 0 &&
77 1.12.6.8 thorpej (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC ||
78 1.12.6.8 thorpej (frame->exc == EXC_PGM && (frame->srr1 & 0x20000)) ||
79 1.12.6.8 thorpej frame->exc == EXC_BPT)) {
80 1.12.6.3 nathanw int type = frame->exc;
81 1.12.6.3 nathanw if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
82 1.12.6.3 nathanw type = T_BREAKPOINT;
83 1.12.6.3 nathanw }
84 1.12.6.3 nathanw return kdb_trap(type, frame);
85 1.12.6.2 nathanw }
86 1.12.6.7 thorpej #endif
87 1.12.6.8 thorpej return 0;
88 1.12.6.2 nathanw }
89 1.12.6.2 nathanw
90 1.12.6.2 nathanw int
91 1.12.6.2 nathanw kdb_trap(type, v)
92 1.12.6.2 nathanw int type;
93 1.12.6.2 nathanw void *v;
94 1.12.6.2 nathanw {
95 1.12.6.2 nathanw struct trapframe *frame = v;
96 1.12.6.2 nathanw
97 1.12.6.3 nathanw #ifdef DDB
98 1.12.6.2 nathanw switch (type) {
99 1.12.6.2 nathanw case T_BREAKPOINT:
100 1.12.6.2 nathanw case -1:
101 1.12.6.2 nathanw break;
102 1.12.6.2 nathanw default:
103 1.12.6.2 nathanw if (!db_onpanic && db_recover == 0)
104 1.12.6.2 nathanw return 0;
105 1.12.6.2 nathanw if (db_recover != 0) {
106 1.12.6.2 nathanw db_error("Faulted in DDB; continuing...\n");
107 1.12.6.2 nathanw /*NOTREACHED*/
108 1.12.6.2 nathanw }
109 1.12.6.2 nathanw }
110 1.12.6.3 nathanw #endif
111 1.12.6.2 nathanw
112 1.12.6.2 nathanw /* XXX Should switch to kdb's own stack here. */
113 1.12.6.2 nathanw
114 1.12.6.2 nathanw memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
115 1.12.6.2 nathanw DDB_REGS->iar = frame->srr0;
116 1.12.6.2 nathanw DDB_REGS->msr = frame->srr1;
117 1.12.6.2 nathanw DDB_REGS->lr = frame->lr;
118 1.12.6.2 nathanw DDB_REGS->ctr = frame->ctr;
119 1.12.6.2 nathanw DDB_REGS->cr = frame->cr;
120 1.12.6.2 nathanw DDB_REGS->xer = frame->xer;
121 1.12.6.2 nathanw #ifdef PPC_IBM4XX
122 1.12.6.2 nathanw DDB_REGS->dear = frame->dear;
123 1.12.6.2 nathanw DDB_REGS->esr = frame->esr;
124 1.12.6.2 nathanw DDB_REGS->pid = frame->pid;
125 1.12.6.2 nathanw #endif
126 1.12.6.2 nathanw
127 1.12.6.3 nathanw #ifdef DDB
128 1.12.6.2 nathanw db_active++;
129 1.12.6.2 nathanw cnpollc(1);
130 1.12.6.2 nathanw db_trap(type, 0);
131 1.12.6.2 nathanw cnpollc(0);
132 1.12.6.2 nathanw db_active--;
133 1.12.6.3 nathanw #elif defined(KGDB)
134 1.12.6.3 nathanw if (!kgdb_trap(type, DDB_REGS))
135 1.12.6.3 nathanw return 0;
136 1.12.6.3 nathanw #endif
137 1.12.6.3 nathanw
138 1.12.6.3 nathanw /* KGDB isn't smart about advancing PC if we
139 1.12.6.3 nathanw * take a breakpoint trap after kgdb_active is set.
140 1.12.6.3 nathanw * Therefore, we help out here.
141 1.12.6.3 nathanw */
142 1.12.6.3 nathanw if (IS_BREAKPOINT_TRAP(type, 0)) {
143 1.12.6.3 nathanw int bkpt;
144 1.12.6.3 nathanw db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
145 1.12.6.3 nathanw if (bkpt== BKPT_INST) {
146 1.12.6.3 nathanw PC_REGS(DDB_REGS) += BKPT_SIZE;
147 1.12.6.3 nathanw }
148 1.12.6.3 nathanw }
149 1.12.6.2 nathanw
150 1.12.6.2 nathanw memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
151 1.12.6.2 nathanw frame->srr0 = DDB_REGS->iar;
152 1.12.6.2 nathanw frame->srr1 = DDB_REGS->msr;
153 1.12.6.2 nathanw frame->lr = DDB_REGS->lr;
154 1.12.6.2 nathanw frame->ctr = DDB_REGS->ctr;
155 1.12.6.2 nathanw frame->cr = DDB_REGS->cr;
156 1.12.6.2 nathanw frame->xer = DDB_REGS->xer;
157 1.12.6.2 nathanw #ifdef PPC_IBM4XX
158 1.12.6.2 nathanw frame->dear = DDB_REGS->dear;
159 1.12.6.2 nathanw frame->esr = DDB_REGS->esr;
160 1.12.6.2 nathanw frame->pid = DDB_REGS->pid;
161 1.12.6.2 nathanw #endif
162 1.12.6.2 nathanw
163 1.12.6.2 nathanw return 1;
164 1.12.6.2 nathanw }
165 1.12.6.2 nathanw
166 1.12.6.2 nathanw #ifdef PPC_IBM4XX
167 1.12.6.7 thorpej db_addr_t
168 1.12.6.7 thorpej branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
169 1.12.6.7 thorpej {
170 1.12.6.7 thorpej
171 1.12.6.7 thorpej if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
172 1.12.6.7 thorpej db_expr_t off;
173 1.12.6.7 thorpej off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
174 1.12.6.7 thorpej return (((inst & 0x2) ? 0 : pc) + off);
175 1.12.6.7 thorpej }
176 1.12.6.7 thorpej
177 1.12.6.7 thorpej if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
178 1.12.6.7 thorpej db_expr_t off;
179 1.12.6.7 thorpej off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
180 1.12.6.7 thorpej return (((inst & 0x2) ? 0 : pc) + off);
181 1.12.6.7 thorpej }
182 1.12.6.7 thorpej
183 1.12.6.7 thorpej if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
184 1.12.6.7 thorpej return (regs->lr);
185 1.12.6.7 thorpej
186 1.12.6.7 thorpej if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
187 1.12.6.7 thorpej return (regs->ctr);
188 1.12.6.7 thorpej
189 1.12.6.7 thorpej db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
190 1.12.6.7 thorpej inst);
191 1.12.6.7 thorpej return (0);
192 1.12.6.7 thorpej }
193 1.12.6.7 thorpej
194 1.12.6.2 nathanw const struct db_command db_machine_command_table[] = {
195 1.12.6.2 nathanw { "ctx", db_ppc4xx_ctx, 0, 0 },
196 1.12.6.2 nathanw { "pv", db_ppc4xx_pv, 0, 0 },
197 1.12.6.2 nathanw { "reset", db_ppc4xx_reset, 0, 0 },
198 1.12.6.7 thorpej { "tf", db_ppc4xx_tf, 0, 0 },
199 1.12.6.2 nathanw { "tlb", db_ppc4xx_dumptlb, 0, 0 },
200 1.12.6.7 thorpej { "dcr", db_ppc4xx_dcr, CS_MORE|CS_SET_DOT, 0 },
201 1.12.6.2 nathanw #ifdef USERACC
202 1.12.6.2 nathanw { "user", db_ppc4xx_useracc, 0, 0 },
203 1.12.6.2 nathanw #endif
204 1.12.6.2 nathanw { NULL, }
205 1.12.6.2 nathanw };
206 1.12.6.2 nathanw
207 1.12.6.2 nathanw static void
208 1.12.6.2 nathanw db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
209 1.12.6.2 nathanw {
210 1.12.6.2 nathanw struct proc *p;
211 1.12.6.2 nathanw
212 1.12.6.2 nathanw /* XXX LOCKING XXX */
213 1.12.6.2 nathanw for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
214 1.12.6.2 nathanw if (p->p_stat) {
215 1.12.6.2 nathanw db_printf("process %p:", p);
216 1.12.6.2 nathanw db_printf("pid:%d pmap:%p ctx:%d %s\n",
217 1.12.6.2 nathanw p->p_pid, p->p_vmspace->vm_map.pmap,
218 1.12.6.2 nathanw p->p_vmspace->vm_map.pmap->pm_ctx,
219 1.12.6.2 nathanw p->p_comm);
220 1.12.6.2 nathanw }
221 1.12.6.2 nathanw }
222 1.12.6.2 nathanw return;
223 1.12.6.2 nathanw }
224 1.12.6.2 nathanw
225 1.12.6.2 nathanw static void
226 1.12.6.2 nathanw db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
227 1.12.6.2 nathanw {
228 1.12.6.2 nathanw struct pv_entry {
229 1.12.6.2 nathanw struct pv_entry *pv_next; /* Linked list of mappings */
230 1.12.6.2 nathanw vaddr_t pv_va; /* virtual address of mapping */
231 1.12.6.2 nathanw struct pmap *pv_pm;
232 1.12.6.2 nathanw };
233 1.12.6.2 nathanw struct pv_entry *pa_to_pv(paddr_t);
234 1.12.6.2 nathanw struct pv_entry *pv;
235 1.12.6.2 nathanw
236 1.12.6.2 nathanw if (!have_addr) {
237 1.12.6.2 nathanw db_printf("pv: <pa>\n");
238 1.12.6.2 nathanw return;
239 1.12.6.2 nathanw }
240 1.12.6.2 nathanw pv = pa_to_pv(addr);
241 1.12.6.2 nathanw db_printf("pv at %p\n", pv);
242 1.12.6.2 nathanw while (pv && pv->pv_pm) {
243 1.12.6.2 nathanw db_printf("next %p va %p pmap %p\n", pv->pv_next,
244 1.12.6.2 nathanw (void *)pv->pv_va, pv->pv_pm);
245 1.12.6.2 nathanw pv = pv->pv_next;
246 1.12.6.2 nathanw }
247 1.12.6.2 nathanw }
248 1.12.6.2 nathanw
249 1.12.6.2 nathanw static void
250 1.12.6.2 nathanw db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
251 1.12.6.2 nathanw {
252 1.12.6.2 nathanw printf("Reseting...\n");
253 1.12.6.2 nathanw ppc4xx_reset();
254 1.12.6.2 nathanw }
255 1.12.6.2 nathanw
256 1.12.6.2 nathanw static void
257 1.12.6.2 nathanw db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
258 1.12.6.2 nathanw {
259 1.12.6.2 nathanw struct trapframe *f;
260 1.12.6.2 nathanw
261 1.12.6.2 nathanw
262 1.12.6.2 nathanw if (have_addr) {
263 1.12.6.2 nathanw f = (struct trapframe *)addr;
264 1.12.6.2 nathanw
265 1.12.6.2 nathanw db_printf("r0-r3: \t%8.8x %8.8x %8.8x %8.8x\n",
266 1.12.6.2 nathanw f->fixreg[0], f->fixreg[1],
267 1.12.6.2 nathanw f->fixreg[2], f->fixreg[3]);
268 1.12.6.2 nathanw db_printf("r4-r7: \t%8.8x %8.8x %8.8x %8.8x\n",
269 1.12.6.2 nathanw f->fixreg[4], f->fixreg[5],
270 1.12.6.2 nathanw f->fixreg[6], f->fixreg[7]);
271 1.12.6.2 nathanw db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
272 1.12.6.2 nathanw f->fixreg[8], f->fixreg[9],
273 1.12.6.2 nathanw f->fixreg[10], f->fixreg[11]);
274 1.12.6.2 nathanw db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
275 1.12.6.2 nathanw f->fixreg[12], f->fixreg[13],
276 1.12.6.2 nathanw f->fixreg[14], f->fixreg[15]);
277 1.12.6.2 nathanw db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
278 1.12.6.2 nathanw f->fixreg[16], f->fixreg[17],
279 1.12.6.2 nathanw f->fixreg[18], f->fixreg[19]);
280 1.12.6.2 nathanw db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
281 1.12.6.2 nathanw f->fixreg[20], f->fixreg[21],
282 1.12.6.2 nathanw f->fixreg[22], f->fixreg[23]);
283 1.12.6.2 nathanw db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
284 1.12.6.2 nathanw f->fixreg[24], f->fixreg[25],
285 1.12.6.2 nathanw f->fixreg[26], f->fixreg[27]);
286 1.12.6.2 nathanw db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
287 1.12.6.2 nathanw f->fixreg[28], f->fixreg[29],
288 1.12.6.2 nathanw f->fixreg[30], f->fixreg[31]);
289 1.12.6.2 nathanw
290 1.12.6.2 nathanw db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
291 1.12.6.2 nathanw f->lr, f->cr, f->xer, f->ctr);
292 1.12.6.2 nathanw db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
293 1.12.6.2 nathanw "dear: %8.8x esr: %8.8x\n",
294 1.12.6.2 nathanw f->srr0, f->srr1, f->dear, f->esr);
295 1.12.6.2 nathanw db_printf("exc: %8.8x pid: %8.8x\n",
296 1.12.6.2 nathanw f->exc, f->pid);
297 1.12.6.2 nathanw }
298 1.12.6.2 nathanw return;
299 1.12.6.2 nathanw }
300 1.12.6.2 nathanw
301 1.12.6.2 nathanw static const char *const tlbsizes[] = {
302 1.12.6.2 nathanw "1kB",
303 1.12.6.2 nathanw "4kB",
304 1.12.6.2 nathanw "16kB",
305 1.12.6.2 nathanw "64kB",
306 1.12.6.2 nathanw "256kB",
307 1.12.6.2 nathanw "1MB",
308 1.12.6.2 nathanw "4MB",
309 1.12.6.2 nathanw "16MB"
310 1.12.6.2 nathanw };
311 1.12.6.2 nathanw
312 1.12.6.2 nathanw static void
313 1.12.6.2 nathanw db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
314 1.12.6.2 nathanw {
315 1.12.6.2 nathanw int i, zone, tlbsize;
316 1.12.6.2 nathanw u_int zpr, pid, opid, msr;
317 1.12.6.2 nathanw u_long tlblo, tlbhi, tlbmask;
318 1.12.6.2 nathanw
319 1.12.6.2 nathanw zpr = mfspr(SPR_ZPR);
320 1.12.6.2 nathanw for (i = 0; i < NTLB; i++) {
321 1.12.6.2 nathanw asm volatile("mfmsr %3;"
322 1.12.6.2 nathanw "mfpid %4;"
323 1.12.6.2 nathanw "li %0,0;"
324 1.12.6.2 nathanw "mtmsr %0;"
325 1.12.6.2 nathanw "sync; isync;"
326 1.12.6.6 thorpej "tlbrelo %0,%5;"
327 1.12.6.6 thorpej "tlbrehi %1,%5;"
328 1.12.6.2 nathanw "mfpid %2;"
329 1.12.6.2 nathanw "mtpid %4;"
330 1.12.6.2 nathanw "mtmsr %3;"
331 1.12.6.2 nathanw "sync; isync"
332 1.12.6.2 nathanw : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
333 1.12.6.2 nathanw "=&r" (msr), "=&r" (opid) : "r" (i));
334 1.12.6.2 nathanw
335 1.12.6.2 nathanw if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
336 1.12.6.2 nathanw continue;
337 1.12.6.2 nathanw
338 1.12.6.2 nathanw tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
339 1.12.6.2 nathanw /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
340 1.12.6.2 nathanw tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
341 1.12.6.2 nathanw
342 1.12.6.2 nathanw if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
343 1.12.6.2 nathanw continue;
344 1.12.6.2 nathanw
345 1.12.6.2 nathanw zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
346 1.12.6.2 nathanw db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
347 1.12.6.2 nathanw db_printf(" PID %3d EPN 0x%08lx %-5s",
348 1.12.6.2 nathanw pid,
349 1.12.6.2 nathanw tlbhi & tlbmask,
350 1.12.6.2 nathanw tlbsizes[tlbsize]);
351 1.12.6.2 nathanw db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
352 1.12.6.2 nathanw tlblo & tlbmask,
353 1.12.6.2 nathanw zone,
354 1.12.6.2 nathanw "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
355 1.12.6.2 nathanw tlblo & TLB_EX ? "EX" : " ",
356 1.12.6.2 nathanw tlblo & TLB_WR ? "WR" : " ",
357 1.12.6.2 nathanw tlblo & TLB_W ? 'W' : ' ',
358 1.12.6.2 nathanw tlblo & TLB_I ? 'I' : ' ',
359 1.12.6.2 nathanw tlblo & TLB_M ? 'M' : ' ',
360 1.12.6.2 nathanw tlblo & TLB_G ? 'G' : ' ',
361 1.12.6.2 nathanw tlbhi & TLB_ENDIAN ? 'E' : ' ',
362 1.12.6.2 nathanw tlbhi & TLB_U0 ? "U0" : " ");
363 1.12.6.2 nathanw db_printf("\n");
364 1.12.6.2 nathanw }
365 1.12.6.2 nathanw }
366 1.12.6.2 nathanw
367 1.12.6.7 thorpej static void
368 1.12.6.7 thorpej db_ppc4xx_dcr(db_expr_t address, int have_addr, db_expr_t count, char *modif)
369 1.12.6.7 thorpej {
370 1.12.6.7 thorpej db_expr_t new_value;
371 1.12.6.7 thorpej db_expr_t addr;
372 1.12.6.7 thorpej
373 1.12.6.7 thorpej if (address < 0 || address > 0x3ff)
374 1.12.6.7 thorpej db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
375 1.12.6.7 thorpej
376 1.12.6.7 thorpej addr = address;
377 1.12.6.7 thorpej
378 1.12.6.7 thorpej while (db_expression(&new_value)) {
379 1.12.6.7 thorpej db_printf("dcr 0x%lx\t\t%s = ", addr,
380 1.12.6.7 thorpej db_num_to_str(db_ppc4xx_mfdcr(addr)));
381 1.12.6.7 thorpej db_ppc4xx_mtdcr(addr, new_value);
382 1.12.6.7 thorpej db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
383 1.12.6.7 thorpej addr += 1;
384 1.12.6.7 thorpej }
385 1.12.6.7 thorpej
386 1.12.6.7 thorpej if (addr == address) {
387 1.12.6.7 thorpej db_next = (db_addr_t)addr + 1;
388 1.12.6.7 thorpej db_prev = (db_addr_t)addr;
389 1.12.6.7 thorpej db_printf("dcr 0x%lx\t\t%s\n", addr,
390 1.12.6.7 thorpej db_num_to_str(db_ppc4xx_mfdcr(addr)));
391 1.12.6.7 thorpej } else {
392 1.12.6.7 thorpej db_next = (db_addr_t)addr;
393 1.12.6.7 thorpej db_prev = (db_addr_t)addr - 1;
394 1.12.6.7 thorpej }
395 1.12.6.7 thorpej
396 1.12.6.7 thorpej db_skip_to_eol();
397 1.12.6.7 thorpej }
398 1.12.6.7 thorpej
399 1.12.6.7 thorpej /*
400 1.12.6.7 thorpej * XXX Grossness Alert! XXX
401 1.12.6.7 thorpej *
402 1.12.6.7 thorpej * Please look away now if you don't like self-modifying code
403 1.12.6.7 thorpej */
404 1.12.6.7 thorpej static u_int32_t db_ppc4xx_dcrfunc[4];
405 1.12.6.7 thorpej
406 1.12.6.7 thorpej static db_expr_t
407 1.12.6.7 thorpej db_ppc4xx_mfdcr(db_expr_t reg)
408 1.12.6.7 thorpej {
409 1.12.6.7 thorpej db_expr_t (*func)(void);
410 1.12.6.7 thorpej
411 1.12.6.7 thorpej reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
412 1.12.6.7 thorpej db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
413 1.12.6.7 thorpej db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
414 1.12.6.7 thorpej db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg; /* mfdcr reg, r3 */
415 1.12.6.7 thorpej db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
416 1.12.6.7 thorpej
417 1.12.6.7 thorpej __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
418 1.12.6.7 thorpej func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
419 1.12.6.7 thorpej
420 1.12.6.7 thorpej return ((*func)());
421 1.12.6.7 thorpej }
422 1.12.6.7 thorpej
423 1.12.6.7 thorpej static void
424 1.12.6.7 thorpej db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
425 1.12.6.7 thorpej {
426 1.12.6.7 thorpej db_expr_t (*func)(db_expr_t);
427 1.12.6.7 thorpej
428 1.12.6.7 thorpej reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
429 1.12.6.7 thorpej db_ppc4xx_dcrfunc[0] = 0x7c0004ac; /* sync */
430 1.12.6.7 thorpej db_ppc4xx_dcrfunc[1] = 0x4c00012c; /* isync */
431 1.12.6.7 thorpej db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg; /* mtdcr r3, reg */
432 1.12.6.7 thorpej db_ppc4xx_dcrfunc[3] = 0x4e800020; /* blr */
433 1.12.6.7 thorpej
434 1.12.6.7 thorpej __syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
435 1.12.6.7 thorpej func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
436 1.12.6.7 thorpej
437 1.12.6.7 thorpej (*func)(val);
438 1.12.6.7 thorpej }
439 1.12.6.7 thorpej
440 1.12.6.2 nathanw #ifdef USERACC
441 1.12.6.2 nathanw static void
442 1.12.6.2 nathanw db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
443 1.12.6.2 nathanw {
444 1.12.6.2 nathanw static paddr_t oldaddr = -1;
445 1.12.6.2 nathanw int instr = 0;
446 1.12.6.2 nathanw int data;
447 1.12.6.2 nathanw extern vaddr_t opc_disasm(vaddr_t loc, int);
448 1.12.6.2 nathanw
449 1.12.6.2 nathanw
450 1.12.6.2 nathanw if (!have_addr) {
451 1.12.6.2 nathanw addr = oldaddr;
452 1.12.6.2 nathanw }
453 1.12.6.2 nathanw if (addr == -1) {
454 1.12.6.2 nathanw db_printf("no address\n");
455 1.12.6.2 nathanw return;
456 1.12.6.2 nathanw }
457 1.12.6.2 nathanw addr &= ~0x3; /* align */
458 1.12.6.2 nathanw {
459 1.12.6.2 nathanw register char c, *cp = modif;
460 1.12.6.2 nathanw while ((c = *cp++) != 0)
461 1.12.6.2 nathanw if (c == 'i')
462 1.12.6.2 nathanw instr = 1;
463 1.12.6.2 nathanw }
464 1.12.6.2 nathanw while (count--) {
465 1.12.6.2 nathanw if (db_print_position() == 0) {
466 1.12.6.2 nathanw /* Always print the address. */
467 1.12.6.2 nathanw db_printf("%8.4lx:\t", addr);
468 1.12.6.2 nathanw }
469 1.12.6.2 nathanw oldaddr=addr;
470 1.12.6.2 nathanw copyin((void *)addr, &data, sizeof(data));
471 1.12.6.2 nathanw if (instr) {
472 1.12.6.2 nathanw opc_disasm(addr, data);
473 1.12.6.2 nathanw } else {
474 1.12.6.2 nathanw db_printf("%4.4x\n", data);
475 1.12.6.2 nathanw }
476 1.12.6.2 nathanw addr += 4;
477 1.12.6.2 nathanw db_end_line();
478 1.12.6.2 nathanw }
479 1.12.6.2 nathanw
480 1.12.6.2 nathanw }
481 1.12.6.2 nathanw #endif
482 1.12.6.2 nathanw
483 1.12.6.2 nathanw #endif /* PPC_IBM4XX */
484