From 00a55fe4c5d206e9ecec9d598dfb99a1ac8b296a Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 17 Sep 2020 15:15:27 +0200 Subject: [PATCH 1/4] Align AARCH32 version of debug.S with AARCH64 Re-order code (put panic and report_exception at the end of the file). Export asm_print_* functions. Add asm_print_line_dec macro, and asm_print_newline func. Align comments in both AARCH32 and AARCH64 files. Add blank lines in AARCH64 files to align with AARCH32. Change-Id: I8e299a27c1390f71f04e260cd4a0e59b2384eb19 Signed-off-by: Yann Gautier --- common/aarch32/debug.S | 163 ++++++++++++++++++++++------------------- common/aarch64/debug.S | 15 +++- 2 files changed, 100 insertions(+), 78 deletions(-) diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S index f50635691..9d410df07 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 @@ assert_msg2: .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 @@ func asm_assert 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 @@ func asm_assert ******************************************************************/ 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 @@ endfunc asm_print_str * 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 @@ func asm_print_hex 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 7db24396e..ad6acd9d2 100644 --- a/common/aarch64/debug.S +++ b/common/aarch64/debug.S @@ -38,11 +38,11 @@ assert_msg2: 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 @@ func asm_assert */ 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 @@ func asm_assert 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 @@ panic_common: 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 From a9eda77c22d045dc7f09272b3cba76225177f9f5 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 15 Sep 2020 12:24:46 +0200 Subject: [PATCH 2/4] stm32mp1: update plat_report_exception In case DEBUG is enabled, plat_report_exception will now display extra information of the cause of the exception. Change-Id: I72cc9d180959cbf31c13821dd051eaf4462b733e Signed-off-by: Yann Gautier --- plat/st/stm32mp1/stm32mp1_helper.S | 57 +++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index bfcd991a3..b4b699ea4 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 */ @@ -32,7 +32,48 @@ func platform_mem_init 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 @@ -174,3 +215,17 @@ func plat_crash_console_putc ldr r1, =STM32MP_DEBUG_USART_BASE b console_stm32_core_putc endfunc plat_crash_console_putc + +#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 From 6397423ed4a08adea3605f60a168a34c2a7ec526 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 15 Sep 2020 12:29:53 +0200 Subject: [PATCH 3/4] stm32mp1: add plat_panic_handler function The STM32MP1 implementation of this function will call plat_report_exception(). It displays more information about the panic if DEBUG is enabled. The LR register is also filled with R6 content, which hold the faulty address. This allows debugger to reconstruct the backtrace. Change-Id: I6710e8e2ab6658b05c5bbad2f3c545f07f355afb Signed-off-by: Yann Gautier --- plat/st/stm32mp1/stm32mp1_helper.S | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index b4b699ea4..560e06e20 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -216,6 +216,23 @@ func plat_crash_console_putc 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: From 4170079ae05a962a43962f426815e12d516fb3f9 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 25 Feb 2020 17:51:52 +0100 Subject: [PATCH 4/4] stm32mp1: correct crash console GPIO alternate configuration If GPIO port for UART TX is less than 8, the register GPIO_AFRL should be used to set the alternate. GPIO_AFRH is used if GPIO port is greater or equal to 8. The macro GPIO_TX_ALT_SHIFT is removed and the GPIO port number is tested against GPIO_ALT_LOWER_LIMIT (=8) in plat_crash_console_init() function. Change-Id: Ibb62223ed6bce589bbcab59a5e986b2677e6d118 Signed-off-by: Yann Gautier --- plat/st/stm32mp1/stm32mp1_helper.S | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 560e06e20..407eb3979 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -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 @@ -170,10 +169,19 @@ func plat_crash_console_init 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