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 <liguiding1@xiaomi.com>
This commit is contained in:
parent
b445029cf2
commit
dfdb3aa2f4
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <nuttx/config.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue