1a43d431bSSoby Mathew/* 2801cf93cSAntonio Nino Diaz * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. 3a43d431bSSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5a43d431bSSoby Mathew */ 6*09d40e0eSAntonio Nino Diaz 7*09d40e0eSAntonio Nino Diaz#include <plat_macros.S> 8*09d40e0eSAntonio Nino Diaz#include <platform_def.h> 9*09d40e0eSAntonio Nino Diaz 10a43d431bSSoby Mathew#include <arch.h> 11a43d431bSSoby Mathew#include <asm_macros.S> 12a43d431bSSoby Mathew#include <context.h> 13*09d40e0eSAntonio Nino Diaz#include <lib/el3_runtime/cpu_data.h> 14*09d40e0eSAntonio Nino Diaz#include <lib/utils_def.h> 15a43d431bSSoby Mathew 16626ed510SSoby Mathew .globl report_unhandled_exception 17626ed510SSoby Mathew .globl report_unhandled_interrupt 18626ed510SSoby Mathew .globl el3_panic 19a43d431bSSoby Mathew 209c22b323SAndrew Thoelke#if CRASH_REPORTING 21626ed510SSoby Mathew 22a43d431bSSoby Mathew /* ------------------------------------------------------ 23a43d431bSSoby Mathew * The below section deals with dumping the system state 24a43d431bSSoby Mathew * when an unhandled exception is taken in EL3. 25a43d431bSSoby Mathew * The layout and the names of the registers which will 26a43d431bSSoby Mathew * be dumped during a unhandled exception is given below. 27a43d431bSSoby Mathew * ------------------------------------------------------ 28a43d431bSSoby Mathew */ 29626ed510SSoby Mathew.section .rodata.crash_prints, "aS" 30626ed510SSoby Mathewprint_spacer: 31626ed510SSoby Mathew .asciz " =\t\t0x" 32a43d431bSSoby Mathew 33626ed510SSoby Mathewgp_regs: 34626ed510SSoby Mathew .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\ 35626ed510SSoby Mathew "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\ 36626ed510SSoby Mathew "x16", "x17", "x18", "x19", "x20", "x21", "x22",\ 37626ed510SSoby Mathew "x23", "x24", "x25", "x26", "x27", "x28", "x29", "" 38626ed510SSoby Mathewel3_sys_regs: 39626ed510SSoby Mathew .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\ 40626ed510SSoby Mathew "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\ 41626ed510SSoby Mathew "esr_el3", "far_el3", "" 42a43d431bSSoby Mathew 43626ed510SSoby Mathewnon_el3_sys_regs: 44626ed510SSoby Mathew .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\ 45a43d431bSSoby Mathew "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\ 46a43d431bSSoby Mathew "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\ 47626ed510SSoby Mathew "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\ 48626ed510SSoby Mathew "tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\ 49626ed510SSoby Mathew "mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\ 50626ed510SSoby Mathew "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\ 5191089f36SDavid Cunado "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" 52a43d431bSSoby Mathew 53626ed510SSoby Mathewpanic_msg: 54626ed510SSoby Mathew .asciz "PANIC in EL3 at x30 = 0x" 55626ed510SSoby Mathewexcpt_msg: 56626ed510SSoby Mathew .asciz "Unhandled Exception in EL3.\nx30 =\t\t0x" 57626ed510SSoby Mathewintr_excpt_msg: 58626ed510SSoby Mathew .asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x" 59626ed510SSoby Mathew 60626ed510SSoby Mathew /* 61626ed510SSoby Mathew * Helper function to print newline to console. 62626ed510SSoby Mathew */ 63626ed510SSoby Mathewfunc print_newline 64626ed510SSoby Mathew mov x0, '\n' 65626ed510SSoby Mathew b plat_crash_console_putc 668b779620SKévin Petitendfunc print_newline 67626ed510SSoby Mathew 68626ed510SSoby Mathew /* 69626ed510SSoby Mathew * Helper function to print from crash buf. 70626ed510SSoby Mathew * The print loop is controlled by the buf size and 71626ed510SSoby Mathew * ascii reg name list which is passed in x6. The 72626ed510SSoby Mathew * function returns the crash buf address in x0. 73626ed510SSoby Mathew * Clobbers : x0 - x7, sp 74626ed510SSoby Mathew */ 75626ed510SSoby Mathewfunc size_controlled_print 76626ed510SSoby Mathew /* Save the lr */ 77626ed510SSoby Mathew mov sp, x30 78626ed510SSoby Mathew /* load the crash buf address */ 79626ed510SSoby Mathew mrs x7, tpidr_el3 80626ed510SSoby Mathewtest_size_list: 81626ed510SSoby Mathew /* Calculate x5 always as it will be clobbered by asm_print_hex */ 82626ed510SSoby Mathew mrs x5, tpidr_el3 83626ed510SSoby Mathew add x5, x5, #CPU_DATA_CRASH_BUF_SIZE 84626ed510SSoby Mathew /* Test whether we have reached end of crash buf */ 85626ed510SSoby Mathew cmp x7, x5 86626ed510SSoby Mathew b.eq exit_size_print 87626ed510SSoby Mathew ldrb w4, [x6] 88626ed510SSoby Mathew /* Test whether we are at end of list */ 89626ed510SSoby Mathew cbz w4, exit_size_print 90626ed510SSoby Mathew mov x4, x6 91626ed510SSoby Mathew /* asm_print_str updates x4 to point to next entry in list */ 92626ed510SSoby Mathew bl asm_print_str 93626ed510SSoby Mathew /* update x6 with the updated list pointer */ 94626ed510SSoby Mathew mov x6, x4 95626ed510SSoby Mathew adr x4, print_spacer 96626ed510SSoby Mathew bl asm_print_str 97155a1006SJulius Werner ldr x4, [x7], #REGSZ 98626ed510SSoby Mathew bl asm_print_hex 99626ed510SSoby Mathew bl print_newline 100626ed510SSoby Mathew b test_size_list 101626ed510SSoby Mathewexit_size_print: 102626ed510SSoby Mathew mov x30, sp 103626ed510SSoby Mathew ret 1048b779620SKévin Petitendfunc size_controlled_print 105626ed510SSoby Mathew 106626ed510SSoby Mathew /* 107626ed510SSoby Mathew * Helper function to store x8 - x15 registers to 108626ed510SSoby Mathew * the crash buf. The system registers values are 109626ed510SSoby Mathew * copied to x8 to x15 by the caller which are then 110626ed510SSoby Mathew * copied to the crash buf by this function. 111626ed510SSoby Mathew * x0 points to the crash buf. It then calls 112626ed510SSoby Mathew * size_controlled_print to print to console. 113626ed510SSoby Mathew * Clobbers : x0 - x7, sp 114626ed510SSoby Mathew */ 115626ed510SSoby Mathewfunc str_in_crash_buf_print 116626ed510SSoby Mathew /* restore the crash buf address in x0 */ 117626ed510SSoby Mathew mrs x0, tpidr_el3 118626ed510SSoby Mathew stp x8, x9, [x0] 119155a1006SJulius Werner stp x10, x11, [x0, #REGSZ * 2] 120155a1006SJulius Werner stp x12, x13, [x0, #REGSZ * 4] 121155a1006SJulius Werner stp x14, x15, [x0, #REGSZ * 6] 122626ed510SSoby Mathew b size_controlled_print 1238b779620SKévin Petitendfunc str_in_crash_buf_print 124626ed510SSoby Mathew 125626ed510SSoby Mathew /* ------------------------------------------------------ 126626ed510SSoby Mathew * This macro calculates the offset to crash buf from 127626ed510SSoby Mathew * cpu_data and stores it in tpidr_el3. It also saves x0 128626ed510SSoby Mathew * and x1 in the crash buf by using sp as a temporary 129626ed510SSoby Mathew * register. 130626ed510SSoby Mathew * ------------------------------------------------------ 131626ed510SSoby Mathew */ 132626ed510SSoby Mathew .macro prepare_crash_buf_save_x0_x1 133626ed510SSoby Mathew /* we can corrupt this reg to free up x0 */ 134626ed510SSoby Mathew mov sp, x0 135626ed510SSoby Mathew /* tpidr_el3 contains the address to cpu_data structure */ 136626ed510SSoby Mathew mrs x0, tpidr_el3 137626ed510SSoby Mathew /* Calculate the Crash buffer offset in cpu_data */ 138626ed510SSoby Mathew add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET 139626ed510SSoby Mathew /* Store crash buffer address in tpidr_el3 */ 140626ed510SSoby Mathew msr tpidr_el3, x0 141155a1006SJulius Werner str x1, [x0, #REGSZ] 142626ed510SSoby Mathew mov x1, sp 143626ed510SSoby Mathew str x1, [x0] 144626ed510SSoby Mathew .endm 145a43d431bSSoby Mathew 146a43d431bSSoby Mathew /* ----------------------------------------------------- 147626ed510SSoby Mathew * This function allows to report a crash (if crash 148626ed510SSoby Mathew * reporting is enabled) when an unhandled exception 149626ed510SSoby Mathew * occurs. It prints the CPU state via the crash console 150626ed510SSoby Mathew * making use of the crash buf. This function will 151626ed510SSoby Mathew * not return. 152a43d431bSSoby Mathew * ----------------------------------------------------- 153a43d431bSSoby Mathew */ 154626ed510SSoby Mathewfunc report_unhandled_exception 155626ed510SSoby Mathew prepare_crash_buf_save_x0_x1 156626ed510SSoby Mathew adr x0, excpt_msg 157626ed510SSoby Mathew mov sp, x0 158626ed510SSoby Mathew /* This call will not return */ 159626ed510SSoby Mathew b do_crash_reporting 1608b779620SKévin Petitendfunc report_unhandled_exception 161a43d431bSSoby Mathew 162a43d431bSSoby Mathew 163626ed510SSoby Mathew /* ----------------------------------------------------- 164626ed510SSoby Mathew * This function allows to report a crash (if crash 165626ed510SSoby Mathew * reporting is enabled) when an unhandled interrupt 166626ed510SSoby Mathew * occurs. It prints the CPU state via the crash console 167626ed510SSoby Mathew * making use of the crash buf. This function will 168626ed510SSoby Mathew * not return. 169626ed510SSoby Mathew * ----------------------------------------------------- 170626ed510SSoby Mathew */ 171626ed510SSoby Mathewfunc report_unhandled_interrupt 172626ed510SSoby Mathew prepare_crash_buf_save_x0_x1 173626ed510SSoby Mathew adr x0, intr_excpt_msg 174626ed510SSoby Mathew mov sp, x0 175626ed510SSoby Mathew /* This call will not return */ 176626ed510SSoby Mathew b do_crash_reporting 1778b779620SKévin Petitendfunc report_unhandled_interrupt 178a43d431bSSoby Mathew 179626ed510SSoby Mathew /* ----------------------------------------------------- 180626ed510SSoby Mathew * This function allows to report a crash (if crash 181626ed510SSoby Mathew * reporting is enabled) when panic() is invoked from 182626ed510SSoby Mathew * C Runtime. It prints the CPU state via the crash 183626ed510SSoby Mathew * console making use of the crash buf. This function 184626ed510SSoby Mathew * will not return. 185626ed510SSoby Mathew * ----------------------------------------------------- 186626ed510SSoby Mathew */ 187626ed510SSoby Mathewfunc el3_panic 188626ed510SSoby Mathew msr spsel, #1 189626ed510SSoby Mathew prepare_crash_buf_save_x0_x1 190626ed510SSoby Mathew adr x0, panic_msg 191626ed510SSoby Mathew mov sp, x0 192626ed510SSoby Mathew /* This call will not return */ 193626ed510SSoby Mathew b do_crash_reporting 1948b779620SKévin Petitendfunc el3_panic 195a43d431bSSoby Mathew 196626ed510SSoby Mathew /* ------------------------------------------------------------ 197626ed510SSoby Mathew * The common crash reporting functionality. It requires x0 198626ed510SSoby Mathew * and x1 has already been stored in crash buf, sp points to 199626ed510SSoby Mathew * crash message and tpidr_el3 contains the crash buf address. 200626ed510SSoby Mathew * The function does the following: 201626ed510SSoby Mathew * - Retrieve the crash buffer from tpidr_el3 202626ed510SSoby Mathew * - Store x2 to x6 in the crash buffer 203626ed510SSoby Mathew * - Initialise the crash console. 204626ed510SSoby Mathew * - Print the crash message by using the address in sp. 205626ed510SSoby Mathew * - Print x30 value to the crash console. 206626ed510SSoby Mathew * - Print x0 - x7 from the crash buf to the crash console. 207626ed510SSoby Mathew * - Print x8 - x29 (in groups of 8 registers) using the 208626ed510SSoby Mathew * crash buf to the crash console. 209626ed510SSoby Mathew * - Print el3 sys regs (in groups of 8 registers) using the 210626ed510SSoby Mathew * crash buf to the crash console. 211626ed510SSoby Mathew * - Print non el3 sys regs (in groups of 8 registers) using 212626ed510SSoby Mathew * the crash buf to the crash console. 213626ed510SSoby Mathew * ------------------------------------------------------------ 214626ed510SSoby Mathew */ 215626ed510SSoby Mathewfunc do_crash_reporting 216626ed510SSoby Mathew /* Retrieve the crash buf from tpidr_el3 */ 217626ed510SSoby Mathew mrs x0, tpidr_el3 218626ed510SSoby Mathew /* Store x2 - x6, x30 in the crash buffer */ 219155a1006SJulius Werner stp x2, x3, [x0, #REGSZ * 2] 220155a1006SJulius Werner stp x4, x5, [x0, #REGSZ * 4] 221155a1006SJulius Werner stp x6, x30, [x0, #REGSZ * 6] 222626ed510SSoby Mathew /* Initialize the crash console */ 223626ed510SSoby Mathew bl plat_crash_console_init 224626ed510SSoby Mathew /* Verify the console is initialized */ 225626ed510SSoby Mathew cbz x0, crash_panic 226626ed510SSoby Mathew /* Print the crash message. sp points to the crash message */ 227626ed510SSoby Mathew mov x4, sp 228626ed510SSoby Mathew bl asm_print_str 229626ed510SSoby Mathew /* load the crash buf address */ 230626ed510SSoby Mathew mrs x0, tpidr_el3 231626ed510SSoby Mathew /* report x30 first from the crash buf */ 232155a1006SJulius Werner ldr x4, [x0, #REGSZ * 7] 233626ed510SSoby Mathew bl asm_print_hex 234626ed510SSoby Mathew bl print_newline 235626ed510SSoby Mathew /* Load the crash buf address */ 236626ed510SSoby Mathew mrs x0, tpidr_el3 237626ed510SSoby Mathew /* Now mov x7 into crash buf */ 238155a1006SJulius Werner str x7, [x0, #REGSZ * 7] 239a43d431bSSoby Mathew 240626ed510SSoby Mathew /* Report x0 - x29 values stored in crash buf*/ 241626ed510SSoby Mathew /* Store the ascii list pointer in x6 */ 242626ed510SSoby Mathew adr x6, gp_regs 243626ed510SSoby Mathew /* Print x0 to x7 from the crash buf */ 244626ed510SSoby Mathew bl size_controlled_print 245626ed510SSoby Mathew /* Store x8 - x15 in crash buf and print */ 246626ed510SSoby Mathew bl str_in_crash_buf_print 247626ed510SSoby Mathew /* Load the crash buf address */ 248626ed510SSoby Mathew mrs x0, tpidr_el3 249626ed510SSoby Mathew /* Store the rest of gp regs and print */ 250626ed510SSoby Mathew stp x16, x17, [x0] 251155a1006SJulius Werner stp x18, x19, [x0, #REGSZ * 2] 252155a1006SJulius Werner stp x20, x21, [x0, #REGSZ * 4] 253155a1006SJulius Werner stp x22, x23, [x0, #REGSZ * 6] 254626ed510SSoby Mathew bl size_controlled_print 255626ed510SSoby Mathew /* Load the crash buf address */ 256626ed510SSoby Mathew mrs x0, tpidr_el3 257626ed510SSoby Mathew stp x24, x25, [x0] 258155a1006SJulius Werner stp x26, x27, [x0, #REGSZ * 2] 259155a1006SJulius Werner stp x28, x29, [x0, #REGSZ * 4] 260626ed510SSoby Mathew bl size_controlled_print 261a43d431bSSoby Mathew 262626ed510SSoby Mathew /* Print the el3 sys registers */ 263626ed510SSoby Mathew adr x6, el3_sys_regs 264626ed510SSoby Mathew mrs x8, scr_el3 265626ed510SSoby Mathew mrs x9, sctlr_el3 266626ed510SSoby Mathew mrs x10, cptr_el3 267626ed510SSoby Mathew mrs x11, tcr_el3 268626ed510SSoby Mathew mrs x12, daif 269626ed510SSoby Mathew mrs x13, mair_el3 270626ed510SSoby Mathew mrs x14, spsr_el3 271626ed510SSoby Mathew mrs x15, elr_el3 272626ed510SSoby Mathew bl str_in_crash_buf_print 273626ed510SSoby Mathew mrs x8, ttbr0_el3 274626ed510SSoby Mathew mrs x9, esr_el3 275626ed510SSoby Mathew mrs x10, far_el3 276626ed510SSoby Mathew bl str_in_crash_buf_print 277a43d431bSSoby Mathew 278626ed510SSoby Mathew /* Print the non el3 sys registers */ 279626ed510SSoby Mathew adr x6, non_el3_sys_regs 280626ed510SSoby Mathew mrs x8, spsr_el1 281626ed510SSoby Mathew mrs x9, elr_el1 282626ed510SSoby Mathew mrs x10, spsr_abt 283626ed510SSoby Mathew mrs x11, spsr_und 284626ed510SSoby Mathew mrs x12, spsr_irq 285626ed510SSoby Mathew mrs x13, spsr_fiq 286626ed510SSoby Mathew mrs x14, sctlr_el1 287626ed510SSoby Mathew mrs x15, actlr_el1 288626ed510SSoby Mathew bl str_in_crash_buf_print 289626ed510SSoby Mathew mrs x8, cpacr_el1 290626ed510SSoby Mathew mrs x9, csselr_el1 291a43d431bSSoby Mathew mrs x10, sp_el1 292a43d431bSSoby Mathew mrs x11, esr_el1 293a43d431bSSoby Mathew mrs x12, ttbr0_el1 294a43d431bSSoby Mathew mrs x13, ttbr1_el1 295a43d431bSSoby Mathew mrs x14, mair_el1 296a43d431bSSoby Mathew mrs x15, amair_el1 297626ed510SSoby Mathew bl str_in_crash_buf_print 298626ed510SSoby Mathew mrs x8, tcr_el1 299626ed510SSoby Mathew mrs x9, tpidr_el1 300626ed510SSoby Mathew mrs x10, tpidr_el0 301626ed510SSoby Mathew mrs x11, tpidrro_el0 302626ed510SSoby Mathew mrs x12, dacr32_el2 303626ed510SSoby Mathew mrs x13, ifsr32_el2 304626ed510SSoby Mathew mrs x14, par_el1 305626ed510SSoby Mathew mrs x15, mpidr_el1 306626ed510SSoby Mathew bl str_in_crash_buf_print 307626ed510SSoby Mathew mrs x8, afsr0_el1 308626ed510SSoby Mathew mrs x9, afsr1_el1 309626ed510SSoby Mathew mrs x10, contextidr_el1 310626ed510SSoby Mathew mrs x11, vbar_el1 311626ed510SSoby Mathew mrs x12, cntp_ctl_el0 312626ed510SSoby Mathew mrs x13, cntp_cval_el0 313626ed510SSoby Mathew mrs x14, cntv_ctl_el0 314626ed510SSoby Mathew mrs x15, cntv_cval_el0 315626ed510SSoby Mathew bl str_in_crash_buf_print 316626ed510SSoby Mathew mrs x8, cntkctl_el1 31791089f36SDavid Cunado mrs x9, sp_el0 31891089f36SDavid Cunado mrs x10, isr_el1 319626ed510SSoby Mathew bl str_in_crash_buf_print 320a43d431bSSoby Mathew 321d3f70af6SSoby Mathew /* Get the cpu specific registers to report */ 322d3f70af6SSoby Mathew bl do_cpu_reg_dump 323d3f70af6SSoby Mathew bl str_in_crash_buf_print 3248c106902SSoby Mathew 3259ff67fa6SGerald Lejeune /* Print some platform registers */ 3269ff67fa6SGerald Lejeune plat_crash_print_regs 3278c106902SSoby Mathew 328801cf93cSAntonio Nino Diaz bl plat_crash_console_flush 329801cf93cSAntonio Nino Diaz 330626ed510SSoby Mathew /* Done reporting */ 331a806dad5SJeenu Viswambharan no_ret plat_panic_handler 3328b779620SKévin Petitendfunc do_crash_reporting 333a43d431bSSoby Mathew 334626ed510SSoby Mathew#else /* CRASH_REPORTING */ 335626ed510SSoby Mathewfunc report_unhandled_exception 336626ed510SSoby Mathewreport_unhandled_interrupt: 337a806dad5SJeenu Viswambharan no_ret plat_panic_handler 3388b779620SKévin Petitendfunc report_unhandled_exception 3391645d3eeSSandrine Bailleux#endif /* CRASH_REPORTING */ 3409c22b323SAndrew Thoelke 341a43d431bSSoby Mathew 342626ed510SSoby Mathewfunc crash_panic 343a806dad5SJeenu Viswambharan no_ret plat_panic_handler 3448b779620SKévin Petitendfunc crash_panic 345