mt_dbg_aarch32.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/uaccess.h>
  4. #include <mt-plat/mt_boot.h>
  5. #ifdef CONFIG_SMP
  6. #include <linux/cpu.h>
  7. #endif
  8. #include "hw_watchpoint_aarch32.h"
  9. #include "mt_dbg_aarch32.h"
  10. struct dbgreg_set dbgregs[8];
  11. unsigned long saved_dbgdscr;
  12. unsigned long saved_dbgvcr;
  13. #ifdef DBG_REG_DUMP
  14. void dump_dbgregs(int cpuid)
  15. {
  16. struct wp_trace_context_t *wp_context;
  17. int i;
  18. int oslsr;
  19. int dbglsr;
  20. register_wp_context(&wp_context);
  21. cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY);
  22. cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY);
  23. smp_call_function_single(cpuid, smp_read_dbgoslsr_callback, &oslsr, 1);
  24. dbglsr = cs_cpu_read(wp_context->debug_regs[cpuid], DBGLSR);
  25. pr_debug("[MTK WP]dump_dbgregs: cpu %d, DBGLSR 0x%x, DBGOSLSR 0x%x\n", cpuid, dbglsr,
  26. oslsr);
  27. isb();
  28. smp_call_function_single(cpuid, smp_read_dbgdscr_callback, &dbgregs[cpuid].DBGDSCRext, 1);
  29. for (i = 1; i < 1 + (wp_context->bp_nr); i++) {
  30. dbgregs[cpuid].regs[i] =
  31. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGBVR + ((i - 1) << 4)));
  32. }
  33. for (i = 7; i < 7 + (wp_context->bp_nr); i++) {
  34. dbgregs[cpuid].regs[i] =
  35. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGBCR + ((i - 7) << 4)));
  36. }
  37. for (i = 13; i < 13 + (wp_context->wp_nr); i++) {
  38. dbgregs[cpuid].regs[i] =
  39. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWVR + ((i - 13) << 4)));
  40. pr_debug("[MTK WP]dump_dbgregs:DBGWVR &0x%p=0x%x\n",
  41. wp_context->debug_regs[cpuid] + (DBGWVR + ((i - 13) << 4)),
  42. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWVR + ((i - 13) << 4))));
  43. }
  44. for (i = 17; i < 17 + (wp_context->wp_nr); i++) {
  45. dbgregs[cpuid].regs[i] =
  46. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWCR + ((i - 17) << 4)));
  47. }
  48. smp_call_function_single(cpuid, smp_read_dbgvcr_callback, &dbgregs[cpuid].DBGVCR, 1);
  49. /*
  50. smp_call_function_single(cpuid,smp_read_dbgsdsr_callback,&dbgregs[cpuid].SDSR,1);
  51. */
  52. isb();
  53. }
  54. void print_dbgregs(int cpuid)
  55. {
  56. pr_debug("[MTK WP] cpu %d, DBGDSCR 0x%lx\n", cpuid, dbgregs[cpuid].DBGDSCRext);
  57. pr_debug("[MTK WP] cpu %d, DBGBVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR0);
  58. pr_debug("[MTK WP] cpu %d, DBGBVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR1);
  59. pr_debug("[MTK WP] cpu %d, DBGBVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR2);
  60. pr_debug("[MTK WP] cpu %d, DBGBVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR3);
  61. pr_debug("[MTK WP] cpu %d, DBGBVR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR4);
  62. pr_debug("[MTK WP] cpu %d, DBGBVR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR5);
  63. pr_debug("[MTK WP] cpu %d, DBGBCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR0);
  64. pr_debug("[MTK WP] cpu %d, DBGBCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR1);
  65. pr_debug("[MTK WP] cpu %d, DBGBCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR2);
  66. pr_debug("[MTK WP] cpu %d, DBGBCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR3);
  67. pr_debug("[MTK WP] cpu %d, DBGBCR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR4);
  68. pr_debug("[MTK WP] cpu %d, DBGBCR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR5);
  69. pr_debug("[MTK WP] cpu %d, DBGWVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR0);
  70. pr_debug("[MTK WP] cpu %d, DBGWVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR1);
  71. pr_debug("[MTK WP] cpu %d, DBGWVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR2);
  72. pr_debug("[MTK WP] cpu %d, DBGWVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR3);
  73. pr_debug("[MTK WP] cpu %d, DBGWCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR0);
  74. pr_debug("[MTK WP] cpu %d, DBGWCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR1);
  75. pr_debug("[MTK WP] cpu %d, DBGWCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR2);
  76. pr_debug("[MTK WP] cpu %d, DBGWCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR3);
  77. pr_debug("[MTK WP] cpu %d, DBGVCR 0x%lx\n", cpuid, dbgregs[cpuid].DBGVCR);
  78. pr_debug("[MTK WP] cpu %d, SDSR 0x%lx\n", cpuid, dbgregs[cpuid].SDSR);
  79. }
  80. #endif
  81. unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid)
  82. {
  83. struct wp_trace_context_t *wp_context;
  84. register_wp_context(&wp_context);
  85. cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY);
  86. cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY);
  87. if (*p == ~0x0) {
  88. pr_err("[MTK WP]restore pointer is NULL\n");
  89. return 0;
  90. }
  91. isb();
  92. /* save register */
  93. __asm__ __volatile__("mrc p14, 0, r4, c0, c2, 2 @DBGDSCR_ext\n\t"
  94. "stm %0!, {r4}\n\t"
  95. "mrc p14, 0, r4, c0, c0, 4 @DBGBVR\n\t"
  96. "mrc p14, 0, r5, c0, c1, 4 @DBGBVR\n\t"
  97. "mrc p14, 0, r6, c0, c2, 4 @DBGBVR\n\t"
  98. "mrc p14, 0, r7, c0, c3, 4 @DBGBVR\n\t"
  99. "mrc p14, 0, r8, c0, c4, 4 @DBGBVR\n\t"
  100. "mrc p14, 0, r9, c0, c5, 4 @DBGBVR\n\t"
  101. "stm %0!, {r4-r9}\n\t"
  102. "mrc p14, 0, r4, c0, c0, 5 @DBGBCR\n\t"
  103. "mrc p14, 0, r5, c0, c1, 5 @DBGBCR\n\t"
  104. "mrc p14, 0, r6, c0, c2, 5 @DBGBCR\n\t"
  105. "mrc p14, 0, r7, c0, c3, 5 @DBGBCR\n\t"
  106. "mrc p14, 0, r8, c0, c4, 5 @DBGBCR\n\t"
  107. "mrc p14, 0, r9, c0, c5, 5 @DBGBCR\n\t"
  108. "stm %0!, {r4-r9}\n\t"
  109. "mrc p14, 0, r4, c0, c0, 6 @DBGWVR\n\t"
  110. "mrc p14, 0, r5, c0, c1, 6 @DBGWVR\n\t"
  111. "mrc p14, 0, r6, c0, c2, 6 @DBGWVR\n\t"
  112. "mrc p14, 0, r7, c0, c3, 6 @DBGWVR\n\t"
  113. "stm %0!, {r4-r7}\n\t"
  114. "mrc p14, 0, r4, c0, c0, 7 @DBGWCR\n\t"
  115. "mrc p14, 0, r5, c0, c1, 7 @DBGWCR\n\t"
  116. "mrc p14, 0, r6, c0, c2, 7 @DBGWCR\n\t"
  117. "mrc p14, 0, r7, c0, c3, 7 @DBGWCR\n\t"
  118. "stm %0!, {r4-r7}\n\t"
  119. "mrc p14, 0, r4, c0, c7, 0 @DBGVCR\n\t" "stm %0!, {r4}\n\t":"+r"(p)
  120. : : "r4", "r5", "r6", "r7", "r8", "r9");
  121. isb();
  122. return p;
  123. }
  124. void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid)
  125. {
  126. unsigned int dscr;
  127. struct wp_trace_context_t *wp_context;
  128. register_wp_context(&wp_context);
  129. /* the dbg container is invalid */
  130. if (*p == ~0x0) {
  131. pr_err("[MTK WP]restore pointer is NULL\n");
  132. return;
  133. }
  134. cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR, UNLOCK_KEY);
  135. cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR, ~UNLOCK_KEY);
  136. isb();
  137. /* restore register */
  138. __asm__ __volatile__("ldm %0!, {r4}\n\t"
  139. "mov %1, r4\n\t"
  140. "mcr p14, 0, r4, c0, c2, 2 @DBGDSCR\n\t"
  141. "ldm %0!, {r4-r9}\n\t"
  142. "mcr p14, 0, r4, c0, c0, 4 @DBGBVR\n\t"
  143. "mcr p14, 0, r5, c0, c1, 4 @DBGBVR\n\t"
  144. "mcr p14, 0, r6, c0, c2, 4 @DBGBVR\n\t"
  145. "mcr p14, 0, r7, c0, c3, 4 @DBGBVR\n\t"
  146. "mcr p14, 0, r8, c0, c4, 4 @DBGBVR\n\t"
  147. "mcr p14, 0, r9, c0, c5, 4 @DBGBVR\n\t"
  148. "ldm %0!, {r4-r9}\n\t"
  149. "mcr p14, 0, r4, c0, c0, 5 @DBGBCR\n\t"
  150. "mcr p14, 0, r5, c0, c1, 5 @DBGBCR\n\t"
  151. "mcr p14, 0, r6, c0, c2, 5 @DBGBCR\n\t"
  152. "mcr p14, 0, r7, c0, c3, 5 @DBGBCR\n\t"
  153. "mcr p14, 0, r8, c0, c4, 5 @DBGBCR\n\t"
  154. "mcr p14, 0, r9, c0, c5, 5 @DBGBCR\n\t"
  155. "ldm %0!, {r4-r7}\n\t"
  156. "mcr p14, 0, r4, c0, c0, 6 @DBGWVR\n\t"
  157. "mcr p14, 0, r5, c0, c1, 6 @DBGWVR\n\t"
  158. "mcr p14, 0, r6, c0, c2, 6 @DBGWVR\n\t"
  159. "mcr p14, 0, r7, c0, c3, 6 @DBGWVR\n\t"
  160. "ldm %0!, {r4-r7}\n\t"
  161. "mcr p14, 0, r4, c0, c0, 7 @DBGWCR\n\t"
  162. "mcr p14, 0, r5, c0, c1, 7 @DBGWCR\n\t"
  163. "mcr p14, 0, r6, c0, c2, 7 @DBGWCR\n\t"
  164. "mcr p14, 0, r7, c0, c3, 7 @DBGWCR\n\t"
  165. "ldm %0!, {r4}\n\t"
  166. "mcr p14, 0, r4, c0, c7, 0 @DBGVCR\n\t":"+r"(p), "=r"(dscr)
  167. : : "r4", "r5", "r6", "r7", "r8", "r9");
  168. /*
  169. cs_cpu_write(wp_context->debug_regs[cpuid], DBGOSLAR ,UNLOCK_KEY);
  170. cs_cpu_write(wp_context->debug_regs[cpuid], DBGLAR ,~UNLOCK_KEY);
  171. */
  172. isb();
  173. }
  174. /** to copy dbg registers from FROM to TO within the same cluster.
  175. * DBG_BASE is the common base of 2 cores debug register space.
  176. **/
  177. void mt_copy_dbg_regs(int to, int from)
  178. {
  179. unsigned long base_to, base_from;
  180. unsigned long args;
  181. struct wp_trace_context_t *wp_context;
  182. register_wp_context(&wp_context);
  183. base_to = (unsigned long)wp_context->debug_regs[to];
  184. base_from = (unsigned long)wp_context->debug_regs[from];
  185. /* os unlock */
  186. cs_cpu_write(wp_context->debug_regs[to], DBGLAR, UNLOCK_KEY);
  187. cs_cpu_write(wp_context->debug_regs[to], DBGOSLAR, ~UNLOCK_KEY);
  188. cs_cpu_write(wp_context->debug_regs[from], DBGLAR, UNLOCK_KEY);
  189. cs_cpu_write(wp_context->debug_regs[from], DBGOSLAR, ~UNLOCK_KEY);
  190. isb();
  191. smp_call_function_single(from, smp_read_dbgdscr_callback, &args, 1);
  192. smp_call_function_single(to, smp_write_dbgdscr_callback, &args, 1);
  193. isb();
  194. dbg_reg_copy(DBGBCR, base_to, base_from);
  195. dbg_reg_copy(DBGBCR + 0x10, base_to, base_from);
  196. dbg_reg_copy(DBGBCR + 0x20, base_to, base_from);
  197. dbg_reg_copy(DBGBCR + 0x30, base_to, base_from);
  198. dbg_reg_copy(DBGBCR + 0x40, base_to, base_from);
  199. dbg_reg_copy(DBGBCR + 0x50, base_to, base_from);
  200. dbg_reg_copy(DBGBVR, base_to, base_from);
  201. dbg_reg_copy(DBGBVR + 0x10, base_to, base_from);
  202. dbg_reg_copy(DBGBVR + 0x20, base_to, base_from);
  203. dbg_reg_copy(DBGBVR + 0x30, base_to, base_from);
  204. dbg_reg_copy(DBGBVR + 0x40, base_to, base_from);
  205. dbg_reg_copy(DBGBVR + 0x50, base_to, base_from);
  206. dbg_reg_copy(DBGWVR, base_to, base_from);
  207. dbg_reg_copy(DBGWVR + 0x10, base_to, base_from);
  208. dbg_reg_copy(DBGWVR + 0x20, base_to, base_from);
  209. dbg_reg_copy(DBGWVR + 0x30, base_to, base_from);
  210. dbg_reg_copy(DBGWCR, base_to, base_from);
  211. dbg_reg_copy(DBGWCR + 0x10, base_to, base_from);
  212. dbg_reg_copy(DBGWCR + 0x20, base_to, base_from);
  213. dbg_reg_copy(DBGWCR + 0x30, base_to, base_from);
  214. smp_call_function_single(from, smp_read_dbgvcr_callback, &args, 1);
  215. ARM_DBG_WRITE(c0, c7, 0, args);
  216. isb();
  217. }
  218. #ifdef CONFIG_SMP
  219. int __cpuinit dbgregs_hotplug_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
  220. {
  221. unsigned int this_cpu = (unsigned int)hcpu;
  222. struct wp_trace_context_t *wp_context;
  223. register_wp_context(&wp_context);
  224. cs_cpu_write(wp_context->debug_regs[this_cpu], DBGLAR, UNLOCK_KEY);
  225. cs_cpu_write(wp_context->debug_regs[this_cpu], DBGOSLAR, ~UNLOCK_KEY);
  226. cs_cpu_write(wp_context->debug_regs[0], DBGLAR, UNLOCK_KEY);
  227. cs_cpu_write(wp_context->debug_regs[0], DBGOSLAR, ~UNLOCK_KEY);
  228. #ifdef DBG_REG_DUMP
  229. pr_debug("[MTK WP] cpu %x do %s,action: 0x%lx\n", this_cpu, __func__, action);
  230. #endif
  231. switch (action) {
  232. case CPU_STARTING:
  233. #ifdef DBG_REG_DUMP
  234. pr_debug("[MTK WP] cpu %x do %s, CPU0's _MDSCR_EL1=0x%lx, action 0x%lx\n",
  235. this_cpu, __func__, saved_dbgdscr, action);
  236. #endif
  237. cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (0 << 4));
  238. /* smp_call_function_single(0, smp_read_dbgdscr_callback, &args, 1); */
  239. ARM_DBG_WRITE(c0, c2, 2, saved_dbgdscr);
  240. ARM_DBG_WRITE(c0, c0, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (0 << 4)));
  241. ARM_DBG_WRITE(c0, c1, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (1 << 4)));
  242. ARM_DBG_WRITE(c0, c2, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (2 << 4)));
  243. ARM_DBG_WRITE(c0, c3, 6, cs_cpu_read(wp_context->debug_regs[0], DBGWVR + (3 << 4)));
  244. ARM_DBG_WRITE(c0, c0, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (0 << 4)));
  245. ARM_DBG_WRITE(c0, c1, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (1 << 4)));
  246. ARM_DBG_WRITE(c0, c2, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (2 << 4)));
  247. ARM_DBG_WRITE(c0, c3, 7, cs_cpu_read(wp_context->debug_regs[0], DBGWCR + (3 << 4)));
  248. ARM_DBG_WRITE(c0, c0, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (0 << 4)));
  249. ARM_DBG_WRITE(c0, c1, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (1 << 4)));
  250. ARM_DBG_WRITE(c0, c2, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (2 << 4)));
  251. ARM_DBG_WRITE(c0, c3, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (3 << 4)));
  252. ARM_DBG_WRITE(c0, c4, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (4 << 4)));
  253. ARM_DBG_WRITE(c0, c5, 4, cs_cpu_read(wp_context->debug_regs[0], DBGBVR + (5 << 4)));
  254. ARM_DBG_WRITE(c0, c0, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (0 << 4)));
  255. ARM_DBG_WRITE(c0, c1, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (1 << 4)));
  256. ARM_DBG_WRITE(c0, c2, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (2 << 4)));
  257. ARM_DBG_WRITE(c0, c3, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (3 << 4)));
  258. ARM_DBG_WRITE(c0, c4, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (4 << 4)));
  259. ARM_DBG_WRITE(c0, c5, 5, cs_cpu_read(wp_context->debug_regs[0], DBGBCR + (5 << 4)));
  260. isb();
  261. /* smp_call_function_single(0, smp_read_dbgvcr_callback, &args, 1); */
  262. ARM_DBG_WRITE(c0, c7, 0, saved_dbgvcr);
  263. /*
  264. smp_call_function_single(0,smp_read_dbgsdsr_callback,&args,1);
  265. smp_write_dbgsdsr_callback(&args);
  266. */
  267. break;
  268. default:
  269. break;
  270. }
  271. return NOTIFY_OK;
  272. }
  273. static struct notifier_block cpu_nfb __cpuinitdata = {
  274. .notifier_call = dbgregs_hotplug_callback
  275. };
  276. static int __init regs_backup(void)
  277. {
  278. register_cpu_notifier(&cpu_nfb);
  279. return 0;
  280. }
  281. module_init(regs_backup);
  282. #endif