1*a47a12beSStefan Roese #include <common.h> 2*a47a12beSStefan Roese #include <command.h> 3*a47a12beSStefan Roese #include <kgdb.h> 4*a47a12beSStefan Roese #include <asm/signal.h> 5*a47a12beSStefan Roese #include <asm/processor.h> 6*a47a12beSStefan Roese 7*a47a12beSStefan Roese #define PC_REGNUM 64 8*a47a12beSStefan Roese #define SP_REGNUM 1 9*a47a12beSStefan Roese 10*a47a12beSStefan Roese void breakinst(void); 11*a47a12beSStefan Roese 12*a47a12beSStefan Roese int 13*a47a12beSStefan Roese kgdb_setjmp(long *buf) 14*a47a12beSStefan Roese { 15*a47a12beSStefan Roese asm ("mflr 0; stw 0,0(%0);" 16*a47a12beSStefan Roese "stw 1,4(%0); stw 2,8(%0);" 17*a47a12beSStefan Roese "mfcr 0; stw 0,12(%0);" 18*a47a12beSStefan Roese "stmw 13,16(%0)" 19*a47a12beSStefan Roese : : "r" (buf)); 20*a47a12beSStefan Roese /* XXX should save fp regs as well */ 21*a47a12beSStefan Roese return 0; 22*a47a12beSStefan Roese } 23*a47a12beSStefan Roese 24*a47a12beSStefan Roese void 25*a47a12beSStefan Roese kgdb_longjmp(long *buf, int val) 26*a47a12beSStefan Roese { 27*a47a12beSStefan Roese if (val == 0) 28*a47a12beSStefan Roese val = 1; 29*a47a12beSStefan Roese asm ("lmw 13,16(%0);" 30*a47a12beSStefan Roese "lwz 0,12(%0); mtcrf 0x38,0;" 31*a47a12beSStefan Roese "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);" 32*a47a12beSStefan Roese "mtlr 0; mr 3,%1" 33*a47a12beSStefan Roese : : "r" (buf), "r" (val)); 34*a47a12beSStefan Roese } 35*a47a12beSStefan Roese 36*a47a12beSStefan Roese static inline unsigned long 37*a47a12beSStefan Roese get_msr(void) 38*a47a12beSStefan Roese { 39*a47a12beSStefan Roese unsigned long msr; 40*a47a12beSStefan Roese asm volatile("mfmsr %0" : "=r" (msr):); 41*a47a12beSStefan Roese return msr; 42*a47a12beSStefan Roese } 43*a47a12beSStefan Roese 44*a47a12beSStefan Roese static inline void 45*a47a12beSStefan Roese set_msr(unsigned long msr) 46*a47a12beSStefan Roese { 47*a47a12beSStefan Roese asm volatile("mtmsr %0" : : "r" (msr)); 48*a47a12beSStefan Roese } 49*a47a12beSStefan Roese 50*a47a12beSStefan Roese /* Convert the SPARC hardware trap type code to a unix signal number. */ 51*a47a12beSStefan Roese /* 52*a47a12beSStefan Roese * This table contains the mapping between PowerPC hardware trap types, and 53*a47a12beSStefan Roese * signals, which are primarily what GDB understands. 54*a47a12beSStefan Roese */ 55*a47a12beSStefan Roese static struct hard_trap_info 56*a47a12beSStefan Roese { 57*a47a12beSStefan Roese unsigned int tt; /* Trap type code for powerpc */ 58*a47a12beSStefan Roese unsigned char signo; /* Signal that we map this trap into */ 59*a47a12beSStefan Roese } hard_trap_info[] = { 60*a47a12beSStefan Roese { 0x200, SIGSEGV }, /* machine check */ 61*a47a12beSStefan Roese { 0x300, SIGSEGV }, /* address error (store) */ 62*a47a12beSStefan Roese { 0x400, SIGBUS }, /* instruction bus error */ 63*a47a12beSStefan Roese { 0x500, SIGINT }, /* interrupt */ 64*a47a12beSStefan Roese { 0x600, SIGBUS }, /* alingment */ 65*a47a12beSStefan Roese { 0x700, SIGTRAP }, /* breakpoint trap */ 66*a47a12beSStefan Roese { 0x800, SIGFPE }, /* fpu unavail */ 67*a47a12beSStefan Roese { 0x900, SIGALRM }, /* decrementer */ 68*a47a12beSStefan Roese { 0xa00, SIGILL }, /* reserved */ 69*a47a12beSStefan Roese { 0xb00, SIGILL }, /* reserved */ 70*a47a12beSStefan Roese { 0xc00, SIGCHLD }, /* syscall */ 71*a47a12beSStefan Roese { 0xd00, SIGTRAP }, /* single-step/watch */ 72*a47a12beSStefan Roese { 0xe00, SIGFPE }, /* fp assist */ 73*a47a12beSStefan Roese { 0, 0} /* Must be last */ 74*a47a12beSStefan Roese }; 75*a47a12beSStefan Roese 76*a47a12beSStefan Roese static int 77*a47a12beSStefan Roese computeSignal(unsigned int tt) 78*a47a12beSStefan Roese { 79*a47a12beSStefan Roese struct hard_trap_info *ht; 80*a47a12beSStefan Roese 81*a47a12beSStefan Roese for (ht = hard_trap_info; ht->tt && ht->signo; ht++) 82*a47a12beSStefan Roese if (ht->tt == tt) 83*a47a12beSStefan Roese return ht->signo; 84*a47a12beSStefan Roese 85*a47a12beSStefan Roese return SIGHUP; /* default for things we don't know about */ 86*a47a12beSStefan Roese } 87*a47a12beSStefan Roese 88*a47a12beSStefan Roese void 89*a47a12beSStefan Roese kgdb_enter(struct pt_regs *regs, kgdb_data *kdp) 90*a47a12beSStefan Roese { 91*a47a12beSStefan Roese unsigned long msr; 92*a47a12beSStefan Roese 93*a47a12beSStefan Roese kdp->private[0] = msr = get_msr(); 94*a47a12beSStefan Roese set_msr(msr & ~MSR_EE); /* disable interrupts */ 95*a47a12beSStefan Roese 96*a47a12beSStefan Roese if (regs->nip == (unsigned long)breakinst) { 97*a47a12beSStefan Roese /* Skip over breakpoint trap insn */ 98*a47a12beSStefan Roese regs->nip += 4; 99*a47a12beSStefan Roese } 100*a47a12beSStefan Roese regs->msr &= ~MSR_SE; 101*a47a12beSStefan Roese 102*a47a12beSStefan Roese /* reply to host that an exception has occurred */ 103*a47a12beSStefan Roese kdp->sigval = computeSignal(regs->trap); 104*a47a12beSStefan Roese 105*a47a12beSStefan Roese kdp->nregs = 2; 106*a47a12beSStefan Roese 107*a47a12beSStefan Roese kdp->regs[0].num = PC_REGNUM; 108*a47a12beSStefan Roese kdp->regs[0].val = regs->nip; 109*a47a12beSStefan Roese 110*a47a12beSStefan Roese kdp->regs[1].num = SP_REGNUM; 111*a47a12beSStefan Roese kdp->regs[1].val = regs->gpr[SP_REGNUM]; 112*a47a12beSStefan Roese } 113*a47a12beSStefan Roese 114*a47a12beSStefan Roese void 115*a47a12beSStefan Roese kgdb_exit(struct pt_regs *regs, kgdb_data *kdp) 116*a47a12beSStefan Roese { 117*a47a12beSStefan Roese unsigned long msr = kdp->private[0]; 118*a47a12beSStefan Roese 119*a47a12beSStefan Roese if (kdp->extype & KGDBEXIT_WITHADDR) 120*a47a12beSStefan Roese regs->nip = kdp->exaddr; 121*a47a12beSStefan Roese 122*a47a12beSStefan Roese switch (kdp->extype & KGDBEXIT_TYPEMASK) { 123*a47a12beSStefan Roese 124*a47a12beSStefan Roese case KGDBEXIT_KILL: 125*a47a12beSStefan Roese case KGDBEXIT_CONTINUE: 126*a47a12beSStefan Roese set_msr(msr); 127*a47a12beSStefan Roese break; 128*a47a12beSStefan Roese 129*a47a12beSStefan Roese case KGDBEXIT_SINGLE: 130*a47a12beSStefan Roese regs->msr |= MSR_SE; 131*a47a12beSStefan Roese #if 0 132*a47a12beSStefan Roese set_msr(msr | MSR_SE); 133*a47a12beSStefan Roese #endif 134*a47a12beSStefan Roese break; 135*a47a12beSStefan Roese } 136*a47a12beSStefan Roese } 137*a47a12beSStefan Roese 138*a47a12beSStefan Roese int 139*a47a12beSStefan Roese kgdb_trap(struct pt_regs *regs) 140*a47a12beSStefan Roese { 141*a47a12beSStefan Roese return (regs->trap); 142*a47a12beSStefan Roese } 143*a47a12beSStefan Roese 144*a47a12beSStefan Roese /* return the value of the CPU registers. 145*a47a12beSStefan Roese * some of them are non-PowerPC names :( 146*a47a12beSStefan Roese * they are stored in gdb like: 147*a47a12beSStefan Roese * struct { 148*a47a12beSStefan Roese * u32 gpr[32]; 149*a47a12beSStefan Roese * f64 fpr[32]; 150*a47a12beSStefan Roese * u32 pc, ps, cnd, lr; (ps=msr) 151*a47a12beSStefan Roese * u32 cnt, xer, mq; 152*a47a12beSStefan Roese * } 153*a47a12beSStefan Roese */ 154*a47a12beSStefan Roese 155*a47a12beSStefan Roese #define SPACE_REQUIRED ((32*4)+(32*8)+(6*4)) 156*a47a12beSStefan Roese 157*a47a12beSStefan Roese #ifdef CONFIG_8260 158*a47a12beSStefan Roese /* store floating double indexed */ 159*a47a12beSStefan Roese #define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n])) 160*a47a12beSStefan Roese /* store floating double multiple */ 161*a47a12beSStefan Roese #define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \ 162*a47a12beSStefan Roese STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \ 163*a47a12beSStefan Roese STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \ 164*a47a12beSStefan Roese STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \ 165*a47a12beSStefan Roese STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \ 166*a47a12beSStefan Roese STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \ 167*a47a12beSStefan Roese STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \ 168*a47a12beSStefan Roese STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); } 169*a47a12beSStefan Roese #endif 170*a47a12beSStefan Roese 171*a47a12beSStefan Roese int 172*a47a12beSStefan Roese kgdb_getregs(struct pt_regs *regs, char *buf, int max) 173*a47a12beSStefan Roese { 174*a47a12beSStefan Roese int i; 175*a47a12beSStefan Roese unsigned long *ptr = (unsigned long *)buf; 176*a47a12beSStefan Roese 177*a47a12beSStefan Roese if (max < SPACE_REQUIRED) 178*a47a12beSStefan Roese kgdb_error(KGDBERR_NOSPACE); 179*a47a12beSStefan Roese 180*a47a12beSStefan Roese if ((unsigned long)ptr & 3) 181*a47a12beSStefan Roese kgdb_error(KGDBERR_ALIGNFAULT); 182*a47a12beSStefan Roese 183*a47a12beSStefan Roese /* General Purpose Regs */ 184*a47a12beSStefan Roese for (i = 0; i < 32; i++) 185*a47a12beSStefan Roese *ptr++ = regs->gpr[i]; 186*a47a12beSStefan Roese 187*a47a12beSStefan Roese /* Floating Point Regs */ 188*a47a12beSStefan Roese #ifdef CONFIG_8260 189*a47a12beSStefan Roese STFDM(ptr); 190*a47a12beSStefan Roese ptr += 32*2; 191*a47a12beSStefan Roese #else 192*a47a12beSStefan Roese for (i = 0; i < 32; i++) { 193*a47a12beSStefan Roese *ptr++ = 0; 194*a47a12beSStefan Roese *ptr++ = 0; 195*a47a12beSStefan Roese } 196*a47a12beSStefan Roese #endif 197*a47a12beSStefan Roese 198*a47a12beSStefan Roese /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ 199*a47a12beSStefan Roese *ptr++ = regs->nip; 200*a47a12beSStefan Roese *ptr++ = regs->msr; 201*a47a12beSStefan Roese *ptr++ = regs->ccr; 202*a47a12beSStefan Roese *ptr++ = regs->link; 203*a47a12beSStefan Roese *ptr++ = regs->ctr; 204*a47a12beSStefan Roese *ptr++ = regs->xer; 205*a47a12beSStefan Roese 206*a47a12beSStefan Roese return (SPACE_REQUIRED); 207*a47a12beSStefan Roese } 208*a47a12beSStefan Roese 209*a47a12beSStefan Roese /* set the value of the CPU registers */ 210*a47a12beSStefan Roese 211*a47a12beSStefan Roese #ifdef CONFIG_8260 212*a47a12beSStefan Roese /* load floating double */ 213*a47a12beSStefan Roese #define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v)) 214*a47a12beSStefan Roese /* load floating double indexed */ 215*a47a12beSStefan Roese #define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n])) 216*a47a12beSStefan Roese /* load floating double multiple */ 217*a47a12beSStefan Roese #define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \ 218*a47a12beSStefan Roese LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \ 219*a47a12beSStefan Roese LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \ 220*a47a12beSStefan Roese LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \ 221*a47a12beSStefan Roese LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \ 222*a47a12beSStefan Roese LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \ 223*a47a12beSStefan Roese LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \ 224*a47a12beSStefan Roese LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); } 225*a47a12beSStefan Roese #endif 226*a47a12beSStefan Roese 227*a47a12beSStefan Roese void 228*a47a12beSStefan Roese kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length) 229*a47a12beSStefan Roese { 230*a47a12beSStefan Roese unsigned long *ptr = (unsigned long *)buf; 231*a47a12beSStefan Roese 232*a47a12beSStefan Roese if (regno < 0 || regno >= 70) 233*a47a12beSStefan Roese kgdb_error(KGDBERR_BADPARAMS); 234*a47a12beSStefan Roese else if (regno >= 32 && regno < 64) { 235*a47a12beSStefan Roese if (length < 8) 236*a47a12beSStefan Roese kgdb_error(KGDBERR_NOSPACE); 237*a47a12beSStefan Roese } 238*a47a12beSStefan Roese else { 239*a47a12beSStefan Roese if (length < 4) 240*a47a12beSStefan Roese kgdb_error(KGDBERR_NOSPACE); 241*a47a12beSStefan Roese } 242*a47a12beSStefan Roese 243*a47a12beSStefan Roese if ((unsigned long)ptr & 3) 244*a47a12beSStefan Roese kgdb_error(KGDBERR_ALIGNFAULT); 245*a47a12beSStefan Roese 246*a47a12beSStefan Roese if (regno >= 0 && regno < 32) 247*a47a12beSStefan Roese regs->gpr[regno] = *ptr; 248*a47a12beSStefan Roese else switch (regno) { 249*a47a12beSStefan Roese 250*a47a12beSStefan Roese #ifdef CONFIG_8260 251*a47a12beSStefan Roese #define caseF(n) \ 252*a47a12beSStefan Roese case (n) + 32: LFD(n, *ptr); break; 253*a47a12beSStefan Roese 254*a47a12beSStefan Roese caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7) 255*a47a12beSStefan Roese caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15) 256*a47a12beSStefan Roese caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23) 257*a47a12beSStefan Roese caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31) 258*a47a12beSStefan Roese 259*a47a12beSStefan Roese #undef caseF 260*a47a12beSStefan Roese #endif 261*a47a12beSStefan Roese 262*a47a12beSStefan Roese case 64: regs->nip = *ptr; break; 263*a47a12beSStefan Roese case 65: regs->msr = *ptr; break; 264*a47a12beSStefan Roese case 66: regs->ccr = *ptr; break; 265*a47a12beSStefan Roese case 67: regs->link = *ptr; break; 266*a47a12beSStefan Roese case 68: regs->ctr = *ptr; break; 267*a47a12beSStefan Roese case 69: regs->ctr = *ptr; break; 268*a47a12beSStefan Roese 269*a47a12beSStefan Roese default: 270*a47a12beSStefan Roese kgdb_error(KGDBERR_BADPARAMS); 271*a47a12beSStefan Roese } 272*a47a12beSStefan Roese } 273*a47a12beSStefan Roese 274*a47a12beSStefan Roese void 275*a47a12beSStefan Roese kgdb_putregs(struct pt_regs *regs, char *buf, int length) 276*a47a12beSStefan Roese { 277*a47a12beSStefan Roese int i; 278*a47a12beSStefan Roese unsigned long *ptr = (unsigned long *)buf; 279*a47a12beSStefan Roese 280*a47a12beSStefan Roese if (length < SPACE_REQUIRED) 281*a47a12beSStefan Roese kgdb_error(KGDBERR_NOSPACE); 282*a47a12beSStefan Roese 283*a47a12beSStefan Roese if ((unsigned long)ptr & 3) 284*a47a12beSStefan Roese kgdb_error(KGDBERR_ALIGNFAULT); 285*a47a12beSStefan Roese 286*a47a12beSStefan Roese /* 287*a47a12beSStefan Roese * If the stack pointer has moved, you should pray. 288*a47a12beSStefan Roese * (cause only god can help you). 289*a47a12beSStefan Roese */ 290*a47a12beSStefan Roese 291*a47a12beSStefan Roese /* General Purpose Regs */ 292*a47a12beSStefan Roese for (i = 0; i < 32; i++) 293*a47a12beSStefan Roese regs->gpr[i] = *ptr++; 294*a47a12beSStefan Roese 295*a47a12beSStefan Roese /* Floating Point Regs */ 296*a47a12beSStefan Roese #ifdef CONFIG_8260 297*a47a12beSStefan Roese LFDM(ptr); 298*a47a12beSStefan Roese #endif 299*a47a12beSStefan Roese ptr += 32*2; 300*a47a12beSStefan Roese 301*a47a12beSStefan Roese /* pc, msr, cr, lr, ctr, xer, (mq is unused) */ 302*a47a12beSStefan Roese regs->nip = *ptr++; 303*a47a12beSStefan Roese regs->msr = *ptr++; 304*a47a12beSStefan Roese regs->ccr = *ptr++; 305*a47a12beSStefan Roese regs->link = *ptr++; 306*a47a12beSStefan Roese regs->ctr = *ptr++; 307*a47a12beSStefan Roese regs->xer = *ptr++; 308*a47a12beSStefan Roese } 309*a47a12beSStefan Roese 310*a47a12beSStefan Roese /* This function will generate a breakpoint exception. It is used at the 311*a47a12beSStefan Roese beginning of a program to sync up with a debugger and can be used 312*a47a12beSStefan Roese otherwise as a quick means to stop program execution and "break" into 313*a47a12beSStefan Roese the debugger. */ 314*a47a12beSStefan Roese 315*a47a12beSStefan Roese void 316*a47a12beSStefan Roese kgdb_breakpoint(int argc, char *argv[]) 317*a47a12beSStefan Roese { 318*a47a12beSStefan Roese asm(" .globl breakinst\n\ 319*a47a12beSStefan Roese breakinst: .long 0x7d821008\n\ 320*a47a12beSStefan Roese "); 321*a47a12beSStefan Roese } 322