mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 10:04:26 +00:00

New helper functions are created to handle data & prefetch aborts in AARCH32. They call platform functions, just like what report_exception is doing. As extended MSR/MRS instructions (to access lr_abt in monitor mode) are only available if CPU (Armv7) has virtualization extension, the functions branch to original report_exception handlers if this is not the case. Those new helpers are created mainly to distinguish data and prefetch aborts, as they both share the same mode. This adds 40 bytes of code. Change-Id: I5dd31930344ad4e3a658f8a9d366a87a300aeb67 Signed-off-by: Yann Gautier <yann.gautier@st.com>
239 lines
6.1 KiB
ArmAsm
239 lines
6.1 KiB
ArmAsm
/*
|
|
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <arch.h>
|
|
#include <asm_macros.S>
|
|
#include <common/debug.h>
|
|
|
|
.globl asm_print_str
|
|
.globl asm_print_hex
|
|
.globl asm_print_hex_bits
|
|
.globl asm_assert
|
|
.globl do_panic
|
|
.globl report_exception
|
|
.globl report_prefetch_abort
|
|
.globl report_data_abort
|
|
|
|
/* Since the max decimal input number is 65536 */
|
|
#define MAX_DEC_DIVISOR 10000
|
|
/* The offset to add to get ascii for numerals '0 - 9' */
|
|
#define ASCII_OFFSET_NUM '0'
|
|
|
|
#if ENABLE_ASSERTIONS
|
|
.section .rodata.assert_str, "aS"
|
|
assert_msg1:
|
|
.asciz "ASSERT: File "
|
|
assert_msg2:
|
|
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
|
/******************************************************************
|
|
* Virtualization comes with the UDIV/SDIV instructions. If missing
|
|
* write file line number in hexadecimal format.
|
|
******************************************************************/
|
|
.asciz " Line 0x"
|
|
#else
|
|
.asciz " Line "
|
|
|
|
/*
|
|
* This macro is intended to be used to print the
|
|
* line number in decimal. Used by asm_assert macro.
|
|
* The max number expected is 65536.
|
|
* In: r4 = the decimal to print.
|
|
* Clobber: lr, r0, r1, r2, r5, r6
|
|
*/
|
|
.macro asm_print_line_dec
|
|
mov r6, #10 /* Divide by 10 after every loop iteration */
|
|
ldr r5, =MAX_DEC_DIVISOR
|
|
dec_print_loop:
|
|
udiv r0, r4, r5 /* Get the quotient */
|
|
mls r4, r0, r5, r4 /* Find the remainder */
|
|
add r0, r0, #ASCII_OFFSET_NUM /* Convert to ascii */
|
|
bl plat_crash_console_putc
|
|
udiv r5, r5, r6 /* Reduce divisor */
|
|
cmp r5, #0
|
|
bne dec_print_loop
|
|
.endm
|
|
#endif
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* Assertion support in assembly.
|
|
* The below function helps to support assertions in assembly where we do not
|
|
* have a C runtime stack. Arguments to the function are :
|
|
* r0 - File name
|
|
* r1 - Line no
|
|
* Clobber list : lr, r0 - r6
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
func asm_assert
|
|
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
|
/*
|
|
* Only print the output if LOG_LEVEL is higher or equal to
|
|
* LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
|
|
*/
|
|
/* Stash the parameters already in r0 and r1 */
|
|
mov r5, r0
|
|
mov r6, r1
|
|
|
|
/* Ensure the console is initialized */
|
|
bl plat_crash_console_init
|
|
|
|
/* Check if the console is initialized */
|
|
cmp r0, #0
|
|
beq _assert_loop
|
|
|
|
/* The console is initialized */
|
|
ldr r4, =assert_msg1
|
|
bl asm_print_str
|
|
mov r4, r5
|
|
bl asm_print_str
|
|
ldr r4, =assert_msg2
|
|
bl asm_print_str
|
|
|
|
/* Check if line number higher than max permitted */
|
|
ldr r4, =~0xffff
|
|
tst r6, r4
|
|
bne _assert_loop
|
|
mov r4, r6
|
|
|
|
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
|
/******************************************************************
|
|
* Virtualization comes with the UDIV/SDIV instructions. If missing
|
|
* write file line number in hexadecimal format.
|
|
******************************************************************/
|
|
bl asm_print_hex
|
|
#else
|
|
asm_print_line_dec
|
|
#endif
|
|
bl plat_crash_console_flush
|
|
_assert_loop:
|
|
#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
|
|
no_ret plat_panic_handler
|
|
endfunc asm_assert
|
|
#endif /* ENABLE_ASSERTIONS */
|
|
|
|
/*
|
|
* This function prints a string from address in r4
|
|
* Clobber: lr, r0 - r4
|
|
*/
|
|
func asm_print_str
|
|
mov r3, lr
|
|
1:
|
|
ldrb r0, [r4], #0x1
|
|
cmp r0, #0
|
|
beq 2f
|
|
bl plat_crash_console_putc
|
|
b 1b
|
|
2:
|
|
bx r3
|
|
endfunc asm_print_str
|
|
|
|
/*
|
|
* This function prints a hexadecimal number in r4.
|
|
* In: r4 = the hexadecimal to print.
|
|
* Clobber: lr, r0 - r3, r5
|
|
*/
|
|
func asm_print_hex
|
|
mov r5, #32 /* No of bits to convert to ascii */
|
|
|
|
/* Convert to ascii number of bits in r5 */
|
|
asm_print_hex_bits:
|
|
mov r3, lr
|
|
1:
|
|
sub r5, r5, #4
|
|
lsr r0, r4, r5
|
|
and r0, r0, #0xf
|
|
cmp r0, #0xa
|
|
blo 2f
|
|
/* Add by 0x27 in addition to ASCII_OFFSET_NUM
|
|
* to get ascii for characters 'a - f'.
|
|
*/
|
|
add r0, r0, #0x27
|
|
2:
|
|
add r0, r0, #ASCII_OFFSET_NUM
|
|
bl plat_crash_console_putc
|
|
cmp r5, #0
|
|
bne 1b
|
|
bx r3
|
|
endfunc asm_print_hex
|
|
|
|
/***********************************************************
|
|
* The common implementation of do_panic for all BL stages
|
|
***********************************************************/
|
|
|
|
.section .rodata.panic_str, "aS"
|
|
panic_msg: .asciz "PANIC at PC : 0x"
|
|
panic_end: .asciz "\r\n"
|
|
|
|
func do_panic
|
|
/* Have LR copy point to PC at the time of panic */
|
|
sub r6, lr, #4
|
|
|
|
/* Initialize crash console and verify success */
|
|
bl plat_crash_console_init
|
|
|
|
/* Check if the console is initialized */
|
|
cmp r0, #0
|
|
beq _panic_handler
|
|
|
|
/* The console is initialized */
|
|
ldr r4, =panic_msg
|
|
bl asm_print_str
|
|
|
|
/* Print LR in hex */
|
|
mov r4, r6
|
|
bl asm_print_hex
|
|
|
|
/* Print new line */
|
|
ldr r4, =panic_end
|
|
bl asm_print_str
|
|
|
|
bl plat_crash_console_flush
|
|
|
|
_panic_handler:
|
|
mov lr, r6
|
|
b plat_panic_handler
|
|
endfunc do_panic
|
|
|
|
/***********************************************************
|
|
* This function is called from the vector table for
|
|
* unhandled exceptions. It reads the current mode and
|
|
* passes it to platform.
|
|
***********************************************************/
|
|
func report_exception
|
|
mrs r0, cpsr
|
|
and r0, #MODE32_MASK
|
|
bl plat_report_exception
|
|
no_ret plat_panic_handler
|
|
endfunc report_exception
|
|
|
|
/***********************************************************
|
|
* This function is called from the vector table for
|
|
* unhandled exceptions. The lr_abt is given as an
|
|
* argument to platform handler.
|
|
***********************************************************/
|
|
func report_prefetch_abort
|
|
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
|
b report_exception
|
|
#else
|
|
mrs r0, lr_abt
|
|
bl plat_report_prefetch_abort
|
|
no_ret plat_panic_handler
|
|
#endif
|
|
endfunc report_prefetch_abort
|
|
|
|
/***********************************************************
|
|
* This function is called from the vector table for
|
|
* unhandled exceptions. The lr_abt is given as an
|
|
* argument to platform handler.
|
|
***********************************************************/
|
|
func report_data_abort
|
|
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
|
|
b report_exception
|
|
#else
|
|
mrs r0, lr_abt
|
|
bl plat_report_data_abort
|
|
no_ret plat_panic_handler
|
|
#endif
|
|
endfunc report_data_abort
|