kgdb.c 7.5 KB

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