Annotation of sys/arch/sh/sh/db_interface.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_interface.c,v 1.2 2006/10/06 21:16:57 mickey Exp $ */
2: /* $NetBSD: db_interface.c,v 1.37 2006/09/06 00:11:49 uwe Exp $ */
3:
4: /*-
5: * Copyright (C) 2002 UCHIYAMA Yasushi. All rights reserved.
6: * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/user.h>
34:
35: #include <uvm/uvm_extern.h>
36:
37: #include <dev/cons.h>
38:
39: #include <machine/db_machdep.h>
40: #include <ddb/db_run.h>
41: #include <ddb/db_sym.h>
42:
43: #include <sh/ubcreg.h>
44:
45: db_regs_t ddb_regs; /* register state */
46:
47:
48: #include <sh/cache.h>
49: #include <sh/cache_sh3.h>
50: #include <sh/cache_sh4.h>
51: #include <sh/mmu.h>
52: #include <sh/mmu_sh3.h>
53: #include <sh/mmu_sh4.h>
54:
55: #include <ddb/db_command.h>
56: #include <ddb/db_extern.h>
57: #include <ddb/db_output.h>
58: #include <ddb/db_run.h>
59: #include <ddb/db_var.h>
60:
61: void kdb_printtrap(u_int, int);
62:
63: void db_tlbdump_cmd(db_expr_t, int, db_expr_t, char *);
64: void __db_tlbdump_page_size_sh4(uint32_t);
65: void __db_tlbdump_pfn(uint32_t);
66: void db_cachedump_cmd(db_expr_t, int, db_expr_t, char *);
67:
68: void __db_cachedump_sh3(vaddr_t);
69: void __db_cachedump_sh4(vaddr_t);
70:
71: void db_stackcheck_cmd(db_expr_t, int, db_expr_t, char *);
72: void db_frame_cmd(db_expr_t, int, db_expr_t, char *);
73: void __db_print_symbol(db_expr_t);
74: char *__db_procname_by_asid(int);
75:
76: struct db_command db_machine_command_table[] = {
77: { "tlb", db_tlbdump_cmd, 0, NULL },
78: { "cache", db_cachedump_cmd, 0, NULL },
79: { "frame", db_frame_cmd, 0, NULL },
80: #ifdef KSTACK_DEBUG
81: { "stack", db_stackcheck_cmd, 0, NULL },
82: #endif
83: { NULL }
84: };
85:
86: int db_active;
87:
88: void
89: db_machine_init(void)
90: {
91:
92: db_machine_commands_install(db_machine_command_table);
93: }
94:
95: void
96: kdb_printtrap(u_int type, int code)
97: {
98: int i;
99: i = type >> 5;
100:
101: db_printf("%s mode trap: ", type & 1 ? "user" : "kernel");
102: if (i >= exp_types)
103: db_printf("type 0x%03x", type & ~1);
104: else
105: db_printf("%s", exp_type[i]);
106:
107: db_printf(" code = 0x%x\n", code);
108: }
109:
110: int
111: kdb_trap(int type, int code, db_regs_t *regs)
112: {
113: extern label_t *db_recover;
114: int s;
115:
116: switch (type) {
117: case EXPEVT_TRAPA: /* trapa instruction */
118: case EXPEVT_BREAK: /* UBC */
119: case -1: /* keyboard interrupt */
120: break;
121: default:
122: if (!db_panic && db_recover == NULL)
123: return 0;
124:
125: kdb_printtrap(type, code);
126: if (db_recover != NULL) {
127: db_error("Faulted in DDB; continuing...\n");
128: /*NOTREACHED*/
129: }
130: }
131:
132: /* XXX Should switch to kdb's own stack here. */
133:
134: ddb_regs = *regs;
135:
136: s = splhigh();
137: db_active++;
138: cnpollc(TRUE);
139: db_trap(type, code);
140: cnpollc(FALSE);
141: db_active--;
142: splx(s);
143:
144: *regs = ddb_regs;
145:
146: return 1;
147: }
148:
149: void
150: Debugger()
151: {
152: __asm volatile("trapa %0" :: "i"(_SH_TRA_BREAK));
153: }
154:
155: #define M_BSR 0xf000
156: #define I_BSR 0xb000
157: #define M_BSRF 0xf0ff
158: #define I_BSRF 0x0003
159: #define M_JSR 0xf0ff
160: #define I_JSR 0x400b
161: #define M_RTS 0xffff
162: #define I_RTS 0x000b
163: #define M_RTE 0xffff
164: #define I_RTE 0x002b
165:
166: boolean_t
167: inst_call(int inst)
168: {
169: #if _BYTE_ORDER == BIG_ENDIAN
170: inst >>= 16;
171: #endif
172: return (inst & M_BSR) == I_BSR || (inst & M_BSRF) == I_BSRF ||
173: (inst & M_JSR) == I_JSR;
174: }
175:
176: boolean_t
177: inst_return(int inst)
178: {
179: #if _BYTE_ORDER == BIG_ENDIAN
180: inst >>= 16;
181: #endif
182: return (inst & M_RTS) == I_RTS;
183: }
184:
185: boolean_t
186: inst_trap_return(int inst)
187: {
188: #if _BYTE_ORDER == BIG_ENDIAN
189: inst >>= 16;
190: #endif
191: return (inst & M_RTE) == I_RTE;
192: }
193:
194: void
195: db_set_single_step(db_regs_t *regs)
196: {
197:
198: _reg_write_2(SH_(BBRA), 0); /* disable break */
199: _reg_write_4(SH_(BARA), 0); /* break address */
200: _reg_write_1(SH_(BASRA), 0); /* break ASID */
201: _reg_write_1(SH_(BAMRA), 0x07); /* break always */
202: _reg_write_2(SH_(BRCR), 0x400); /* break after each execution */
203:
204: regs->tf_ubc = 0x0014; /* will be written to BBRA */
205: }
206:
207: void
208: db_clear_single_step(db_regs_t *regs)
209: {
210:
211: regs->tf_ubc = 0;
212: }
213:
214: #define ON(x, c) ((x) & (c) ? '|' : '.')
215:
216: /*
217: * MMU
218: */
219: void
220: db_tlbdump_cmd(db_expr_t addr, int have_addr, db_expr_t count,
221: char *modif)
222: {
223: static const char *pr[] = { "_r", "_w", "rr", "ww" };
224: static const char title[] =
225: " VPN ASID PFN AREA VDCGWtPR SZ";
226: static const char title2[] =
227: " U/K U/K";
228: uint32_t r, e;
229: int i;
230: #ifdef SH3
231: if (CPU_IS_SH3) {
232: /* MMU configuration. */
233: r = _reg_read_4(SH3_MMUCR);
234: db_printf("%s-mode, %s virtual storage mode\n",
235: r & SH3_MMUCR_IX
236: ? "ASID + VPN" : "VPN only",
237: r & SH3_MMUCR_SV ? "single" : "multiple");
238: i = _reg_read_4(SH3_PTEH) & SH3_PTEH_ASID_MASK;
239: db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i));
240:
241: db_printf("---TLB DUMP---\n%s\n%s\n", title, title2);
242: for (i = 0; i < SH3_MMU_WAY; i++) {
243: db_printf(" [way %d]\n", i);
244: for (e = 0; e < SH3_MMU_ENTRY; e++) {
245: uint32_t a;
246: /* address/data array common offset. */
247: a = (e << SH3_MMU_VPN_SHIFT) |
248: (i << SH3_MMU_WAY_SHIFT);
249:
250: r = _reg_read_4(SH3_MMUAA | a);
251: if (r == 0) {
252: db_printf("---------- - --- ----------"
253: " - ----x -- --\n");
254: } else {
255: vaddr_t va;
256: int asid;
257: asid = r & SH3_MMUAA_D_ASID_MASK;
258: r &= SH3_MMUAA_D_VPN_MASK_1K;
259: va = r | (e << SH3_MMU_VPN_SHIFT);
260: db_printf("0x%08lx %c %3d", va,
261: (int)va < 0 ? 'K' : 'U', asid);
262:
263: r = _reg_read_4(SH3_MMUDA | a);
264: __db_tlbdump_pfn(r);
265:
266: db_printf(" %c%c%c%cx %s %2dK\n",
267: ON(r, SH3_MMUDA_D_V),
268: ON(r, SH3_MMUDA_D_D),
269: ON(r, SH3_MMUDA_D_C),
270: ON(r, SH3_MMUDA_D_SH),
271: pr[(r & SH3_MMUDA_D_PR_MASK) >>
272: SH3_MMUDA_D_PR_SHIFT],
273: r & SH3_MMUDA_D_SZ ? 4 : 1);
274: }
275: }
276: }
277: }
278: #endif /* SH3 */
279: #ifdef SH4
280: if (CPU_IS_SH4) {
281: /* MMU configuration */
282: r = _reg_read_4(SH4_MMUCR);
283: db_printf("%s virtual storage mode, SQ access: (kernel%s)\n",
284: r & SH3_MMUCR_SV ? "single" : "multiple",
285: r & SH4_MMUCR_SQMD ? "" : "/user");
286: db_printf("random counter limit=%d\n",
287: (r & SH4_MMUCR_URB_MASK) >> SH4_MMUCR_URB_SHIFT);
288:
289: i = _reg_read_4(SH4_PTEH) & SH4_PTEH_ASID_MASK;
290: db_printf("ASID=%d (%s)", i, __db_procname_by_asid(i));
291:
292: /* Dump ITLB */
293: db_printf("---ITLB DUMP ---\n%s TC SA\n%s\n", title, title2);
294: for (i = 0; i < 4; i++) {
295: e = i << SH4_ITLB_E_SHIFT;
296:
297: r = _reg_read_4(SH4_ITLB_AA | e);
298: db_printf("0x%08x %3d",
299: r & SH4_ITLB_AA_VPN_MASK,
300: r & SH4_ITLB_AA_ASID_MASK);
301:
302: r = _reg_read_4(SH4_ITLB_DA1 | e);
303: __db_tlbdump_pfn(r);
304: db_printf(" %c_%c%c_ %s ",
305: ON(r, SH4_ITLB_DA1_V),
306: ON(r, SH4_ITLB_DA1_C),
307: ON(r, SH4_ITLB_DA1_SH),
308: pr[(r & SH4_ITLB_DA1_PR) >>
309: SH4_UTLB_DA1_PR_SHIFT]);
310: __db_tlbdump_page_size_sh4(r);
311:
312: #if 0 /* XXX: causes weird effects on landisk */
313: r = _reg_read_4(SH4_ITLB_DA2 | e);
314: db_printf(" %c %d\n",
315: ON(r, SH4_ITLB_DA2_TC),
316: r & SH4_ITLB_DA2_SA_MASK);
317: #else
318: db_printf("\n");
319: #endif
320: }
321:
322: /* Dump UTLB */
323: db_printf("---UTLB DUMP---\n%s TC SA\n%s\n", title, title2);
324: for (i = 0; i < 64; i++) {
325: e = i << SH4_UTLB_E_SHIFT;
326:
327: r = _reg_read_4(SH4_UTLB_AA | e);
328: db_printf("0x%08x %3d",
329: r & SH4_UTLB_AA_VPN_MASK,
330: r & SH4_UTLB_AA_ASID_MASK);
331:
332: r = _reg_read_4(SH4_UTLB_DA1 | e);
333: __db_tlbdump_pfn(r);
334: db_printf(" %c%c%c%c%c %s ",
335: ON(r, SH4_UTLB_DA1_V),
336: ON(r, SH4_UTLB_DA1_D),
337: ON(r, SH4_UTLB_DA1_C),
338: ON(r, SH4_UTLB_DA1_SH),
339: ON(r, SH4_UTLB_DA1_WT),
340: pr[(r & SH4_UTLB_DA1_PR_MASK) >>
341: SH4_UTLB_DA1_PR_SHIFT]
342: );
343: __db_tlbdump_page_size_sh4(r);
344:
345: #if 0 /* XXX: causes weird effects on landisk */
346: r = _reg_read_4(SH4_UTLB_DA2 | e);
347: db_printf(" %c %d\n",
348: ON(r, SH4_UTLB_DA2_TC),
349: r & SH4_UTLB_DA2_SA_MASK);
350: #else
351: db_printf("\n");
352: #endif
353: }
354: }
355: #endif /* SH4 */
356: }
357:
358: void
359: __db_tlbdump_pfn(uint32_t r)
360: {
361: uint32_t pa = (r & SH3_MMUDA_D_PPN_MASK);
362:
363: db_printf(" 0x%08x %d", pa, (pa >> 26) & 7);
364: }
365:
366: char *
367: __db_procname_by_asid(int asid)
368: {
369: static char notfound[] = "---";
370: struct proc *p;
371:
372: LIST_FOREACH(p, &allproc, p_list) {
373: if (p->p_vmspace->vm_map.pmap->pm_asid == asid)
374: return (p->p_comm);
375: }
376:
377: return (notfound);
378: }
379:
380: #ifdef SH4
381: void
382: __db_tlbdump_page_size_sh4(uint32_t r)
383: {
384: switch (r & SH4_PTEL_SZ_MASK) {
385: case SH4_PTEL_SZ_1K:
386: db_printf(" 1K");
387: break;
388: case SH4_PTEL_SZ_4K:
389: db_printf(" 4K");
390: break;
391: case SH4_PTEL_SZ_64K:
392: db_printf("64K");
393: break;
394: case SH4_PTEL_SZ_1M:
395: db_printf(" 1M");
396: break;
397: }
398: }
399: #endif /* SH4 */
400:
401: /*
402: * CACHE
403: */
404: void
405: db_cachedump_cmd(db_expr_t addr, int have_addr, db_expr_t count,
406: char *modif)
407: {
408: #ifdef SH3
409: if (CPU_IS_SH3)
410: __db_cachedump_sh3(have_addr ? addr : 0);
411: #endif
412: #ifdef SH4
413: if (CPU_IS_SH4)
414: __db_cachedump_sh4(have_addr ? addr : 0);
415: #endif
416: }
417:
418: #ifdef SH3
419: void
420: __db_cachedump_sh3(vaddr_t va_start)
421: {
422: uint32_t r;
423: vaddr_t va, va_end, cca;
424: int entry, way;
425:
426: RUN_P2;
427: /* disable cache */
428: _reg_write_4(SH3_CCR,
429: _reg_read_4(SH3_CCR) & ~SH3_CCR_CE);
430:
431: if (va_start) {
432: va = va_start & ~(sh_cache_line_size - 1);
433: va_end = va + sh_cache_line_size;
434: } else {
435: va = 0;
436: va_end = sh_cache_way_size;
437: }
438:
439: db_printf("%d-way, way-size=%dB, way-shift=%d, entry-mask=%08x, "
440: "line-size=%dB \n", sh_cache_ways, sh_cache_way_size,
441: sh_cache_way_shift, sh_cache_entry_mask, sh_cache_line_size);
442: db_printf("Entry Way 0 UV Way 1 UV Way 2 UV Way 3 UV\n");
443: for (; va < va_end; va += sh_cache_line_size) {
444: entry = va & sh_cache_entry_mask;
445: cca = SH3_CCA | entry;
446: db_printf(" %3d ", entry >> CCA_ENTRY_SHIFT);
447: for (way = 0; way < sh_cache_ways; way++) {
448: r = _reg_read_4(cca | (way << sh_cache_way_shift));
449: db_printf("%08x %c%c ", r & CCA_TAGADDR_MASK,
450: ON(r, CCA_U), ON(r, CCA_V));
451: }
452: db_printf("\n");
453: }
454:
455: /* enable cache */
456: _reg_bset_4(SH3_CCR, SH3_CCR_CE);
457: sh_icache_sync_all();
458:
459: RUN_P1;
460: }
461: #endif /* SH3 */
462:
463: #ifdef SH4
464: void
465: __db_cachedump_sh4(vaddr_t va)
466: {
467: uint32_t r, e;
468: int i, istart, iend;
469:
470: RUN_P2; /* must access from P2 */
471:
472: /* disable I/D-cache */
473: _reg_write_4(SH4_CCR,
474: _reg_read_4(SH4_CCR) & ~(SH4_CCR_ICE | SH4_CCR_OCE));
475:
476: if (va) {
477: istart = ((va & CCIA_ENTRY_MASK) >> CCIA_ENTRY_SHIFT) & ~3;
478: iend = istart + 4;
479: } else {
480: istart = 0;
481: iend = SH4_ICACHE_SIZE / SH4_CACHE_LINESZ;
482: }
483:
484: db_printf("[I-cache]\n");
485: db_printf(" Entry V V V V\n");
486: for (i = istart; i < iend; i++) {
487: if ((i & 3) == 0)
488: db_printf("\n[%3d-%3d] ", i, i + 3);
489: r = _reg_read_4(SH4_CCIA | (i << CCIA_ENTRY_SHIFT));
490: db_printf("%08x _%c ", r & CCIA_TAGADDR_MASK, ON(r, CCIA_V));
491: }
492:
493: db_printf("\n[D-cache]\n");
494: db_printf(" Entry UV UV UV UV\n");
495: for (i = istart; i < iend; i++) {
496: if ((i & 3) == 0)
497: db_printf("\n[%3d-%3d] ", i, i + 3);
498: e = (i << CCDA_ENTRY_SHIFT);
499: r = _reg_read_4(SH4_CCDA | e);
500: db_printf("%08x %c%c ", r & CCDA_TAGADDR_MASK, ON(r, CCDA_U),
501: ON(r, CCDA_V));
502:
503: }
504: db_printf("\n");
505:
506: _reg_write_4(SH4_CCR,
507: _reg_read_4(SH4_CCR) | SH4_CCR_ICE | SH4_CCR_OCE);
508: sh_icache_sync_all();
509:
510: RUN_P1;
511: }
512: #endif /* SH4 */
513:
514: #undef ON
515:
516: void
517: db_frame_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
518: {
519: struct switchframe *sf = &curpcb->pcb_sf;
520: struct trapframe *tf, *tftop;
521:
522: /* Print switch frame */
523: db_printf("[switch frame]\n");
524:
525: #define SF(x) db_printf("sf_" #x "\t\t0x%08x\t", sf->sf_ ## x); \
526: __db_print_symbol(sf->sf_ ## x)
527:
528: SF(sr);
529: SF(r15);
530: SF(r14);
531: SF(r13);
532: SF(r12);
533: SF(r11);
534: SF(r10);
535: SF(r9);
536: SF(r8);
537: SF(pr);
538: db_printf("sf_r6_bank\t0x%08x\n", sf->sf_r6_bank);
539: db_printf("sf_r7_bank\t0x%08x\n", sf->sf_r7_bank);
540:
541:
542: /* Print trap frame stack */
543: db_printf("[trap frame]\n");
544:
545: __asm("stc r6_bank, %0" : "=r"(tf));
546: tftop = (struct trapframe *)((vaddr_t)curpcb + PAGE_SIZE);
547:
548: for (; tf != tftop; tf++) {
549: db_printf("-- %p-%p --\n", tf, tf + 1);
550: db_printf("tf_expevt\t0x%08x\n", tf->tf_expevt);
551:
552: #define TF(x) db_printf("tf_" #x "\t\t0x%08x\t", tf->tf_ ## x); \
553: __db_print_symbol(tf->tf_ ## x)
554:
555: TF(ubc);
556: TF(spc);
557: TF(ssr);
558: TF(macl);
559: TF(mach);
560: TF(pr);
561: TF(r13);
562: TF(r12);
563: TF(r11);
564: TF(r10);
565: TF(r9);
566: TF(r8);
567: TF(r7);
568: TF(r6);
569: TF(r5);
570: TF(r4);
571: TF(r3);
572: TF(r2);
573: TF(r1);
574: TF(r0);
575: TF(r15);
576: TF(r14);
577: }
578: #undef SF
579: #undef TF
580: }
581:
582: void
583: __db_print_symbol(db_expr_t value)
584: {
585: char *name;
586: db_expr_t offset;
587:
588: db_find_sym_and_offset((db_addr_t)value, &name, &offset);
589: if (name != NULL && offset <= db_maxoff && offset != value)
590: db_printsym(value, DB_STGY_ANY, db_printf);
591:
592: db_printf("\n");
593: }
594:
595: #ifdef KSTACK_DEBUG
596: /*
597: * Stack overflow check
598: */
599: void
600: db_stackcheck_cmd(db_expr_t addr, int have_addr, db_expr_t count,
601: char *modif)
602: {
603: struct proc *p;
604: struct user *u;
605: struct pcb *pcb;
606: uint32_t *t32;
607: uint8_t *t8;
608: int i, j;
609:
610: #define MAX_STACK (USPACE - PAGE_SIZE)
611: #define MAX_FRAME (PAGE_SIZE - sizeof(struct user))
612:
613: db_printf("stack max: %d byte, frame max %d byte,"
614: " sizeof(struct trapframe) %d byte\n", MAX_STACK, MAX_FRAME,
615: sizeof(struct trapframe));
616: db_printf(" PID.LID "
617: "stack top max used frame top max used"
618: " nest\n");
619:
620: LIST_FOREACH(p, &allproc, p_list) {
621: u = p->p_addr;
622: pcb = &u->u_pcb;
623: /* stack */
624: t32 = (uint32_t *)(pcb->pcb_sf.sf_r7_bank - MAX_STACK);
625: for (i = 0; *t32++ == 0xa5a5a5a5; i++)
626: continue;
627: i = MAX_STACK - i * sizeof(int);
628:
629: /* frame */
630: t8 = (uint8_t *)((vaddr_t)pcb + PAGE_SIZE - MAX_FRAME);
631: for (j = 0; *t8++ == 0x5a; j++)
632: continue;
633: j = MAX_FRAME - j;
634:
635: db_printf("%6d 0x%08x %6d (%3d%%) 0x%08lx %6d (%3d%%) %d %s\n",
636: p->p_lid,
637: pcb->pcb_sf.sf_r7_bank, i, i * 100 / MAX_STACK,
638: (vaddr_t)pcb + PAGE_SIZE, j, j * 100 / MAX_FRAME,
639: j / sizeof(struct trapframe),
640: p->p_comm);
641: }
642: #undef MAX_STACK
643: #undef MAX_FRAME
644: }
645: #endif /* KSTACK_DEBUG */
CVSweb