tz_log.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. /* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/debugfs.h>
  14. #include <linux/errno.h>
  15. #include <linux/delay.h>
  16. #include <linux/io.h>
  17. #include <linux/msm_ion.h>
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/slab.h>
  22. #include <linux/string.h>
  23. #include <linux/types.h>
  24. #include <linux/uaccess.h>
  25. #include <linux/of.h>
  26. #include <soc/qcom/scm.h>
  27. #include <soc/qcom/qseecomi.h>
  28. /* QSEE_LOG_BUF_SIZE = 32K */
  29. #define QSEE_LOG_BUF_SIZE 0x8000
  30. /* TZ Diagnostic Area legacy version number */
  31. #define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2
  32. /*
  33. * Preprocessor Definitions and Constants
  34. */
  35. #define TZBSP_MAX_CPU_COUNT 0x08
  36. /*
  37. * Number of VMID Tables
  38. */
  39. #define TZBSP_DIAG_NUM_OF_VMID 16
  40. /*
  41. * VMID Description length
  42. */
  43. #define TZBSP_DIAG_VMID_DESC_LEN 7
  44. /*
  45. * Number of Interrupts
  46. */
  47. #define TZBSP_DIAG_INT_NUM 32
  48. /*
  49. * Length of descriptive name associated with Interrupt
  50. */
  51. #define TZBSP_MAX_INT_DESC 16
  52. /*
  53. * TZ 3.X version info
  54. */
  55. #define QSEE_VERSION_TZ_3_X 0x800000
  56. /*
  57. * TZ 4.X version info
  58. */
  59. #define QSEE_VERSION_TZ_4_X 0x1000000
  60. #define TZBSP_AES_256_ENCRYPTED_KEY_SIZE 256
  61. #define TZBSP_NONCE_LEN 12
  62. #define TZBSP_TAG_LEN 16
  63. /*
  64. * VMID Table
  65. */
  66. struct tzdbg_vmid_t {
  67. uint8_t vmid; /* Virtual Machine Identifier */
  68. uint8_t desc[TZBSP_DIAG_VMID_DESC_LEN]; /* ASCII Text */
  69. };
  70. /*
  71. * Boot Info Table
  72. */
  73. struct tzdbg_boot_info_t {
  74. uint32_t wb_entry_cnt; /* Warmboot entry CPU Counter */
  75. uint32_t wb_exit_cnt; /* Warmboot exit CPU Counter */
  76. uint32_t pc_entry_cnt; /* Power Collapse entry CPU Counter */
  77. uint32_t pc_exit_cnt; /* Power Collapse exit CPU counter */
  78. uint32_t warm_jmp_addr; /* Last Warmboot Jump Address */
  79. uint32_t spare; /* Reserved for future use. */
  80. };
  81. /*
  82. * Boot Info Table for 64-bit
  83. */
  84. struct tzdbg_boot_info64_t {
  85. uint32_t wb_entry_cnt; /* Warmboot entry CPU Counter */
  86. uint32_t wb_exit_cnt; /* Warmboot exit CPU Counter */
  87. uint32_t pc_entry_cnt; /* Power Collapse entry CPU Counter */
  88. uint32_t pc_exit_cnt; /* Power Collapse exit CPU counter */
  89. uint32_t psci_entry_cnt;/* PSCI syscall entry CPU Counter */
  90. uint32_t psci_exit_cnt; /* PSCI syscall exit CPU Counter */
  91. uint64_t warm_jmp_addr; /* Last Warmboot Jump Address */
  92. uint32_t warm_jmp_instr; /* Last Warmboot Jump Address Instruction */
  93. };
  94. /*
  95. * Reset Info Table
  96. */
  97. struct tzdbg_reset_info_t {
  98. uint32_t reset_type; /* Reset Reason */
  99. uint32_t reset_cnt; /* Number of resets occurred/CPU */
  100. };
  101. /*
  102. * Interrupt Info Table
  103. */
  104. struct tzdbg_int_t {
  105. /*
  106. * Type of Interrupt/exception
  107. */
  108. uint16_t int_info;
  109. /*
  110. * Availability of the slot
  111. */
  112. uint8_t avail;
  113. /*
  114. * Reserved for future use
  115. */
  116. uint8_t spare;
  117. /*
  118. * Interrupt # for IRQ and FIQ
  119. */
  120. uint32_t int_num;
  121. /*
  122. * ASCII text describing type of interrupt e.g:
  123. * Secure Timer, EBI XPU. This string is always null terminated,
  124. * supporting at most TZBSP_MAX_INT_DESC characters.
  125. * Any additional characters are truncated.
  126. */
  127. uint8_t int_desc[TZBSP_MAX_INT_DESC];
  128. uint64_t int_count[TZBSP_MAX_CPU_COUNT]; /* # of times seen per CPU */
  129. };
  130. /*
  131. * Interrupt Info Table used in tz version >=4.X
  132. */
  133. struct tzdbg_int_t_tz40 {
  134. uint16_t int_info;
  135. uint8_t avail;
  136. uint8_t spare;
  137. uint32_t int_num;
  138. uint8_t int_desc[TZBSP_MAX_INT_DESC];
  139. uint32_t int_count[TZBSP_MAX_CPU_COUNT]; /* uint32_t in TZ ver >= 4.x*/
  140. };
  141. /* warm boot reason for cores */
  142. struct tzbsp_diag_wakeup_info_t {
  143. /* Wake source info : APCS_GICC_HPPIR */
  144. uint32_t HPPIR;
  145. /* Wake source info : APCS_GICC_AHPPIR */
  146. uint32_t AHPPIR;
  147. };
  148. /*
  149. * Log ring buffer position
  150. */
  151. struct tzdbg_log_pos_t {
  152. uint16_t wrap;
  153. uint16_t offset;
  154. };
  155. /*
  156. * Log ring buffer
  157. */
  158. struct tzdbg_log_t {
  159. struct tzdbg_log_pos_t log_pos;
  160. /* open ended array to the end of the 4K IMEM buffer */
  161. uint8_t log_buf[];
  162. };
  163. /*
  164. * Diagnostic Table
  165. * Note: This is the reference data structure for tz diagnostic table
  166. * supporting TZBSP_MAX_CPU_COUNT, the real diagnostic data is directly
  167. * copied into buffer from i/o memory.
  168. */
  169. struct tzdbg_t {
  170. uint32_t magic_num;
  171. uint32_t version;
  172. /*
  173. * Number of CPU's
  174. */
  175. uint32_t cpu_count;
  176. /*
  177. * Offset of VMID Table
  178. */
  179. uint32_t vmid_info_off;
  180. /*
  181. * Offset of Boot Table
  182. */
  183. uint32_t boot_info_off;
  184. /*
  185. * Offset of Reset info Table
  186. */
  187. uint32_t reset_info_off;
  188. /*
  189. * Offset of Interrupt info Table
  190. */
  191. uint32_t int_info_off;
  192. /*
  193. * Ring Buffer Offset
  194. */
  195. uint32_t ring_off;
  196. /*
  197. * Ring Buffer Length
  198. */
  199. uint32_t ring_len;
  200. /* Offset for Wakeup info */
  201. uint32_t wakeup_info_off;
  202. /*
  203. * VMID to EE Mapping
  204. */
  205. struct tzdbg_vmid_t vmid_info[TZBSP_DIAG_NUM_OF_VMID];
  206. /*
  207. * Boot Info
  208. */
  209. struct tzdbg_boot_info_t boot_info[TZBSP_MAX_CPU_COUNT];
  210. /*
  211. * Reset Info
  212. */
  213. struct tzdbg_reset_info_t reset_info[TZBSP_MAX_CPU_COUNT];
  214. uint32_t num_interrupts;
  215. struct tzdbg_int_t int_info[TZBSP_DIAG_INT_NUM];
  216. /* Wake up info */
  217. struct tzbsp_diag_wakeup_info_t wakeup_info[TZBSP_MAX_CPU_COUNT];
  218. uint8_t key[TZBSP_AES_256_ENCRYPTED_KEY_SIZE];
  219. uint8_t nonce[TZBSP_NONCE_LEN];
  220. uint8_t tag[TZBSP_TAG_LEN];
  221. /*
  222. * We need at least 2K for the ring buffer
  223. */
  224. struct tzdbg_log_t ring_buffer; /* TZ Ring Buffer */
  225. };
  226. struct hypdbg_log_pos_t {
  227. uint16_t wrap;
  228. uint16_t offset;
  229. };
  230. struct hypdbg_boot_info_t {
  231. uint32_t warm_entry_cnt;
  232. uint32_t warm_exit_cnt;
  233. };
  234. struct hypdbg_t {
  235. /* Magic Number */
  236. uint32_t magic_num;
  237. /* Number of CPU's */
  238. uint32_t cpu_count;
  239. /* Ring Buffer Offset */
  240. uint32_t ring_off;
  241. /* Ring buffer position mgmt */
  242. struct hypdbg_log_pos_t log_pos;
  243. uint32_t log_len;
  244. /* S2 fault numbers */
  245. uint32_t s2_fault_counter;
  246. /* Boot Info */
  247. struct hypdbg_boot_info_t boot_info[TZBSP_MAX_CPU_COUNT];
  248. /* Ring buffer pointer */
  249. uint8_t log_buf_p[];
  250. };
  251. /*
  252. * Enumeration order for VMID's
  253. */
  254. enum tzdbg_stats_type {
  255. TZDBG_BOOT = 0,
  256. TZDBG_RESET,
  257. TZDBG_INTERRUPT,
  258. TZDBG_VMID,
  259. TZDBG_GENERAL,
  260. TZDBG_LOG,
  261. TZDBG_QSEE_LOG,
  262. TZDBG_HYP_GENERAL,
  263. TZDBG_HYP_LOG,
  264. TZDBG_STATS_MAX
  265. };
  266. struct tzdbg_stat {
  267. char *name;
  268. char *data;
  269. };
  270. struct tzdbg {
  271. void __iomem *virt_iobase;
  272. void __iomem *hyp_virt_iobase;
  273. struct tzdbg_t *diag_buf;
  274. struct hypdbg_t *hyp_diag_buf;
  275. char *disp_buf;
  276. int debug_tz[TZDBG_STATS_MAX];
  277. struct tzdbg_stat stat[TZDBG_STATS_MAX];
  278. uint32_t hyp_debug_rw_buf_size;
  279. bool is_hyplog_enabled;
  280. uint32_t tz_version;
  281. };
  282. static struct tzdbg tzdbg = {
  283. .stat[TZDBG_BOOT].name = "boot",
  284. .stat[TZDBG_RESET].name = "reset",
  285. .stat[TZDBG_INTERRUPT].name = "interrupt",
  286. .stat[TZDBG_VMID].name = "vmid",
  287. .stat[TZDBG_GENERAL].name = "general",
  288. .stat[TZDBG_LOG].name = "log",
  289. .stat[TZDBG_QSEE_LOG].name = "qsee_log",
  290. .stat[TZDBG_HYP_GENERAL].name = "hyp_general",
  291. .stat[TZDBG_HYP_LOG].name = "hyp_log",
  292. };
  293. static struct tzdbg_log_t *g_qsee_log;
  294. static uint32_t debug_rw_buf_size;
  295. /*
  296. * Debugfs data structure and functions
  297. */
  298. static int _disp_tz_general_stats(void)
  299. {
  300. int len = 0;
  301. len += snprintf(tzdbg.disp_buf + len, debug_rw_buf_size - 1,
  302. " Version : 0x%x\n"
  303. " Magic Number : 0x%x\n"
  304. " Number of CPU : %d\n",
  305. tzdbg.diag_buf->version,
  306. tzdbg.diag_buf->magic_num,
  307. tzdbg.diag_buf->cpu_count);
  308. tzdbg.stat[TZDBG_GENERAL].data = tzdbg.disp_buf;
  309. return len;
  310. }
  311. static int _disp_tz_vmid_stats(void)
  312. {
  313. int i, num_vmid;
  314. int len = 0;
  315. struct tzdbg_vmid_t *ptr;
  316. ptr = (struct tzdbg_vmid_t *)((unsigned char *)tzdbg.diag_buf +
  317. tzdbg.diag_buf->vmid_info_off);
  318. num_vmid = ((tzdbg.diag_buf->boot_info_off -
  319. tzdbg.diag_buf->vmid_info_off)/
  320. (sizeof(struct tzdbg_vmid_t)));
  321. for (i = 0; i < num_vmid; i++) {
  322. if (ptr->vmid < 0xFF) {
  323. len += snprintf(tzdbg.disp_buf + len,
  324. (debug_rw_buf_size - 1) - len,
  325. " 0x%x %s\n",
  326. (uint32_t)ptr->vmid, (uint8_t *)ptr->desc);
  327. }
  328. if (len > (debug_rw_buf_size - 1)) {
  329. pr_warn("%s: Cannot fit all info into the buffer\n",
  330. __func__);
  331. break;
  332. }
  333. ptr++;
  334. }
  335. tzdbg.stat[TZDBG_VMID].data = tzdbg.disp_buf;
  336. return len;
  337. }
  338. static int _disp_tz_boot_stats(void)
  339. {
  340. int i;
  341. int len = 0;
  342. struct tzdbg_boot_info_t *ptr = NULL;
  343. struct tzdbg_boot_info64_t *ptr_64 = NULL;
  344. pr_info("qsee_version = 0x%x\n", tzdbg.tz_version);
  345. if (tzdbg.tz_version >= QSEE_VERSION_TZ_3_X) {
  346. ptr_64 = (struct tzdbg_boot_info64_t *)((unsigned char *)
  347. tzdbg.diag_buf + tzdbg.diag_buf->boot_info_off);
  348. } else {
  349. ptr = (struct tzdbg_boot_info_t *)((unsigned char *)
  350. tzdbg.diag_buf + tzdbg.diag_buf->boot_info_off);
  351. }
  352. for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
  353. if (tzdbg.tz_version >= QSEE_VERSION_TZ_3_X) {
  354. len += snprintf(tzdbg.disp_buf + len,
  355. (debug_rw_buf_size - 1) - len,
  356. " CPU #: %d\n"
  357. " Warmboot jump address : 0x%llx\n"
  358. " Warmboot entry CPU counter : 0x%x\n"
  359. " Warmboot exit CPU counter : 0x%x\n"
  360. " Power Collapse entry CPU counter : 0x%x\n"
  361. " Power Collapse exit CPU counter : 0x%x\n"
  362. " Psci entry CPU counter : 0x%x\n"
  363. " Psci exit CPU counter : 0x%x\n"
  364. " Warmboot Jump Address Instruction : 0x%x\n",
  365. i, (uint64_t)ptr_64->warm_jmp_addr,
  366. ptr_64->wb_entry_cnt,
  367. ptr_64->wb_exit_cnt,
  368. ptr_64->pc_entry_cnt,
  369. ptr_64->pc_exit_cnt,
  370. ptr_64->psci_entry_cnt,
  371. ptr_64->psci_exit_cnt,
  372. ptr_64->warm_jmp_instr);
  373. if (len > (debug_rw_buf_size - 1)) {
  374. pr_warn("%s: Cannot fit all info into the buffer\n",
  375. __func__);
  376. break;
  377. }
  378. ptr_64++;
  379. } else {
  380. len += snprintf(tzdbg.disp_buf + len,
  381. (debug_rw_buf_size - 1) - len,
  382. " CPU #: %d\n"
  383. " Warmboot jump address : 0x%x\n"
  384. " Warmboot entry CPU counter: 0x%x\n"
  385. " Warmboot exit CPU counter : 0x%x\n"
  386. " Power Collapse entry CPU counter: 0x%x\n"
  387. " Power Collapse exit CPU counter : 0x%x\n",
  388. i, ptr->warm_jmp_addr,
  389. ptr->wb_entry_cnt,
  390. ptr->wb_exit_cnt,
  391. ptr->pc_entry_cnt,
  392. ptr->pc_exit_cnt);
  393. if (len > (debug_rw_buf_size - 1)) {
  394. pr_warn("%s: Cannot fit all info into the buffer\n",
  395. __func__);
  396. break;
  397. }
  398. ptr++;
  399. }
  400. }
  401. tzdbg.stat[TZDBG_BOOT].data = tzdbg.disp_buf;
  402. return len;
  403. }
  404. static int _disp_tz_reset_stats(void)
  405. {
  406. int i;
  407. int len = 0;
  408. struct tzdbg_reset_info_t *ptr;
  409. ptr = (struct tzdbg_reset_info_t *)((unsigned char *)tzdbg.diag_buf +
  410. tzdbg.diag_buf->reset_info_off);
  411. for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
  412. len += snprintf(tzdbg.disp_buf + len,
  413. (debug_rw_buf_size - 1) - len,
  414. " CPU #: %d\n"
  415. " Reset Type (reason) : 0x%x\n"
  416. " Reset counter : 0x%x\n",
  417. i, ptr->reset_type, ptr->reset_cnt);
  418. if (len > (debug_rw_buf_size - 1)) {
  419. pr_warn("%s: Cannot fit all info into the buffer\n",
  420. __func__);
  421. break;
  422. }
  423. ptr++;
  424. }
  425. tzdbg.stat[TZDBG_RESET].data = tzdbg.disp_buf;
  426. return len;
  427. }
  428. static int _disp_tz_interrupt_stats(void)
  429. {
  430. int i, j;
  431. int len = 0;
  432. int *num_int;
  433. void *ptr;
  434. struct tzdbg_int_t *tzdbg_ptr;
  435. struct tzdbg_int_t_tz40 *tzdbg_ptr_tz40;
  436. num_int = (uint32_t *)((unsigned char *)tzdbg.diag_buf +
  437. (tzdbg.diag_buf->int_info_off - sizeof(uint32_t)));
  438. ptr = ((unsigned char *)tzdbg.diag_buf +
  439. tzdbg.diag_buf->int_info_off);
  440. pr_info("qsee_version = 0x%x\n", tzdbg.tz_version);
  441. if (tzdbg.tz_version < QSEE_VERSION_TZ_4_X) {
  442. tzdbg_ptr = ptr;
  443. for (i = 0; i < (*num_int); i++) {
  444. len += snprintf(tzdbg.disp_buf + len,
  445. (debug_rw_buf_size - 1) - len,
  446. " Interrupt Number : 0x%x\n"
  447. " Type of Interrupt : 0x%x\n"
  448. " Description of interrupt : %s\n",
  449. tzdbg_ptr->int_num,
  450. (uint32_t)tzdbg_ptr->int_info,
  451. (uint8_t *)tzdbg_ptr->int_desc);
  452. for (j = 0; j < tzdbg.diag_buf->cpu_count; j++) {
  453. len += snprintf(tzdbg.disp_buf + len,
  454. (debug_rw_buf_size - 1) - len,
  455. " int_count on CPU # %d : %u\n",
  456. (uint32_t)j,
  457. (uint32_t)tzdbg_ptr->int_count[j]);
  458. }
  459. len += snprintf(tzdbg.disp_buf + len,
  460. debug_rw_buf_size - 1, "\n");
  461. if (len > (debug_rw_buf_size - 1)) {
  462. pr_warn("%s: Cannot fit all info into buf\n",
  463. __func__);
  464. break;
  465. }
  466. tzdbg_ptr++;
  467. }
  468. } else {
  469. tzdbg_ptr_tz40 = ptr;
  470. for (i = 0; i < (*num_int); i++) {
  471. len += snprintf(tzdbg.disp_buf + len,
  472. (debug_rw_buf_size - 1) - len,
  473. " Interrupt Number : 0x%x\n"
  474. " Type of Interrupt : 0x%x\n"
  475. " Description of interrupt : %s\n",
  476. tzdbg_ptr_tz40->int_num,
  477. (uint32_t)tzdbg_ptr_tz40->int_info,
  478. (uint8_t *)tzdbg_ptr_tz40->int_desc);
  479. for (j = 0; j < tzdbg.diag_buf->cpu_count; j++) {
  480. len += snprintf(tzdbg.disp_buf + len,
  481. (debug_rw_buf_size - 1) - len,
  482. " int_count on CPU # %d : %u\n",
  483. (uint32_t)j,
  484. (uint32_t)tzdbg_ptr_tz40->int_count[j]);
  485. }
  486. len += snprintf(tzdbg.disp_buf + len,
  487. debug_rw_buf_size - 1, "\n");
  488. if (len > (debug_rw_buf_size - 1)) {
  489. pr_warn("%s: Cannot fit all info into buf\n",
  490. __func__);
  491. break;
  492. }
  493. tzdbg_ptr_tz40++;
  494. }
  495. }
  496. tzdbg.stat[TZDBG_INTERRUPT].data = tzdbg.disp_buf;
  497. return len;
  498. }
  499. static int _disp_tz_log_stats_legacy(void)
  500. {
  501. int len = 0;
  502. unsigned char *ptr;
  503. ptr = (unsigned char *)tzdbg.diag_buf +
  504. tzdbg.diag_buf->ring_off;
  505. len += snprintf(tzdbg.disp_buf, (debug_rw_buf_size - 1) - len,
  506. "%s\n", ptr);
  507. tzdbg.stat[TZDBG_LOG].data = tzdbg.disp_buf;
  508. return len;
  509. }
  510. static int _disp_log_stats(struct tzdbg_log_t *log,
  511. struct tzdbg_log_pos_t *log_start, uint32_t log_len,
  512. size_t count, uint32_t buf_idx)
  513. {
  514. uint32_t wrap_start;
  515. uint32_t wrap_end;
  516. uint32_t wrap_cnt;
  517. int max_len;
  518. int len = 0;
  519. int i = 0;
  520. wrap_start = log_start->wrap;
  521. wrap_end = log->log_pos.wrap;
  522. /* Calculate difference in # of buffer wrap-arounds */
  523. if (wrap_end >= wrap_start) {
  524. wrap_cnt = wrap_end - wrap_start;
  525. } else {
  526. /* wrap counter has wrapped around, invalidate start position */
  527. wrap_cnt = 2;
  528. }
  529. if (wrap_cnt > 1) {
  530. /* end position has wrapped around more than once, */
  531. /* current start no longer valid */
  532. log_start->wrap = log->log_pos.wrap - 1;
  533. log_start->offset = (log->log_pos.offset + 1) % log_len;
  534. } else if ((wrap_cnt == 1) &&
  535. (log->log_pos.offset > log_start->offset)) {
  536. /* end position has overwritten start */
  537. log_start->offset = (log->log_pos.offset + 1) % log_len;
  538. }
  539. while (log_start->offset == log->log_pos.offset) {
  540. /*
  541. * No data in ring buffer,
  542. * so we'll hang around until something happens
  543. */
  544. unsigned long t = msleep_interruptible(50);
  545. if (t != 0) {
  546. /* Some event woke us up, so let's quit */
  547. return 0;
  548. }
  549. if (buf_idx == TZDBG_LOG)
  550. memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
  551. debug_rw_buf_size);
  552. }
  553. max_len = (count > debug_rw_buf_size) ? debug_rw_buf_size : count;
  554. /*
  555. * Read from ring buff while there is data and space in return buff
  556. */
  557. while ((log_start->offset != log->log_pos.offset) && (len < max_len)) {
  558. tzdbg.disp_buf[i++] = log->log_buf[log_start->offset];
  559. log_start->offset = (log_start->offset + 1) % log_len;
  560. if (log_start->offset == 0)
  561. ++log_start->wrap;
  562. ++len;
  563. }
  564. /*
  565. * return buffer to caller
  566. */
  567. tzdbg.stat[buf_idx].data = tzdbg.disp_buf;
  568. return len;
  569. }
  570. static int __disp_hyp_log_stats(uint8_t *log,
  571. struct hypdbg_log_pos_t *log_start, uint32_t log_len,
  572. size_t count, uint32_t buf_idx)
  573. {
  574. struct hypdbg_t *hyp = tzdbg.hyp_diag_buf;
  575. unsigned long t = 0;
  576. uint32_t wrap_start;
  577. uint32_t wrap_end;
  578. uint32_t wrap_cnt;
  579. int max_len;
  580. int len = 0;
  581. int i = 0;
  582. wrap_start = log_start->wrap;
  583. wrap_end = hyp->log_pos.wrap;
  584. /* Calculate difference in # of buffer wrap-arounds */
  585. if (wrap_end >= wrap_start) {
  586. wrap_cnt = wrap_end - wrap_start;
  587. } else {
  588. /* wrap counter has wrapped around, invalidate start position */
  589. wrap_cnt = 2;
  590. }
  591. if (wrap_cnt > 1) {
  592. /* end position has wrapped around more than once, */
  593. /* current start no longer valid */
  594. log_start->wrap = hyp->log_pos.wrap - 1;
  595. log_start->offset = (hyp->log_pos.offset + 1) % log_len;
  596. } else if ((wrap_cnt == 1) &&
  597. (hyp->log_pos.offset > log_start->offset)) {
  598. /* end position has overwritten start */
  599. log_start->offset = (hyp->log_pos.offset + 1) % log_len;
  600. }
  601. while (log_start->offset == hyp->log_pos.offset) {
  602. /*
  603. * No data in ring buffer,
  604. * so we'll hang around until something happens
  605. */
  606. t = msleep_interruptible(50);
  607. if (t != 0) {
  608. /* Some event woke us up, so let's quit */
  609. return 0;
  610. }
  611. /* TZDBG_HYP_LOG */
  612. memcpy_fromio((void *)tzdbg.hyp_diag_buf, tzdbg.hyp_virt_iobase,
  613. tzdbg.hyp_debug_rw_buf_size);
  614. }
  615. max_len = (count > tzdbg.hyp_debug_rw_buf_size) ?
  616. tzdbg.hyp_debug_rw_buf_size : count;
  617. /*
  618. * Read from ring buff while there is data and space in return buff
  619. */
  620. while ((log_start->offset != hyp->log_pos.offset) && (len < max_len)) {
  621. tzdbg.disp_buf[i++] = log[log_start->offset];
  622. log_start->offset = (log_start->offset + 1) % log_len;
  623. if (log_start->offset == 0)
  624. ++log_start->wrap;
  625. ++len;
  626. }
  627. /*
  628. * return buffer to caller
  629. */
  630. tzdbg.stat[buf_idx].data = tzdbg.disp_buf;
  631. return len;
  632. }
  633. static int _disp_tz_log_stats(size_t count)
  634. {
  635. static struct tzdbg_log_pos_t log_start = {0};
  636. struct tzdbg_log_t *log_ptr;
  637. log_ptr = (struct tzdbg_log_t *)((unsigned char *)tzdbg.diag_buf +
  638. tzdbg.diag_buf->ring_off -
  639. offsetof(struct tzdbg_log_t, log_buf));
  640. return _disp_log_stats(log_ptr, &log_start,
  641. tzdbg.diag_buf->ring_len, count, TZDBG_LOG);
  642. }
  643. static int _disp_hyp_log_stats(size_t count)
  644. {
  645. static struct hypdbg_log_pos_t log_start = {0};
  646. uint8_t *log_ptr;
  647. log_ptr = (uint8_t *)((unsigned char *)tzdbg.hyp_diag_buf +
  648. tzdbg.hyp_diag_buf->ring_off);
  649. return __disp_hyp_log_stats(log_ptr, &log_start,
  650. tzdbg.hyp_debug_rw_buf_size, count, TZDBG_HYP_LOG);
  651. }
  652. static int _disp_qsee_log_stats(size_t count)
  653. {
  654. static struct tzdbg_log_pos_t log_start = {0};
  655. return _disp_log_stats(g_qsee_log, &log_start,
  656. QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
  657. count, TZDBG_QSEE_LOG);
  658. }
  659. static int _disp_hyp_general_stats(size_t count)
  660. {
  661. int len = 0;
  662. int i;
  663. struct hypdbg_boot_info_t *ptr = NULL;
  664. len += snprintf((unsigned char *)tzdbg.disp_buf + len,
  665. tzdbg.hyp_debug_rw_buf_size - 1,
  666. " Magic Number : 0x%x\n"
  667. " CPU Count : 0x%x\n"
  668. " S2 Fault Counter: 0x%x\n",
  669. tzdbg.hyp_diag_buf->magic_num,
  670. tzdbg.hyp_diag_buf->cpu_count,
  671. tzdbg.hyp_diag_buf->s2_fault_counter);
  672. ptr = tzdbg.hyp_diag_buf->boot_info;
  673. for (i = 0; i < tzdbg.hyp_diag_buf->cpu_count; i++) {
  674. len += snprintf((unsigned char *)tzdbg.disp_buf + len,
  675. (tzdbg.hyp_debug_rw_buf_size - 1) - len,
  676. " CPU #: %d\n"
  677. " Warmboot entry CPU counter: 0x%x\n"
  678. " Warmboot exit CPU counter : 0x%x\n",
  679. i, ptr->warm_entry_cnt, ptr->warm_exit_cnt);
  680. if (len > (tzdbg.hyp_debug_rw_buf_size - 1)) {
  681. pr_warn("%s: Cannot fit all info into the buffer\n",
  682. __func__);
  683. break;
  684. }
  685. ptr++;
  686. }
  687. tzdbg.stat[TZDBG_HYP_GENERAL].data = (char *)tzdbg.disp_buf;
  688. return len;
  689. }
  690. static ssize_t tzdbgfs_read(struct file *file, char __user *buf,
  691. size_t count, loff_t *offp)
  692. {
  693. int len = 0;
  694. int *tz_id = file->private_data;
  695. if (*tz_id == TZDBG_BOOT || *tz_id == TZDBG_RESET ||
  696. *tz_id == TZDBG_INTERRUPT || *tz_id == TZDBG_GENERAL ||
  697. *tz_id == TZDBG_VMID || *tz_id == TZDBG_LOG)
  698. memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
  699. debug_rw_buf_size);
  700. if (*tz_id == TZDBG_HYP_GENERAL || *tz_id == TZDBG_HYP_LOG)
  701. memcpy_fromio((void *)tzdbg.hyp_diag_buf, tzdbg.hyp_virt_iobase,
  702. tzdbg.hyp_debug_rw_buf_size);
  703. switch (*tz_id) {
  704. case TZDBG_BOOT:
  705. len = _disp_tz_boot_stats();
  706. break;
  707. case TZDBG_RESET:
  708. len = _disp_tz_reset_stats();
  709. break;
  710. case TZDBG_INTERRUPT:
  711. len = _disp_tz_interrupt_stats();
  712. break;
  713. case TZDBG_GENERAL:
  714. len = _disp_tz_general_stats();
  715. break;
  716. case TZDBG_VMID:
  717. len = _disp_tz_vmid_stats();
  718. break;
  719. case TZDBG_LOG:
  720. if (TZBSP_DIAG_MAJOR_VERSION_LEGACY <
  721. (tzdbg.diag_buf->version >> 16)) {
  722. len = _disp_tz_log_stats(count);
  723. *offp = 0;
  724. } else {
  725. len = _disp_tz_log_stats_legacy();
  726. }
  727. break;
  728. case TZDBG_QSEE_LOG:
  729. len = _disp_qsee_log_stats(count);
  730. *offp = 0;
  731. break;
  732. case TZDBG_HYP_GENERAL:
  733. len = _disp_hyp_general_stats(count);
  734. break;
  735. case TZDBG_HYP_LOG:
  736. len = _disp_hyp_log_stats(count);
  737. *offp = 0;
  738. break;
  739. default:
  740. break;
  741. }
  742. if (len > count)
  743. len = count;
  744. return simple_read_from_buffer(buf, len, offp,
  745. tzdbg.stat[(*tz_id)].data, len);
  746. }
  747. static int tzdbgfs_open(struct inode *inode, struct file *pfile)
  748. {
  749. pfile->private_data = inode->i_private;
  750. return 0;
  751. }
  752. const struct file_operations tzdbg_fops = {
  753. .owner = THIS_MODULE,
  754. .read = tzdbgfs_read,
  755. .open = tzdbgfs_open,
  756. };
  757. static struct ion_client *g_ion_clnt;
  758. static struct ion_handle *g_ihandle;
  759. /*
  760. * Allocates log buffer from ION, registers the buffer at TZ
  761. */
  762. static void tzdbg_register_qsee_log_buf(void)
  763. {
  764. /* register log buffer scm request */
  765. struct qseecom_reg_log_buf_ireq req;
  766. /* scm response */
  767. struct qseecom_command_scm_resp resp = {};
  768. ion_phys_addr_t pa = 0;
  769. size_t len;
  770. int ret = 0;
  771. /* Create ION msm client */
  772. g_ion_clnt = msm_ion_client_create("qsee_log");
  773. if (g_ion_clnt == NULL) {
  774. pr_err("%s: Ion client cannot be created\n", __func__);
  775. return;
  776. }
  777. g_ihandle = ion_alloc(g_ion_clnt, QSEE_LOG_BUF_SIZE,
  778. 4096, ION_HEAP(ION_QSECOM_HEAP_ID), 0);
  779. if (IS_ERR_OR_NULL(g_ihandle)) {
  780. pr_err("%s: Ion client could not retrieve the handle\n",
  781. __func__);
  782. goto err1;
  783. }
  784. ret = ion_phys(g_ion_clnt, g_ihandle, &pa, &len);
  785. if (ret) {
  786. pr_err("%s: Ion conversion to physical address failed\n",
  787. __func__);
  788. goto err2;
  789. }
  790. req.qsee_cmd_id = QSEOS_REGISTER_LOG_BUF_COMMAND;
  791. req.phy_addr = (uint32_t)pa;
  792. req.len = len;
  793. if (!is_scm_armv8()) {
  794. /* SCM_CALL to register the log buffer */
  795. ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req),
  796. &resp, sizeof(resp));
  797. } else {
  798. struct scm_desc desc = {0};
  799. desc.args[0] = pa;
  800. desc.args[1] = len;
  801. desc.arginfo = 0x22;
  802. ret = scm_call2(SCM_QSEEOS_FNID(1, 6), &desc);
  803. resp.result = desc.ret[0];
  804. }
  805. if (ret) {
  806. pr_err("%s: scm_call to register log buffer failed\n",
  807. __func__);
  808. goto err2;
  809. }
  810. if (resp.result != QSEOS_RESULT_SUCCESS) {
  811. pr_err(
  812. "%s: scm_call to register log buf failed, resp result =%d\n",
  813. __func__, resp.result);
  814. goto err2;
  815. }
  816. g_qsee_log =
  817. (struct tzdbg_log_t *)ion_map_kernel(g_ion_clnt, g_ihandle);
  818. if (IS_ERR(g_qsee_log)) {
  819. pr_err("%s: Couldn't map ion buffer to kernel\n",
  820. __func__);
  821. goto err2;
  822. }
  823. g_qsee_log->log_pos.wrap = g_qsee_log->log_pos.offset = 0;
  824. return;
  825. err2:
  826. ion_free(g_ion_clnt, g_ihandle);
  827. g_ihandle = NULL;
  828. err1:
  829. ion_client_destroy(g_ion_clnt);
  830. g_ion_clnt = NULL;
  831. }
  832. static int tzdbgfs_init(struct platform_device *pdev)
  833. {
  834. int rc = 0;
  835. int i;
  836. struct dentry *dent_dir;
  837. struct dentry *dent;
  838. dent_dir = debugfs_create_dir("tzdbg", NULL);
  839. if (dent_dir == NULL) {
  840. dev_err(&pdev->dev, "tzdbg debugfs_create_dir failed\n");
  841. return -ENOMEM;
  842. }
  843. for (i = 0; i < TZDBG_STATS_MAX; i++) {
  844. tzdbg.debug_tz[i] = i;
  845. dent = debugfs_create_file_unsafe(tzdbg.stat[i].name,
  846. 0444, dent_dir,
  847. &tzdbg.debug_tz[i], &tzdbg_fops);
  848. if (dent == NULL) {
  849. dev_err(&pdev->dev, "TZ debugfs_create_file failed\n");
  850. rc = -ENOMEM;
  851. goto err;
  852. }
  853. }
  854. tzdbg.disp_buf = kzalloc(max(debug_rw_buf_size,
  855. tzdbg.hyp_debug_rw_buf_size), GFP_KERNEL);
  856. if (tzdbg.disp_buf == NULL)
  857. goto err;
  858. platform_set_drvdata(pdev, dent_dir);
  859. return 0;
  860. err:
  861. debugfs_remove_recursive(dent_dir);
  862. return rc;
  863. }
  864. static void tzdbgfs_exit(struct platform_device *pdev)
  865. {
  866. struct dentry *dent_dir;
  867. kzfree(tzdbg.disp_buf);
  868. dent_dir = platform_get_drvdata(pdev);
  869. debugfs_remove_recursive(dent_dir);
  870. if (g_ion_clnt != NULL) {
  871. if (!IS_ERR_OR_NULL(g_ihandle)) {
  872. ion_unmap_kernel(g_ion_clnt, g_ihandle);
  873. ion_free(g_ion_clnt, g_ihandle);
  874. }
  875. ion_client_destroy(g_ion_clnt);
  876. }
  877. }
  878. static int __update_hypdbg_base(struct platform_device *pdev,
  879. void __iomem *virt_iobase)
  880. {
  881. phys_addr_t hypdiag_phy_iobase;
  882. uint32_t hyp_address_offset;
  883. uint32_t hyp_size_offset;
  884. struct hypdbg_t *hyp;
  885. uint32_t *ptr = NULL;
  886. if (of_property_read_u32((&pdev->dev)->of_node, "hyplog-address-offset",
  887. &hyp_address_offset)) {
  888. dev_err(&pdev->dev, "hyplog address offset is not defined\n");
  889. return -EINVAL;
  890. }
  891. if (of_property_read_u32((&pdev->dev)->of_node, "hyplog-size-offset",
  892. &hyp_size_offset)) {
  893. dev_err(&pdev->dev, "hyplog size offset is not defined\n");
  894. return -EINVAL;
  895. }
  896. hypdiag_phy_iobase = readl_relaxed(virt_iobase + hyp_address_offset);
  897. tzdbg.hyp_debug_rw_buf_size = readl_relaxed(virt_iobase +
  898. hyp_size_offset);
  899. tzdbg.hyp_virt_iobase = devm_ioremap_nocache(&pdev->dev,
  900. hypdiag_phy_iobase,
  901. tzdbg.hyp_debug_rw_buf_size);
  902. if (!tzdbg.hyp_virt_iobase) {
  903. dev_err(&pdev->dev, "ERROR could not ioremap: start=%pr, len=%u\n",
  904. &hypdiag_phy_iobase, tzdbg.hyp_debug_rw_buf_size);
  905. return -ENXIO;
  906. }
  907. ptr = kzalloc(tzdbg.hyp_debug_rw_buf_size, GFP_KERNEL);
  908. if (!ptr)
  909. return -ENOMEM;
  910. tzdbg.hyp_diag_buf = (struct hypdbg_t *)ptr;
  911. hyp = tzdbg.hyp_diag_buf;
  912. hyp->log_pos.wrap = hyp->log_pos.offset = 0;
  913. return 0;
  914. }
  915. static void tzdbg_get_tz_version(void)
  916. {
  917. uint32_t smc_id = 0;
  918. uint32_t feature = 10;
  919. struct qseecom_command_scm_resp resp = {0};
  920. struct scm_desc desc = {0};
  921. int ret = 0;
  922. if (!is_scm_armv8()) {
  923. ret = scm_call(SCM_SVC_INFO, SCM_SVC_UTIL, &feature,
  924. sizeof(feature), &resp, sizeof(resp));
  925. } else {
  926. smc_id = TZ_INFO_GET_FEATURE_VERSION_ID;
  927. desc.arginfo = TZ_INFO_GET_FEATURE_VERSION_ID_PARAM_ID;
  928. desc.args[0] = feature;
  929. ret = scm_call2(smc_id, &desc);
  930. resp.result = desc.ret[0];
  931. }
  932. if (ret)
  933. pr_err("%s: scm_call to get tz version failed\n",
  934. __func__);
  935. else
  936. tzdbg.tz_version = resp.result;
  937. }
  938. /*
  939. * Driver functions
  940. */
  941. static int tz_log_probe(struct platform_device *pdev)
  942. {
  943. struct resource *resource;
  944. void __iomem *virt_iobase;
  945. phys_addr_t tzdiag_phy_iobase;
  946. uint32_t *ptr = NULL;
  947. int ret = 0;
  948. /*
  949. * Get address that stores the physical location diagnostic data
  950. */
  951. resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  952. if (!resource) {
  953. dev_err(&pdev->dev,
  954. "%s: ERROR Missing MEM resource\n", __func__);
  955. return -ENXIO;
  956. };
  957. /*
  958. * Get the debug buffer size
  959. */
  960. debug_rw_buf_size = resource->end - resource->start + 1;
  961. /*
  962. * Map address that stores the physical location diagnostic data
  963. */
  964. virt_iobase = devm_ioremap_nocache(&pdev->dev, resource->start,
  965. debug_rw_buf_size);
  966. if (!virt_iobase) {
  967. dev_err(&pdev->dev,
  968. "%s: ERROR could not ioremap: start=%pr, len=%u\n",
  969. __func__, &resource->start,
  970. (unsigned int)(debug_rw_buf_size));
  971. return -ENXIO;
  972. }
  973. if (pdev->dev.of_node) {
  974. tzdbg.is_hyplog_enabled = of_property_read_bool(
  975. (&pdev->dev)->of_node, "qcom,hyplog-enabled");
  976. if (tzdbg.is_hyplog_enabled) {
  977. ret = __update_hypdbg_base(pdev, virt_iobase);
  978. if (ret) {
  979. dev_err(&pdev->dev, "%s() failed to get device tree data ret = %d\n",
  980. __func__, ret);
  981. return -EINVAL;
  982. }
  983. } else {
  984. dev_info(&pdev->dev, "Hyp log service is not supported\n");
  985. }
  986. } else {
  987. dev_dbg(&pdev->dev, "Device tree data is not found\n");
  988. }
  989. /*
  990. * Retrieve the address of diagnostic data
  991. */
  992. tzdiag_phy_iobase = readl_relaxed(virt_iobase);
  993. /*
  994. * Map the diagnostic information area
  995. */
  996. tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
  997. tzdiag_phy_iobase, debug_rw_buf_size);
  998. if (!tzdbg.virt_iobase) {
  999. dev_err(&pdev->dev,
  1000. "%s: ERROR could not ioremap: start=%pr, len=%u\n",
  1001. __func__, &tzdiag_phy_iobase,
  1002. debug_rw_buf_size);
  1003. return -ENXIO;
  1004. }
  1005. ptr = kzalloc(debug_rw_buf_size, GFP_KERNEL);
  1006. if (ptr == NULL)
  1007. return -ENXIO;
  1008. tzdbg.diag_buf = (struct tzdbg_t *)ptr;
  1009. if (tzdbgfs_init(pdev))
  1010. goto err;
  1011. tzdbg_register_qsee_log_buf();
  1012. tzdbg_get_tz_version();
  1013. return 0;
  1014. err:
  1015. kfree(tzdbg.diag_buf);
  1016. return -ENXIO;
  1017. }
  1018. static int tz_log_remove(struct platform_device *pdev)
  1019. {
  1020. kzfree(tzdbg.diag_buf);
  1021. if (tzdbg.hyp_diag_buf)
  1022. kzfree(tzdbg.hyp_diag_buf);
  1023. tzdbgfs_exit(pdev);
  1024. return 0;
  1025. }
  1026. static const struct of_device_id tzlog_match[] = {
  1027. { .compatible = "qcom,tz-log",
  1028. },
  1029. {}
  1030. };
  1031. static struct platform_driver tz_log_driver = {
  1032. .probe = tz_log_probe,
  1033. .remove = tz_log_remove,
  1034. .driver = {
  1035. .name = "tz_log",
  1036. .owner = THIS_MODULE,
  1037. .of_match_table = tzlog_match,
  1038. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1039. },
  1040. };
  1041. static int __init tz_log_init(void)
  1042. {
  1043. return platform_driver_register(&tz_log_driver);
  1044. }
  1045. static void __exit tz_log_exit(void)
  1046. {
  1047. platform_driver_unregister(&tz_log_driver);
  1048. }
  1049. module_init(tz_log_init);
  1050. module_exit(tz_log_exit);
  1051. MODULE_LICENSE("GPL v2");
  1052. MODULE_DESCRIPTION("TZ Log driver");
  1053. MODULE_ALIAS("platform:tz_log");