mt_dbg_aarch64.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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_aarch64.h"
  9. #include "mt_dbg_aarch64.h"
  10. struct dbgreg_set dbgregs[8];
  11. unsigned long saved_MDSCR_EL1;
  12. #ifdef DBG_REG_DUMP
  13. void dump_dbgregs(int cpuid)
  14. {
  15. struct wp_trace_context_t *wp_context;
  16. int i;
  17. register_wp_context(&wp_context);
  18. cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY);
  19. cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY);
  20. isb();
  21. smp_call_function_single(cpuid, smp_read_MDSCR_EL1_callback, &dbgregs[cpuid].MDSCR_EL1, 1);
  22. for (i = 1; i < 1 + (wp_context->bp_nr); i++) {
  23. dbgregs[cpuid].regs[i] =
  24. cs_cpu_read_64(wp_context->debug_regs[cpuid], (DBGBVR + ((i - 1) << 4)));
  25. }
  26. for (i = 7; i < 7 + (wp_context->bp_nr); i++) {
  27. dbgregs[cpuid].regs[i] =
  28. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGBCR + ((i - 7) << 4)));
  29. }
  30. for (i = 13; i < 13 + (wp_context->wp_nr); i++) {
  31. dbgregs[cpuid].regs[i] =
  32. cs_cpu_read_64(wp_context->debug_regs[cpuid], (DBGWVR + ((i - 13) << 4)));
  33. }
  34. for (i = 17; i < 17 + (wp_context->wp_nr); i++) {
  35. dbgregs[cpuid].regs[i] =
  36. cs_cpu_read(wp_context->debug_regs[cpuid], (DBGWCR + ((i - 17) << 4)));
  37. }
  38. isb();
  39. }
  40. void print_dbgregs(int cpuid)
  41. {
  42. pr_debug("[MTK WP] cpu %d, MDSCR_EL1 0x%lx\n", cpuid, dbgregs[cpuid].MDSCR_EL1);
  43. pr_debug("[MTK WP] cpu %d, DBGBVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR0);
  44. pr_debug("[MTK WP] cpu %d, DBGBVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR1);
  45. pr_debug("[MTK WP] cpu %d, DBGBVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR2);
  46. pr_debug("[MTK WP] cpu %d, DBGBVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR3);
  47. pr_debug("[MTK WP] cpu %d, DBGBVR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR4);
  48. pr_debug("[MTK WP] cpu %d, DBGBVR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBVR5);
  49. pr_debug("[MTK WP] cpu %d, DBGBCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR0);
  50. pr_debug("[MTK WP] cpu %d, DBGBCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR1);
  51. pr_debug("[MTK WP] cpu %d, DBGBCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR2);
  52. pr_debug("[MTK WP] cpu %d, DBGBCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR3);
  53. pr_debug("[MTK WP] cpu %d, DBGBCR4 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR4);
  54. pr_debug("[MTK WP] cpu %d, DBGBCR5 0x%lx\n", cpuid, dbgregs[cpuid].DBGBCR5);
  55. pr_debug("[MTK WP] cpu %d, DBGWVR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR0);
  56. pr_debug("[MTK WP] cpu %d, DBGWVR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR1);
  57. pr_debug("[MTK WP] cpu %d, DBGWVR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR2);
  58. pr_debug("[MTK WP] cpu %d, DBGWVR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWVR3);
  59. pr_debug("[MTK WP] cpu %d, DBGWCR0 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR0);
  60. pr_debug("[MTK WP] cpu %d, DBGWCR1 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR1);
  61. pr_debug("[MTK WP] cpu %d, DBGWCR2 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR2);
  62. pr_debug("[MTK WP] cpu %d, DBGWCR3 0x%lx\n", cpuid, dbgregs[cpuid].DBGWCR3);
  63. /*
  64. pr_debug("[MTK WP] cpu %d, DBGVCR 0x%lx\n",cpuid,dbgregs[cpuid].DBGVCR);
  65. pr_debug("[MTK WP] cpu %d, SDSR 0x%lx\n",cpuid,dbgregs[cpuid].SDSR);
  66. } */
  67. #endif
  68. #if 1
  69. unsigned int *mt_save_dbg_regs(unsigned int *p, unsigned int cpuid)
  70. {
  71. struct wp_trace_context_t *wp_context;
  72. register_wp_context(&wp_context);
  73. cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY);
  74. cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY);
  75. #ifdef DBG_REG_DUMP
  76. pr_debug("[MTK WP] %s\n", __func__);
  77. #endif
  78. if (*p == ~0x0) {
  79. pr_err("[MTK WP]restore pointer is NULL\n");
  80. return 0;
  81. }
  82. isb();
  83. /* save register */
  84. __asm__ __volatile__("mrs x0, MDSCR_EL1\n\t"
  85. "str x0, [%0],#0x8\n\t"
  86. "mrs x0, DBGBVR0_EL1\n\t"
  87. "mrs x1, DBGBVR1_EL1\n\t"
  88. "mrs x2, DBGBVR2_EL1\n\t"
  89. "mrs x3, DBGBVR3_EL1\n\t"
  90. "mrs x4, DBGBVR4_EL1\n\t"
  91. "mrs x5, DBGBVR5_EL1\n\t"
  92. "str x0 , [%0],#0x8\n\t"
  93. "str x1 , [%0],#0x8\n\t"
  94. "str x2 , [%0],#0x8\n\t"
  95. "str x3 , [%0],#0x8\n\t"
  96. "str x4 , [%0],#0x8\n\t"
  97. "str x5 , [%0],#0x8\n\t"
  98. "mrs x0, DBGBCR0_EL1\n\t"
  99. "mrs x1, DBGBCR1_EL1\n\t"
  100. "mrs x2, DBGBCR2_EL1\n\t"
  101. "mrs x3, DBGBCR3_EL1\n\t"
  102. "mrs x4, DBGBCR4_EL1\n\t"
  103. "mrs x5, DBGBCR5_EL1\n\t"
  104. "str x0 , [%0],#0x8\n\t"
  105. "str x1 , [%0],#0x8\n\t"
  106. "str x2 , [%0],#0x8\n\t"
  107. "str x3 , [%0],#0x8\n\t"
  108. "str x4 , [%0],#0x8\n\t"
  109. "str x5 , [%0],#0x8\n\t"
  110. "mrs x0, DBGWVR0_EL1\n\t"
  111. "mrs x1, DBGWVR1_EL1\n\t"
  112. "mrs x2, DBGWVR2_EL1\n\t"
  113. "mrs x3, DBGWVR3_EL1\n\t"
  114. "str x0 , [%0],#0x8\n\t"
  115. "str x1 , [%0],#0x8\n\t"
  116. "str x2 , [%0],#0x8\n\t"
  117. "str x3 , [%0],#0x8\n\t"
  118. "mrs x0, DBGWCR0_EL1\n\t"
  119. "mrs x1, DBGWCR1_EL1\n\t"
  120. "mrs x2, DBGWCR2_EL1\n\t"
  121. "mrs x3, DBGWCR3_EL1\n\t"
  122. "str x0 , [%0],#0x8\n\t"
  123. "str x1 , [%0],#0x8\n\t"
  124. "str x2 , [%0],#0x8\n\t" "str x3 , [%0],#0x8\n\t":"+r"(p)
  125. : : "x0", "x1", "x2", "x3", "x4", "x5");
  126. isb();
  127. return p;
  128. }
  129. void mt_restore_dbg_regs(unsigned int *p, unsigned int cpuid)
  130. {
  131. unsigned long dscr;
  132. struct wp_trace_context_t *wp_context;
  133. #ifdef DBG_REG_DUMP
  134. pr_debug("[MTK WP] %s\n", __func__);
  135. #endif
  136. register_wp_context(&wp_context);
  137. /* the dbg container is invalid */
  138. if (*p == ~0x0) {
  139. pr_err("[MTK WP]restore pointer is NULL\n");
  140. return;
  141. }
  142. cs_cpu_write(wp_context->debug_regs[cpuid], EDLAR, UNLOCK_KEY);
  143. cs_cpu_write(wp_context->debug_regs[cpuid], OSLAR_EL1, ~UNLOCK_KEY);
  144. isb();
  145. /* restore register */
  146. #if 1
  147. __asm__ __volatile__("ldr x0, [%0],#0x8\n\t"
  148. "mov %1, x0\n\t"
  149. "msr MDSCR_EL1,x0\n\t"
  150. "ldr x0 , [%0],#0x8\n\t"
  151. "ldr x1 , [%0],#0x8\n\t"
  152. "ldr x2 , [%0],#0x8\n\t"
  153. "ldr x3 , [%0],#0x8\n\t"
  154. "ldr x4 , [%0],#0x8\n\t"
  155. "ldr x5 , [%0],#0x8\n\t"
  156. "msr DBGBVR0_EL1,x0\n\t"
  157. "msr DBGBVR1_EL1,x1\n\t"
  158. "msr DBGBVR2_EL1,x2\n\t"
  159. "msr DBGBVR3_EL1,x3\n\t"
  160. "msr DBGBVR4_EL1,x4\n\t"
  161. "msr DBGBVR5_EL1,x5\n\t"
  162. "ldr x0 , [%0],#0x8\n\t"
  163. "ldr x1 , [%0],#0x8\n\t"
  164. "ldr x2 , [%0],#0x8\n\t"
  165. "ldr x3 , [%0],#0x8\n\t"
  166. "ldr x4 , [%0],#0x8\n\t"
  167. "ldr x5 , [%0],#0x8\n\t"
  168. "msr DBGBCR0_EL1,x0\n\t"
  169. "msr DBGBCR1_EL1,x1\n\t"
  170. "msr DBGBCR2_EL1,x2\n\t"
  171. "msr DBGBCR3_EL1,x3\n\t"
  172. "msr DBGBCR4_EL1,x4\n\t"
  173. "msr DBGBCR5_EL1,x5\n\t"
  174. "ldr x0 , [%0],#0x8\n\t"
  175. "ldr x1 , [%0],#0x8\n\t"
  176. "ldr x2 , [%0],#0x8\n\t"
  177. "ldr x3 , [%0],#0x8\n\t"
  178. "msr DBGWVR0_EL1,x0\n\t"
  179. "msr DBGWVR1_EL1,x1\n\t"
  180. "msr DBGWVR2_EL1,x2\n\t"
  181. "msr DBGWVR3_EL1,x3\n\t"
  182. "ldr x0 , [%0],#0x8\n\t"
  183. "ldr x1 , [%0],#0x8\n\t"
  184. "ldr x2 , [%0],#0x8\n\t"
  185. "ldr x3 , [%0],#0x8\n\t"
  186. "msr DBGWCR0_EL1,x0\n\t"
  187. "msr DBGWCR1_EL1,x1\n\t"
  188. "msr DBGWCR2_EL1,x2\n\t"
  189. "msr DBGWCR3_EL1,x3\n\t":"+r"(p), "=r"(dscr)
  190. : : "x0", "x1", "x2", "x3", "x4", "x5");
  191. #endif
  192. isb();
  193. }
  194. /** to copy dbg registers from FROM to TO within the same cluster.
  195. * DBG_BASE is the common base of 2 cores debug register space.
  196. **/
  197. void mt_copy_dbg_regs(int to, int from)
  198. {
  199. unsigned long base_to, base_from;
  200. unsigned long args;
  201. struct wp_trace_context_t *wp_context;
  202. register_wp_context(&wp_context);
  203. base_to = (unsigned long)wp_context->debug_regs[to];
  204. base_from = (unsigned long)wp_context->debug_regs[from];
  205. /* os unlock */
  206. cs_cpu_write(wp_context->debug_regs[to], EDLAR, UNLOCK_KEY);
  207. cs_cpu_write(wp_context->debug_regs[to], OSLAR_EL1, ~UNLOCK_KEY);
  208. cs_cpu_write(wp_context->debug_regs[from], EDLAR, UNLOCK_KEY);
  209. cs_cpu_write(wp_context->debug_regs[from], OSLAR_EL1, ~UNLOCK_KEY);
  210. isb();
  211. smp_call_function_single(from, smp_read_MDSCR_EL1_callback, &args, 1);
  212. smp_call_function_single(to, smp_write_MDSCR_EL1_callback, &args, 1);
  213. isb();
  214. dbg_reg_copy(DBGBCR, base_to, base_from);
  215. dbg_reg_copy(DBGBCR + 0x10, base_to, base_from);
  216. dbg_reg_copy(DBGBCR + 0x20, base_to, base_from);
  217. dbg_reg_copy(DBGBCR + 0x30, base_to, base_from);
  218. dbg_reg_copy(DBGBCR + 0x40, base_to, base_from);
  219. dbg_reg_copy(DBGBCR + 0x50, base_to, base_from);
  220. dbg_reg_copy_64(DBGBVR, base_to, base_from);
  221. dbg_reg_copy_64(DBGBVR + 0x10, base_to, base_from);
  222. dbg_reg_copy_64(DBGBVR + 0x20, base_to, base_from);
  223. dbg_reg_copy_64(DBGBVR + 0x30, base_to, base_from);
  224. dbg_reg_copy_64(DBGBVR + 0x40, base_to, base_from);
  225. dbg_reg_copy_64(DBGBVR + 0x50, base_to, base_from);
  226. dbg_reg_copy_64(DBGWVR, base_to, base_from);
  227. dbg_reg_copy_64(DBGWVR + 0x10, base_to, base_from);
  228. dbg_reg_copy_64(DBGWVR + 0x20, base_to, base_from);
  229. dbg_reg_copy_64(DBGWVR + 0x30, base_to, base_from);
  230. dbg_reg_copy(DBGWCR, base_to, base_from);
  231. dbg_reg_copy(DBGWCR + 0x10, base_to, base_from);
  232. dbg_reg_copy(DBGWCR + 0x20, base_to, base_from);
  233. dbg_reg_copy(DBGWCR + 0x30, base_to, base_from);
  234. isb();
  235. }
  236. #ifdef CONFIG_SMP
  237. int __cpuinit dbgregs_hotplug_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
  238. {
  239. unsigned long this_cpu = (unsigned long)hcpu;
  240. unsigned int args = 0;
  241. struct wp_trace_context_t *wp_context;
  242. unsigned long base_to, base_from;
  243. register_wp_context(&wp_context);
  244. cs_cpu_write(wp_context->debug_regs[this_cpu], EDLAR, UNLOCK_KEY);
  245. cs_cpu_write(wp_context->debug_regs[this_cpu], OSLAR_EL1, ~UNLOCK_KEY);
  246. cs_cpu_write(wp_context->debug_regs[0], EDLAR, UNLOCK_KEY);
  247. cs_cpu_write(wp_context->debug_regs[0], OSLAR_EL1, ~UNLOCK_KEY);
  248. base_to = (unsigned long)wp_context->debug_regs[this_cpu];
  249. base_from = (unsigned long)wp_context->debug_regs[0];
  250. action = action & 0xf;
  251. #ifdef DBG_REG_DUMP
  252. pr_debug("[MTK WP] cpu %lx do %s,action: 0x%lx\n", this_cpu, __func__, action);
  253. #endif
  254. switch (action) {
  255. case CPU_STARTING:
  256. /* smp_call_function_single(0, smp_read_MDSCR_EL1_callback, &args, 1); */
  257. args = saved_MDSCR_EL1;
  258. #ifdef DBG_REG_DUMP
  259. pr_debug("[MTK WP] cpu %lx do %s, CPU0's _MDSCR_EL1=0x%x\n", this_cpu, __func__,
  260. args);
  261. #endif
  262. asm volatile ("msr MDSCR_EL1, %0" : : "r" (args));
  263. isb();
  264. dbg_reg_copy(DBGBCR, base_to, base_from);
  265. dbg_reg_copy(DBGBCR + 0x10, base_to, base_from);
  266. dbg_reg_copy(DBGBCR + 0x20, base_to, base_from);
  267. dbg_reg_copy(DBGBCR + 0x30, base_to, base_from);
  268. dbg_reg_copy(DBGBCR + 0x40, base_to, base_from);
  269. dbg_reg_copy(DBGBCR + 0x50, base_to, base_from);
  270. dbg_reg_copy_64(DBGBVR, base_to, base_from);
  271. dbg_reg_copy_64(DBGBVR + 0x10, base_to, base_from);
  272. dbg_reg_copy_64(DBGBVR + 0x20, base_to, base_from);
  273. dbg_reg_copy_64(DBGBVR + 0x30, base_to, base_from);
  274. dbg_reg_copy_64(DBGBVR + 0x40, base_to, base_from);
  275. dbg_reg_copy_64(DBGBVR + 0x50, base_to, base_from);
  276. dbg_reg_copy_64(DBGWVR, base_to, base_from);
  277. dbg_reg_copy_64(DBGWVR + 0x10, base_to, base_from);
  278. dbg_reg_copy_64(DBGWVR + 0x20, base_to, base_from);
  279. dbg_reg_copy_64(DBGWVR + 0x30, base_to, base_from);
  280. dbg_reg_copy(DBGWCR, base_to, base_from);
  281. dbg_reg_copy(DBGWCR + 0x10, base_to, base_from);
  282. dbg_reg_copy(DBGWCR + 0x20, base_to, base_from);
  283. dbg_reg_copy(DBGWCR + 0x30, base_to, base_from);
  284. isb();
  285. break;
  286. default:
  287. break;
  288. }
  289. return NOTIFY_OK;
  290. }
  291. static struct notifier_block cpu_nfb __cpuinitdata = {
  292. .notifier_call = dbgregs_hotplug_callback
  293. };
  294. static int __init regs_backup(void)
  295. {
  296. register_cpu_notifier(&cpu_nfb);
  297. return 0;
  298. }
  299. module_init(regs_backup);
  300. #endif
  301. #endif