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