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