diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S index f506356..9d410df 100644 --- a/common/aarch32/debug.S +++ b/common/aarch32/debug.S @@ -1,71 +1,25 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include +#include + .globl asm_print_str + .globl asm_print_hex + .globl asm_print_hex_bits .globl asm_assert .globl do_panic .globl report_exception /* Since the max decimal input number is 65536 */ #define MAX_DEC_DIVISOR 10000 - /* The offset to add to get ascii for numerals '0 - 9' */ #define ASCII_OFFSET_NUM '0' - .section .rodata.panic_str, "aS" -panic_msg: - .asciz "PANIC at PC : 0x" -panic_end: - .asciz "\r\n" - - /*********************************************************** - * The common implementation of do_panic for all BL stages - ***********************************************************/ -func do_panic - /* Have LR copy point to PC at the time of panic */ - sub r6, lr, #4 - - /* Initialize crash console and verify success */ - bl plat_crash_console_init - cmp r0, #0 - beq 1f - - /* Print panic message */ - ldr r4, =panic_msg - bl asm_print_str - - /* Print LR in hex */ - mov r4, r6 - bl asm_print_hex - - /* Print new line */ - ldr r4, =panic_end - bl asm_print_str - - bl plat_crash_console_flush - -1: - mov lr, r6 - b plat_panic_handler -endfunc do_panic - - /*********************************************************** - * This function is called from the vector table for - * unhandled exceptions. It reads the current mode and - * passes it to platform. - ***********************************************************/ -func report_exception - mrs r0, cpsr - and r0, #MODE32_MASK - bl plat_report_exception - no_ret plat_panic_handler -endfunc report_exception - #if ENABLE_ASSERTIONS .section .rodata.assert_str, "aS" assert_msg1: @@ -79,6 +33,26 @@ .asciz " Line 0x" #else .asciz " Line " + + /* + * This macro is intended to be used to print the + * line number in decimal. Used by asm_assert macro. + * The max number expected is 65536. + * In: r4 = the decimal to print. + * Clobber: lr, r0, r1, r2, r5, r6 + */ + .macro asm_print_line_dec + mov r6, #10 /* Divide by 10 after every loop iteration */ + ldr r5, =MAX_DEC_DIVISOR +dec_print_loop: + udiv r0, r4, r5 /* Get the quotient */ + mls r4, r0, r5, r4 /* Find the remainder */ + add r0, r0, #ASCII_OFFSET_NUM /* Convert to ascii */ + bl plat_crash_console_putc + udiv r5, r5, r6 /* Reduce divisor */ + cmp r5, #0 + bne dec_print_loop + .endm #endif /* --------------------------------------------------------------------------- @@ -100,25 +74,25 @@ mov r5, r0 mov r6, r1 - /* Initialize crash console and verify success */ + /* Ensure the console is initialized */ bl plat_crash_console_init - cmp r0, #0 - beq 1f - /* Print file name */ + /* Check if the console is initialized */ + cmp r0, #0 + beq _assert_loop + + /* The console is initialized */ ldr r4, =assert_msg1 bl asm_print_str mov r4, r5 bl asm_print_str - - /* Print line number string */ ldr r4, =assert_msg2 bl asm_print_str - /* Test for maximum supported line number */ + /* Check if line number higher than max permitted */ ldr r4, =~0xffff tst r6, r4 - bne 1f + bne _assert_loop mov r4, r6 #if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) @@ -128,22 +102,10 @@ ******************************************************************/ bl asm_print_hex #else - /* Print line number in decimal */ - mov r6, #10 /* Divide by 10 after every loop iteration */ - ldr r5, =MAX_DEC_DIVISOR -dec_print_loop: - udiv r0, r4, r5 /* Quotient */ - mls r4, r0, r5, r4 /* Remainder */ - add r0, r0, #ASCII_OFFSET_NUM /* Convert to ASCII */ - bl plat_crash_console_putc - udiv r5, r5, r6 /* Reduce divisor */ - cmp r5, #0 - bne dec_print_loop + asm_print_line_dec #endif - bl plat_crash_console_flush - -1: +_assert_loop: #endif /* LOG_LEVEL >= LOG_LEVEL_INFO */ no_ret plat_panic_handler endfunc asm_assert @@ -171,8 +133,11 @@ * Clobber: lr, r0 - r3, r5 */ func asm_print_hex - mov r3, lr mov r5, #32 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in r5 */ +asm_print_hex_bits: + mov r3, lr 1: sub r5, r5, #4 lsr r0, r4, r5 @@ -190,3 +155,53 @@ bne 1b bx r3 endfunc asm_print_hex + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + panic_end: .asciz "\r\n" + +func do_panic + /* Have LR copy point to PC at the time of panic */ + sub r6, lr, #4 + + /* Initialize crash console and verify success */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cmp r0, #0 + beq _panic_handler + + /* The console is initialized */ + ldr r4, =panic_msg + bl asm_print_str + + /* Print LR in hex */ + mov r4, r6 + bl asm_print_hex + + /* Print new line */ + ldr r4, =panic_end + bl asm_print_str + + bl plat_crash_console_flush + +_panic_handler: + mov lr, r6 + b plat_panic_handler +endfunc do_panic + + /*********************************************************** + * This function is called from the vector table for + * unhandled exceptions. It reads the current mode and + * passes it to platform. + ***********************************************************/ +func report_exception + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception + no_ret plat_panic_handler +endfunc report_exception diff --git a/common/aarch64/debug.S b/common/aarch64/debug.S index 7db2439..ad6acd9 100644 --- a/common/aarch64/debug.S +++ b/common/aarch64/debug.S @@ -38,11 +38,11 @@ mov x6, #10 /* Divide by 10 after every loop iteration */ mov x5, #MAX_DEC_DIVISOR dec_print_loop: - udiv x0, x4, x5 /* Get the quotient */ - msub x4, x0, x5, x4 /* Find the remainder */ - add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ + udiv x0, x4, x5 /* Get the quotient */ + msub x4, x0, x5, x4 /* Find the remainder */ + add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ bl plat_crash_console_putc - udiv x5, x5, x6 /* Reduce divisor */ + udiv x5, x5, x6 /* Reduce divisor */ cbnz x5, dec_print_loop .endm @@ -64,10 +64,13 @@ */ mov x5, x0 mov x6, x1 + /* Ensure the console is initialized */ bl plat_crash_console_init + /* Check if the console is initialized */ cbz x0, _assert_loop + /* The console is initialized */ adr x4, assert_msg1 bl asm_print_str @@ -75,6 +78,7 @@ bl asm_print_str adr x4, assert_msg2 bl asm_print_str + /* Check if line number higher than max permitted */ tst x6, #~0xffff b.ne _assert_loop @@ -191,12 +195,15 @@ el3_panic: mov x6, x30 bl plat_crash_console_init + /* Check if the console is initialized */ cbz x0, _panic_handler + /* The console is initialized */ adr x4, panic_msg bl asm_print_str mov x4, x6 + /* The panic location is lr -4 */ sub x4, x4, #4 bl asm_print_hex diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index bfcd991..407eb39 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,7 +12,6 @@ #include #define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) -#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) .globl platform_mem_init .globl plat_report_exception @@ -32,7 +31,48 @@ endfunc platform_mem_init func plat_report_exception +#if DEBUG + mov r8, lr + + /* Test if an abort occurred */ + cmp r0, #MODE32_abt + bne undef_inst_lbl + ldr r4, =abort_str + bl asm_print_str + mrs r4, lr_abt + sub r4, r4, #4 + b print_exception_info + +undef_inst_lbl: + /* Test for an undefined instruction */ + cmp r0, #MODE32_und + bne other_exception_lbl + ldr r4, =undefined_str + bl asm_print_str + mrs r4, lr_und + b print_exception_info + +other_exception_lbl: + /* Other exceptions */ + mov r9, r0 + ldr r4, =exception_start_str + bl asm_print_str + mov r4, r9 + bl asm_print_hex + ldr r4, =exception_end_str + bl asm_print_str + mov r4, r6 + +print_exception_info: + bl asm_print_hex + + ldr r4, =end_error_str + bl asm_print_str + + bx r8 +#else bx lr +#endif endfunc plat_report_exception func plat_reset_handler @@ -129,10 +169,19 @@ bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) str r2, [r1, #GPIO_PUPD_OFFSET] /* Set alternate */ +#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT ldr r2, [r1, #GPIO_AFRH_OFFSET] - bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) - orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT) + bic r2, r2, #(GPIO_ALTERNATE_MASK << \ + ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \ + ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)) str r2, [r1, #GPIO_AFRH_OFFSET] +#else + ldr r2, [r1, #GPIO_AFRL_OFFSET] + bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2)) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2)) + str r2, [r1, #GPIO_AFRL_OFFSET] +#endif /* Enable UART clock, with its source */ ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) mov r2, #DEBUG_UART_TX_CLKSRC @@ -174,3 +223,34 @@ ldr r1, =STM32MP_DEBUG_USART_BASE b console_stm32_core_putc endfunc plat_crash_console_putc + + /* ---------------------------------------------------------- + * void plat_panic_handler(void) __dead2; + * Report exception + endless loop. + * + * r6 holds the address where the fault occurred. + * Filling lr with this value allows debuggers to reconstruct + * the backtrace. + * ---------------------------------------------------------- + */ +func plat_panic_handler + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception + mov lr, r6 + b . +endfunc plat_panic_handler + +#if DEBUG +.section .rodata.rev_err_str, "aS" +abort_str: + .asciz "\nAbort at: 0x" +undefined_str: + .asciz "\nUndefined instruction at: 0x" +exception_start_str: + .asciz "\nException mode=0x" +exception_end_str: + .asciz " at: 0x" +end_error_str: + .asciz "\n\r" +#endif