From dfdb3aa2f4e3c0897d0115db0d55e14863de364c Mon Sep 17 00:00:00 2001 From: ligd Date: Thu, 18 May 2023 23:42:03 +0800 Subject: [PATCH] armv8m: support busfault forward to TEE For TEE & REE, securefault & busfault are not banked, so the faults can only forword to TEE/REE. But how to crash dump the other core which not handled faults ? Here we provide a way to resolve this problem: 1. Set the securefault & busfault to TEE 2. busfault happend from TEE, then directly dump TEE 3. busfault happend from REE, then generate nonsecurefault 4. Back to REE, and dump Signed-off-by: ligd --- arch/arm/src/armv8-m/CMakeLists.txt | 4 + arch/arm/src/armv8-m/Make.defs | 4 + arch/arm/src/armv8-m/arm_busfault.c | 7 ++ arch/arm/src/armv8-m/arm_gen_nonsecfault.c | 136 +++++++++++++++++++++ arch/arm/src/armv8-m/arm_securefault.c | 48 +------- arch/arm/src/common/arm_internal.h | 6 + 6 files changed, 158 insertions(+), 47 deletions(-) create mode 100644 arch/arm/src/armv8-m/arm_gen_nonsecfault.c diff --git a/arch/arm/src/armv8-m/CMakeLists.txt b/arch/arm/src/armv8-m/CMakeLists.txt index 251a02a9e7..78f85cc122 100644 --- a/arch/arm/src/armv8-m/CMakeLists.txt +++ b/arch/arm/src/armv8-m/CMakeLists.txt @@ -66,4 +66,8 @@ if(CONFIG_ARM_MPU OR CONFIG_ARM_MPU_EARLY_RESET) list(APPEND SRCS arm_mpu.c) endif() +if(CONFIG_ARCH_TRUSTZONE_SECURE) + list(APPEND SRCS arm_gen_nonsecfault.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/armv8-m/Make.defs b/arch/arm/src/armv8-m/Make.defs index c3e05ffc11..d74ab316be 100644 --- a/arch/arm/src/armv8-m/Make.defs +++ b/arch/arm/src/armv8-m/Make.defs @@ -56,3 +56,7 @@ endif ifneq ($(filter y,$(CONFIG_ARM_MPU) $(CONFIG_ARM_MPU_EARLY_RESET)),) CMN_CSRCS += arm_mpu.c endif + +ifeq ($(CONFIG_ARCH_TRUSTZONE_SECURE),y) + CMN_CSRCS += arm_gen_nonsecfault.c +endif diff --git a/arch/arm/src/armv8-m/arm_busfault.c b/arch/arm/src/armv8-m/arm_busfault.c index 2060cae591..c324555600 100644 --- a/arch/arm/src/armv8-m/arm_busfault.c +++ b/arch/arm/src/armv8-m/arm_busfault.c @@ -102,6 +102,13 @@ int arm_busfault(int irq, void *context, void *arg) bfalert("\tFloating-point lazy state preservation error\n"); } +#ifdef CONFIG_DEBUG_BUSFAULT + if (arm_gen_nonsecurefault(irq, context)) + { + return OK; + } +#endif + up_irq_save(); PANIC_WITH_REGS("panic", context); return OK; diff --git a/arch/arm/src/armv8-m/arm_gen_nonsecfault.c b/arch/arm/src/armv8-m/arm_gen_nonsecfault.c new file mode 100644 index 0000000000..f54fc92ad0 --- /dev/null +++ b/arch/arm/src/armv8-m/arm_gen_nonsecfault.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * arch/arm/src/armv8-m/arm_gen_nonsecfault.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include "nvic.h" +#include "sau.h" +#include "arm_internal.h" +#include "exc_return.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define OFFSET_R0 (0 * 4) /* R0 */ +#define OFFSET_R1 (1 * 4) /* R1 */ +#define OFFSET_R2 (2 * 4) /* R2 */ +#define OFFSET_R3 (3 * 4) /* R3 */ +#define OFFSET_R12 (4 * 4) /* R12 */ +#define OFFSET_R14 (5 * 4) /* R14 = LR */ +#define OFFSET_R15 (6 * 4) /* R15 = PC */ +#define OFFSET_XPSR (7 * 4) /* xPSR */ + +/**************************************************************************** + * Name: arm_should_gen_nonsecurefault + * + * Description: + * Check whether should generate non-secure IRQ from securefault + * + ****************************************************************************/ + +bool weak_function arm_should_gen_nonsecurefault(void) +{ + return true; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_gen_nonsecurefault + * + * Description: + * For TEE & REE, securefault & busfault are not banked, so the faults can + * only forword to TEE/REE. + * But how to crash dump the other core which not handled faults ? + * + * Here we provide a way to resolve this problem: + * 1. Set the securefault & busfault to TEE + * 2. busfault happend from TEE, then directly dump TEE + * 3. busfault happend from REE, then generate nonsecurefault + * 4. Back to REE, and dump + * + * Return values: + * 1 means generated done + * 0 means don't need generated + * + ****************************************************************************/ + +int arm_gen_nonsecurefault(int irq, uint32_t *regs) +{ + uint32_t nsp; + + if (!arm_should_gen_nonsecurefault()) + { + return 0; + } + + /* Check whether come from REE */ + + if (regs[REG_EXC_RETURN] & EXC_RETURN_SECURE_STACK) + { + return 0; + } + + /* busfault are forward to REE ? */ + + if (getreg32(NVIC_AIRCR) & NVIC_AIRCR_BFHFNMINS) + { + return 0; + } + + /* Redict busfault to REE */ + + up_secure_irq(NVIC_IRQ_BUSFAULT, false); + + /* Get non-secure SP */ + + __asm__ __volatile__ ("mrs %0, msp_ns" : "=r" (nsp)); + + _alert("Dump REE registers:\n"); + _alert("R0: %08" PRIx32 " R1: %08" PRIx32 + " R2: %08" PRIx32 " R3: %08" PRIx32 "\n", + getreg32(nsp + OFFSET_R0), getreg32(nsp + OFFSET_R1), + getreg32(nsp + OFFSET_R2), getreg32(nsp + OFFSET_R3)); + _alert("IP: %08" PRIx32 " SP: %08" PRIx32 + " LR: %08" PRIx32 " PC: %08" PRIx32 "\n", + getreg32(nsp + OFFSET_R12), nsp, + getreg32(nsp + OFFSET_R14), getreg32(nsp + OFFSET_R15)); + syslog_flush(); + + /* Force set return ReturnAddress to 0, then non-secure cpu will crash. + * Also, the ReturnAddress is very important, so move it to R12. + */ + + putreg32(getreg32(nsp + OFFSET_R15), nsp + OFFSET_R12); + putreg32(0, nsp + OFFSET_R15); + + return 1; +} diff --git a/arch/arm/src/armv8-m/arm_securefault.c b/arch/arm/src/armv8-m/arm_securefault.c index 45c18375d7..fb0f2a4736 100644 --- a/arch/arm/src/armv8-m/arm_securefault.c +++ b/arch/arm/src/armv8-m/arm_securefault.c @@ -43,38 +43,6 @@ #ifdef CONFIG_DEBUG_SECUREFAULT # define sfalert(format, ...) _alert(format, ##__VA_ARGS__) - -# define OFFSET_R0 (0 * 4) /* R0 */ -# define OFFSET_R1 (1 * 4) /* R1 */ -# define OFFSET_R2 (2 * 4) /* R2 */ -# define OFFSET_R3 (3 * 4) /* R3 */ -# define OFFSET_R12 (4 * 4) /* R12 */ -# define OFFSET_R14 (5 * 4) /* R14 = LR */ -# define OFFSET_R15 (6 * 4) /* R15 = PC */ -# define OFFSET_XPSR (7 * 4) /* xPSR */ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static void generate_nonsecure_busfault(void) -{ - uint32_t nsp; - - /* Get non-secure SP */ - - __asm__ __volatile__ ("mrs %0, msp_ns" : "=r" (nsp)); - - sfalert("Non-sec sp %08" PRIx32 "\n", nsp); - syslog_flush(); - - /* Force set return ReturnAddress to 0, then non-secure cpu will crash. - * Also, the ReturnAddress is very important, so move it to R12. - */ - - putreg32(getreg32(nsp + OFFSET_R15), nsp + OFFSET_R12); - putreg32(0, nsp + OFFSET_R15); -} #else # define sfalert(...) #endif @@ -83,19 +51,6 @@ static void generate_nonsecure_busfault(void) * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: arm_securefault_should_generate - * - * Description: - * Check whether should generate non-secure IRQ from securefault - * - ****************************************************************************/ - -bool weak_function arm_should_generate_nonsecure_busfault(void) -{ - return true; -} - /**************************************************************************** * Name: arm_securefault * @@ -161,9 +116,8 @@ int arm_securefault(int irq, void *context, void *arg) putreg32(0xff, SAU_SFSR); #ifdef CONFIG_DEBUG_SECUREFAULT - if (arm_should_generate_nonsecure_busfault()) + if (arm_gen_nonsecurefault(irq, context)) { - generate_nonsecure_busfault(); return OK; } #endif diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h index 7c625d847b..75918424c6 100644 --- a/arch/arm/src/common/arm_internal.h +++ b/arch/arm/src/common/arm_internal.h @@ -522,6 +522,12 @@ size_t arm_stack_check(void *stackbase, size_t nbytes); void arm_stack_color(void *stackbase, size_t nbytes); #endif +#ifdef CONFIG_ARCH_TRUSTZONE_SECURE +int arm_gen_nonsecurefault(int irq, uint32_t *regs); +#else +# define arm_gen_nonsecurefault(i, r) (0) +#endif + #undef EXTERN #ifdef __cplusplus }