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