Home | History | Annotate | Download | only in aarch64
      1 /*
      2  * Copyright (c) 2014-2017, 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 <debug.h>
     10 
     11 	.globl	asm_print_str
     12 	.globl	asm_print_hex
     13 	.globl	asm_assert
     14 	.globl	do_panic
     15 
     16 /* Since the max decimal input number is 65536 */
     17 #define MAX_DEC_DIVISOR		10000
     18 /* The offset to add to get ascii for numerals '0 - 9' */
     19 #define ASCII_OFFSET_NUM	0x30
     20 
     21 #if ENABLE_ASSERTIONS
     22 .section .rodata.assert_str, "aS"
     23 assert_msg1:
     24 	.asciz "ASSERT: File "
     25 assert_msg2:
     26 	.asciz " Line "
     27 
     28 	/*
     29 	 * This macro is intended to be used to print the
     30 	 * line number in decimal. Used by asm_assert macro.
     31 	 * The max number expected is 65536.
     32 	 * In: x4 = the decimal to print.
     33 	 * Clobber: x30, x0, x1, x2, x5, x6
     34 	 */
     35 	.macro asm_print_line_dec
     36 	mov	x6, #10		/* Divide by 10 after every loop iteration */
     37 	mov	x5, #MAX_DEC_DIVISOR
     38 dec_print_loop:
     39 	udiv	x0, x4, x5		/* Get the quotient */
     40 	msub	x4, x0, x5, x4		/* Find the remainder */
     41 	add	x0, x0, #ASCII_OFFSET_NUM		/* Convert to ascii */
     42 	bl	plat_crash_console_putc
     43 	udiv	x5, x5, x6		/* Reduce divisor */
     44 	cbnz	x5, dec_print_loop
     45 	.endm
     46 
     47 
     48 /* ---------------------------------------------------------------------------
     49  * Assertion support in assembly.
     50  * The below function helps to support assertions in assembly where we do not
     51  * have a C runtime stack. Arguments to the function are :
     52  * x0 - File name
     53  * x1 - Line no
     54  * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6.
     55  * ---------------------------------------------------------------------------
     56  */
     57 func asm_assert
     58 #if LOG_LEVEL >= LOG_LEVEL_INFO
     59 	/*
     60 	 * Only print the output if LOG_LEVEL is higher or equal to
     61 	 * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1.
     62 	 */
     63 	mov	x5, x0
     64 	mov	x6, x1
     65 	/* Ensure the console is initialized */
     66 	bl	plat_crash_console_init
     67 	/* Check if the console is initialized */
     68 	cbz	x0, _assert_loop
     69 	/* The console is initialized */
     70 	adr	x4, assert_msg1
     71 	bl	asm_print_str
     72 	mov	x4, x5
     73 	bl	asm_print_str
     74 	adr	x4, assert_msg2
     75 	bl	asm_print_str
     76 	/* Check if line number higher than max permitted */
     77 	tst	x6, #~0xffff
     78 	b.ne	_assert_loop
     79 	mov	x4, x6
     80 	asm_print_line_dec
     81 	bl	plat_crash_console_flush
     82 _assert_loop:
     83 #endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
     84 	no_ret	plat_panic_handler
     85 endfunc asm_assert
     86 #endif /* ENABLE_ASSERTIONS */
     87 
     88 /*
     89  * This function prints a string from address in x4.
     90  * In: x4 = pointer to string.
     91  * Clobber: x30, x0, x1, x2, x3
     92  */
     93 func asm_print_str
     94 	mov	x3, x30
     95 1:
     96 	ldrb	w0, [x4], #0x1
     97 	cbz	x0, 2f
     98 	bl	plat_crash_console_putc
     99 	b	1b
    100 2:
    101 	ret	x3
    102 endfunc asm_print_str
    103 
    104 /*
    105  * This function prints a hexadecimal number in x4.
    106  * In: x4 = the hexadecimal to print.
    107  * Clobber: x30, x0 - x3, x5
    108  */
    109 func asm_print_hex
    110 	mov	x3, x30
    111 	mov	x5, #64  /* No of bits to convert to ascii */
    112 1:
    113 	sub	x5, x5, #4
    114 	lsrv	x0, x4, x5
    115 	and	x0, x0, #0xf
    116 	cmp	x0, #0xA
    117 	b.lo	2f
    118 	/* Add by 0x27 in addition to ASCII_OFFSET_NUM
    119 	 * to get ascii for characters 'a - f'.
    120 	 */
    121 	add	x0, x0, #0x27
    122 2:
    123 	add	x0, x0, #ASCII_OFFSET_NUM
    124 	bl	plat_crash_console_putc
    125 	cbnz	x5, 1b
    126 	ret	x3
    127 endfunc asm_print_hex
    128 
    129 	/***********************************************************
    130 	 * The common implementation of do_panic for all BL stages
    131 	 ***********************************************************/
    132 
    133 .section .rodata.panic_str, "aS"
    134 	panic_msg: .asciz "PANIC at PC : 0x"
    135 
    136 /* ---------------------------------------------------------------------------
    137  * do_panic assumes that it is invoked from a C Runtime Environment ie a
    138  * valid stack exists. This call will not return.
    139  * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6
    140  * ---------------------------------------------------------------------------
    141  */
    142 
    143 /* This is for the non el3 BL stages to compile through */
    144 	.weak el3_panic
    145 
    146 func do_panic
    147 #if CRASH_REPORTING
    148 	str	x0, [sp, #-0x10]!
    149 	mrs	x0, currentel
    150 	ubfx	x0, x0, #2, #2
    151 	cmp	x0, #0x3
    152 	ldr	x0, [sp], #0x10
    153 	b.eq	el3_panic
    154 #endif
    155 
    156 panic_common:
    157 /*
    158  * el3_panic will be redefined by the BL31
    159  * crash reporting mechanism (if enabled)
    160  */
    161 el3_panic:
    162 	mov	x6, x30
    163 	bl	plat_crash_console_init
    164 	/* Check if the console is initialized */
    165 	cbz	x0, _panic_handler
    166 	/* The console is initialized */
    167 	adr	x4, panic_msg
    168 	bl	asm_print_str
    169 	mov	x4, x6
    170 	/* The panic location is lr -4 */
    171 	sub	x4, x4, #4
    172 	bl	asm_print_hex
    173 
    174 	bl	plat_crash_console_flush
    175 
    176 _panic_handler:
    177 	/* Pass to plat_panic_handler the address from where el3_panic was
    178 	 * called, not the address of the call from el3_panic. */
    179 	mov	x30, x6
    180 	b	plat_panic_handler
    181 endfunc do_panic
    182