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