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