xref: /aosp_15_r20/external/arm-trusted-firmware/common/aarch64/debug.S (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park/*
2*54fd6939SJiyong Park * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park#include <arch.h>
8*54fd6939SJiyong Park#include <asm_macros.S>
9*54fd6939SJiyong Park#include <common/debug.h>
10*54fd6939SJiyong Park
11*54fd6939SJiyong Park	.globl	asm_print_str
12*54fd6939SJiyong Park	.globl	asm_print_hex
13*54fd6939SJiyong Park	.globl	asm_print_hex_bits
14*54fd6939SJiyong Park	.globl	asm_print_newline
15*54fd6939SJiyong Park	.globl	asm_assert
16*54fd6939SJiyong Park	.globl	do_panic
17*54fd6939SJiyong Park
18*54fd6939SJiyong Park/* Since the max decimal input number is 65536 */
19*54fd6939SJiyong Park#define MAX_DEC_DIVISOR		10000
20*54fd6939SJiyong Park/* The offset to add to get ascii for numerals '0 - 9' */
21*54fd6939SJiyong Park#define ASCII_OFFSET_NUM	0x30
22*54fd6939SJiyong Park
23*54fd6939SJiyong Park#if ENABLE_ASSERTIONS
24*54fd6939SJiyong Park.section .rodata.assert_str, "aS"
25*54fd6939SJiyong Parkassert_msg1:
26*54fd6939SJiyong Park	.asciz "ASSERT: File "
27*54fd6939SJiyong Parkassert_msg2:
28*54fd6939SJiyong Park	.asciz " Line "
29*54fd6939SJiyong Park
30*54fd6939SJiyong Park	/*
31*54fd6939SJiyong Park	 * This macro is intended to be used to print the
32*54fd6939SJiyong Park	 * line number in decimal. Used by asm_assert macro.
33*54fd6939SJiyong Park	 * The max number expected is 65536.
34*54fd6939SJiyong Park	 * In: x4 = the decimal to print.
35*54fd6939SJiyong Park	 * Clobber: x30, x0, x1, x2, x5, x6
36*54fd6939SJiyong Park	 */
37*54fd6939SJiyong Park	.macro asm_print_line_dec
38*54fd6939SJiyong Park	mov	x6, #10		/* Divide by 10 after every loop iteration */
39*54fd6939SJiyong Park	mov	x5, #MAX_DEC_DIVISOR
40*54fd6939SJiyong Parkdec_print_loop:
41*54fd6939SJiyong Park	udiv	x0, x4, x5			/* Get the quotient */
42*54fd6939SJiyong Park	msub	x4, x0, x5, x4			/* Find the remainder */
43*54fd6939SJiyong Park	add	x0, x0, #ASCII_OFFSET_NUM	/* Convert to ascii */
44*54fd6939SJiyong Park	bl	plat_crash_console_putc
45*54fd6939SJiyong Park	udiv	x5, x5, x6			/* Reduce divisor */
46*54fd6939SJiyong Park	cbnz	x5, dec_print_loop
47*54fd6939SJiyong Park	.endm
48*54fd6939SJiyong Park
49*54fd6939SJiyong Park
50*54fd6939SJiyong Park/* ---------------------------------------------------------------------------
51*54fd6939SJiyong Park * Assertion support in assembly.
52*54fd6939SJiyong Park * The below function helps to support assertions in assembly where we do not
53*54fd6939SJiyong Park * have a C runtime stack. Arguments to the function are :
54*54fd6939SJiyong Park * x0 - File name
55*54fd6939SJiyong Park * x1 - Line no
56*54fd6939SJiyong Park * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6.
57*54fd6939SJiyong Park * ---------------------------------------------------------------------------
58*54fd6939SJiyong Park */
59*54fd6939SJiyong Parkfunc asm_assert
60*54fd6939SJiyong Park#if LOG_LEVEL >= LOG_LEVEL_INFO
61*54fd6939SJiyong Park	/*
62*54fd6939SJiyong Park	 * Only print the output if LOG_LEVEL is higher or equal to
63*54fd6939SJiyong Park	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
64*54fd6939SJiyong Park	 */
65*54fd6939SJiyong Park	mov	x5, x0
66*54fd6939SJiyong Park	mov	x6, x1
67*54fd6939SJiyong Park
68*54fd6939SJiyong Park	/* Ensure the console is initialized */
69*54fd6939SJiyong Park	bl	plat_crash_console_init
70*54fd6939SJiyong Park
71*54fd6939SJiyong Park	/* Check if the console is initialized */
72*54fd6939SJiyong Park	cbz	x0, _assert_loop
73*54fd6939SJiyong Park
74*54fd6939SJiyong Park	/* The console is initialized */
75*54fd6939SJiyong Park	adr	x4, assert_msg1
76*54fd6939SJiyong Park	bl	asm_print_str
77*54fd6939SJiyong Park	mov	x4, x5
78*54fd6939SJiyong Park	bl	asm_print_str
79*54fd6939SJiyong Park	adr	x4, assert_msg2
80*54fd6939SJiyong Park	bl	asm_print_str
81*54fd6939SJiyong Park
82*54fd6939SJiyong Park	/* Check if line number higher than max permitted */
83*54fd6939SJiyong Park	tst	x6, #~0xffff
84*54fd6939SJiyong Park	b.ne	_assert_loop
85*54fd6939SJiyong Park	mov	x4, x6
86*54fd6939SJiyong Park	asm_print_line_dec
87*54fd6939SJiyong Park	bl	plat_crash_console_flush
88*54fd6939SJiyong Park_assert_loop:
89*54fd6939SJiyong Park#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
90*54fd6939SJiyong Park	no_ret	plat_panic_handler
91*54fd6939SJiyong Parkendfunc asm_assert
92*54fd6939SJiyong Park#endif /* ENABLE_ASSERTIONS */
93*54fd6939SJiyong Park
94*54fd6939SJiyong Park/*
95*54fd6939SJiyong Park * This function prints a string from address in x4.
96*54fd6939SJiyong Park * In: x4 = pointer to string.
97*54fd6939SJiyong Park * Clobber: x30, x0, x1, x2, x3
98*54fd6939SJiyong Park */
99*54fd6939SJiyong Parkfunc asm_print_str
100*54fd6939SJiyong Park	mov	x3, x30
101*54fd6939SJiyong Park1:
102*54fd6939SJiyong Park	ldrb	w0, [x4], #0x1
103*54fd6939SJiyong Park	cbz	x0, 2f
104*54fd6939SJiyong Park	bl	plat_crash_console_putc
105*54fd6939SJiyong Park	b	1b
106*54fd6939SJiyong Park2:
107*54fd6939SJiyong Park	ret	x3
108*54fd6939SJiyong Parkendfunc asm_print_str
109*54fd6939SJiyong Park
110*54fd6939SJiyong Park/*
111*54fd6939SJiyong Park * This function prints a hexadecimal number in x4.
112*54fd6939SJiyong Park * In: x4 = the hexadecimal to print.
113*54fd6939SJiyong Park * Clobber: x30, x0 - x3, x5
114*54fd6939SJiyong Park */
115*54fd6939SJiyong Parkfunc asm_print_hex
116*54fd6939SJiyong Park	mov	x5, #64  /* No of bits to convert to ascii */
117*54fd6939SJiyong Park
118*54fd6939SJiyong Park	/* Convert to ascii number of bits in x5 */
119*54fd6939SJiyong Parkasm_print_hex_bits:
120*54fd6939SJiyong Park	mov	x3, x30
121*54fd6939SJiyong Park1:
122*54fd6939SJiyong Park	sub	x5, x5, #4
123*54fd6939SJiyong Park	lsrv	x0, x4, x5
124*54fd6939SJiyong Park	and	x0, x0, #0xf
125*54fd6939SJiyong Park	cmp	x0, #0xA
126*54fd6939SJiyong Park	b.lo	2f
127*54fd6939SJiyong Park	/* Add by 0x27 in addition to ASCII_OFFSET_NUM
128*54fd6939SJiyong Park	 * to get ascii for characters 'a - f'.
129*54fd6939SJiyong Park	 */
130*54fd6939SJiyong Park	add	x0, x0, #0x27
131*54fd6939SJiyong Park2:
132*54fd6939SJiyong Park	add	x0, x0, #ASCII_OFFSET_NUM
133*54fd6939SJiyong Park	bl	plat_crash_console_putc
134*54fd6939SJiyong Park	cbnz	x5, 1b
135*54fd6939SJiyong Park	ret	x3
136*54fd6939SJiyong Parkendfunc asm_print_hex
137*54fd6939SJiyong Park
138*54fd6939SJiyong Park/*
139*54fd6939SJiyong Park * Helper function to print newline to console
140*54fd6939SJiyong Park * Clobber: x0
141*54fd6939SJiyong Park */
142*54fd6939SJiyong Parkfunc asm_print_newline
143*54fd6939SJiyong Park	mov	x0, '\n'
144*54fd6939SJiyong Park	b	plat_crash_console_putc
145*54fd6939SJiyong Parkendfunc asm_print_newline
146*54fd6939SJiyong Park
147*54fd6939SJiyong Park	/***********************************************************
148*54fd6939SJiyong Park	 * The common implementation of do_panic for all BL stages
149*54fd6939SJiyong Park	 ***********************************************************/
150*54fd6939SJiyong Park
151*54fd6939SJiyong Park.section .rodata.panic_str, "aS"
152*54fd6939SJiyong Park	panic_msg: .asciz "PANIC at PC : 0x"
153*54fd6939SJiyong Park
154*54fd6939SJiyong Park/* ---------------------------------------------------------------------------
155*54fd6939SJiyong Park * do_panic assumes that it is invoked from a C Runtime Environment ie a
156*54fd6939SJiyong Park * valid stack exists. This call will not return.
157*54fd6939SJiyong Park * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6
158*54fd6939SJiyong Park * ---------------------------------------------------------------------------
159*54fd6939SJiyong Park */
160*54fd6939SJiyong Park
161*54fd6939SJiyong Park/* This is for the non el3 BL stages to compile through */
162*54fd6939SJiyong Park	.weak el3_panic
163*54fd6939SJiyong Park	.weak elx_panic
164*54fd6939SJiyong Park
165*54fd6939SJiyong Parkfunc do_panic
166*54fd6939SJiyong Park#if CRASH_REPORTING
167*54fd6939SJiyong Park	str	x0, [sp, #-0x10]!
168*54fd6939SJiyong Park	mrs	x0, currentel
169*54fd6939SJiyong Park	ubfx	x0, x0, #MODE_EL_SHIFT, #MODE_EL_WIDTH
170*54fd6939SJiyong Park	cmp	x0, #MODE_EL3
171*54fd6939SJiyong Park#if !HANDLE_EA_EL3_FIRST
172*54fd6939SJiyong Park	ldr	x0, [sp], #0x10
173*54fd6939SJiyong Park	b.eq	el3_panic
174*54fd6939SJiyong Park#else
175*54fd6939SJiyong Park	b.ne	to_panic_common
176*54fd6939SJiyong Park
177*54fd6939SJiyong Park	/* Check EL the exception taken from */
178*54fd6939SJiyong Park	mrs	x0, spsr_el3
179*54fd6939SJiyong Park	ubfx	x0, x0, #SPSR_EL_SHIFT, #SPSR_EL_WIDTH
180*54fd6939SJiyong Park	cmp	x0, #MODE_EL3
181*54fd6939SJiyong Park	b.ne	elx_panic
182*54fd6939SJiyong Park	ldr	x0, [sp], #0x10
183*54fd6939SJiyong Park	b	el3_panic
184*54fd6939SJiyong Park
185*54fd6939SJiyong Parkto_panic_common:
186*54fd6939SJiyong Park	ldr	x0, [sp], #0x10
187*54fd6939SJiyong Park#endif /* HANDLE_EA_EL3_FIRST */
188*54fd6939SJiyong Park#endif /* CRASH_REPORTING */
189*54fd6939SJiyong Park
190*54fd6939SJiyong Parkpanic_common:
191*54fd6939SJiyong Park/*
192*54fd6939SJiyong Park * el3_panic will be redefined by the BL31
193*54fd6939SJiyong Park * crash reporting mechanism (if enabled)
194*54fd6939SJiyong Park */
195*54fd6939SJiyong Parkel3_panic:
196*54fd6939SJiyong Park	mov	x6, x30
197*54fd6939SJiyong Park	bl	plat_crash_console_init
198*54fd6939SJiyong Park
199*54fd6939SJiyong Park	/* Check if the console is initialized */
200*54fd6939SJiyong Park	cbz	x0, _panic_handler
201*54fd6939SJiyong Park
202*54fd6939SJiyong Park	/* The console is initialized */
203*54fd6939SJiyong Park	adr	x4, panic_msg
204*54fd6939SJiyong Park	bl	asm_print_str
205*54fd6939SJiyong Park	mov	x4, x6
206*54fd6939SJiyong Park
207*54fd6939SJiyong Park	/* The panic location is lr -4 */
208*54fd6939SJiyong Park	sub	x4, x4, #4
209*54fd6939SJiyong Park	bl	asm_print_hex
210*54fd6939SJiyong Park
211*54fd6939SJiyong Park	/* Print new line */
212*54fd6939SJiyong Park	bl	asm_print_newline
213*54fd6939SJiyong Park
214*54fd6939SJiyong Park	bl	plat_crash_console_flush
215*54fd6939SJiyong Park
216*54fd6939SJiyong Park_panic_handler:
217*54fd6939SJiyong Park	/* Pass to plat_panic_handler the address from where el3_panic was
218*54fd6939SJiyong Park	 * called, not the address of the call from el3_panic. */
219*54fd6939SJiyong Park	mov	x30, x6
220*54fd6939SJiyong Park	b	plat_panic_handler
221*54fd6939SJiyong Parkendfunc do_panic
222