xref: /arm-trusted-firmware/common/aarch32/debug.S (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu/*
2*91f16700Schasinglulu * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu *
4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu */
6*91f16700Schasinglulu
7*91f16700Schasinglulu#include <arch.h>
8*91f16700Schasinglulu#include <asm_macros.S>
9*91f16700Schasinglulu#include <common/debug.h>
10*91f16700Schasinglulu
11*91f16700Schasinglulu	.globl	asm_print_str
12*91f16700Schasinglulu	.globl	asm_print_hex
13*91f16700Schasinglulu	.globl	asm_print_hex_bits
14*91f16700Schasinglulu	.globl	asm_assert
15*91f16700Schasinglulu	.globl	el3_panic
16*91f16700Schasinglulu	.globl	report_exception
17*91f16700Schasinglulu	.globl	report_prefetch_abort
18*91f16700Schasinglulu	.globl	report_data_abort
19*91f16700Schasinglulu
20*91f16700Schasinglulu/* Since the max decimal input number is 65536 */
21*91f16700Schasinglulu#define MAX_DEC_DIVISOR		10000
22*91f16700Schasinglulu/* The offset to add to get ascii for numerals '0 - 9' */
23*91f16700Schasinglulu#define ASCII_OFFSET_NUM	'0'
24*91f16700Schasinglulu
25*91f16700Schasinglulu#if ENABLE_ASSERTIONS
26*91f16700Schasinglulu.section .rodata.assert_str, "aS"
27*91f16700Schasingluluassert_msg1:
28*91f16700Schasinglulu	.asciz "ASSERT: File "
29*91f16700Schasingluluassert_msg2:
30*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
31*91f16700Schasinglulu	/******************************************************************
32*91f16700Schasinglulu	 * Virtualization comes with the UDIV/SDIV instructions. If missing
33*91f16700Schasinglulu	 * write file line number in hexadecimal format.
34*91f16700Schasinglulu	 ******************************************************************/
35*91f16700Schasinglulu	.asciz " Line 0x"
36*91f16700Schasinglulu#else
37*91f16700Schasinglulu	.asciz " Line "
38*91f16700Schasinglulu
39*91f16700Schasinglulu	/*
40*91f16700Schasinglulu	 * This macro is intended to be used to print the
41*91f16700Schasinglulu	 * line number in decimal. Used by asm_assert macro.
42*91f16700Schasinglulu	 * The max number expected is 65536.
43*91f16700Schasinglulu	 * In: r4 = the decimal to print.
44*91f16700Schasinglulu	 * Clobber: lr, r0, r1, r2, r5, r6
45*91f16700Schasinglulu	 */
46*91f16700Schasinglulu	.macro asm_print_line_dec
47*91f16700Schasinglulu	mov	r6, #10		/* Divide by 10 after every loop iteration */
48*91f16700Schasinglulu	ldr	r5, =MAX_DEC_DIVISOR
49*91f16700Schasingluludec_print_loop:
50*91f16700Schasinglulu	udiv	r0, r4, r5			/* Get the quotient */
51*91f16700Schasinglulu	mls	r4, r0, r5, r4			/* Find the remainder */
52*91f16700Schasinglulu	add	r0, r0, #ASCII_OFFSET_NUM	/* Convert to ascii */
53*91f16700Schasinglulu	bl	plat_crash_console_putc
54*91f16700Schasinglulu	udiv	r5, r5, r6			/* Reduce divisor */
55*91f16700Schasinglulu	cmp	r5, #0
56*91f16700Schasinglulu	bne	dec_print_loop
57*91f16700Schasinglulu	.endm
58*91f16700Schasinglulu#endif
59*91f16700Schasinglulu
60*91f16700Schasinglulu/* ---------------------------------------------------------------------------
61*91f16700Schasinglulu * Assertion support in assembly.
62*91f16700Schasinglulu * The below function helps to support assertions in assembly where we do not
63*91f16700Schasinglulu * have a C runtime stack. Arguments to the function are :
64*91f16700Schasinglulu * r0 - File name
65*91f16700Schasinglulu * r1 - Line no
66*91f16700Schasinglulu * Clobber list : lr, r0 - r6
67*91f16700Schasinglulu * ---------------------------------------------------------------------------
68*91f16700Schasinglulu */
69*91f16700Schasinglulufunc asm_assert
70*91f16700Schasinglulu#if LOG_LEVEL >= LOG_LEVEL_INFO
71*91f16700Schasinglulu	/*
72*91f16700Schasinglulu	 * Only print the output if LOG_LEVEL is higher or equal to
73*91f16700Schasinglulu	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
74*91f16700Schasinglulu	 */
75*91f16700Schasinglulu	/* Stash the parameters already in r0 and r1 */
76*91f16700Schasinglulu	mov	r5, r0
77*91f16700Schasinglulu	mov	r6, r1
78*91f16700Schasinglulu
79*91f16700Schasinglulu	/* Ensure the console is initialized */
80*91f16700Schasinglulu	bl	plat_crash_console_init
81*91f16700Schasinglulu
82*91f16700Schasinglulu	/* Check if the console is initialized */
83*91f16700Schasinglulu	cmp	r0, #0
84*91f16700Schasinglulu	beq	_assert_loop
85*91f16700Schasinglulu
86*91f16700Schasinglulu	/* The console is initialized */
87*91f16700Schasinglulu	ldr	r4, =assert_msg1
88*91f16700Schasinglulu	bl	asm_print_str
89*91f16700Schasinglulu	mov	r4, r5
90*91f16700Schasinglulu	bl	asm_print_str
91*91f16700Schasinglulu	ldr	r4, =assert_msg2
92*91f16700Schasinglulu	bl	asm_print_str
93*91f16700Schasinglulu
94*91f16700Schasinglulu	/* Check if line number higher than max permitted */
95*91f16700Schasinglulu	ldr	r4, =~0xffff
96*91f16700Schasinglulu	tst	r6, r4
97*91f16700Schasinglulu	bne	_assert_loop
98*91f16700Schasinglulu	mov	r4, r6
99*91f16700Schasinglulu
100*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
101*91f16700Schasinglulu	/******************************************************************
102*91f16700Schasinglulu	 * Virtualization comes with the UDIV/SDIV instructions. If missing
103*91f16700Schasinglulu	 * write file line number in hexadecimal format.
104*91f16700Schasinglulu	 ******************************************************************/
105*91f16700Schasinglulu	bl	asm_print_hex
106*91f16700Schasinglulu#else
107*91f16700Schasinglulu	asm_print_line_dec
108*91f16700Schasinglulu#endif
109*91f16700Schasinglulu	bl	plat_crash_console_flush
110*91f16700Schasinglulu_assert_loop:
111*91f16700Schasinglulu#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
112*91f16700Schasinglulu	no_ret	plat_panic_handler
113*91f16700Schasingluluendfunc asm_assert
114*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */
115*91f16700Schasinglulu
116*91f16700Schasinglulu/*
117*91f16700Schasinglulu * This function prints a string from address in r4
118*91f16700Schasinglulu * Clobber: lr, r0 - r4
119*91f16700Schasinglulu */
120*91f16700Schasinglulufunc asm_print_str
121*91f16700Schasinglulu	mov	r3, lr
122*91f16700Schasinglulu1:
123*91f16700Schasinglulu	ldrb	r0, [r4], #0x1
124*91f16700Schasinglulu	cmp	r0, #0
125*91f16700Schasinglulu	beq	2f
126*91f16700Schasinglulu	bl	plat_crash_console_putc
127*91f16700Schasinglulu	b	1b
128*91f16700Schasinglulu2:
129*91f16700Schasinglulu	bx	r3
130*91f16700Schasingluluendfunc asm_print_str
131*91f16700Schasinglulu
132*91f16700Schasinglulu/*
133*91f16700Schasinglulu * This function prints a hexadecimal number in r4.
134*91f16700Schasinglulu * In: r4 = the hexadecimal to print.
135*91f16700Schasinglulu * Clobber: lr, r0 - r3, r5
136*91f16700Schasinglulu */
137*91f16700Schasinglulufunc asm_print_hex
138*91f16700Schasinglulu	mov	r5, #32  /* No of bits to convert to ascii */
139*91f16700Schasinglulu
140*91f16700Schasinglulu	/* Convert to ascii number of bits in r5 */
141*91f16700Schasingluluasm_print_hex_bits:
142*91f16700Schasinglulu	mov	r3, lr
143*91f16700Schasinglulu1:
144*91f16700Schasinglulu	sub	r5, r5, #4
145*91f16700Schasinglulu	lsr	r0, r4, r5
146*91f16700Schasinglulu	and	r0, r0, #0xf
147*91f16700Schasinglulu	cmp	r0, #0xa
148*91f16700Schasinglulu	blo	2f
149*91f16700Schasinglulu	/* Add by 0x27 in addition to ASCII_OFFSET_NUM
150*91f16700Schasinglulu	 * to get ascii for characters 'a - f'.
151*91f16700Schasinglulu	 */
152*91f16700Schasinglulu	add	r0, r0, #0x27
153*91f16700Schasinglulu2:
154*91f16700Schasinglulu	add	r0, r0, #ASCII_OFFSET_NUM
155*91f16700Schasinglulu	bl	plat_crash_console_putc
156*91f16700Schasinglulu	cmp	r5, #0
157*91f16700Schasinglulu	bne	1b
158*91f16700Schasinglulu	bx	r3
159*91f16700Schasingluluendfunc asm_print_hex
160*91f16700Schasinglulu
161*91f16700Schasinglulu	/***********************************************************
162*91f16700Schasinglulu	 * The common implementation of el3_panic for all BL stages
163*91f16700Schasinglulu	 ***********************************************************/
164*91f16700Schasinglulu
165*91f16700Schasinglulu.section .rodata.panic_str, "aS"
166*91f16700Schasinglulu	panic_msg: .asciz "PANIC at PC : 0x"
167*91f16700Schasinglulu	panic_end: .asciz "\r\n"
168*91f16700Schasinglulu
169*91f16700Schasinglulufunc el3_panic
170*91f16700Schasinglulu	/* Have LR copy point to PC at the time of panic */
171*91f16700Schasinglulu	sub	r6, lr, #4
172*91f16700Schasinglulu
173*91f16700Schasinglulu	/* Initialize crash console and verify success */
174*91f16700Schasinglulu	bl	plat_crash_console_init
175*91f16700Schasinglulu
176*91f16700Schasinglulu	/* Check if the console is initialized */
177*91f16700Schasinglulu	cmp	r0, #0
178*91f16700Schasinglulu	beq	_panic_handler
179*91f16700Schasinglulu
180*91f16700Schasinglulu	/* The console is initialized */
181*91f16700Schasinglulu	ldr	r4, =panic_msg
182*91f16700Schasinglulu	bl	asm_print_str
183*91f16700Schasinglulu
184*91f16700Schasinglulu	/* Print LR in hex */
185*91f16700Schasinglulu	mov	r4, r6
186*91f16700Schasinglulu	bl	asm_print_hex
187*91f16700Schasinglulu
188*91f16700Schasinglulu	/* Print new line */
189*91f16700Schasinglulu	ldr	r4, =panic_end
190*91f16700Schasinglulu	bl	asm_print_str
191*91f16700Schasinglulu
192*91f16700Schasinglulu	bl	plat_crash_console_flush
193*91f16700Schasinglulu
194*91f16700Schasinglulu_panic_handler:
195*91f16700Schasinglulu	mov	lr, r6
196*91f16700Schasinglulu	b	plat_panic_handler
197*91f16700Schasingluluendfunc el3_panic
198*91f16700Schasinglulu
199*91f16700Schasinglulu	/***********************************************************
200*91f16700Schasinglulu	 * This function is called from the vector table for
201*91f16700Schasinglulu	 * unhandled exceptions. It reads the current mode and
202*91f16700Schasinglulu	 * passes it to platform.
203*91f16700Schasinglulu	 ***********************************************************/
204*91f16700Schasinglulufunc report_exception
205*91f16700Schasinglulu	mrs	r0, cpsr
206*91f16700Schasinglulu	and	r0, #MODE32_MASK
207*91f16700Schasinglulu	bl	plat_report_exception
208*91f16700Schasinglulu	no_ret	plat_panic_handler
209*91f16700Schasingluluendfunc report_exception
210*91f16700Schasinglulu
211*91f16700Schasinglulu	/***********************************************************
212*91f16700Schasinglulu	 * This function is called from the vector table for
213*91f16700Schasinglulu	 * unhandled exceptions. The lr_abt is given as an
214*91f16700Schasinglulu	 * argument to platform handler.
215*91f16700Schasinglulu	 ***********************************************************/
216*91f16700Schasinglulufunc report_prefetch_abort
217*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
218*91f16700Schasinglulu	b	report_exception
219*91f16700Schasinglulu#else
220*91f16700Schasinglulu	mrs	r0, lr_abt
221*91f16700Schasinglulu	bl	plat_report_prefetch_abort
222*91f16700Schasinglulu	no_ret	plat_panic_handler
223*91f16700Schasinglulu#endif
224*91f16700Schasingluluendfunc report_prefetch_abort
225*91f16700Schasinglulu
226*91f16700Schasinglulu	/***********************************************************
227*91f16700Schasinglulu	 * This function is called from the vector table for
228*91f16700Schasinglulu	 * unhandled exceptions. The lr_abt is given as an
229*91f16700Schasinglulu	 * argument to platform handler.
230*91f16700Schasinglulu	 ***********************************************************/
231*91f16700Schasinglulufunc report_data_abort
232*91f16700Schasinglulu#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
233*91f16700Schasinglulu	b	report_exception
234*91f16700Schasinglulu#else
235*91f16700Schasinglulu	mrs	r0, lr_abt
236*91f16700Schasinglulu	bl	plat_report_data_abort
237*91f16700Schasinglulu	no_ret	plat_panic_handler
238*91f16700Schasinglulu#endif
239*91f16700Schasingluluendfunc report_data_abort
240