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