Home | History | Annotate | Download | only in aarch64
      1 /*
      2  * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 #include <arch.h>
      7 #include <asm_macros.S>
      8 #include <context.h>
      9 #include <cpu_data.h>
     10 #include <plat_macros.S>
     11 #include <platform_def.h>
     12 
     13 	.globl	report_unhandled_exception
     14 	.globl	report_unhandled_interrupt
     15 	.globl	el3_panic
     16 
     17 #if CRASH_REPORTING
     18 #define REG_SIZE	0x8
     19 
     20 	/* ------------------------------------------------------
     21 	 * The below section deals with dumping the system state
     22 	 * when an unhandled exception is taken in EL3.
     23 	 * The layout and the names of the registers which will
     24 	 * be dumped during a unhandled exception is given below.
     25 	 * ------------------------------------------------------
     26 	 */
     27 .section .rodata.crash_prints, "aS"
     28 print_spacer:
     29 	.asciz	" =\t\t0x"
     30 
     31 gp_regs:
     32 	.asciz	"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
     33 		"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
     34 		"x16", "x17", "x18", "x19", "x20", "x21", "x22",\
     35 		"x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
     36 el3_sys_regs:
     37 	.asciz	"scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
     38 		"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
     39 		"esr_el3", "far_el3", ""
     40 
     41 non_el3_sys_regs:
     42 	.asciz	"spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
     43 		"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
     44 		"csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
     45 		"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
     46 		"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
     47 		"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
     48 		"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
     49 		"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0",\
     50 		"isr_el1", ""
     51 
     52 panic_msg:
     53 	.asciz "PANIC in EL3 at x30 = 0x"
     54 excpt_msg:
     55 	.asciz "Unhandled Exception in EL3.\nx30 =\t\t0x"
     56 intr_excpt_msg:
     57 	.asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x"
     58 
     59 	/*
     60 	 * Helper function to print newline to console.
     61 	 */
     62 func print_newline
     63 	mov	x0, '\n'
     64 	b	plat_crash_console_putc
     65 endfunc print_newline
     66 
     67 	/*
     68 	 * Helper function to print from crash buf.
     69 	 * The print loop is controlled by the buf size and
     70 	 * ascii reg name list which is passed in x6. The
     71 	 * function returns the crash buf address in x0.
     72 	 * Clobbers : x0 - x7, sp
     73 	 */
     74 func size_controlled_print
     75 	/* Save the lr */
     76 	mov	sp, x30
     77 	/* load the crash buf address */
     78 	mrs	x7, tpidr_el3
     79 test_size_list:
     80 	/* Calculate x5 always as it will be clobbered by asm_print_hex */
     81 	mrs	x5, tpidr_el3
     82 	add	x5, x5, #CPU_DATA_CRASH_BUF_SIZE
     83 	/* Test whether we have reached end of crash buf */
     84 	cmp	x7, x5
     85 	b.eq	exit_size_print
     86 	ldrb	w4, [x6]
     87 	/* Test whether we are at end of list */
     88 	cbz	w4, exit_size_print
     89 	mov	x4, x6
     90 	/* asm_print_str updates x4 to point to next entry in list */
     91 	bl	asm_print_str
     92 	/* update x6 with the updated list pointer */
     93 	mov	x6, x4
     94 	adr	x4, print_spacer
     95 	bl	asm_print_str
     96 	ldr	x4, [x7], #REG_SIZE
     97 	bl	asm_print_hex
     98 	bl	print_newline
     99 	b	test_size_list
    100 exit_size_print:
    101 	mov	x30, sp
    102 	ret
    103 endfunc size_controlled_print
    104 
    105 	/*
    106 	 * Helper function to store x8 - x15 registers to
    107 	 * the crash buf. The system registers values are
    108 	 * copied to x8 to x15 by the caller which are then
    109 	 * copied to the crash buf by this function.
    110 	 * x0 points to the crash buf. It then calls
    111 	 * size_controlled_print to print to console.
    112 	 * Clobbers : x0 - x7, sp
    113 	 */
    114 func str_in_crash_buf_print
    115 	/* restore the crash buf address in x0 */
    116 	mrs	x0, tpidr_el3
    117 	stp	x8, x9, [x0]
    118 	stp	x10, x11, [x0, #REG_SIZE * 2]
    119 	stp	x12, x13, [x0, #REG_SIZE * 4]
    120 	stp	x14, x15, [x0, #REG_SIZE * 6]
    121 	b	size_controlled_print
    122 endfunc str_in_crash_buf_print
    123 
    124 	/* ------------------------------------------------------
    125 	 * This macro calculates the offset to crash buf from
    126 	 * cpu_data and stores it in tpidr_el3. It also saves x0
    127 	 * and x1 in the crash buf by using sp as a temporary
    128 	 * register.
    129 	 * ------------------------------------------------------
    130 	 */
    131 	.macro prepare_crash_buf_save_x0_x1
    132 	/* we can corrupt this reg to free up x0 */
    133 	mov	sp, x0
    134 	/* tpidr_el3 contains the address to cpu_data structure */
    135 	mrs	x0, tpidr_el3
    136 	/* Calculate the Crash buffer offset in cpu_data */
    137 	add	x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
    138 	/* Store crash buffer address in tpidr_el3 */
    139 	msr	tpidr_el3, x0
    140 	str	x1, [x0, #REG_SIZE]
    141 	mov	x1, sp
    142 	str	x1, [x0]
    143 	.endm
    144 
    145 	/* -----------------------------------------------------
    146 	 * This function allows to report a crash (if crash
    147 	 * reporting is enabled) when an unhandled exception
    148 	 * occurs. It prints the CPU state via the crash console
    149 	 * making use of the crash buf. This function will
    150 	 * not return.
    151 	 * -----------------------------------------------------
    152 	 */
    153 func report_unhandled_exception
    154 	prepare_crash_buf_save_x0_x1
    155 	adr	x0, excpt_msg
    156 	mov	sp, x0
    157 	/* This call will not return */
    158 	b	do_crash_reporting
    159 endfunc report_unhandled_exception
    160 
    161 
    162 	/* -----------------------------------------------------
    163 	 * This function allows to report a crash (if crash
    164 	 * reporting is enabled) when an unhandled interrupt
    165 	 * occurs. It prints the CPU state via the crash console
    166 	 * making use of the crash buf. This function will
    167 	 * not return.
    168 	 * -----------------------------------------------------
    169 	 */
    170 func report_unhandled_interrupt
    171 	prepare_crash_buf_save_x0_x1
    172 	adr	x0, intr_excpt_msg
    173 	mov	sp, x0
    174 	/* This call will not return */
    175 	b	do_crash_reporting
    176 endfunc report_unhandled_interrupt
    177 
    178 	/* -----------------------------------------------------
    179 	 * This function allows to report a crash (if crash
    180 	 * reporting is enabled) when panic() is invoked from
    181 	 * C Runtime. It prints the CPU state via the crash
    182 	 * console making use of the crash buf. This function
    183 	 * will not return.
    184 	 * -----------------------------------------------------
    185 	 */
    186 func el3_panic
    187 	msr	spsel, #1
    188 	prepare_crash_buf_save_x0_x1
    189 	adr	x0, panic_msg
    190 	mov	sp, x0
    191 	/* This call will not return */
    192 	b	do_crash_reporting
    193 endfunc el3_panic
    194 
    195 	/* ------------------------------------------------------------
    196 	 * The common crash reporting functionality. It requires x0
    197 	 * and x1 has already been stored in crash buf, sp points to
    198 	 * crash message and tpidr_el3 contains the crash buf address.
    199 	 * The function does the following:
    200 	 *   - Retrieve the crash buffer from tpidr_el3
    201 	 *   - Store x2 to x6 in the crash buffer
    202 	 *   - Initialise the crash console.
    203 	 *   - Print the crash message by using the address in sp.
    204 	 *   - Print x30 value to the crash console.
    205 	 *   - Print x0 - x7 from the crash buf to the crash console.
    206 	 *   - Print x8 - x29 (in groups of 8 registers) using the
    207 	 *     crash buf to the crash console.
    208 	 *   - Print el3 sys regs (in groups of 8 registers) using the
    209 	 *     crash buf to the crash console.
    210 	 *   - Print non el3 sys regs (in groups of 8 registers) using
    211 	 *     the crash buf to the crash console.
    212 	 * ------------------------------------------------------------
    213 	 */
    214 func do_crash_reporting
    215 	/* Retrieve the crash buf from tpidr_el3 */
    216 	mrs	x0, tpidr_el3
    217 	/* Store x2 - x6, x30 in the crash buffer */
    218 	stp	x2, x3, [x0, #REG_SIZE * 2]
    219 	stp	x4, x5, [x0, #REG_SIZE * 4]
    220 	stp	x6, x30, [x0, #REG_SIZE * 6]
    221 	/* Initialize the crash console */
    222 	bl	plat_crash_console_init
    223 	/* Verify the console is initialized */
    224 	cbz	x0, crash_panic
    225 	/* Print the crash message. sp points to the crash message */
    226 	mov	x4, sp
    227 	bl	asm_print_str
    228 	/* load the crash buf address */
    229 	mrs	x0, tpidr_el3
    230 	/* report x30 first from the crash buf */
    231 	ldr	x4, [x0, #REG_SIZE * 7]
    232 	bl	asm_print_hex
    233 	bl	print_newline
    234 	/* Load the crash buf address */
    235 	mrs	x0, tpidr_el3
    236 	/* Now mov x7 into crash buf */
    237 	str	x7, [x0, #REG_SIZE * 7]
    238 
    239 	/* Report x0 - x29 values stored in crash buf*/
    240 	/* Store the ascii list pointer in x6 */
    241 	adr	x6, gp_regs
    242 	/* Print x0 to x7 from the crash buf */
    243 	bl	size_controlled_print
    244 	/* Store x8 - x15 in crash buf and print */
    245 	bl	str_in_crash_buf_print
    246 	/* Load the crash buf address */
    247 	mrs	x0, tpidr_el3
    248 	/* Store the rest of gp regs and print */
    249 	stp	x16, x17, [x0]
    250 	stp	x18, x19, [x0, #REG_SIZE * 2]
    251 	stp	x20, x21, [x0, #REG_SIZE * 4]
    252 	stp	x22, x23, [x0, #REG_SIZE * 6]
    253 	bl	size_controlled_print
    254 	/* Load the crash buf address */
    255 	mrs	x0, tpidr_el3
    256 	stp	x24, x25, [x0]
    257 	stp	x26, x27, [x0, #REG_SIZE * 2]
    258 	stp	x28, x29, [x0, #REG_SIZE * 4]
    259 	bl	size_controlled_print
    260 
    261 	/* Print the el3 sys registers */
    262 	adr	x6, el3_sys_regs
    263 	mrs	x8, scr_el3
    264 	mrs	x9, sctlr_el3
    265 	mrs	x10, cptr_el3
    266 	mrs	x11, tcr_el3
    267 	mrs	x12, daif
    268 	mrs	x13, mair_el3
    269 	mrs	x14, spsr_el3
    270 	mrs	x15, elr_el3
    271 	bl	str_in_crash_buf_print
    272 	mrs	x8, ttbr0_el3
    273 	mrs	x9, esr_el3
    274 	mrs	x10, far_el3
    275 	bl	str_in_crash_buf_print
    276 
    277 	/* Print the non el3 sys registers */
    278 	adr	x6, non_el3_sys_regs
    279 	mrs	x8, spsr_el1
    280 	mrs	x9, elr_el1
    281 	mrs	x10, spsr_abt
    282 	mrs	x11, spsr_und
    283 	mrs	x12, spsr_irq
    284 	mrs	x13, spsr_fiq
    285 	mrs	x14, sctlr_el1
    286 	mrs	x15, actlr_el1
    287 	bl	str_in_crash_buf_print
    288 	mrs	x8, cpacr_el1
    289 	mrs	x9, csselr_el1
    290 	mrs	x10, sp_el1
    291 	mrs	x11, esr_el1
    292 	mrs	x12, ttbr0_el1
    293 	mrs	x13, ttbr1_el1
    294 	mrs	x14, mair_el1
    295 	mrs	x15, amair_el1
    296 	bl	str_in_crash_buf_print
    297 	mrs	x8, tcr_el1
    298 	mrs	x9, tpidr_el1
    299 	mrs	x10, tpidr_el0
    300 	mrs	x11, tpidrro_el0
    301 	mrs	x12, dacr32_el2
    302 	mrs	x13, ifsr32_el2
    303 	mrs	x14, par_el1
    304 	mrs	x15, mpidr_el1
    305 	bl	str_in_crash_buf_print
    306 	mrs	x8, afsr0_el1
    307 	mrs	x9, afsr1_el1
    308 	mrs	x10, contextidr_el1
    309 	mrs	x11, vbar_el1
    310 	mrs	x12, cntp_ctl_el0
    311 	mrs	x13, cntp_cval_el0
    312 	mrs	x14, cntv_ctl_el0
    313 	mrs	x15, cntv_cval_el0
    314 	bl	str_in_crash_buf_print
    315 	mrs	x8, cntkctl_el1
    316 	mrs	x9, fpexc32_el2
    317 	mrs	x10, sp_el0
    318 	mrs	x11, isr_el1
    319 	bl	str_in_crash_buf_print
    320 
    321 	/* Get the cpu specific registers to report */
    322 	bl	do_cpu_reg_dump
    323 	bl	str_in_crash_buf_print
    324 
    325 	/* Print some platform registers */
    326 	plat_crash_print_regs
    327 
    328 	bl	plat_crash_console_flush
    329 
    330 	/* Done reporting */
    331 	no_ret	plat_panic_handler
    332 endfunc do_crash_reporting
    333 
    334 #else	/* CRASH_REPORTING */
    335 func report_unhandled_exception
    336 report_unhandled_interrupt:
    337 	no_ret	plat_panic_handler
    338 endfunc report_unhandled_exception
    339 #endif	/* CRASH_REPORTING */
    340 
    341 
    342 func crash_panic
    343 	no_ret	plat_panic_handler
    344 endfunc crash_panic
    345