arch: arm: SecureFault Handling for Cortex-M33

This commit contributes the implementation of the SecureFault
handling for ARMv8-M-based Cortex-M33. The implementation is
compiled conditionally with compile-time directive
CONFIG_ARM_SECURE_FIRMWARE, which is to signify the intention to
build a Secure image on ARMv8-M with Security Extensions.

Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
This commit is contained in:
Ioannis Glaropoulos 2018-02-28 12:48:31 +01:00 committed by Kumar Gala
parent 92c7bd036a
commit a01e7903b2
5 changed files with 110 additions and 0 deletions

View file

@ -53,7 +53,11 @@ SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
.word __mpu_fault
.word __bus_fault
.word __usage_fault
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
.word __secure_fault
#else
.word __reserved
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
.word __reserved
.word __reserved
.word __reserved

View file

@ -44,6 +44,9 @@ GTEXT(__svc)
GTEXT(__mpu_fault)
GTEXT(__bus_fault)
GTEXT(__usage_fault)
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
GTEXT(__secure_fault)
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
GTEXT(__svc)
GTEXT(__debug_monitor)
#else

View file

@ -74,6 +74,9 @@ void _FaultDump(const NANO_ESF *esf, int fault)
PR_EXC("MMFSR: 0x%x, BFSR: 0x%x, UFSR: 0x%x\n",
SCB_MMFSR, SCB_BFSR, SCB_MMFSR);
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
PR_EXC("SFSR: 0x%x\n", SAU->SFSR);
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
/* In a fault handler, to determine the true faulting address:
* 1. Read and save the MMFAR or BFAR value.
@ -85,6 +88,9 @@ void _FaultDump(const NANO_ESF *esf, int fault)
*/
STORE_xFAR(mmfar, SCB->MMFAR);
STORE_xFAR(bfar, SCB->BFAR);
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
STORE_xFAR(sfar, SAU->SFAR);
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
if (SCB->CFSR & CFSR_MMARVALID_Msk) {
PR_EXC("MMFAR: 0x%x\n", mmfar);
@ -100,6 +106,18 @@ void _FaultDump(const NANO_ESF *esf, int fault)
SCB->CFSR &= ~CFSR_BFARVALID_Msk;
}
}
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
if (SAU->SFSR & SAU_SFSR_SFARVALID_Msk) {
PR_EXC("SFAR: 0x%x\n", sfar);
if (escalation) {
/* clear SFSR_SFAR[VALID] to reset */
SAU->SFSR &= ~SAU_SFSR_SFARVALID_Msk;
}
}
/* clear SFSR sticky bits */
SAU->SFSR |= 0xFF;
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
/* clear USFR sticky bits */
SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
@ -274,6 +292,61 @@ static void _UsageFault(const NANO_ESF *esf)
SCB->CFSR |= SCB_CFSR_USGFAULTSR_Msk;
}
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
/**
*
* @brief Dump secure fault information
*
* See _FaultDump() for example.
*
* @return N/A
*/
static void _SecureFault(const NANO_ESF *esf)
{
PR_EXC("***** SECURE FAULT *****\n");
_FaultThreadShow(esf);
STORE_xFAR(sfar, SAU->SFAR);
if (SAU->SFSR & SAU_SFSR_SFARVALID_Msk) {
PR_EXC(" Address: 0x%x\n", sfar);
}
/* bits are sticky: they stack and must be reset */
if (SAU->SFSR & SAU_SFSR_INVEP_Msk) {
PR_EXC(" Invalid entry point\n");
} else if (SAU->SFSR & SAU_SFSR_INVIS_Msk) {
PR_EXC(" Invalid integrity signature\n");
} else if (SAU->SFSR & SAU_SFSR_INVER_Msk) {
PR_EXC(" Invalid exception return\n");
} else if (SAU->SFSR & SAU_SFSR_AUVIOL_Msk) {
PR_EXC(" Attribution unit violation\n");
} else if (SAU->SFSR & SAU_SFSR_INVTRAN_Msk) {
PR_EXC(" Invalid transition\n");
} else if (SAU->SFSR & SAU_SFSR_LSPERR_Msk) {
PR_EXC(" Lazy state preservation\n");
} else if (SAU->SFSR & SAU_SFSR_LSERR_Msk) {
PR_EXC(" Lazy state error\n");
}
/* SecureFault is never banked between security states. Therefore,
* we may wish to, additionally, inspect the state of the Non-Secure
* execution (program counter), to gain more information regarding
* the root cause of the fault.
*/
NANO_ESF *esf_ns;
if (SCB_NS->ICSR & SCB_ICSR_RETTOBASE_Msk) {
esf_ns = (NANO_ESF *)__TZ_get_PSP_NS();
} else {
esf_ns = (NANO_ESF *)__TZ_get_MSP_NS();
}
PR_EXC(" NS instruction address: 0x%x\n", esf_ns->pc);
/* clear SFSR sticky bits */
SAU->SFSR |= 0xFF;
}
#endif /* defined(CONFIG_ARM_SECURE_FIRMWARE) */
/**
*
* @brief Dump debug monitor exception information
@ -318,6 +391,10 @@ static void _HardFault(const NANO_ESF *esf)
_BusFault(esf, 1);
} else if (SCB_UFSR) {
_UsageFault(esf);
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
} else if (SAU->SFSR) {
_SecureFault(esf);
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
}
}
#else
@ -379,6 +456,11 @@ static void _FaultDump(const NANO_ESF *esf, int fault)
case 6:
_UsageFault(esf);
break;
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
case 7:
_SecureFault(esf);
break;
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
case 12:
_DebugMonitor(esf);
break;

View file

@ -26,6 +26,9 @@ GTEXT(__hard_fault)
GTEXT(__mpu_fault)
GTEXT(__bus_fault)
GTEXT(__usage_fault)
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
GTEXT(__secure_fault)
#endif /* CONFIG_ARM_SECURE_FIRMWARE*/
GTEXT(__debug_monitor)
#else
#error Unknown ARM architecture
@ -51,6 +54,7 @@ GTEXT(__reserved)
* __mpu_fault
* __bus_fault
* __usage_fault
* __secure_fault
* __debug_monitor
* __reserved
*/
@ -62,6 +66,9 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__hard_fault)
SECTION_SUBSEC_FUNC(TEXT,__fault,__mpu_fault)
SECTION_SUBSEC_FUNC(TEXT,__fault,__bus_fault)
SECTION_SUBSEC_FUNC(TEXT,__fault,__usage_fault)
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
SECTION_SUBSEC_FUNC(TEXT,__fault,__secure_fault)
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
SECTION_SUBSEC_FUNC(TEXT,__fault,__debug_monitor)
#else
#error Unknown ARM architecture

View file

@ -102,10 +102,24 @@ static ALWAYS_INLINE void _ExcSetup(void)
NVIC_SetPriority(MemoryManagement_IRQn, _EXC_FAULT_PRIO);
NVIC_SetPriority(BusFault_IRQn, _EXC_FAULT_PRIO);
NVIC_SetPriority(UsageFault_IRQn, _EXC_FAULT_PRIO);
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
NVIC_SetPriority(SecureFault_IRQn, _EXC_FAULT_PRIO);
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
/* Enable Usage, Mem, & Bus Faults */
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_MEMFAULTENA_Msk |
SCB_SHCSR_BUSFAULTENA_Msk;
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
/* Enable Secure Fault */
SCB->SHCSR |= SCB_SHCSR_SECUREFAULTENA_Msk;
/* Clear BFAR before setting BusFaults to target Non-Secure state. */
SCB->BFAR = 0;
/* Set NMI, Hard, and Bus Faults as Non-Secure.
* NMI and Bus Faults targeting the Secure state will
* escalate to a SecureFault or SecureHardFault.
*/
SCB->AIRCR |= SCB_AIRCR_BFHFNMINS_Msk;
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
#endif
}