xref: /rk3399_ARM-atf/bl31/aarch64/crash_reporting.S (revision 4779becd386cbaa1c1871d3e887704d63492ffb0)
1a43d431bSSoby Mathew/*
258fadd62SIgor Podgainõi * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
3a43d431bSSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
5a43d431bSSoby Mathew */
609d40e0eSAntonio Nino Diaz
709d40e0eSAntonio Nino Diaz#include <plat_macros.S>
809d40e0eSAntonio Nino Diaz#include <platform_def.h>
909d40e0eSAntonio Nino Diaz
10a43d431bSSoby Mathew#include <arch.h>
11a43d431bSSoby Mathew#include <asm_macros.S>
12a43d431bSSoby Mathew#include <context.h>
1309d40e0eSAntonio Nino Diaz#include <lib/el3_runtime/cpu_data.h>
1409d40e0eSAntonio Nino Diaz#include <lib/utils_def.h>
15a43d431bSSoby Mathew
16626ed510SSoby Mathew	.globl	report_unhandled_exception
17626ed510SSoby Mathew	.globl	report_unhandled_interrupt
18f300ef66SGovindraj Raja	.globl	report_el3_panic
197e619eccSGovindraj Raja	.globl	report_elx_panic
20a43d431bSSoby Mathew
219c22b323SAndrew Thoelke#if CRASH_REPORTING
22626ed510SSoby Mathew
23a43d431bSSoby Mathew	/* ------------------------------------------------------
24a43d431bSSoby Mathew	 * The below section deals with dumping the system state
25a43d431bSSoby Mathew	 * when an unhandled exception is taken in EL3.
26a43d431bSSoby Mathew	 * The layout and the names of the registers which will
27a43d431bSSoby Mathew	 * be dumped during a unhandled exception is given below.
28a43d431bSSoby Mathew	 * ------------------------------------------------------
29a43d431bSSoby Mathew	 */
30626ed510SSoby Mathew.section .rodata.crash_prints, "aS"
31626ed510SSoby Mathewprint_spacer:
326c6a470fSAlexei Fedorov	.asciz	"             = 0x"
33a43d431bSSoby Mathew
34626ed510SSoby Mathewgp_regs:
35626ed510SSoby Mathew	.asciz	"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
36626ed510SSoby Mathew		"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
37626ed510SSoby Mathew		"x16", "x17", "x18", "x19", "x20", "x21", "x22",\
38626ed510SSoby Mathew		"x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
39626ed510SSoby Mathewel3_sys_regs:
40626ed510SSoby Mathew	.asciz	"scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
41626ed510SSoby Mathew		"daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
42626ed510SSoby Mathew		"esr_el3", "far_el3", ""
43a43d431bSSoby Mathew
4458fadd62SIgor Podgainõinon_el3_sys_regs_1:
45626ed510SSoby Mathew	.asciz	"spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
46a43d431bSSoby Mathew		"spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
4758fadd62SIgor Podgainõi		"csselr_el1", "sp_el1", "esr_el1", ""
4858fadd62SIgor Podgainõi
4958fadd62SIgor Podgainõittbr_regs:
5058fadd62SIgor Podgainõi	.asciz	"ttbr0_el1", "ttbr0_el2", "ttbr1_el1", "vttbr_el2", ""
5158fadd62SIgor Podgainõi
5258fadd62SIgor Podgainõinon_el3_sys_regs_2:
5358fadd62SIgor Podgainõi	.asciz	"mair_el1", "amair_el1", "tcr_el1", "tpidr_el1",\
5458fadd62SIgor Podgainõi		"tpidr_el0", "tpidrro_el0", ""
5558fadd62SIgor Podgainõi
5658fadd62SIgor Podgainõipar_reg:
5758fadd62SIgor Podgainõi	.asciz	"par_el1", ""
5858fadd62SIgor Podgainõi
5958fadd62SIgor Podgainõinon_el3_sys_regs_3:
6058fadd62SIgor Podgainõi	.asciz	"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
6158fadd62SIgor Podgainõi		"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
6258fadd62SIgor Podgainõi		"cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", ""
63c424b91eSImre Kis
64c424b91eSImre Kis#if CTX_INCLUDE_AARCH32_REGS
65c424b91eSImre Kisaarch32_regs:
66c424b91eSImre Kis	.asciz	"dacr32_el2", "ifsr32_el2", ""
67c424b91eSImre Kis#endif /* CTX_INCLUDE_AARCH32_REGS */
68a43d431bSSoby Mathew
69626ed510SSoby Mathewpanic_msg:
706c6a470fSAlexei Fedorov	.asciz "PANIC in EL3.\nx30"
71626ed510SSoby Mathewexcpt_msg:
726c6a470fSAlexei Fedorov	.asciz "Unhandled Exception in EL3.\nx30"
73626ed510SSoby Mathewintr_excpt_msg:
74b4292bc6SAlexei Fedorov	.ascii "Unhandled Interrupt Exception in EL3.\n"
75b4292bc6SAlexei Fedorovx30_msg:
76b4292bc6SAlexei Fedorov	.asciz "x30"
77b4292bc6SAlexei Fedorovexcpt_msg_el:
787e619eccSGovindraj Raja	.asciz "Unhandled Exception from lower EL.\n"
79626ed510SSoby Mathew
80626ed510SSoby Mathew	/*
81626ed510SSoby Mathew	 * Helper function to print from crash buf.
82626ed510SSoby Mathew	 * The print loop is controlled by the buf size and
83626ed510SSoby Mathew	 * ascii reg name list which is passed in x6. The
84626ed510SSoby Mathew	 * function returns the crash buf address in x0.
8558fadd62SIgor Podgainõi	 * Clobbers : x0 - x7, x20, sp
86626ed510SSoby Mathew	 */
8758fadd62SIgor Podgainõifunc size_controlled_print_helper
8858fadd62SIgor Podgainõi#if ENABLE_FEAT_D128
8958fadd62SIgor Podgainõisize_controlled_print_128:
9058fadd62SIgor Podgainõi	/* Set flag to print 128-bit registers */
9158fadd62SIgor Podgainõi	mov	x20, #1
9258fadd62SIgor Podgainõi	b	1f
9358fadd62SIgor Podgainõi
9458fadd62SIgor Podgainõisize_controlled_print:
9558fadd62SIgor Podgainõi	/* Set flag to print 64-bit registers */
9658fadd62SIgor Podgainõi	mov	x20, #0
9758fadd62SIgor Podgainõi1:
9858fadd62SIgor Podgainõi#else
9958fadd62SIgor Podgainõisize_controlled_print:
10058fadd62SIgor Podgainõi#endif
101626ed510SSoby Mathew	/* Save the lr */
102626ed510SSoby Mathew	mov	sp, x30
103626ed510SSoby Mathew	/* load the crash buf address */
104626ed510SSoby Mathew	mrs	x7, tpidr_el3
105626ed510SSoby Mathewtest_size_list:
106626ed510SSoby Mathew	/* Calculate x5 always as it will be clobbered by asm_print_hex */
107626ed510SSoby Mathew	mrs	x5, tpidr_el3
108*4779becdSBoyan Karatotev	add	x5, x5, #CPU_DATA_CRASH_BUF_BYTES
109626ed510SSoby Mathew	/* Test whether we have reached end of crash buf */
110626ed510SSoby Mathew	cmp	x7, x5
111626ed510SSoby Mathew	b.eq	exit_size_print
112626ed510SSoby Mathew	ldrb	w4, [x6]
113626ed510SSoby Mathew	/* Test whether we are at end of list */
114626ed510SSoby Mathew	cbz	w4, exit_size_print
115626ed510SSoby Mathew	mov	x4, x6
116626ed510SSoby Mathew	/* asm_print_str updates x4 to point to next entry in list */
117626ed510SSoby Mathew	bl	asm_print_str
1186c6a470fSAlexei Fedorov	/* x0 = number of symbols printed + 1 */
1196c6a470fSAlexei Fedorov	sub	x0, x4, x6
120626ed510SSoby Mathew	/* update x6 with the updated list pointer */
121626ed510SSoby Mathew	mov	x6, x4
1226c6a470fSAlexei Fedorov	bl	print_alignment
12358fadd62SIgor Podgainõi	/* Print the high 64 bits (or whole 64-bit register) */
124155a1006SJulius Werner	ldr	x4, [x7], #REGSZ
125626ed510SSoby Mathew	bl	asm_print_hex
12658fadd62SIgor Podgainõi#if ENABLE_FEAT_D128
12758fadd62SIgor Podgainõi	cbz	x20, 2f
12858fadd62SIgor Podgainõi	/* Print the low 64 bits in case of a 128-bit register */
12958fadd62SIgor Podgainõi	ldr	x4, [x7], #REGSZ
13058fadd62SIgor Podgainõi	bl	asm_print_hex
13158fadd62SIgor Podgainõi2:
13258fadd62SIgor Podgainõi#endif
13353d7e003SJustin Chadwell	bl	asm_print_newline
134626ed510SSoby Mathew	b	test_size_list
135626ed510SSoby Mathewexit_size_print:
136626ed510SSoby Mathew	mov	x30, sp
137626ed510SSoby Mathew	ret
13858fadd62SIgor Podgainõiendfunc size_controlled_print_helper
139626ed510SSoby Mathew
1406c6a470fSAlexei Fedorov	/* -----------------------------------------------------
1416c6a470fSAlexei Fedorov	 * This function calculates and prints required number
1426c6a470fSAlexei Fedorov	 * of space characters followed by "= 0x", based on the
1436c6a470fSAlexei Fedorov	 * length of ascii register name.
1446c6a470fSAlexei Fedorov 	 * x0: length of ascii register name + 1
1456c6a470fSAlexei Fedorov	 * ------------------------------------------------------
1466c6a470fSAlexei Fedorov 	 */
1476c6a470fSAlexei Fedorovfunc print_alignment
1486c6a470fSAlexei Fedorov	/* The minimum ascii length is 3, e.g. for "x0" */
1496c6a470fSAlexei Fedorov	adr	x4, print_spacer - 3
1506c6a470fSAlexei Fedorov	add	x4, x4, x0
1516c6a470fSAlexei Fedorov	b	asm_print_str
1526c6a470fSAlexei Fedorovendfunc print_alignment
1536c6a470fSAlexei Fedorov
154626ed510SSoby Mathew	/*
155626ed510SSoby Mathew	 * Helper function to store x8 - x15 registers to
156626ed510SSoby Mathew	 * the crash buf. The system registers values are
157626ed510SSoby Mathew	 * copied to x8 to x15 by the caller which are then
158626ed510SSoby Mathew	 * copied to the crash buf by this function.
159626ed510SSoby Mathew	 * x0 points to the crash buf. It then calls
160626ed510SSoby Mathew	 * size_controlled_print to print to console.
16158fadd62SIgor Podgainõi	 * Clobbers : x0 - x7, x20, sp
162626ed510SSoby Mathew	 */
163626ed510SSoby Mathewfunc str_in_crash_buf_print
164626ed510SSoby Mathew	/* restore the crash buf address in x0 */
165626ed510SSoby Mathew	mrs	x0, tpidr_el3
166626ed510SSoby Mathew	stp	x8, x9, [x0]
167155a1006SJulius Werner	stp	x10, x11, [x0, #REGSZ * 2]
168155a1006SJulius Werner	stp	x12, x13, [x0, #REGSZ * 4]
169155a1006SJulius Werner	stp	x14, x15, [x0, #REGSZ * 6]
170626ed510SSoby Mathew	b	size_controlled_print
1718b779620SKévin Petitendfunc str_in_crash_buf_print
172626ed510SSoby Mathew
17358fadd62SIgor Podgainõi	/*
17458fadd62SIgor Podgainõi	 * An equivalent helper function for storing x8 - x15
17558fadd62SIgor Podgainõi	 * registers in a different order inside the crash buf.
17658fadd62SIgor Podgainõi	 * In the end the function size_controlled_print_128 is
17758fadd62SIgor Podgainõi	 * called to print the registers to the console.
17858fadd62SIgor Podgainõi	 * Clobbers : x0 - x7, x20, sp
17958fadd62SIgor Podgainõi	 */
18058fadd62SIgor Podgainõifunc str_in_crash_buf_print_128
18158fadd62SIgor Podgainõi	/* restore the crash buf address in x0 */
18258fadd62SIgor Podgainõi	mrs	x0, tpidr_el3
18358fadd62SIgor Podgainõi	stp	x8, x9, [x0]
18458fadd62SIgor Podgainõi	stp	x10, x11, [x0, #REGSZ * 2]
18558fadd62SIgor Podgainõi	stp	x12, x13, [x0, #REGSZ * 4]
18658fadd62SIgor Podgainõi	stp	x14, x15, [x0, #REGSZ * 6]
18758fadd62SIgor Podgainõi	b	size_controlled_print_128
18858fadd62SIgor Podgainõiendfunc str_in_crash_buf_print_128
18958fadd62SIgor Podgainõi
190626ed510SSoby Mathew	/* ------------------------------------------------------
191626ed510SSoby Mathew	 * This macro calculates the offset to crash buf from
192626ed510SSoby Mathew	 * cpu_data and stores it in tpidr_el3. It also saves x0
193626ed510SSoby Mathew	 * and x1 in the crash buf by using sp as a temporary
194626ed510SSoby Mathew	 * register.
195626ed510SSoby Mathew	 * ------------------------------------------------------
196626ed510SSoby Mathew	 */
197626ed510SSoby Mathew	.macro prepare_crash_buf_save_x0_x1
198626ed510SSoby Mathew	/* we can corrupt this reg to free up x0 */
199626ed510SSoby Mathew	mov	sp, x0
200626ed510SSoby Mathew	/* tpidr_el3 contains the address to cpu_data structure */
201626ed510SSoby Mathew	mrs	x0, tpidr_el3
202626ed510SSoby Mathew	/* Calculate the Crash buffer offset in cpu_data */
203*4779becdSBoyan Karatotev	add	x0, x0, #CPU_DATA_CRASH_BUF
204626ed510SSoby Mathew	/* Store crash buffer address in tpidr_el3 */
205626ed510SSoby Mathew	msr	tpidr_el3, x0
206155a1006SJulius Werner	str	x1, [x0, #REGSZ]
207626ed510SSoby Mathew	mov	x1, sp
208626ed510SSoby Mathew	str	x1, [x0]
209626ed510SSoby Mathew	.endm
210a43d431bSSoby Mathew
211a43d431bSSoby Mathew	/* -----------------------------------------------------
212626ed510SSoby Mathew	 * This function allows to report a crash (if crash
213626ed510SSoby Mathew	 * reporting is enabled) when an unhandled exception
214626ed510SSoby Mathew	 * occurs. It prints the CPU state via the crash console
215626ed510SSoby Mathew	 * making use of the crash buf. This function will
216626ed510SSoby Mathew	 * not return.
217a43d431bSSoby Mathew	 * -----------------------------------------------------
218a43d431bSSoby Mathew	 */
219626ed510SSoby Mathewfunc report_unhandled_exception
220626ed510SSoby Mathew	prepare_crash_buf_save_x0_x1
221626ed510SSoby Mathew	adr	x0, excpt_msg
222626ed510SSoby Mathew	mov	sp, x0
223626ed510SSoby Mathew	/* This call will not return */
224626ed510SSoby Mathew	b	do_crash_reporting
2258b779620SKévin Petitendfunc report_unhandled_exception
226a43d431bSSoby Mathew
227626ed510SSoby Mathew	/* -----------------------------------------------------
228626ed510SSoby Mathew	 * This function allows to report a crash (if crash
229626ed510SSoby Mathew	 * reporting is enabled) when an unhandled interrupt
230626ed510SSoby Mathew	 * occurs. It prints the CPU state via the crash console
231626ed510SSoby Mathew	 * making use of the crash buf. This function will
232626ed510SSoby Mathew	 * not return.
233626ed510SSoby Mathew	 * -----------------------------------------------------
234626ed510SSoby Mathew	 */
235626ed510SSoby Mathewfunc report_unhandled_interrupt
236626ed510SSoby Mathew	prepare_crash_buf_save_x0_x1
237626ed510SSoby Mathew	adr	x0, intr_excpt_msg
238626ed510SSoby Mathew	mov	sp, x0
239626ed510SSoby Mathew	/* This call will not return */
240626ed510SSoby Mathew	b	do_crash_reporting
2418b779620SKévin Petitendfunc report_unhandled_interrupt
242a43d431bSSoby Mathew
243626ed510SSoby Mathew	/* -----------------------------------------------------
244b4292bc6SAlexei Fedorov	 * This function allows to report a crash from the lower
245b4292bc6SAlexei Fedorov	 * exception level (if crash reporting is enabled) when
2467e619eccSGovindraj Raja	 * lower_el_panic() is invoked from C Runtime.
247b4292bc6SAlexei Fedorov	 * It prints the CPU state via the crash console making
248b4292bc6SAlexei Fedorov	 * use of 'cpu_context' structure where general purpose
249b4292bc6SAlexei Fedorov	 * registers are saved and the crash buf.
250b4292bc6SAlexei Fedorov	 * This function will not return.
251b4292bc6SAlexei Fedorov	 * -----------------------------------------------------
252b4292bc6SAlexei Fedorov	 */
2537e619eccSGovindraj Rajafunc report_elx_panic
254b4292bc6SAlexei Fedorov	msr	spsel, #MODE_SP_ELX
255b4292bc6SAlexei Fedorov
256b4292bc6SAlexei Fedorov	/* Print the crash message */
257b4292bc6SAlexei Fedorov	adr	x4, excpt_msg_el
258b4292bc6SAlexei Fedorov	bl	asm_print_str
259b4292bc6SAlexei Fedorov
260b4292bc6SAlexei Fedorov	/* Report x0 - x29 values stored in 'gpregs_ctx' structure */
261b4292bc6SAlexei Fedorov	/* Store the ascii list pointer in x6 */
262b4292bc6SAlexei Fedorov	adr	x6, gp_regs
263b4292bc6SAlexei Fedorov	add	x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0
264b4292bc6SAlexei Fedorov
265b4292bc6SAlexei Fedorovprint_next:
266b4292bc6SAlexei Fedorov	ldrb	w4, [x6]
267b4292bc6SAlexei Fedorov	/* Test whether we are at end of list */
268b4292bc6SAlexei Fedorov	cbz	w4, print_x30
269b4292bc6SAlexei Fedorov	mov	x4, x6
270b4292bc6SAlexei Fedorov	/* asm_print_str updates x4 to point to next entry in list */
271b4292bc6SAlexei Fedorov	bl	asm_print_str
272b4292bc6SAlexei Fedorov	/* x0 = number of symbols printed + 1 */
273b4292bc6SAlexei Fedorov	sub	x0, x4, x6
274b4292bc6SAlexei Fedorov	/* Update x6 with the updated list pointer */
275b4292bc6SAlexei Fedorov	mov	x6, x4
276b4292bc6SAlexei Fedorov	bl	print_alignment
277b4292bc6SAlexei Fedorov	ldr	x4, [x7], #REGSZ
278b4292bc6SAlexei Fedorov	bl	asm_print_hex
279b4292bc6SAlexei Fedorov	bl	asm_print_newline
280b4292bc6SAlexei Fedorov	b	print_next
281b4292bc6SAlexei Fedorov
282b4292bc6SAlexei Fedorovprint_x30:
283b4292bc6SAlexei Fedorov	adr	x4, x30_msg
284b4292bc6SAlexei Fedorov	bl	asm_print_str
285b4292bc6SAlexei Fedorov
286b4292bc6SAlexei Fedorov	/* Print spaces to align "x30" string */
287b4292bc6SAlexei Fedorov	mov	x0, #4
288b4292bc6SAlexei Fedorov	bl	print_alignment
289b4292bc6SAlexei Fedorov
290b4292bc6SAlexei Fedorov	/* Report x30 */
291b4292bc6SAlexei Fedorov	ldr	x4, [x7]
292b4292bc6SAlexei Fedorov
293b4292bc6SAlexei Fedorov	/* ----------------------------------------------------------------
294b4292bc6SAlexei Fedorov	 * Different virtual address space size can be defined for each EL.
295b4292bc6SAlexei Fedorov	 * Ensure that we use the proper one by reading the corresponding
296b4292bc6SAlexei Fedorov	 * TCR_ELx register.
297b4292bc6SAlexei Fedorov	 * ----------------------------------------------------------------
298b4292bc6SAlexei Fedorov	 */
299b4292bc6SAlexei Fedorov	cmp	x8, #MODE_EL2
300b4292bc6SAlexei Fedorov	b.lt	from_el1	/* EL1 */
301b4292bc6SAlexei Fedorov	mrs	x2, sctlr_el2
302b4292bc6SAlexei Fedorov	mrs	x1, tcr_el2
303b4292bc6SAlexei Fedorov
304b4292bc6SAlexei Fedorov	/* ----------------------------------------------------------------
305b4292bc6SAlexei Fedorov	 * Check if pointer authentication is enabled at the specified EL.
306b4292bc6SAlexei Fedorov	 * If it isn't, we can then skip stripping a PAC code.
307b4292bc6SAlexei Fedorov	 * ----------------------------------------------------------------
308b4292bc6SAlexei Fedorov	 */
309b4292bc6SAlexei Fedorovtest_pauth:
310b4292bc6SAlexei Fedorov	tst	x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT)
311b4292bc6SAlexei Fedorov	b.eq	no_pauth
312b4292bc6SAlexei Fedorov
313b4292bc6SAlexei Fedorov	/* Demangle address */
314b4292bc6SAlexei Fedorov	and	x1, x1, #0x3F	/* T0SZ = TCR_ELx[5:0] */
315b4292bc6SAlexei Fedorov	sub	x1, x1, #64
316b4292bc6SAlexei Fedorov	neg	x1, x1		/* bottom_pac_bit = 64 - T0SZ */
317b4292bc6SAlexei Fedorov	mov	x2, #-1
318b4292bc6SAlexei Fedorov	lsl	x2, x2, x1
319b4292bc6SAlexei Fedorov	bic	x4, x4, x2
320b4292bc6SAlexei Fedorov
321b4292bc6SAlexei Fedorovno_pauth:
322b4292bc6SAlexei Fedorov	bl	asm_print_hex
323b4292bc6SAlexei Fedorov	bl	asm_print_newline
324b4292bc6SAlexei Fedorov
325b4292bc6SAlexei Fedorov	/* tpidr_el3 contains the address to cpu_data structure */
326b4292bc6SAlexei Fedorov	mrs	x0, tpidr_el3
327b4292bc6SAlexei Fedorov	/* Calculate the Crash buffer offset in cpu_data */
328*4779becdSBoyan Karatotev	add	x0, x0, #CPU_DATA_CRASH_BUF
329b4292bc6SAlexei Fedorov	/* Store crash buffer address in tpidr_el3 */
330b4292bc6SAlexei Fedorov	msr	tpidr_el3, x0
331b4292bc6SAlexei Fedorov
332b4292bc6SAlexei Fedorov	/* Print the rest of crash dump */
333b4292bc6SAlexei Fedorov	b	print_el3_sys_regs
334b4292bc6SAlexei Fedorov
335b4292bc6SAlexei Fedorovfrom_el1:
336b4292bc6SAlexei Fedorov	mrs	x2, sctlr_el1
337b4292bc6SAlexei Fedorov	mrs	x1, tcr_el1
338b4292bc6SAlexei Fedorov	b	test_pauth
3397e619eccSGovindraj Rajaendfunc	report_elx_panic
340b4292bc6SAlexei Fedorov
341b4292bc6SAlexei Fedorov	/* -----------------------------------------------------
342626ed510SSoby Mathew	 * This function allows to report a crash (if crash
343626ed510SSoby Mathew	 * reporting is enabled) when panic() is invoked from
344626ed510SSoby Mathew	 * C Runtime. It prints the CPU state via the crash
345626ed510SSoby Mathew	 * console making use of the crash buf. This function
346626ed510SSoby Mathew	 * will not return.
347626ed510SSoby Mathew	 * -----------------------------------------------------
348626ed510SSoby Mathew	 */
349f300ef66SGovindraj Rajafunc report_el3_panic
3506c6a470fSAlexei Fedorov	msr	spsel, #MODE_SP_ELX
351626ed510SSoby Mathew	prepare_crash_buf_save_x0_x1
352626ed510SSoby Mathew	adr	x0, panic_msg
353626ed510SSoby Mathew	mov	sp, x0
354b4292bc6SAlexei Fedorov	/* Fall through to 'do_crash_reporting' */
355a43d431bSSoby Mathew
356626ed510SSoby Mathew	/* ------------------------------------------------------------
357626ed510SSoby Mathew	 * The common crash reporting functionality. It requires x0
358626ed510SSoby Mathew	 * and x1 has already been stored in crash buf, sp points to
359626ed510SSoby Mathew	 * crash message and tpidr_el3 contains the crash buf address.
360626ed510SSoby Mathew	 * The function does the following:
361626ed510SSoby Mathew	 *   - Retrieve the crash buffer from tpidr_el3
362626ed510SSoby Mathew	 *   - Store x2 to x6 in the crash buffer
363626ed510SSoby Mathew	 *   - Initialise the crash console.
364626ed510SSoby Mathew	 *   - Print the crash message by using the address in sp.
365626ed510SSoby Mathew	 *   - Print x30 value to the crash console.
366626ed510SSoby Mathew	 *   - Print x0 - x7 from the crash buf to the crash console.
367626ed510SSoby Mathew	 *   - Print x8 - x29 (in groups of 8 registers) using the
368626ed510SSoby Mathew	 *     crash buf to the crash console.
369626ed510SSoby Mathew	 *   - Print el3 sys regs (in groups of 8 registers) using the
370626ed510SSoby Mathew	 *     crash buf to the crash console.
371626ed510SSoby Mathew	 *   - Print non el3 sys regs (in groups of 8 registers) using
37258fadd62SIgor Podgainõi	 *     the crash buf to the crash console. A group may be
37358fadd62SIgor Podgainõi	 *     interrupted in case a potential group of 128-bit
37458fadd62SIgor Podgainõi	 *     sys regs needs to be printed.
375626ed510SSoby Mathew	 * ------------------------------------------------------------
376626ed510SSoby Mathew	 */
377b4292bc6SAlexei Fedorovdo_crash_reporting:
378626ed510SSoby Mathew	/* Retrieve the crash buf from tpidr_el3 */
379626ed510SSoby Mathew	mrs	x0, tpidr_el3
380626ed510SSoby Mathew	/* Store x2 - x6, x30 in the crash buffer */
381155a1006SJulius Werner	stp	x2, x3, [x0, #REGSZ * 2]
382155a1006SJulius Werner	stp	x4, x5, [x0, #REGSZ * 4]
383155a1006SJulius Werner	stp	x6, x30, [x0, #REGSZ * 6]
384626ed510SSoby Mathew	/* Initialize the crash console */
385626ed510SSoby Mathew	bl	plat_crash_console_init
386626ed510SSoby Mathew	/* Verify the console is initialized */
387626ed510SSoby Mathew	cbz	x0, crash_panic
388626ed510SSoby Mathew	/* Print the crash message. sp points to the crash message */
389626ed510SSoby Mathew	mov	x4, sp
390626ed510SSoby Mathew	bl	asm_print_str
3916c6a470fSAlexei Fedorov	/* Print spaces to align "x30" string */
3926c6a470fSAlexei Fedorov	mov	x0, #4
3936c6a470fSAlexei Fedorov	bl	print_alignment
394b4292bc6SAlexei Fedorov	/* Load the crash buf address */
395626ed510SSoby Mathew	mrs	x0, tpidr_el3
396b4292bc6SAlexei Fedorov	/* Report x30 first from the crash buf */
397155a1006SJulius Werner	ldr	x4, [x0, #REGSZ * 7]
39868c76088SAlexei Fedorov
39968c76088SAlexei Fedorov#if ENABLE_PAUTH
4008d9f5f25SBoyan Karatotev#if ENABLE_PAUTH == 2
4018d9f5f25SBoyan Karatotev	/* Skip if not present in hardware */
4028d9f5f25SBoyan Karatotev	is_feat_pauth_present_asm x0, x1
4038d9f5f25SBoyan Karatotev	beq	1f
4048d9f5f25SBoyan Karatotev#endif
4058d9f5f25SBoyan Karatotev	/*
4068d9f5f25SBoyan Karatotev	 * The assembler must see support for xpaci. So turn the compiler
4078d9f5f25SBoyan Karatotev	 * extension on. GCC prior to 10 doesn't understand the PAuth extension
4088d9f5f25SBoyan Karatotev	 * but it does understand armv8.3-a in general. Avoid using 8.3 if
4098d9f5f25SBoyan Karatotev	 * the compiler understands "pauth" so we don't downgrade a higher
4108d9f5f25SBoyan Karatotev	 * -march that was specified on the commandline.
4118d9f5f25SBoyan Karatotev	 */
4128d9f5f25SBoyan Karatotev#if __GNUC__ < 10
4138d9f5f25SBoyan Karatotev	.arch armv8.3-a
4148d9f5f25SBoyan Karatotev#else
4158d9f5f25SBoyan Karatotev	.arch_extension pauth
4168d9f5f25SBoyan Karatotev#endif
41768c76088SAlexei Fedorov	/* Demangle address */
41868c76088SAlexei Fedorov	xpaci	x4
4198d9f5f25SBoyan Karatotev1:
42068c76088SAlexei Fedorov#endif
421626ed510SSoby Mathew	bl	asm_print_hex
42253d7e003SJustin Chadwell	bl	asm_print_newline
423626ed510SSoby Mathew	/* Load the crash buf address */
424626ed510SSoby Mathew	mrs	x0, tpidr_el3
425626ed510SSoby Mathew	/* Now mov x7 into crash buf */
426155a1006SJulius Werner	str	x7, [x0, #REGSZ * 7]
427a43d431bSSoby Mathew
428626ed510SSoby Mathew	/* Report x0 - x29 values stored in crash buf */
429626ed510SSoby Mathew	/* Store the ascii list pointer in x6 */
430626ed510SSoby Mathew	adr	x6, gp_regs
431626ed510SSoby Mathew	/* Print x0 to x7 from the crash buf */
432626ed510SSoby Mathew	bl	size_controlled_print
433626ed510SSoby Mathew	/* Store x8 - x15 in crash buf and print */
434626ed510SSoby Mathew	bl	str_in_crash_buf_print
435626ed510SSoby Mathew	/* Load the crash buf address */
436626ed510SSoby Mathew	mrs	x0, tpidr_el3
437626ed510SSoby Mathew	/* Store the rest of gp regs and print */
438626ed510SSoby Mathew	stp	x16, x17, [x0]
439155a1006SJulius Werner	stp	x18, x19, [x0, #REGSZ * 2]
440155a1006SJulius Werner	stp	x20, x21, [x0, #REGSZ * 4]
441155a1006SJulius Werner	stp	x22, x23, [x0, #REGSZ * 6]
442626ed510SSoby Mathew	bl	size_controlled_print
443626ed510SSoby Mathew	/* Load the crash buf address */
444626ed510SSoby Mathew	mrs	x0, tpidr_el3
445626ed510SSoby Mathew	stp	x24, x25, [x0]
446155a1006SJulius Werner	stp	x26, x27, [x0, #REGSZ * 2]
447155a1006SJulius Werner	stp	x28, x29, [x0, #REGSZ * 4]
448626ed510SSoby Mathew	bl	size_controlled_print
449a43d431bSSoby Mathew
450626ed510SSoby Mathew	/* Print the el3 sys registers */
451b4292bc6SAlexei Fedorovprint_el3_sys_regs:
452626ed510SSoby Mathew	adr	x6, el3_sys_regs
453626ed510SSoby Mathew	mrs	x8, scr_el3
454626ed510SSoby Mathew	mrs	x9, sctlr_el3
455626ed510SSoby Mathew	mrs	x10, cptr_el3
456626ed510SSoby Mathew	mrs	x11, tcr_el3
457626ed510SSoby Mathew	mrs	x12, daif
458626ed510SSoby Mathew	mrs	x13, mair_el3
459626ed510SSoby Mathew	mrs	x14, spsr_el3
460626ed510SSoby Mathew	mrs	x15, elr_el3
461626ed510SSoby Mathew	bl	str_in_crash_buf_print
462626ed510SSoby Mathew	mrs	x8, ttbr0_el3
463626ed510SSoby Mathew	mrs	x9, esr_el3
464626ed510SSoby Mathew	mrs	x10, far_el3
465626ed510SSoby Mathew	bl	str_in_crash_buf_print
466a43d431bSSoby Mathew
467626ed510SSoby Mathew	/* Print the non el3 sys registers */
46858fadd62SIgor Podgainõi	adr	x6, non_el3_sys_regs_1
469626ed510SSoby Mathew	mrs	x8, spsr_el1
470626ed510SSoby Mathew	mrs	x9, elr_el1
471626ed510SSoby Mathew	mrs	x10, spsr_abt
472626ed510SSoby Mathew	mrs	x11, spsr_und
473626ed510SSoby Mathew	mrs	x12, spsr_irq
474626ed510SSoby Mathew	mrs	x13, spsr_fiq
475626ed510SSoby Mathew	mrs	x14, sctlr_el1
476626ed510SSoby Mathew	mrs	x15, actlr_el1
477626ed510SSoby Mathew	bl	str_in_crash_buf_print
478626ed510SSoby Mathew	mrs	x8, cpacr_el1
479626ed510SSoby Mathew	mrs	x9, csselr_el1
480a43d431bSSoby Mathew	mrs	x10, sp_el1
481a43d431bSSoby Mathew	mrs	x11, esr_el1
482626ed510SSoby Mathew	bl	str_in_crash_buf_print
48358fadd62SIgor Podgainõi
48458fadd62SIgor Podgainõi	adr	x6, ttbr_regs
48558fadd62SIgor Podgainõi#if ENABLE_FEAT_D128
48658fadd62SIgor Podgainõi	is_feat_sysreg128_present_asm	x19
48758fadd62SIgor Podgainõi	/* Fallback to 64-bit if FEAT_SYSREG128 is disabled */
48858fadd62SIgor Podgainõi	cbz	x19, ttbr_regs_64_bit
48958fadd62SIgor Podgainõi	bl	read_ttbr0_el1
49058fadd62SIgor Podgainõi	mov	x8, x1
49158fadd62SIgor Podgainõi	mov	x9, x0
49258fadd62SIgor Podgainõi	bl	read_ttbr0_el2
49358fadd62SIgor Podgainõi	mov	x10, x1
49458fadd62SIgor Podgainõi	mov	x11, x0
49558fadd62SIgor Podgainõi	bl	read_ttbr1_el1
49658fadd62SIgor Podgainõi	mov	x12, x1
49758fadd62SIgor Podgainõi	mov	x13, x0
49858fadd62SIgor Podgainõi	bl	read_vttbr_el2
49958fadd62SIgor Podgainõi	mov	x14, x1
50058fadd62SIgor Podgainõi	mov	x15, x0
50158fadd62SIgor Podgainõi	bl	str_in_crash_buf_print_128
50258fadd62SIgor Podgainõi	b	1f
50358fadd62SIgor Podgainõi
50458fadd62SIgor Podgainõittbr_regs_64_bit:
50558fadd62SIgor Podgainõi#endif
50658fadd62SIgor Podgainõi	mrs	x8, ttbr0_el1
50758fadd62SIgor Podgainõi	mrs	x9, ttbr0_el2
50858fadd62SIgor Podgainõi	mrs	x10, ttbr1_el1
50958fadd62SIgor Podgainõi	mrs	x11, vttbr_el2
510626ed510SSoby Mathew	bl	str_in_crash_buf_print
51158fadd62SIgor Podgainõi1:
51258fadd62SIgor Podgainõi	adr	x6, non_el3_sys_regs_2
51358fadd62SIgor Podgainõi	mrs	x8, mair_el1
51458fadd62SIgor Podgainõi	mrs	x9, amair_el1
51558fadd62SIgor Podgainõi	mrs	x10, tcr_el1
51658fadd62SIgor Podgainõi	mrs	x11, tpidr_el1
51758fadd62SIgor Podgainõi	mrs	x12, tpidr_el0
51858fadd62SIgor Podgainõi	mrs	x13, tpidrro_el0
519626ed510SSoby Mathew	bl	str_in_crash_buf_print
52058fadd62SIgor Podgainõi
52158fadd62SIgor Podgainõi	adr	x6, par_reg
52258fadd62SIgor Podgainõi#if ENABLE_FEAT_D128
52358fadd62SIgor Podgainõi	/* Fallback to 64-bit if FEAT_SYSREG128 is disabled */
52458fadd62SIgor Podgainõi	cbz	x19, par_reg_64_bit
52558fadd62SIgor Podgainõi	bl	read_par_el1
52658fadd62SIgor Podgainõi	mov	x8, x1
52758fadd62SIgor Podgainõi	mov	x9, x0
52858fadd62SIgor Podgainõi	bl	str_in_crash_buf_print_128
52958fadd62SIgor Podgainõi	b	2f
53058fadd62SIgor Podgainõi
53158fadd62SIgor Podgainõipar_reg_64_bit:
53258fadd62SIgor Podgainõi#endif
53358fadd62SIgor Podgainõi	mrs	x8, par_el1
53458fadd62SIgor Podgainõi	bl	str_in_crash_buf_print
53558fadd62SIgor Podgainõi2:
53658fadd62SIgor Podgainõi	adr	x6, non_el3_sys_regs_3
53758fadd62SIgor Podgainõi	mrs	x8, mpidr_el1
53858fadd62SIgor Podgainõi	mrs	x9, afsr0_el1
53958fadd62SIgor Podgainõi	mrs	x10, afsr1_el1
54058fadd62SIgor Podgainõi	mrs	x11, contextidr_el1
54158fadd62SIgor Podgainõi	mrs	x12, vbar_el1
54258fadd62SIgor Podgainõi	mrs	x13, cntp_ctl_el0
54358fadd62SIgor Podgainõi	mrs	x14, cntp_cval_el0
54458fadd62SIgor Podgainõi	mrs	x15, cntv_ctl_el0
54558fadd62SIgor Podgainõi	bl	str_in_crash_buf_print
54658fadd62SIgor Podgainõi	mrs	x8, cntv_cval_el0
54758fadd62SIgor Podgainõi	mrs	x9, cntkctl_el1
54858fadd62SIgor Podgainõi	mrs	x10, sp_el0
54958fadd62SIgor Podgainõi	mrs	x11, isr_el1
550626ed510SSoby Mathew	bl	str_in_crash_buf_print
551a43d431bSSoby Mathew
552c424b91eSImre Kis#if CTX_INCLUDE_AARCH32_REGS
553c424b91eSImre Kis	/* Print the AArch32 registers */
554c424b91eSImre Kis	adr	x6, aarch32_regs
555c424b91eSImre Kis	mrs	x8, dacr32_el2
556c424b91eSImre Kis	mrs	x9, ifsr32_el2
557c424b91eSImre Kis	bl	str_in_crash_buf_print
558c424b91eSImre Kis#endif /* CTX_INCLUDE_AARCH32_REGS */
559c424b91eSImre Kis
560d3f70af6SSoby Mathew	/* Get the cpu specific registers to report */
561d3f70af6SSoby Mathew	bl	do_cpu_reg_dump
562d3f70af6SSoby Mathew	bl	str_in_crash_buf_print
5638c106902SSoby Mathew
5649ff67fa6SGerald Lejeune	/* Print some platform registers */
5659ff67fa6SGerald Lejeune	plat_crash_print_regs
5668c106902SSoby Mathew
567801cf93cSAntonio Nino Diaz	bl	plat_crash_console_flush
568801cf93cSAntonio Nino Diaz
569626ed510SSoby Mathew	/* Done reporting */
570a806dad5SJeenu Viswambharan	no_ret	plat_panic_handler
571f300ef66SGovindraj Rajaendfunc report_el3_panic
572a43d431bSSoby Mathew
573626ed510SSoby Mathew#else	/* CRASH_REPORTING */
574626ed510SSoby Mathewfunc report_unhandled_exception
575626ed510SSoby Mathewreport_unhandled_interrupt:
576a806dad5SJeenu Viswambharan	no_ret	plat_panic_handler
5778b779620SKévin Petitendfunc report_unhandled_exception
5781645d3eeSSandrine Bailleux#endif	/* CRASH_REPORTING */
5799c22b323SAndrew Thoelke
580626ed510SSoby Mathewfunc crash_panic
581a806dad5SJeenu Viswambharan	no_ret	plat_panic_handler
5828b779620SKévin Petitendfunc crash_panic
583