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