aee-common.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <linux/bug.h>
  2. #include <linux/module.h>
  3. #include <linux/slab.h>
  4. #include <mt-plat/aee.h>
  5. #include <linux/kgdb.h>
  6. #include <linux/kdb.h>
  7. #include <linux/utsname.h>
  8. #include <linux/sched.h>
  9. #include <linux/list.h>
  10. #include <linux/init.h>
  11. #include <linux/smp.h>
  12. #include <linux/io.h>
  13. #include <linux/delay.h>
  14. #include <mach/wd_api.h>
  15. #include "aee-common.h"
  16. #include <linux/uaccess.h>
  17. #include <linux/fs.h>
  18. #include <linux/vmalloc.h>
  19. static struct aee_kernel_api *g_aee_api;
  20. #define KERNEL_REPORT_LENGTH 384
  21. #ifdef CONFIG_KGDB_KDB
  22. /* Press key to enter kdb */
  23. void aee_trigger_kdb(void)
  24. {
  25. int res = 0;
  26. struct wd_api *wd_api = NULL;
  27. res = get_wd_api(&wd_api);
  28. /* disable Watchdog HW, note it will not enable WDT again when kdb return */
  29. if (res)
  30. LOGE("aee_trigger_kdb, get wd api error\n");
  31. else
  32. wd_api->wd_disable_all();
  33. #ifdef CONFIG_SCHED_DEBUG
  34. sysrq_sched_debug_show();
  35. #endif
  36. LOGI("User trigger KDB\n");
  37. /* mtk_set_kgdboc_var(); */
  38. kgdb_breakpoint();
  39. LOGI("Exit KDB\n");
  40. #ifdef CONFIG_LOCAL_WDT
  41. /* enable local WDT */
  42. if (res)
  43. LOGD("aee_trigger_kdb, get wd api error\n");
  44. else
  45. wd_api->wd_restart(WD_TYPE_NOLOCK);
  46. #endif
  47. }
  48. #else
  49. /* For user mode or the case KDB is not enabled, print basic debug messages */
  50. void aee_dumpbasic(void)
  51. {
  52. struct task_struct *p = current;
  53. int orig_log_level = console_loglevel;
  54. preempt_disable();
  55. console_loglevel = 7;
  56. LOGI("kernel : %s-%s\n", init_uts_ns.name.sysname, init_uts_ns.name.release);
  57. LOGI("version : %s\n", init_uts_ns.name.version);
  58. LOGI("machine : %s\n\n", init_uts_ns.name.machine);
  59. #ifdef CONFIG_SCHED_DEBUG
  60. sysrq_sched_debug_show();
  61. #endif
  62. LOGI("\n%-*s Pid Parent Command\n", (int)(2 * sizeof(void *)) + 2, "Task Addr");
  63. LOGI("0x%p %8d %8d %s\n\n", (void *)p, p->pid, p->parent->pid, p->comm);
  64. LOGI("Stack traceback for current pid %d\n", p->pid);
  65. show_stack(p, NULL);
  66. #ifdef CONFIG_MTK_AEE_IPANIC_64
  67. aee_dumpnative();
  68. #endif
  69. console_loglevel = orig_log_level;
  70. preempt_enable();
  71. }
  72. void aee_trigger_kdb(void)
  73. {
  74. LOGI("\nKDB is not enabled ! Dump basic debug info...\n\n");
  75. aee_dumpbasic();
  76. }
  77. #endif
  78. struct aee_oops *aee_oops_create(AE_DEFECT_ATTR attr, AE_EXP_CLASS clazz, const char *module)
  79. {
  80. struct aee_oops *oops = kzalloc(sizeof(struct aee_oops), GFP_ATOMIC);
  81. if (NULL == oops) {
  82. LOGE("%s : kzalloc() fail\n", __func__);
  83. return NULL;
  84. }
  85. oops->attr = attr;
  86. oops->clazz = clazz;
  87. if (module != NULL)
  88. strlcpy(oops->module, module, sizeof(oops->module));
  89. else
  90. strcpy(oops->module, "N/A");
  91. strcpy(oops->backtrace, "N/A");
  92. strcpy(oops->process_path, "N/A");
  93. return oops;
  94. }
  95. EXPORT_SYMBOL(aee_oops_create);
  96. void aee_oops_set_process_path(struct aee_oops *oops, const char *process_path)
  97. {
  98. if (process_path != NULL)
  99. strlcpy(oops->process_path, process_path, sizeof(oops->process_path));
  100. }
  101. void aee_oops_set_backtrace(struct aee_oops *oops, const char *backtrace)
  102. {
  103. if (backtrace != NULL)
  104. strlcpy(oops->backtrace, backtrace, sizeof(oops->backtrace));
  105. }
  106. void aee_oops_free(struct aee_oops *oops)
  107. {
  108. kfree(oops->console);
  109. kfree(oops->android_main);
  110. kfree(oops->android_radio);
  111. kfree(oops->android_system);
  112. kfree(oops->userspace_info);
  113. kfree(oops->mmprofile);
  114. kfree(oops->mini_rdump);
  115. vfree(oops->userthread_stack.Userthread_Stack);
  116. kfree(oops);
  117. LOGE("aee_oops_free\n");
  118. }
  119. EXPORT_SYMBOL(aee_oops_free);
  120. void aee_register_api(struct aee_kernel_api *aee_api)
  121. {
  122. if (!aee_api)
  123. BUG();
  124. g_aee_api = aee_api;
  125. }
  126. EXPORT_SYMBOL(aee_register_api);
  127. void aee_disable_api(void)
  128. {
  129. if (g_aee_api) {
  130. LOGI("disable aee kernel api");
  131. g_aee_api = NULL;
  132. }
  133. }
  134. EXPORT_SYMBOL(aee_disable_api);
  135. void aee_kernel_exception_api(const char *file, const int line, const int db_opt,
  136. const char *module, const char *msg, ...)
  137. {
  138. char msgbuf[KERNEL_REPORT_LENGTH];
  139. int offset = 0;
  140. va_list args;
  141. va_start(args, msg);
  142. offset += snprintf(msgbuf, KERNEL_REPORT_LENGTH, "<%s:%d> ", file, line);
  143. offset += vsnprintf(msgbuf + offset, KERNEL_REPORT_LENGTH - offset, msg, args);
  144. if (g_aee_api && g_aee_api->kernel_reportAPI)
  145. g_aee_api->kernel_reportAPI(AE_DEFECT_EXCEPTION, db_opt, module, msgbuf);
  146. else
  147. LOGE("AEE kernel exception: %s", msgbuf);
  148. va_end(args);
  149. }
  150. EXPORT_SYMBOL(aee_kernel_exception_api);
  151. void aee_kernel_warning_api(const char *file, const int line, const int db_opt, const char *module,
  152. const char *msg, ...)
  153. {
  154. char msgbuf[KERNEL_REPORT_LENGTH];
  155. int offset = 0;
  156. va_list args;
  157. va_start(args, msg);
  158. offset += snprintf(msgbuf, KERNEL_REPORT_LENGTH, "<%s:%d> ", file, line);
  159. offset += vsnprintf(msgbuf + offset, KERNEL_REPORT_LENGTH - offset, msg, args);
  160. if (g_aee_api && g_aee_api->kernel_reportAPI)
  161. g_aee_api->kernel_reportAPI(AE_DEFECT_WARNING, db_opt, module, msgbuf);
  162. else
  163. LOGE("AEE kernel warning: %s", msgbuf);
  164. va_end(args);
  165. }
  166. EXPORT_SYMBOL(aee_kernel_warning_api);
  167. void aee_kernel_reminding_api(const char *file, const int line, const int db_opt,
  168. const char *module, const char *msg, ...)
  169. {
  170. char msgbuf[KERNEL_REPORT_LENGTH];
  171. int offset = 0;
  172. va_list args;
  173. va_start(args, msg);
  174. offset += snprintf(msgbuf, KERNEL_REPORT_LENGTH, "<%s:%d> ", file, line);
  175. offset += vsnprintf(msgbuf + offset, KERNEL_REPORT_LENGTH - offset, msg, args);
  176. if (g_aee_api && g_aee_api->kernel_reportAPI)
  177. g_aee_api->kernel_reportAPI(AE_DEFECT_REMINDING, db_opt, module, msgbuf);
  178. else
  179. LOGE("AEE kernel reminding: %s", msgbuf);
  180. va_end(args);
  181. }
  182. EXPORT_SYMBOL(aee_kernel_reminding_api);
  183. void aed_md_exception_api(const int *log, int log_size, const int *phy, int phy_size,
  184. const char *detail, const int db_opt)
  185. {
  186. #ifdef CONFIG_MTK_AEE_AED
  187. LOGD("%s\n", __func__);
  188. if (g_aee_api) {
  189. if (g_aee_api->md_exception) {
  190. g_aee_api->md_exception("modem", log, log_size, phy, phy_size, detail,
  191. db_opt);
  192. } else {
  193. LOGD("g_aee_api->md_exception = 0x%p\n", g_aee_api->md_exception);
  194. }
  195. } else {
  196. LOGD("g_aee_api is null\n");
  197. }
  198. LOGD("%s out\n", __func__);
  199. #endif
  200. }
  201. EXPORT_SYMBOL(aed_md_exception_api);
  202. void aed_md32_exception_api(const int *log, int log_size, const int *phy, int phy_size,
  203. const char *detail, const int db_opt)
  204. {
  205. #ifdef CONFIG_MTK_AEE_AED
  206. LOGD("%s\n", __func__);
  207. if (g_aee_api) {
  208. if (g_aee_api->md_exception) {
  209. g_aee_api->md_exception("md32", log, log_size, phy, phy_size, detail,
  210. db_opt);
  211. } else {
  212. LOGD("g_aee_api->md32_exception = 0x%p\n", g_aee_api->md32_exception);
  213. }
  214. } else {
  215. LOGD("g_aee_api is null\n");
  216. }
  217. LOGD("%s out\n", __func__);
  218. #endif
  219. }
  220. EXPORT_SYMBOL(aed_md32_exception_api);
  221. void aed_scp_exception_api(const int *log, int log_size, const int *phy, int phy_size,
  222. const char *detail, const int db_opt)
  223. {
  224. #ifdef CONFIG_MTK_AEE_AED
  225. LOGD("%s\n", __func__);
  226. if (g_aee_api) {
  227. if (g_aee_api->md_exception) {
  228. g_aee_api->md_exception("scp", log, log_size, phy, phy_size, detail,
  229. db_opt);
  230. } else {
  231. LOGD("g_aee_api->scp_exception = 0x%p\n", g_aee_api->scp_exception);
  232. }
  233. } else {
  234. LOGD("g_aee_api is null\n");
  235. }
  236. LOGD("%s out\n", __func__);
  237. #endif
  238. }
  239. EXPORT_SYMBOL(aed_scp_exception_api);
  240. void aed_combo_exception_api(const int *log, int log_size, const int *phy, int phy_size,
  241. const char *detail, const int db_opt)
  242. {
  243. #ifdef CONFIG_MTK_AEE_AED
  244. LOGD("aed_combo_exception\n");
  245. if (g_aee_api) {
  246. if (g_aee_api->combo_exception) {
  247. g_aee_api->combo_exception("combo", log, log_size, phy, phy_size, detail,
  248. db_opt);
  249. } else {
  250. LOGD("g_aee_api->combo_exception = 0x%p\n", g_aee_api->combo_exception);
  251. }
  252. } else {
  253. LOGD("g_aee_api is null\n");
  254. }
  255. LOGD("aed_combo_exception out\n");
  256. #endif
  257. }
  258. EXPORT_SYMBOL(aed_combo_exception_api);
  259. char sram_printk_buf[256];
  260. void aee_sram_printk(const char *fmt, ...)
  261. {
  262. #ifdef CONFIG_MTK_RAM_CONSOLE
  263. unsigned long long t;
  264. unsigned long nanosec_rem;
  265. va_list args;
  266. int r, tlen;
  267. va_start(args, fmt);
  268. preempt_disable();
  269. t = cpu_clock(smp_processor_id());
  270. nanosec_rem = do_div(t, 1000000000);
  271. tlen = sprintf(sram_printk_buf, ">%5lu.%06lu< ", (unsigned long)t, nanosec_rem / 1000);
  272. r = vsnprintf(sram_printk_buf + tlen, sizeof(sram_printk_buf) - tlen, fmt, args);
  273. ram_console_write(NULL, sram_printk_buf, r + tlen);
  274. preempt_enable();
  275. va_end(args);
  276. #endif
  277. }
  278. EXPORT_SYMBOL(aee_sram_printk);
  279. static int __init aee_common_init(void)
  280. {
  281. int ret = 0;
  282. return ret;
  283. }
  284. static void __exit aee_common_exit(void)
  285. {
  286. }
  287. module_init(aee_common_init);
  288. module_exit(aee_common_exit);