summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powerpc/db_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/powerpc/powerpc/db_interface.c')
-rw-r--r--sys/powerpc/powerpc/db_interface.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/sys/powerpc/powerpc/db_interface.c b/sys/powerpc/powerpc/db_interface.c
new file mode 100644
index 0000000..8eda5c4
--- /dev/null
+++ b/sys/powerpc/powerpc/db_interface.c
@@ -0,0 +1,377 @@
+/* $FreeBSD$ */
+/* $NetBSD: db_interface.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */
+/* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */
+
+#define USERACC
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <machine/db_machdep.h>
+#include <machine/frame.h>
+#include <machine/trap.h>
+#ifdef PPC_IBM4XX
+#include <machine/tlb.h>
+#include <powerpc/spr.h>
+#include <uvm/uvm_extern.h>
+#endif
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_command.h>
+#include <ddb/db_access.h>
+#include <ddb/db_output.h>
+#endif
+
+#ifdef KGDB
+#include <sys/kgdb.h>
+#endif
+
+#include <dev/ofw/openfirm.h>
+
+int db_active = 0;
+
+db_regs_t ddb_regs;
+
+void ddb_trap(void); /* Call into trap_subr.S */
+int ddb_trap_glue(struct trapframe *); /* Called from trap_subr.S */
+#ifdef PPC_IBM4XX
+static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
+static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
+static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
+static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
+static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
+#ifdef USERACC
+static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
+#endif
+#endif /* PPC_IBM4XX */
+
+#ifdef DDB
+void
+Debugger(const char *msg)
+{
+ db_printf("Welcome to Debugger, %s\n", msg);
+ ddb_trap();
+}
+#endif
+
+int
+ddb_trap_glue(frame)
+ struct trapframe *frame;
+{
+ if (!(frame->srr1 & PSL_PR)
+ && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
+ || (frame->exc == EXC_PGM
+ && (frame->srr1 & 0x20000))
+ || frame->exc == EXC_BPT)) {
+ int type = frame->exc;
+ if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
+ type = T_BREAKPOINT;
+ }
+ return kdb_trap(type, frame);
+ }
+ return 0;
+}
+
+int
+kdb_trap(type, v)
+ int type;
+ void *v;
+{
+ struct trapframe *frame = v;
+
+#if 0
+ switch (type) {
+ case T_BREAKPOINT:
+ case -1:
+ break;
+ default:
+ if (!db_onpanic && db_recover == 0)
+ return 0;
+ if (db_recover != 0) {
+ db_error("Faulted in DDB; continuing...\n");
+ /*NOTREACHED*/
+ }
+ }
+#endif
+
+ /* XXX Should switch to kdb's own stack here. */
+
+ memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
+ DDB_REGS->iar = frame->srr0;
+ DDB_REGS->msr = frame->srr1;
+ DDB_REGS->lr = frame->lr;
+ DDB_REGS->ctr = frame->ctr;
+ DDB_REGS->cr = frame->cr;
+ DDB_REGS->xer = frame->xer;
+#ifdef PPC_IBM4XX
+ DDB_REGS->dear = frame->dear;
+ DDB_REGS->esr = frame->esr;
+ DDB_REGS->pid = frame->pid;
+#endif
+
+#ifdef DDB
+ db_active++;
+ cndbctl(1);
+ db_trap(type, 0);
+ cndbctl(0);
+ db_active--;
+#elif defined(KGDB)
+ if (!kgdb_trap(type, DDB_REGS))
+ return 0;
+#endif
+
+ /* KGDB isn't smart about advancing PC if we
+ * take a breakpoint trap after kgdb_active is set.
+ * Therefore, we help out here.
+ */
+ if (IS_BREAKPOINT_TRAP(type, 0)) {
+ int bkpt;
+ db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
+ if (bkpt== BKPT_INST) {
+ PC_REGS(DDB_REGS) += BKPT_SIZE;
+ }
+ }
+
+ memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
+ frame->srr0 = DDB_REGS->iar;
+ frame->srr1 = DDB_REGS->msr;
+ frame->lr = DDB_REGS->lr;
+ frame->ctr = DDB_REGS->ctr;
+ frame->cr = DDB_REGS->cr;
+ frame->xer = DDB_REGS->xer;
+#ifdef PPC_IBM4XX
+ frame->dear = DDB_REGS->dear;
+ frame->esr = DDB_REGS->esr;
+ frame->pid = DDB_REGS->pid;
+#endif
+
+ return 1;
+}
+
+#ifdef PPC_IBM4XX
+const struct db_command db_machine_command_table[] = {
+ { "ctx", db_ppc4xx_ctx, 0, 0 },
+ { "pv", db_ppc4xx_pv, 0, 0 },
+ { "reset", db_ppc4xx_reset, 0, 0 },
+ { "tf", db_ppc4xx_tf, 0, 0 },
+ { "tlb", db_ppc4xx_dumptlb, 0, 0 },
+#ifdef USERACC
+ { "user", db_ppc4xx_useracc, 0, 0 },
+#endif
+ { NULL, }
+};
+
+static void
+db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ struct proc *p;
+
+ /* XXX LOCKING XXX */
+ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
+ if (p->p_stat) {
+ db_printf("process %p:", p);
+ db_printf("pid:%d pmap:%p ctx:%d %s\n",
+ p->p_pid, p->p_vmspace->vm_map.pmap,
+ p->p_vmspace->vm_map.pmap->pm_ctx,
+ p->p_comm);
+ }
+ }
+ return;
+}
+
+static void
+db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ struct pv_entry {
+ struct pv_entry *pv_next; /* Linked list of mappings */
+ vaddr_t pv_va; /* virtual address of mapping */
+ struct pmap *pv_pm;
+ };
+ struct pv_entry *pa_to_pv(paddr_t);
+ struct pv_entry *pv;
+
+ if (!have_addr) {
+ db_printf("pv: <pa>\n");
+ return;
+ }
+ pv = pa_to_pv(addr);
+ db_printf("pv at %p\n", pv);
+ while (pv && pv->pv_pm) {
+ db_printf("next %p va %p pmap %p\n", pv->pv_next,
+ (void *)pv->pv_va, pv->pv_pm);
+ pv = pv->pv_next;
+ }
+}
+
+static void
+db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ printf("Reseting...\n");
+ ppc4xx_reset();
+}
+
+static void
+db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ struct trapframe *f;
+
+
+ if (have_addr) {
+ f = (struct trapframe *)addr;
+
+ db_printf("r0-r3: \t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[0], f->fixreg[1],
+ f->fixreg[2], f->fixreg[3]);
+ db_printf("r4-r7: \t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[4], f->fixreg[5],
+ f->fixreg[6], f->fixreg[7]);
+ db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[8], f->fixreg[9],
+ f->fixreg[10], f->fixreg[11]);
+ db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[12], f->fixreg[13],
+ f->fixreg[14], f->fixreg[15]);
+ db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[16], f->fixreg[17],
+ f->fixreg[18], f->fixreg[19]);
+ db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[20], f->fixreg[21],
+ f->fixreg[22], f->fixreg[23]);
+ db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[24], f->fixreg[25],
+ f->fixreg[26], f->fixreg[27]);
+ db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
+ f->fixreg[28], f->fixreg[29],
+ f->fixreg[30], f->fixreg[31]);
+
+ db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
+ f->lr, f->cr, f->xer, f->ctr);
+ db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
+ "dear: %8.8x esr: %8.8x\n",
+ f->srr0, f->srr1, f->dear, f->esr);
+ db_printf("exc: %8.8x pid: %8.8x\n",
+ f->exc, f->pid);
+ }
+ return;
+}
+
+static const char *const tlbsizes[] = {
+ "1kB",
+ "4kB",
+ "16kB",
+ "64kB",
+ "256kB",
+ "1MB",
+ "4MB",
+ "16MB"
+};
+
+static void
+db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ int i, zone, tlbsize;
+ u_int zpr, pid, opid, msr;
+ u_long tlblo, tlbhi, tlbmask;
+
+ zpr = mfspr(SPR_ZPR);
+ for (i = 0; i < NTLB; i++) {
+ asm volatile("mfmsr %3;"
+ "mfpid %4;"
+ "li %0,0;"
+ "mtmsr %0;"
+ "sync; isync;"
+ "tlbre %0,%5,1;"
+ "tlbre %1,%5,0;"
+ "mfpid %2;"
+ "mtpid %4;"
+ "mtmsr %3;"
+ "sync; isync"
+ : "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
+ "=&r" (msr), "=&r" (opid) : "r" (i));
+
+ if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
+ continue;
+
+ tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
+ /* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
+ tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
+
+ if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
+ continue;
+
+ zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
+ db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
+ db_printf(" PID %3d EPN 0x%08lx %-5s",
+ pid,
+ tlbhi & tlbmask,
+ tlbsizes[tlbsize]);
+ db_printf(" RPN 0x%08lx ZONE %2d%c %s %s %c%c%c%c%c %s",
+ tlblo & tlbmask,
+ zone,
+ "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
+ tlblo & TLB_EX ? "EX" : " ",
+ tlblo & TLB_WR ? "WR" : " ",
+ tlblo & TLB_W ? 'W' : ' ',
+ tlblo & TLB_I ? 'I' : ' ',
+ tlblo & TLB_M ? 'M' : ' ',
+ tlblo & TLB_G ? 'G' : ' ',
+ tlbhi & TLB_ENDIAN ? 'E' : ' ',
+ tlbhi & TLB_U0 ? "U0" : " ");
+ db_printf("\n");
+ }
+}
+
+#ifdef USERACC
+static void
+db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ static paddr_t oldaddr = -1;
+ int instr = 0;
+ int data;
+ extern vaddr_t opc_disasm(vaddr_t loc, int);
+
+
+ if (!have_addr) {
+ addr = oldaddr;
+ }
+ if (addr == -1) {
+ db_printf("no address\n");
+ return;
+ }
+ addr &= ~0x3; /* align */
+ {
+ register char c, *cp = modif;
+ while ((c = *cp++) != 0)
+ if (c == 'i')
+ instr = 1;
+ }
+ while (count--) {
+ if (db_print_position() == 0) {
+ /* Always print the address. */
+ db_printf("%8.4lx:\t", addr);
+ }
+ oldaddr=addr;
+ copyin((void *)addr, &data, sizeof(data));
+ if (instr) {
+ opc_disasm(addr, data);
+ } else {
+ db_printf("%4.4x\n", data);
+ }
+ addr += 4;
+ db_end_line();
+ }
+
+}
+#endif
+
+#endif /* PPC_IBM4XX */
+
+void
+db_show_mdpcpu(struct pcpu *pc)
+{
+}
OpenPOWER on IntegriCloud