crash_reporting.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /*
  2. * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <plat_macros.S>
  7. #include <platform_def.h>
  8. #include <arch.h>
  9. #include <asm_macros.S>
  10. #include <context.h>
  11. #include <lib/el3_runtime/cpu_data.h>
  12. #include <lib/utils_def.h>
  13. .globl report_unhandled_exception
  14. .globl report_unhandled_interrupt
  15. .globl report_el3_panic
  16. .globl report_elx_panic
  17. #if CRASH_REPORTING
  18. /* ------------------------------------------------------
  19. * The below section deals with dumping the system state
  20. * when an unhandled exception is taken in EL3.
  21. * The layout and the names of the registers which will
  22. * be dumped during a unhandled exception is given below.
  23. * ------------------------------------------------------
  24. */
  25. .section .rodata.crash_prints, "aS"
  26. print_spacer:
  27. .asciz " = 0x"
  28. gp_regs:
  29. .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
  30. "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
  31. "x16", "x17", "x18", "x19", "x20", "x21", "x22",\
  32. "x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
  33. el3_sys_regs:
  34. .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
  35. "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
  36. "esr_el3", "far_el3", ""
  37. non_el3_sys_regs:
  38. .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
  39. "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
  40. "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
  41. "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
  42. "tpidrro_el0", "par_el1", "mpidr_el1", "afsr0_el1", "afsr1_el1",\
  43. "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\
  44. "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", ""
  45. #if CTX_INCLUDE_AARCH32_REGS
  46. aarch32_regs:
  47. .asciz "dacr32_el2", "ifsr32_el2", ""
  48. #endif /* CTX_INCLUDE_AARCH32_REGS */
  49. panic_msg:
  50. .asciz "PANIC in EL3.\nx30"
  51. excpt_msg:
  52. .asciz "Unhandled Exception in EL3.\nx30"
  53. intr_excpt_msg:
  54. .ascii "Unhandled Interrupt Exception in EL3.\n"
  55. x30_msg:
  56. .asciz "x30"
  57. excpt_msg_el:
  58. .asciz "Unhandled Exception from lower EL.\n"
  59. /*
  60. * Helper function to print from crash buf.
  61. * The print loop is controlled by the buf size and
  62. * ascii reg name list which is passed in x6. The
  63. * function returns the crash buf address in x0.
  64. * Clobbers : x0 - x7, sp
  65. */
  66. func size_controlled_print
  67. /* Save the lr */
  68. mov sp, x30
  69. /* load the crash buf address */
  70. mrs x7, tpidr_el3
  71. test_size_list:
  72. /* Calculate x5 always as it will be clobbered by asm_print_hex */
  73. mrs x5, tpidr_el3
  74. add x5, x5, #CPU_DATA_CRASH_BUF_SIZE
  75. /* Test whether we have reached end of crash buf */
  76. cmp x7, x5
  77. b.eq exit_size_print
  78. ldrb w4, [x6]
  79. /* Test whether we are at end of list */
  80. cbz w4, exit_size_print
  81. mov x4, x6
  82. /* asm_print_str updates x4 to point to next entry in list */
  83. bl asm_print_str
  84. /* x0 = number of symbols printed + 1 */
  85. sub x0, x4, x6
  86. /* update x6 with the updated list pointer */
  87. mov x6, x4
  88. bl print_alignment
  89. ldr x4, [x7], #REGSZ
  90. bl asm_print_hex
  91. bl asm_print_newline
  92. b test_size_list
  93. exit_size_print:
  94. mov x30, sp
  95. ret
  96. endfunc size_controlled_print
  97. /* -----------------------------------------------------
  98. * This function calculates and prints required number
  99. * of space characters followed by "= 0x", based on the
  100. * length of ascii register name.
  101. * x0: length of ascii register name + 1
  102. * ------------------------------------------------------
  103. */
  104. func print_alignment
  105. /* The minimum ascii length is 3, e.g. for "x0" */
  106. adr x4, print_spacer - 3
  107. add x4, x4, x0
  108. b asm_print_str
  109. endfunc print_alignment
  110. /*
  111. * Helper function to store x8 - x15 registers to
  112. * the crash buf. The system registers values are
  113. * copied to x8 to x15 by the caller which are then
  114. * copied to the crash buf by this function.
  115. * x0 points to the crash buf. It then calls
  116. * size_controlled_print to print to console.
  117. * Clobbers : x0 - x7, sp
  118. */
  119. func str_in_crash_buf_print
  120. /* restore the crash buf address in x0 */
  121. mrs x0, tpidr_el3
  122. stp x8, x9, [x0]
  123. stp x10, x11, [x0, #REGSZ * 2]
  124. stp x12, x13, [x0, #REGSZ * 4]
  125. stp x14, x15, [x0, #REGSZ * 6]
  126. b size_controlled_print
  127. endfunc str_in_crash_buf_print
  128. /* ------------------------------------------------------
  129. * This macro calculates the offset to crash buf from
  130. * cpu_data and stores it in tpidr_el3. It also saves x0
  131. * and x1 in the crash buf by using sp as a temporary
  132. * register.
  133. * ------------------------------------------------------
  134. */
  135. .macro prepare_crash_buf_save_x0_x1
  136. /* we can corrupt this reg to free up x0 */
  137. mov sp, x0
  138. /* tpidr_el3 contains the address to cpu_data structure */
  139. mrs x0, tpidr_el3
  140. /* Calculate the Crash buffer offset in cpu_data */
  141. add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
  142. /* Store crash buffer address in tpidr_el3 */
  143. msr tpidr_el3, x0
  144. str x1, [x0, #REGSZ]
  145. mov x1, sp
  146. str x1, [x0]
  147. .endm
  148. /* -----------------------------------------------------
  149. * This function allows to report a crash (if crash
  150. * reporting is enabled) when an unhandled exception
  151. * occurs. It prints the CPU state via the crash console
  152. * making use of the crash buf. This function will
  153. * not return.
  154. * -----------------------------------------------------
  155. */
  156. func report_unhandled_exception
  157. prepare_crash_buf_save_x0_x1
  158. adr x0, excpt_msg
  159. mov sp, x0
  160. /* This call will not return */
  161. b do_crash_reporting
  162. endfunc report_unhandled_exception
  163. /* -----------------------------------------------------
  164. * This function allows to report a crash (if crash
  165. * reporting is enabled) when an unhandled interrupt
  166. * occurs. It prints the CPU state via the crash console
  167. * making use of the crash buf. This function will
  168. * not return.
  169. * -----------------------------------------------------
  170. */
  171. func report_unhandled_interrupt
  172. prepare_crash_buf_save_x0_x1
  173. adr x0, intr_excpt_msg
  174. mov sp, x0
  175. /* This call will not return */
  176. b do_crash_reporting
  177. endfunc report_unhandled_interrupt
  178. /* -----------------------------------------------------
  179. * This function allows to report a crash from the lower
  180. * exception level (if crash reporting is enabled) when
  181. * lower_el_panic() is invoked from C Runtime.
  182. * It prints the CPU state via the crash console making
  183. * use of 'cpu_context' structure where general purpose
  184. * registers are saved and the crash buf.
  185. * This function will not return.
  186. * -----------------------------------------------------
  187. */
  188. func report_elx_panic
  189. msr spsel, #MODE_SP_ELX
  190. /* Print the crash message */
  191. adr x4, excpt_msg_el
  192. bl asm_print_str
  193. /* Report x0 - x29 values stored in 'gpregs_ctx' structure */
  194. /* Store the ascii list pointer in x6 */
  195. adr x6, gp_regs
  196. add x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0
  197. print_next:
  198. ldrb w4, [x6]
  199. /* Test whether we are at end of list */
  200. cbz w4, print_x30
  201. mov x4, x6
  202. /* asm_print_str updates x4 to point to next entry in list */
  203. bl asm_print_str
  204. /* x0 = number of symbols printed + 1 */
  205. sub x0, x4, x6
  206. /* Update x6 with the updated list pointer */
  207. mov x6, x4
  208. bl print_alignment
  209. ldr x4, [x7], #REGSZ
  210. bl asm_print_hex
  211. bl asm_print_newline
  212. b print_next
  213. print_x30:
  214. adr x4, x30_msg
  215. bl asm_print_str
  216. /* Print spaces to align "x30" string */
  217. mov x0, #4
  218. bl print_alignment
  219. /* Report x30 */
  220. ldr x4, [x7]
  221. /* ----------------------------------------------------------------
  222. * Different virtual address space size can be defined for each EL.
  223. * Ensure that we use the proper one by reading the corresponding
  224. * TCR_ELx register.
  225. * ----------------------------------------------------------------
  226. */
  227. cmp x8, #MODE_EL2
  228. b.lt from_el1 /* EL1 */
  229. mrs x2, sctlr_el2
  230. mrs x1, tcr_el2
  231. /* ----------------------------------------------------------------
  232. * Check if pointer authentication is enabled at the specified EL.
  233. * If it isn't, we can then skip stripping a PAC code.
  234. * ----------------------------------------------------------------
  235. */
  236. test_pauth:
  237. tst x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT)
  238. b.eq no_pauth
  239. /* Demangle address */
  240. and x1, x1, #0x3F /* T0SZ = TCR_ELx[5:0] */
  241. sub x1, x1, #64
  242. neg x1, x1 /* bottom_pac_bit = 64 - T0SZ */
  243. mov x2, #-1
  244. lsl x2, x2, x1
  245. bic x4, x4, x2
  246. no_pauth:
  247. bl asm_print_hex
  248. bl asm_print_newline
  249. /* tpidr_el3 contains the address to cpu_data structure */
  250. mrs x0, tpidr_el3
  251. /* Calculate the Crash buffer offset in cpu_data */
  252. add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
  253. /* Store crash buffer address in tpidr_el3 */
  254. msr tpidr_el3, x0
  255. /* Print the rest of crash dump */
  256. b print_el3_sys_regs
  257. from_el1:
  258. mrs x2, sctlr_el1
  259. mrs x1, tcr_el1
  260. b test_pauth
  261. endfunc report_elx_panic
  262. /* -----------------------------------------------------
  263. * This function allows to report a crash (if crash
  264. * reporting is enabled) when panic() is invoked from
  265. * C Runtime. It prints the CPU state via the crash
  266. * console making use of the crash buf. This function
  267. * will not return.
  268. * -----------------------------------------------------
  269. */
  270. func report_el3_panic
  271. msr spsel, #MODE_SP_ELX
  272. prepare_crash_buf_save_x0_x1
  273. adr x0, panic_msg
  274. mov sp, x0
  275. /* Fall through to 'do_crash_reporting' */
  276. /* ------------------------------------------------------------
  277. * The common crash reporting functionality. It requires x0
  278. * and x1 has already been stored in crash buf, sp points to
  279. * crash message and tpidr_el3 contains the crash buf address.
  280. * The function does the following:
  281. * - Retrieve the crash buffer from tpidr_el3
  282. * - Store x2 to x6 in the crash buffer
  283. * - Initialise the crash console.
  284. * - Print the crash message by using the address in sp.
  285. * - Print x30 value to the crash console.
  286. * - Print x0 - x7 from the crash buf to the crash console.
  287. * - Print x8 - x29 (in groups of 8 registers) using the
  288. * crash buf to the crash console.
  289. * - Print el3 sys regs (in groups of 8 registers) using the
  290. * crash buf to the crash console.
  291. * - Print non el3 sys regs (in groups of 8 registers) using
  292. * the crash buf to the crash console.
  293. * ------------------------------------------------------------
  294. */
  295. do_crash_reporting:
  296. /* Retrieve the crash buf from tpidr_el3 */
  297. mrs x0, tpidr_el3
  298. /* Store x2 - x6, x30 in the crash buffer */
  299. stp x2, x3, [x0, #REGSZ * 2]
  300. stp x4, x5, [x0, #REGSZ * 4]
  301. stp x6, x30, [x0, #REGSZ * 6]
  302. /* Initialize the crash console */
  303. bl plat_crash_console_init
  304. /* Verify the console is initialized */
  305. cbz x0, crash_panic
  306. /* Print the crash message. sp points to the crash message */
  307. mov x4, sp
  308. bl asm_print_str
  309. /* Print spaces to align "x30" string */
  310. mov x0, #4
  311. bl print_alignment
  312. /* Load the crash buf address */
  313. mrs x0, tpidr_el3
  314. /* Report x30 first from the crash buf */
  315. ldr x4, [x0, #REGSZ * 7]
  316. #if ENABLE_PAUTH
  317. /* Demangle address */
  318. xpaci x4
  319. #endif
  320. bl asm_print_hex
  321. bl asm_print_newline
  322. /* Load the crash buf address */
  323. mrs x0, tpidr_el3
  324. /* Now mov x7 into crash buf */
  325. str x7, [x0, #REGSZ * 7]
  326. /* Report x0 - x29 values stored in crash buf */
  327. /* Store the ascii list pointer in x6 */
  328. adr x6, gp_regs
  329. /* Print x0 to x7 from the crash buf */
  330. bl size_controlled_print
  331. /* Store x8 - x15 in crash buf and print */
  332. bl str_in_crash_buf_print
  333. /* Load the crash buf address */
  334. mrs x0, tpidr_el3
  335. /* Store the rest of gp regs and print */
  336. stp x16, x17, [x0]
  337. stp x18, x19, [x0, #REGSZ * 2]
  338. stp x20, x21, [x0, #REGSZ * 4]
  339. stp x22, x23, [x0, #REGSZ * 6]
  340. bl size_controlled_print
  341. /* Load the crash buf address */
  342. mrs x0, tpidr_el3
  343. stp x24, x25, [x0]
  344. stp x26, x27, [x0, #REGSZ * 2]
  345. stp x28, x29, [x0, #REGSZ * 4]
  346. bl size_controlled_print
  347. /* Print the el3 sys registers */
  348. print_el3_sys_regs:
  349. adr x6, el3_sys_regs
  350. mrs x8, scr_el3
  351. mrs x9, sctlr_el3
  352. mrs x10, cptr_el3
  353. mrs x11, tcr_el3
  354. mrs x12, daif
  355. mrs x13, mair_el3
  356. mrs x14, spsr_el3
  357. mrs x15, elr_el3
  358. bl str_in_crash_buf_print
  359. mrs x8, ttbr0_el3
  360. mrs x9, esr_el3
  361. mrs x10, far_el3
  362. bl str_in_crash_buf_print
  363. /* Print the non el3 sys registers */
  364. adr x6, non_el3_sys_regs
  365. mrs x8, spsr_el1
  366. mrs x9, elr_el1
  367. mrs x10, spsr_abt
  368. mrs x11, spsr_und
  369. mrs x12, spsr_irq
  370. mrs x13, spsr_fiq
  371. mrs x14, sctlr_el1
  372. mrs x15, actlr_el1
  373. bl str_in_crash_buf_print
  374. mrs x8, cpacr_el1
  375. mrs x9, csselr_el1
  376. mrs x10, sp_el1
  377. mrs x11, esr_el1
  378. mrs x12, ttbr0_el1
  379. mrs x13, ttbr1_el1
  380. mrs x14, mair_el1
  381. mrs x15, amair_el1
  382. bl str_in_crash_buf_print
  383. mrs x8, tcr_el1
  384. mrs x9, tpidr_el1
  385. mrs x10, tpidr_el0
  386. mrs x11, tpidrro_el0
  387. mrs x12, par_el1
  388. mrs x13, mpidr_el1
  389. mrs x14, afsr0_el1
  390. mrs x15, afsr1_el1
  391. bl str_in_crash_buf_print
  392. mrs x8, contextidr_el1
  393. mrs x9, vbar_el1
  394. mrs x10, cntp_ctl_el0
  395. mrs x11, cntp_cval_el0
  396. mrs x12, cntv_ctl_el0
  397. mrs x13, cntv_cval_el0
  398. mrs x14, cntkctl_el1
  399. mrs x15, sp_el0
  400. bl str_in_crash_buf_print
  401. mrs x8, isr_el1
  402. bl str_in_crash_buf_print
  403. #if CTX_INCLUDE_AARCH32_REGS
  404. /* Print the AArch32 registers */
  405. adr x6, aarch32_regs
  406. mrs x8, dacr32_el2
  407. mrs x9, ifsr32_el2
  408. bl str_in_crash_buf_print
  409. #endif /* CTX_INCLUDE_AARCH32_REGS */
  410. /* Get the cpu specific registers to report */
  411. bl do_cpu_reg_dump
  412. bl str_in_crash_buf_print
  413. /* Print some platform registers */
  414. plat_crash_print_regs
  415. bl plat_crash_console_flush
  416. /* Done reporting */
  417. no_ret plat_panic_handler
  418. endfunc report_el3_panic
  419. #else /* CRASH_REPORTING */
  420. func report_unhandled_exception
  421. report_unhandled_interrupt:
  422. no_ret plat_panic_handler
  423. endfunc report_unhandled_exception
  424. #endif /* CRASH_REPORTING */
  425. func crash_panic
  426. no_ret plat_panic_handler
  427. endfunc crash_panic