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