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