pseudodbg.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* The fake debug assert instructions
  2. *
  3. * Copyright 2010 Analog Devices Inc.
  4. *
  5. * Licensed under the GPL-2 or later
  6. */
  7. #include <linux/types.h>
  8. #include <linux/kernel.h>
  9. #include <linux/ptrace.h>
  10. const char * const greg_names[] = {
  11. "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
  12. "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
  13. "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
  14. "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
  15. "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
  16. "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
  17. "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
  18. "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
  19. };
  20. static const char *get_allreg_name(int grp, int reg)
  21. {
  22. return greg_names[(grp << 3) | reg];
  23. }
  24. /*
  25. * Unfortunately, the pt_regs structure is not laid out the same way as the
  26. * hardware register file, so we need to do some fix ups.
  27. *
  28. * CYCLES is not stored in the pt_regs structure - so, we just read it from
  29. * the hardware.
  30. *
  31. * Don't support:
  32. * - All reserved registers
  33. * - All in group 7 are (supervisors only)
  34. */
  35. static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg)
  36. {
  37. long *val = &fp->r0;
  38. unsigned long tmp;
  39. /* Only do Dregs and Pregs for now */
  40. if (grp == 5 ||
  41. (grp == 4 && (reg == 4 || reg == 5)) ||
  42. (grp == 7))
  43. return false;
  44. if (grp == 0 || (grp == 1 && reg < 6))
  45. val -= (reg + 8 * grp);
  46. else if (grp == 1 && reg == 6)
  47. val = &fp->usp;
  48. else if (grp == 1 && reg == 7)
  49. val = &fp->fp;
  50. else if (grp == 2) {
  51. val = &fp->i0;
  52. val -= reg;
  53. } else if (grp == 3 && reg >= 4) {
  54. val = &fp->l0;
  55. val -= (reg - 4);
  56. } else if (grp == 3 && reg < 4) {
  57. val = &fp->b0;
  58. val -= reg;
  59. } else if (grp == 4 && reg < 4) {
  60. val = &fp->a0x;
  61. val -= reg;
  62. } else if (grp == 4 && reg == 6)
  63. val = &fp->astat;
  64. else if (grp == 4 && reg == 7)
  65. val = &fp->rets;
  66. else if (grp == 6 && reg < 6) {
  67. val = &fp->lc0;
  68. val -= reg;
  69. } else if (grp == 6 && reg == 6) {
  70. __asm__ __volatile__("%0 = cycles;\n" : "=d"(tmp));
  71. val = &tmp;
  72. } else if (grp == 6 && reg == 7) {
  73. __asm__ __volatile__("%0 = cycles2;\n" : "=d"(tmp));
  74. val = &tmp;
  75. }
  76. *value = *val;
  77. return true;
  78. }
  79. #define PseudoDbg_Assert_opcode 0xf0000000
  80. #define PseudoDbg_Assert_expected_bits 0
  81. #define PseudoDbg_Assert_expected_mask 0xffff
  82. #define PseudoDbg_Assert_regtest_bits 16
  83. #define PseudoDbg_Assert_regtest_mask 0x7
  84. #define PseudoDbg_Assert_grp_bits 19
  85. #define PseudoDbg_Assert_grp_mask 0x7
  86. #define PseudoDbg_Assert_dbgop_bits 22
  87. #define PseudoDbg_Assert_dbgop_mask 0x3
  88. #define PseudoDbg_Assert_dontcare_bits 24
  89. #define PseudoDbg_Assert_dontcare_mask 0x7
  90. #define PseudoDbg_Assert_code_bits 27
  91. #define PseudoDbg_Assert_code_mask 0x1f
  92. /*
  93. * DBGA - debug assert
  94. */
  95. bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
  96. {
  97. int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
  98. int dbgop = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask);
  99. int grp = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask);
  100. int regtest = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask);
  101. long value;
  102. if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
  103. return false;
  104. if (!fix_up_reg(fp, &value, grp, regtest))
  105. return false;
  106. if (dbgop == 0 || dbgop == 2) {
  107. /* DBGA ( regs_lo , uimm16 ) */
  108. /* DBGAL ( regs , uimm16 ) */
  109. if (expected != (value & 0xFFFF)) {
  110. pr_notice("DBGA (%s.L,0x%x) failure, got 0x%x\n",
  111. get_allreg_name(grp, regtest),
  112. expected, (unsigned int)(value & 0xFFFF));
  113. return false;
  114. }
  115. } else if (dbgop == 1 || dbgop == 3) {
  116. /* DBGA ( regs_hi , uimm16 ) */
  117. /* DBGAH ( regs , uimm16 ) */
  118. if (expected != ((value >> 16) & 0xFFFF)) {
  119. pr_notice("DBGA (%s.H,0x%x) failure, got 0x%x\n",
  120. get_allreg_name(grp, regtest),
  121. expected, (unsigned int)((value >> 16) & 0xFFFF));
  122. return false;
  123. }
  124. }
  125. fp->pc += 4;
  126. return true;
  127. }
  128. #define PseudoDbg_opcode 0xf8000000
  129. #define PseudoDbg_reg_bits 0
  130. #define PseudoDbg_reg_mask 0x7
  131. #define PseudoDbg_grp_bits 3
  132. #define PseudoDbg_grp_mask 0x7
  133. #define PseudoDbg_fn_bits 6
  134. #define PseudoDbg_fn_mask 0x3
  135. #define PseudoDbg_code_bits 8
  136. #define PseudoDbg_code_mask 0xff
  137. /*
  138. * DBG - debug (dump a register value out)
  139. */
  140. bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode)
  141. {
  142. int grp, fn, reg;
  143. long value, value1;
  144. if ((opcode & 0xFF000000) != PseudoDbg_opcode)
  145. return false;
  146. opcode >>= 16;
  147. grp = ((opcode >> PseudoDbg_grp_bits) & PseudoDbg_reg_mask);
  148. fn = ((opcode >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
  149. reg = ((opcode >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
  150. if (fn == 3 && (reg == 0 || reg == 1)) {
  151. if (!fix_up_reg(fp, &value, 4, 2 * reg))
  152. return false;
  153. if (!fix_up_reg(fp, &value1, 4, 2 * reg + 1))
  154. return false;
  155. pr_notice("DBG A%i = %02lx%08lx\n", reg, value & 0xFF, value1);
  156. fp->pc += 2;
  157. return true;
  158. } else if (fn == 0) {
  159. if (!fix_up_reg(fp, &value, grp, reg))
  160. return false;
  161. pr_notice("DBG %s = %08lx\n", get_allreg_name(grp, reg), value);
  162. fp->pc += 2;
  163. return true;
  164. }
  165. return false;
  166. }