mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-22 04:24:19 +00:00
Merge changes from topic "mp/exceptions" into integration
* changes: docs(ras): update RAS documentation docs(el3-runtime): update BL31 exception vector handling fix(el3-runtime): restrict lower el EA handlers in FFH mode fix(ras): remove RAS_FFH_SUPPORT and introduce FFH_SUPPORT fix(ras): restrict ENABLE_FEAT_RAS to have only two states feat(ras): use FEAT_IESB for error synchronization feat(el3-runtime): modify vector entry paths
This commit is contained in:
commit
6f802c44e9
38 changed files with 536 additions and 240 deletions
27
Makefile
27
Makefile
|
@ -809,6 +809,14 @@ else
|
||||||
BL2_RUNS_AT_EL3 := 0
|
BL2_RUNS_AT_EL3 := 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# This internal flag is set to 1 when Firmware First handling of External aborts
|
||||||
|
# is required by lowe ELs. Currently only NS requires this support.
|
||||||
|
ifeq ($(HANDLE_EA_EL3_FIRST_NS),1)
|
||||||
|
FFH_SUPPORT := 1
|
||||||
|
else
|
||||||
|
FFH_SUPPORT := 0
|
||||||
|
endif
|
||||||
|
|
||||||
$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
|
$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
|
||||||
|
|
||||||
ifeq (${ARM_ARCH_MAJOR},7)
|
ifeq (${ARM_ARCH_MAJOR},7)
|
||||||
|
@ -970,18 +978,9 @@ endif
|
||||||
# RAS_EXTENSION is deprecated, provide alternate build options
|
# RAS_EXTENSION is deprecated, provide alternate build options
|
||||||
ifeq ($(RAS_EXTENSION),1)
|
ifeq ($(RAS_EXTENSION),1)
|
||||||
$(error "RAS_EXTENSION is now deprecated, please use ENABLE_FEAT_RAS \
|
$(error "RAS_EXTENSION is now deprecated, please use ENABLE_FEAT_RAS \
|
||||||
and RAS_FFH_SUPPORT instead")
|
and HANDLE_EA_EL3_FIRST_NS instead")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# RAS firmware first handling requires that EAs are handled in EL3 first
|
|
||||||
ifeq ($(RAS_FFH_SUPPORT),1)
|
|
||||||
ifneq ($(ENABLE_FEAT_RAS),1)
|
|
||||||
$(error For RAS_FFH_SUPPORT, ENABLE_FEAT_RAS must also be 1)
|
|
||||||
endif
|
|
||||||
ifneq ($(HANDLE_EA_EL3_FIRST_NS),1)
|
|
||||||
$(error For RAS_FFH_SUPPORT, HANDLE_EA_EL3_FIRST_NS must also be 1)
|
|
||||||
endif
|
|
||||||
endif #(RAS_FFH_SUPPORT)
|
|
||||||
|
|
||||||
# When FAULT_INJECTION_SUPPORT is used, require that FEAT_RAS is enabled
|
# When FAULT_INJECTION_SUPPORT is used, require that FEAT_RAS is enabled
|
||||||
ifeq ($(FAULT_INJECTION_SUPPORT),1)
|
ifeq ($(FAULT_INJECTION_SUPPORT),1)
|
||||||
|
@ -1283,6 +1282,8 @@ $(eval $(call assert_booleans,\
|
||||||
ENABLE_RUNTIME_INSTRUMENTATION \
|
ENABLE_RUNTIME_INSTRUMENTATION \
|
||||||
ENABLE_SME_FOR_SWD \
|
ENABLE_SME_FOR_SWD \
|
||||||
ENABLE_SVE_FOR_SWD \
|
ENABLE_SVE_FOR_SWD \
|
||||||
|
ENABLE_FEAT_RAS \
|
||||||
|
FFH_SUPPORT \
|
||||||
ERROR_DEPRECATED \
|
ERROR_DEPRECATED \
|
||||||
FAULT_INJECTION_SUPPORT \
|
FAULT_INJECTION_SUPPORT \
|
||||||
GENERATE_COT \
|
GENERATE_COT \
|
||||||
|
@ -1337,7 +1338,6 @@ $(eval $(call assert_booleans,\
|
||||||
ERRATA_ABI_SUPPORT \
|
ERRATA_ABI_SUPPORT \
|
||||||
ERRATA_NON_ARM_INTERCONNECT \
|
ERRATA_NON_ARM_INTERCONNECT \
|
||||||
CONDITIONAL_CMO \
|
CONDITIONAL_CMO \
|
||||||
RAS_FFH_SUPPORT \
|
|
||||||
PSA_CRYPTO \
|
PSA_CRYPTO \
|
||||||
ENABLE_CONSOLE_GETC \
|
ENABLE_CONSOLE_GETC \
|
||||||
)))
|
)))
|
||||||
|
@ -1360,7 +1360,6 @@ $(eval $(call assert_numerics,\
|
||||||
ENABLE_FEAT_AMU \
|
ENABLE_FEAT_AMU \
|
||||||
ENABLE_FEAT_AMUv1p1 \
|
ENABLE_FEAT_AMUv1p1 \
|
||||||
ENABLE_FEAT_CSV2_2 \
|
ENABLE_FEAT_CSV2_2 \
|
||||||
ENABLE_FEAT_RAS \
|
|
||||||
ENABLE_FEAT_DIT \
|
ENABLE_FEAT_DIT \
|
||||||
ENABLE_FEAT_ECV \
|
ENABLE_FEAT_ECV \
|
||||||
ENABLE_FEAT_FGT \
|
ENABLE_FEAT_FGT \
|
||||||
|
@ -1443,6 +1442,8 @@ $(eval $(call add_defines,\
|
||||||
ENABLE_SPE_FOR_NS \
|
ENABLE_SPE_FOR_NS \
|
||||||
ENABLE_SVE_FOR_NS \
|
ENABLE_SVE_FOR_NS \
|
||||||
ENABLE_SVE_FOR_SWD \
|
ENABLE_SVE_FOR_SWD \
|
||||||
|
ENABLE_FEAT_RAS \
|
||||||
|
FFH_SUPPORT \
|
||||||
ENCRYPT_BL31 \
|
ENCRYPT_BL31 \
|
||||||
ENCRYPT_BL32 \
|
ENCRYPT_BL32 \
|
||||||
ERROR_DEPRECATED \
|
ERROR_DEPRECATED \
|
||||||
|
@ -1460,8 +1461,6 @@ $(eval $(call add_defines,\
|
||||||
PROGRAMMABLE_RESET_ADDRESS \
|
PROGRAMMABLE_RESET_ADDRESS \
|
||||||
PSCI_EXTENDED_STATE_ID \
|
PSCI_EXTENDED_STATE_ID \
|
||||||
PSCI_OS_INIT_MODE \
|
PSCI_OS_INIT_MODE \
|
||||||
ENABLE_FEAT_RAS \
|
|
||||||
RAS_FFH_SUPPORT \
|
|
||||||
RESET_TO_BL31 \
|
RESET_TO_BL31 \
|
||||||
SEPARATE_CODE_AND_RODATA \
|
SEPARATE_CODE_AND_RODATA \
|
||||||
SEPARATE_BL2_NOLOAD_REGION \
|
SEPARATE_BL2_NOLOAD_REGION \
|
||||||
|
|
|
@ -15,31 +15,11 @@
|
||||||
#include <cpu_macros.S>
|
#include <cpu_macros.S>
|
||||||
#include <context.h>
|
#include <context.h>
|
||||||
|
|
||||||
.globl handle_lower_el_ea_esb
|
|
||||||
.globl handle_lower_el_sync_ea
|
.globl handle_lower_el_sync_ea
|
||||||
.globl handle_lower_el_async_ea
|
.globl handle_lower_el_async_ea
|
||||||
|
.globl handle_pending_async_ea
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to delegate External Aborts synchronized by ESB instruction at EL3
|
* This function handles Synchronous External Aborts from lower EL.
|
||||||
* vector entry. This function assumes GP registers x0-x29 have been saved, and
|
|
||||||
* are available for use. It delegates the handling of the EA to platform
|
|
||||||
* handler, and returns only upon successfully handling the EA; otherwise
|
|
||||||
* panics. On return from this function, the original exception handler is
|
|
||||||
* expected to resume.
|
|
||||||
*/
|
|
||||||
func handle_lower_el_ea_esb
|
|
||||||
mov x0, #ERROR_EA_ESB
|
|
||||||
mrs x1, DISR_EL1
|
|
||||||
b ea_proceed
|
|
||||||
endfunc handle_lower_el_ea_esb
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function forms the tail end of Synchronous Exception entry from lower
|
|
||||||
* EL, and expects to handle Synchronous External Aborts from lower EL and CPU
|
|
||||||
* Implementation Defined Exceptions. If any other kind of exception is detected,
|
|
||||||
* then this function reports unhandled exception.
|
|
||||||
*
|
*
|
||||||
* It delegates the handling of the EA to platform handler, and upon successfully
|
* It delegates the handling of the EA to platform handler, and upon successfully
|
||||||
* handling the EA, exits EL3; otherwise panics.
|
* handling the EA, exits EL3; otherwise panics.
|
||||||
|
@ -57,27 +37,8 @@ func handle_lower_el_sync_ea
|
||||||
cmp x30, #EC_DABORT_LOWER_EL
|
cmp x30, #EC_DABORT_LOWER_EL
|
||||||
b.eq 1f
|
b.eq 1f
|
||||||
|
|
||||||
/* Save GP registers */
|
/* EA other than above are unhandled exceptions */
|
||||||
stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
|
no_ret report_unhandled_exception
|
||||||
stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
|
|
||||||
stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
|
|
||||||
|
|
||||||
/* Get the cpu_ops pointer */
|
|
||||||
bl get_cpu_ops_ptr
|
|
||||||
|
|
||||||
/* Get the cpu_ops exception handler */
|
|
||||||
ldr x0, [x0, #CPU_E_HANDLER_FUNC]
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the reserved function pointer is NULL, this CPU does not have an
|
|
||||||
* implementation defined exception handler function
|
|
||||||
*/
|
|
||||||
cbz x0, 2f
|
|
||||||
mrs x1, esr_el3
|
|
||||||
ubfx x1, x1, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
|
||||||
blr x0
|
|
||||||
b 2f
|
|
||||||
|
|
||||||
1:
|
1:
|
||||||
/*
|
/*
|
||||||
* Save general purpose and ARMv8.3-PAuth registers (if enabled).
|
* Save general purpose and ARMv8.3-PAuth registers (if enabled).
|
||||||
|
@ -98,14 +59,6 @@ func handle_lower_el_sync_ea
|
||||||
/* el3_exit assumes SP_EL0 on entry */
|
/* el3_exit assumes SP_EL0 on entry */
|
||||||
msr spsel, #MODE_SP_EL0
|
msr spsel, #MODE_SP_EL0
|
||||||
b el3_exit
|
b el3_exit
|
||||||
2:
|
|
||||||
ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
|
|
||||||
ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
|
|
||||||
ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
|
|
||||||
|
|
||||||
/* Synchronous exceptions other than the above are assumed to be EA */
|
|
||||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
|
||||||
no_ret report_unhandled_exception
|
|
||||||
endfunc handle_lower_el_sync_ea
|
endfunc handle_lower_el_sync_ea
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,6 +93,73 @@ func handle_lower_el_async_ea
|
||||||
b el3_exit
|
b el3_exit
|
||||||
endfunc handle_lower_el_async_ea
|
endfunc handle_lower_el_async_ea
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for async EA from lower EL synchronized at EL3 entry in FFH mode.
|
||||||
|
*
|
||||||
|
* This scenario may arise when there is an error (EA) in the system which is not
|
||||||
|
* yet signaled to PE while executing in lower EL. During entry into EL3, the errors
|
||||||
|
* are synchronized either implicitly or explicitly causing async EA to pend at EL3.
|
||||||
|
*
|
||||||
|
* On detecting the pending EA (via ISR_EL1.A), if the EA routing model is Firmware
|
||||||
|
* First handling (FFH, SCR_EL3.EA = 1) this handler first handles the pending EA
|
||||||
|
* and then handles the original exception.
|
||||||
|
*
|
||||||
|
* This function assumes x30 has been saved.
|
||||||
|
*/
|
||||||
|
func handle_pending_async_ea
|
||||||
|
/*
|
||||||
|
* Prepare for nested handling of EA. Stash sysregs clobbered by nested
|
||||||
|
* exception and handler
|
||||||
|
*/
|
||||||
|
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_GPREG_LR]
|
||||||
|
mrs x30, esr_el3
|
||||||
|
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ESR_EL3]
|
||||||
|
mrs x30, spsr_el3
|
||||||
|
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_SPSR_EL3]
|
||||||
|
mrs x30, elr_el3
|
||||||
|
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ELR_EL3]
|
||||||
|
|
||||||
|
mov x30, #1
|
||||||
|
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
|
/*
|
||||||
|
* Restore the original x30 saved as part of entering EL3. This is not
|
||||||
|
* required for the current function but for EL3 SError vector entry
|
||||||
|
* once PSTATE.A bit is unmasked. We restore x30 and then the same
|
||||||
|
* value is stored in EL3 SError vector entry.
|
||||||
|
*/
|
||||||
|
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After clearing PSTATE.A bit pending SError will trigger at current EL.
|
||||||
|
* Put explicit synchronization event to ensure newly unmasked interrupt
|
||||||
|
* is taken immediately.
|
||||||
|
*/
|
||||||
|
unmask_async_ea
|
||||||
|
|
||||||
|
/* Restore the original exception information along with zeroing the storage */
|
||||||
|
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ELR_EL3]
|
||||||
|
msr elr_el3, x30
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ELR_EL3]
|
||||||
|
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_SPSR_EL3]
|
||||||
|
msr spsr_el3, x30
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_SPSR_EL3]
|
||||||
|
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ESR_EL3]
|
||||||
|
msr esr_el3, x30
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ESR_EL3]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the original exception corresponds to SError from lower El, eret back
|
||||||
|
* to lower EL, otherwise return to vector table for original exception handling.
|
||||||
|
*/
|
||||||
|
ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
||||||
|
cmp x30, #EC_SERROR
|
||||||
|
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_GPREG_LR]
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_GPREG_LR]
|
||||||
|
b.eq 1f
|
||||||
|
ret
|
||||||
|
1:
|
||||||
|
exception_return
|
||||||
|
endfunc handle_pending_async_ea
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prelude for Synchronous External Abort handling. This function assumes that
|
* Prelude for Synchronous External Abort handling. This function assumes that
|
||||||
|
@ -149,7 +169,7 @@ endfunc handle_lower_el_async_ea
|
||||||
* x1: EA syndrome
|
* x1: EA syndrome
|
||||||
*/
|
*/
|
||||||
func delegate_sync_ea
|
func delegate_sync_ea
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
/*
|
/*
|
||||||
* Check for Uncontainable error type. If so, route to the platform
|
* Check for Uncontainable error type. If so, route to the platform
|
||||||
* fatal error handler rather than the generic EA one.
|
* fatal error handler rather than the generic EA one.
|
||||||
|
@ -179,7 +199,7 @@ endfunc delegate_sync_ea
|
||||||
* x1: EA syndrome
|
* x1: EA syndrome
|
||||||
*/
|
*/
|
||||||
func delegate_async_ea
|
func delegate_async_ea
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
/* Check Exception Class to ensure SError, as this function should
|
/* Check Exception Class to ensure SError, as this function should
|
||||||
* only be invoked for SError. If that is not the case, which implies
|
* only be invoked for SError. If that is not the case, which implies
|
||||||
* either an HW error or programming error, panic.
|
* either an HW error or programming error, panic.
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <bl31/sync_handle.h>
|
#include <bl31/sync_handle.h>
|
||||||
#include <common/runtime_svc.h>
|
#include <common/runtime_svc.h>
|
||||||
#include <context.h>
|
#include <context.h>
|
||||||
|
#include <cpu_macros.S>
|
||||||
#include <el3_common_macros.S>
|
#include <el3_common_macros.S>
|
||||||
#include <lib/el3_runtime/cpu_data.h>
|
#include <lib/el3_runtime/cpu_data.h>
|
||||||
#include <lib/smccc.h>
|
#include <lib/smccc.h>
|
||||||
|
@ -47,72 +48,30 @@
|
||||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
.macro restore_x30
|
||||||
* Macro that prepares entry to EL3 upon taking an exception.
|
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||||
*
|
.endm
|
||||||
* With RAS_FFH_SUPPORT, this macro synchronizes pending errors with an
|
|
||||||
* ESB instruction. When an error is thus synchronized, the handling is
|
|
||||||
* delegated to platform EA handler.
|
|
||||||
*
|
|
||||||
* Without RAS_FFH_SUPPORT, this macro synchronizes pending errors using
|
|
||||||
* a DSB, unmasks Asynchronous External Aborts and saves X30 before
|
|
||||||
* setting the flag CTX_IS_IN_EL3.
|
|
||||||
*/
|
|
||||||
.macro check_and_unmask_ea
|
|
||||||
#if RAS_FFH_SUPPORT
|
|
||||||
/* Synchronize pending External Aborts */
|
|
||||||
esb
|
|
||||||
|
|
||||||
/* Unmask the SError interrupt */
|
|
||||||
msr daifclr, #DAIF_ABT_BIT
|
|
||||||
|
|
||||||
/* Check for SErrors synchronized by the ESB instruction */
|
|
||||||
mrs x30, DISR_EL1
|
|
||||||
tbz x30, #DISR_A_BIT, 1f
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save general purpose and ARMv8.3-PAuth registers (if enabled).
|
* Macro that synchronizes errors (EA) and checks for pending SError.
|
||||||
* Also save PMCR_EL0 and set the PSTATE to a known state.
|
* On detecting a pending SError it either reflects it back to lower
|
||||||
|
* EL (KFH) or handles it in EL3 (FFH) based on EA routing model.
|
||||||
*/
|
*/
|
||||||
bl prepare_el3_entry
|
.macro sync_and_handle_pending_serror
|
||||||
|
synchronize_errors
|
||||||
bl handle_lower_el_ea_esb
|
mrs x30, ISR_EL1
|
||||||
|
tbz x30, #ISR_A_SHIFT, 2f
|
||||||
/* Restore general purpose, PMCR_EL0 and ARMv8.3-PAuth registers */
|
#if FFH_SUPPORT
|
||||||
bl restore_gp_pmcr_pauth_regs
|
mrs x30, scr_el3
|
||||||
1:
|
tst x30, #SCR_EA_BIT
|
||||||
#else
|
b.eq 1f
|
||||||
/*
|
bl handle_pending_async_ea
|
||||||
* Note 1: The explicit DSB at the entry of various exception vectors
|
b 2f
|
||||||
* for handling exceptions from lower ELs can inadvertently trigger an
|
|
||||||
* SError exception in EL3 due to pending asynchronous aborts in lower
|
|
||||||
* ELs. This will end up being handled by serror_sp_elx which will
|
|
||||||
* ultimately panic and die.
|
|
||||||
* The way to workaround is to update a flag to indicate if the exception
|
|
||||||
* truly came from EL3. This flag is allocated in the cpu_context
|
|
||||||
* structure and located at offset "CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3"
|
|
||||||
* This is not a bullet proof solution to the problem at hand because
|
|
||||||
* we assume the instructions following "isb" that help to update the
|
|
||||||
* flag execute without causing further exceptions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For SoCs which do not implement RAS, use DSB as a barrier to
|
|
||||||
* synchronize pending external aborts.
|
|
||||||
*/
|
|
||||||
dsb sy
|
|
||||||
|
|
||||||
/* Unmask the SError interrupt */
|
|
||||||
msr daifclr, #DAIF_ABT_BIT
|
|
||||||
|
|
||||||
/* Use ISB for the above unmask operation to take effect immediately */
|
|
||||||
isb
|
|
||||||
|
|
||||||
/* Refer Note 1. */
|
|
||||||
mov x30, #1
|
|
||||||
str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
|
|
||||||
dmb sy
|
|
||||||
#endif
|
#endif
|
||||||
|
1:
|
||||||
|
/* This function never returns, but need LR for decision making */
|
||||||
|
bl reflect_pending_async_ea_to_lower_el
|
||||||
|
2:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
|
@ -147,9 +106,19 @@
|
||||||
cmp x30, #EC_AARCH64_SYS
|
cmp x30, #EC_AARCH64_SYS
|
||||||
b.eq sync_handler64
|
b.eq sync_handler64
|
||||||
|
|
||||||
/* Synchronous exceptions other than the above are assumed to be EA */
|
cmp x30, #EC_IMP_DEF_EL3
|
||||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
b.eq imp_def_el3_handler
|
||||||
|
|
||||||
|
/* If FFH Support then try to handle lower EL EA exceptions. */
|
||||||
|
#if FFH_SUPPORT
|
||||||
|
mrs x30, scr_el3
|
||||||
|
tst x30, #SCR_EA_BIT
|
||||||
|
b.eq 1f
|
||||||
b handle_lower_el_sync_ea
|
b handle_lower_el_sync_ea
|
||||||
|
#endif
|
||||||
|
1:
|
||||||
|
/* Synchronous exceptions other than the above are unhandled */
|
||||||
|
b report_unhandled_exception
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
vector_base runtime_exceptions
|
vector_base runtime_exceptions
|
||||||
|
@ -217,22 +186,33 @@ vector_entry fiq_sp_elx
|
||||||
end_vector_entry fiq_sp_elx
|
end_vector_entry fiq_sp_elx
|
||||||
|
|
||||||
vector_entry serror_sp_elx
|
vector_entry serror_sp_elx
|
||||||
#if !RAS_FFH_SUPPORT
|
#if FFH_SUPPORT
|
||||||
/*
|
/*
|
||||||
* This will trigger if the exception was taken due to SError in EL3 or
|
* This will trigger if the exception was taken due to SError in EL3 or
|
||||||
* because of pending asynchronous external aborts from lower EL that got
|
* because of pending asynchronous external aborts from lower EL that got
|
||||||
* triggered due to explicit synchronization in EL3. Refer Note 1.
|
* triggered due to implicit/explicit synchronization in EL3 (SCR_EL3.EA=1)
|
||||||
|
* during EL3 entry. For the former case we continue with "plat_handle_el3_ea".
|
||||||
|
* The later case will occur when PSTATE.A bit is cleared in
|
||||||
|
* "handle_pending_async_ea". This means we are doing a nested
|
||||||
|
* exception in EL3. Call the handler for async EA which will eret back to
|
||||||
|
* original el3 handler if it is nested exception. Also, unmask EA so that we
|
||||||
|
* catch any further EA arise when handling this nested exception at EL3.
|
||||||
*/
|
*/
|
||||||
/* Assumes SP_EL3 on entry */
|
|
||||||
save_x30
|
save_x30
|
||||||
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
|
ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
cbnz x30, 1f
|
cbz x30, 1f
|
||||||
|
/*
|
||||||
/* Handle asynchronous external abort from lower EL */
|
* This is nested exception handling, clear the flag to avoid taking this
|
||||||
|
* path for further exceptions caused by EA handling
|
||||||
|
*/
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
|
unmask_async_ea
|
||||||
b handle_lower_el_async_ea
|
b handle_lower_el_async_ea
|
||||||
1:
|
1:
|
||||||
|
restore_x30
|
||||||
#endif
|
#endif
|
||||||
no_ret plat_handle_el3_ea
|
no_ret plat_handle_el3_ea
|
||||||
|
|
||||||
end_vector_entry serror_sp_elx
|
end_vector_entry serror_sp_elx
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
|
@ -248,34 +228,41 @@ vector_entry sync_exception_aarch64
|
||||||
*/
|
*/
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
handle_sync_exception
|
handle_sync_exception
|
||||||
end_vector_entry sync_exception_aarch64
|
end_vector_entry sync_exception_aarch64
|
||||||
|
|
||||||
vector_entry irq_aarch64
|
vector_entry irq_aarch64
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
b handle_interrupt_exception
|
b handle_interrupt_exception
|
||||||
end_vector_entry irq_aarch64
|
end_vector_entry irq_aarch64
|
||||||
|
|
||||||
vector_entry fiq_aarch64
|
vector_entry fiq_aarch64
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
b handle_interrupt_exception
|
b handle_interrupt_exception
|
||||||
end_vector_entry fiq_aarch64
|
end_vector_entry fiq_aarch64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to synchronize any outstanding SError since we can get a burst of errors.
|
||||||
|
* So reuse the sync mechanism to catch any further errors which are pending.
|
||||||
|
*/
|
||||||
vector_entry serror_aarch64
|
vector_entry serror_aarch64
|
||||||
|
#if FFH_SUPPORT
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
#if RAS_FFH_SUPPORT
|
sync_and_handle_pending_serror
|
||||||
msr daifclr, #DAIF_ABT_BIT
|
unmask_async_ea
|
||||||
#else
|
|
||||||
check_and_unmask_ea
|
|
||||||
#endif
|
|
||||||
b handle_lower_el_async_ea
|
b handle_lower_el_async_ea
|
||||||
|
#else
|
||||||
|
b report_unhandled_exception
|
||||||
|
#endif
|
||||||
end_vector_entry serror_aarch64
|
end_vector_entry serror_aarch64
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
|
@ -291,34 +278,41 @@ vector_entry sync_exception_aarch32
|
||||||
*/
|
*/
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
handle_sync_exception
|
handle_sync_exception
|
||||||
end_vector_entry sync_exception_aarch32
|
end_vector_entry sync_exception_aarch32
|
||||||
|
|
||||||
vector_entry irq_aarch32
|
vector_entry irq_aarch32
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
b handle_interrupt_exception
|
b handle_interrupt_exception
|
||||||
end_vector_entry irq_aarch32
|
end_vector_entry irq_aarch32
|
||||||
|
|
||||||
vector_entry fiq_aarch32
|
vector_entry fiq_aarch32
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
check_and_unmask_ea
|
sync_and_handle_pending_serror
|
||||||
|
unmask_async_ea
|
||||||
b handle_interrupt_exception
|
b handle_interrupt_exception
|
||||||
end_vector_entry fiq_aarch32
|
end_vector_entry fiq_aarch32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to synchronize any outstanding SError since we can get a burst of errors.
|
||||||
|
* So reuse the sync mechanism to catch any further errors which are pending.
|
||||||
|
*/
|
||||||
vector_entry serror_aarch32
|
vector_entry serror_aarch32
|
||||||
|
#if FFH_SUPPORT
|
||||||
save_x30
|
save_x30
|
||||||
apply_at_speculative_wa
|
apply_at_speculative_wa
|
||||||
#if RAS_FFH_SUPPORT
|
sync_and_handle_pending_serror
|
||||||
msr daifclr, #DAIF_ABT_BIT
|
unmask_async_ea
|
||||||
#else
|
|
||||||
check_and_unmask_ea
|
|
||||||
#endif
|
|
||||||
b handle_lower_el_async_ea
|
b handle_lower_el_async_ea
|
||||||
|
#else
|
||||||
|
b report_unhandled_exception
|
||||||
|
#endif
|
||||||
end_vector_entry serror_aarch32
|
end_vector_entry serror_aarch32
|
||||||
|
|
||||||
#ifdef MONITOR_TRAPS
|
#ifdef MONITOR_TRAPS
|
||||||
|
@ -608,6 +602,114 @@ interrupt_exit:
|
||||||
b el3_exit
|
b el3_exit
|
||||||
endfunc handle_interrupt_exception
|
endfunc handle_interrupt_exception
|
||||||
|
|
||||||
|
func imp_def_el3_handler
|
||||||
|
/* Save GP registers */
|
||||||
|
stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
|
||||||
|
stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
|
||||||
|
stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
|
||||||
|
|
||||||
|
/* Get the cpu_ops pointer */
|
||||||
|
bl get_cpu_ops_ptr
|
||||||
|
|
||||||
|
/* Get the cpu_ops exception handler */
|
||||||
|
ldr x0, [x0, #CPU_E_HANDLER_FUNC]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the reserved function pointer is NULL, this CPU does not have an
|
||||||
|
* implementation defined exception handler function
|
||||||
|
*/
|
||||||
|
cbz x0, el3_handler_exit
|
||||||
|
mrs x1, esr_el3
|
||||||
|
ubfx x1, x1, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
||||||
|
blr x0
|
||||||
|
el3_handler_exit:
|
||||||
|
ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
|
||||||
|
ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
|
||||||
|
ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
|
||||||
|
restore_x30
|
||||||
|
no_ret report_unhandled_exception
|
||||||
|
endfunc imp_def_el3_handler
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for async EA from lower EL synchronized at EL3 entry in KFH mode.
|
||||||
|
*
|
||||||
|
* This scenario may arise when there is an error (EA) in the system which is not
|
||||||
|
* yet signaled to PE while executing in lower EL. During entry into EL3, the errors
|
||||||
|
* are synchronized either implicitly or explicitly causing async EA to pend at EL3.
|
||||||
|
*
|
||||||
|
* On detecting the pending EA (via ISR_EL1.A) and if the EA routing model is
|
||||||
|
* KFH (SCR_EL3.EA = 1) this handler reflects ther error back to lower EL.
|
||||||
|
*
|
||||||
|
* This function assumes x30 has been saved.
|
||||||
|
*/
|
||||||
|
func reflect_pending_async_ea_to_lower_el
|
||||||
|
/*
|
||||||
|
* As the original exception was not handled we need to ensure that we return
|
||||||
|
* back to the instruction which caused the exception. To acheive that, eret
|
||||||
|
* to "elr-4" (Label "subtract_elr_el3") for SMC or simply eret otherwise
|
||||||
|
* (Label "skip_smc_check").
|
||||||
|
*
|
||||||
|
* LIMITATION: It could be that async EA is masked at the target exception level
|
||||||
|
* or the priority of async EA wrt to the EL3/secure interrupt is lower, which
|
||||||
|
* causes back and forth between lower EL and EL3. In case of back and forth between
|
||||||
|
* lower EL and EL3, we can track the loop count in "CTX_NESTED_EA_FLAG" and leverage
|
||||||
|
* previous ELR in "CTX_SAVED_ELR_EL3" to detect this cycle and further panic
|
||||||
|
* to indicate a problem here (Label "check_loop_ctr"). If we are in this cycle, loop
|
||||||
|
* counter retains its value but if we do a normal el3_exit this flag gets cleared.
|
||||||
|
* However, setting SCR_EL3.IESB = 1, should give priority to SError handling
|
||||||
|
* as per AArch64.TakeException pseudo code in Arm ARM.
|
||||||
|
*
|
||||||
|
* TODO: In future if EL3 gets a capability to inject a virtual SError to lower
|
||||||
|
* ELs, we can remove the el3_panic and handle the original exception first and
|
||||||
|
* inject SError to lower EL before ereting back.
|
||||||
|
*/
|
||||||
|
stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
|
||||||
|
ldr x29, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ELR_EL3]
|
||||||
|
mrs x28, elr_el3
|
||||||
|
cmp x29, x28
|
||||||
|
b.eq check_loop_ctr
|
||||||
|
str x28, [sp, #CTX_EL3STATE_OFFSET + CTX_SAVED_ELR_EL3]
|
||||||
|
/* Zero the loop counter */
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
|
b skip_loop_ctr
|
||||||
|
check_loop_ctr:
|
||||||
|
ldr x29, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
|
add x29, x29, #1
|
||||||
|
str x29, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
|
cmp x29, #ASYNC_EA_REPLAY_COUNTER
|
||||||
|
b.ge el3_panic
|
||||||
|
skip_loop_ctr:
|
||||||
|
/*
|
||||||
|
* Logic to distinguish if we came from SMC or any other exception.
|
||||||
|
* Use offsets in vector entry to get which exception we are handling.
|
||||||
|
* In each vector entry of size 0x200, address "0x0-0x80" is for sync
|
||||||
|
* exception and "0x80-0x200" is for async exceptions.
|
||||||
|
* Use vector base address (vbar_el3) and exception offset (LR) to
|
||||||
|
* calculate whether the address we came from is any of the following
|
||||||
|
* "0x0-0x80", "0x200-0x280", "0x400-0x480" or "0x600-0x680"
|
||||||
|
*/
|
||||||
|
mrs x29, vbar_el3
|
||||||
|
sub x30, x30, x29
|
||||||
|
and x30, x30, #0x1ff
|
||||||
|
cmp x30, #0x80
|
||||||
|
b.ge skip_smc_check
|
||||||
|
/* Its a synchronous exception, Now check if it is SMC or not? */
|
||||||
|
mrs x30, esr_el3
|
||||||
|
ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
|
||||||
|
cmp x30, #EC_AARCH32_SMC
|
||||||
|
b.eq subtract_elr_el3
|
||||||
|
cmp x30, #EC_AARCH64_SMC
|
||||||
|
b.eq subtract_elr_el3
|
||||||
|
b skip_smc_check
|
||||||
|
subtract_elr_el3:
|
||||||
|
sub x28, x28, #4
|
||||||
|
skip_smc_check:
|
||||||
|
msr elr_el3, x28
|
||||||
|
ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
|
||||||
|
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||||
|
exception_return
|
||||||
|
endfunc reflect_pending_async_ea_to_lower_el
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* The following code handles exceptions caused by BRK instructions.
|
* The following code handles exceptions caused by BRK instructions.
|
||||||
* Following a BRK instruction, the only real valid cause of action is
|
* Following a BRK instruction, the only real valid cause of action is
|
||||||
|
|
|
@ -39,7 +39,6 @@ BL31_SOURCES += bl31/bl31_main.c \
|
||||||
bl31/interrupt_mgmt.c \
|
bl31/interrupt_mgmt.c \
|
||||||
bl31/aarch64/bl31_entrypoint.S \
|
bl31/aarch64/bl31_entrypoint.S \
|
||||||
bl31/aarch64/crash_reporting.S \
|
bl31/aarch64/crash_reporting.S \
|
||||||
bl31/aarch64/ea_delegate.S \
|
|
||||||
bl31/aarch64/runtime_exceptions.S \
|
bl31/aarch64/runtime_exceptions.S \
|
||||||
bl31/bl31_context_mgmt.c \
|
bl31/bl31_context_mgmt.c \
|
||||||
bl31/bl31_traps.c \
|
bl31/bl31_traps.c \
|
||||||
|
@ -67,6 +66,10 @@ ifeq (${EL3_EXCEPTION_HANDLING},1)
|
||||||
BL31_SOURCES += bl31/ehf.c
|
BL31_SOURCES += bl31/ehf.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (${FFH_SUPPORT},1)
|
||||||
|
BL31_SOURCES += bl31/aarch64/ea_delegate.S
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (${SDEI_SUPPORT},1)
|
ifeq (${SDEI_SUPPORT},1)
|
||||||
ifeq (${EL3_EXCEPTION_HANDLING},0)
|
ifeq (${EL3_EXCEPTION_HANDLING},0)
|
||||||
$(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support)
|
$(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support)
|
||||||
|
|
|
@ -10,6 +10,9 @@ precise definition of RAS terminology, please refer to the Arm Architecture
|
||||||
Reference Manual and `RAS Supplement`_. The rest of this document assumes
|
Reference Manual and `RAS Supplement`_. The rest of this document assumes
|
||||||
familiarity with architecture and terminology.
|
familiarity with architecture and terminology.
|
||||||
|
|
||||||
|
**IMPORTANT NOTE**: TF-A implementation assumes that if RAS extension is present
|
||||||
|
then FEAT_IESB is also implmented.
|
||||||
|
|
||||||
There are two philosophies for handling RAS errors from Non-secure world point
|
There are two philosophies for handling RAS errors from Non-secure world point
|
||||||
of view.
|
of view.
|
||||||
|
|
||||||
|
@ -56,26 +59,87 @@ Introduction
|
||||||
EA's originating/attributed to NS world are handled first in NS and Kernel navigates
|
EA's originating/attributed to NS world are handled first in NS and Kernel navigates
|
||||||
the std error records directly.
|
the std error records directly.
|
||||||
|
|
||||||
**KFH can be supported in a platform without TF-A being aware of it but there are few
|
- KFH is the default handling mode if platform does not explicitly enable FFH mode.
|
||||||
corner cases where TF-A needs to have special handling, which is currently missing and
|
- KFH mode does not need any EL3 involvement except for the reflection of errors back
|
||||||
will be added in future**
|
to lower EL. This happens when there is an error (EA) in the system which is not yet
|
||||||
|
signaled to PE while executing at lower EL. During entry into EL3 the errors (EA) are
|
||||||
|
synchronized causing async EA to pend at EL3.
|
||||||
|
|
||||||
|
Error Syncronization at EL3 entry
|
||||||
|
=================================
|
||||||
|
|
||||||
|
During entry to EL3 from lower EL, if there is any pending async EAs they are either
|
||||||
|
reflected back to lower EL (KFH) or handled in EL3 itself (FFH).
|
||||||
|
|
||||||
|
|Image 1|
|
||||||
|
|
||||||
TF-A build options
|
TF-A build options
|
||||||
==================
|
==================
|
||||||
|
|
||||||
- **ENABLE_FEAT_RAS**: Manage FEAT_RAS extension when switching the world.
|
- **ENABLE_FEAT_RAS**: Enable RAS extension feature at EL3.
|
||||||
- **RAS_FFH_SUPPORT**: Pull in necessary framework and platform hooks for Firmware first
|
- **HANDLE_EA_EL3_FIRST_NS**: Required for FFH
|
||||||
handling(FFH) of RAS errors.
|
|
||||||
- **RAS_TRAP_NS_ERR_REC_ACCESS**: Trap Non-secure access of RAS error record registers.
|
- **RAS_TRAP_NS_ERR_REC_ACCESS**: Trap Non-secure access of RAS error record registers.
|
||||||
- **RAS_EXTENSION**: Deprecated macro, equivalent to ENABLE_FEAT_RAS and RAS_FFH_SUPPORT
|
- **RAS_EXTENSION**: Deprecated macro, equivalent to ENABLE_FEAT_RAS and
|
||||||
put together.
|
HANDLE_EA_EL3_FIRST_NS put together.
|
||||||
|
|
||||||
|
RAS internal macros
|
||||||
|
|
||||||
|
- **FFH_SUPPORT**: Gets enabled if **HANDLE_EA_EL3_FIRST_NS** is enabled.
|
||||||
|
|
||||||
RAS feature has dependency on some other TF-A build flags
|
RAS feature has dependency on some other TF-A build flags
|
||||||
|
|
||||||
- **EL3_EXCEPTION_HANDLING**: Required for FFH
|
- **EL3_EXCEPTION_HANDLING**: Required for FFH
|
||||||
- **HANDLE_EA_EL3_FIRST_NS**: Required for FFH
|
|
||||||
- **FAULT_INJECTION_SUPPORT**: Required for testing RAS feature on fvp platform
|
- **FAULT_INJECTION_SUPPORT**: Required for testing RAS feature on fvp platform
|
||||||
|
|
||||||
|
TF-A Tests
|
||||||
|
==========
|
||||||
|
|
||||||
|
RAS functionality is regularly tested in TF-A CI using `RAS test group`_ which has multiple
|
||||||
|
configurations for testing lower EL External aborts.
|
||||||
|
|
||||||
|
All the tests are written in TF-A tests which runs as NS-EL2 payload.
|
||||||
|
|
||||||
|
- **FFH without RAS extension**
|
||||||
|
|
||||||
|
*fvp-ea-ffh,fvp-ea-ffh:fvp-tftf-fip.tftf-aemv8a-debug*
|
||||||
|
|
||||||
|
Couple of tests, one each for sync EA and async EA from lower EL which gets handled in El3.
|
||||||
|
Inject External aborts(sync/async) which traps in EL3, FVP has a handler which gracefully
|
||||||
|
handles these errors and returns back to TF-A Tests
|
||||||
|
|
||||||
|
Build Configs : **HANDLE_EA_EL3_FIRST_NS** , **PLATFORM_TEST_EA_FFH**
|
||||||
|
|
||||||
|
- **FFH with RAS extension**
|
||||||
|
|
||||||
|
Three Tests :
|
||||||
|
|
||||||
|
- *fvp-ras-ffh,fvp-single-fault:fvp-tftf-fip.tftf-aemv8a.fi-debug*
|
||||||
|
|
||||||
|
Inject an unrecoverable RAS error, which gets handled in EL3.
|
||||||
|
|
||||||
|
- *fvp-ras-ffh,fvp-uncontainable:fvp-tftf.fault-fip.tftf-aemv8a.fi-debug*
|
||||||
|
|
||||||
|
Inject uncontainable RAS errors which causes platform to panic.
|
||||||
|
|
||||||
|
- *fvp-ras-ffh,fvp-ras-ffh-nested:fvp-tftf-fip.tftf-ras_ffh_nested-aemv8a.fi-debug*
|
||||||
|
|
||||||
|
Test nested exception handling at El3 for synchronized async EAs. Inject an SError in lower EL
|
||||||
|
which remain pending until we enter EL3 through SMC call. At EL3 entry on encountering a pending
|
||||||
|
async EA it will handle the async EA first (nested exception) before handling the original SMC call.
|
||||||
|
|
||||||
|
- **KFH with RAS extension**
|
||||||
|
|
||||||
|
Couple of tests in the group :
|
||||||
|
|
||||||
|
- *fvp-ras-kfh,fvp-ras-kfh:fvp-tftf-fip.tftf-aemv8a.fi-debug*
|
||||||
|
|
||||||
|
Inject and handle RAS errors in TF-A tests (no El3 involvement)
|
||||||
|
|
||||||
|
- *fvp-ras-kfh,fvp-ras-kfh-reflect:fvp-tftf-fip.tftf-ras_kfh_reflection-aemv8a.fi-debug*
|
||||||
|
|
||||||
|
Reflection of synchronized errors from EL3 to TF-A tests, two tests one each for reflecting
|
||||||
|
in IRQ and SMC path.
|
||||||
|
|
||||||
RAS Framework
|
RAS Framework
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
@ -238,7 +302,7 @@ Engaging the RAS framework
|
||||||
Enabling RAS support is a platform choice
|
Enabling RAS support is a platform choice
|
||||||
|
|
||||||
The RAS support in |TF-A| introduces a default implementation of
|
The RAS support in |TF-A| introduces a default implementation of
|
||||||
``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_FFH_SUPPORT``
|
``plat_ea_handler``, the External Abort handler in EL3. When ``ENABLE_FEAT_RAS``
|
||||||
is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the
|
is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the
|
||||||
top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating
|
top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating
|
||||||
to through platform-supplied error records, probe them, and when an error is
|
to through platform-supplied error records, probe them, and when an error is
|
||||||
|
@ -277,3 +341,6 @@ for non-interrupt exceptions, they're explicit using :ref:`EHF APIs
|
||||||
*Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.*
|
*Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.*
|
||||||
|
|
||||||
.. _RAS Supplement: https://developer.arm.com/documentation/ddi0587/latest
|
.. _RAS Supplement: https://developer.arm.com/documentation/ddi0587/latest
|
||||||
|
.. _RAS Test group: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/group/tf-l3-boot-tests-ras?h=refs/heads/master
|
||||||
|
|
||||||
|
.. |Image 1| image:: ../resources/diagrams/bl31-exception-entry-error-synchronization.png
|
||||||
|
|
|
@ -1118,6 +1118,65 @@ returning through EL3 and running the non-trusted firmware (BL33):
|
||||||
``bl31_main()`` will set up the return to the normal world firmware BL33 and
|
``bl31_main()`` will set up the return to the normal world firmware BL33 and
|
||||||
continue the boot process in the normal world.
|
continue the boot process in the normal world.
|
||||||
|
|
||||||
|
Exception handling in BL31
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
When exception occurs, PE must execute handler corresponding to exception. The
|
||||||
|
location in memory where the handler is stored is called the exception vector.
|
||||||
|
For ARM architecture, exception vectors are stored in a table, called the exception
|
||||||
|
vector table.
|
||||||
|
|
||||||
|
Each EL (except EL0) has its own vector table, VBAR_ELn register stores the base
|
||||||
|
of vector table. Refer to `AArch64 exception vector table`_
|
||||||
|
|
||||||
|
Current EL with SP_EL0
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- Sync exception : Not expected except for BRK instruction, its debugging tool which
|
||||||
|
a programmer may place at specific points in a program, to check the state of
|
||||||
|
processor flags at these points in the code.
|
||||||
|
|
||||||
|
- IRQ/FIQ : Unexpected exception, panic
|
||||||
|
|
||||||
|
- SError : "plat_handle_el3_ea", defaults to panic
|
||||||
|
|
||||||
|
Current EL with SP_ELx
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- Sync exception : Unexpected exception, panic
|
||||||
|
|
||||||
|
- IRQ/FIQ : Unexpected exception, panic
|
||||||
|
|
||||||
|
- SError : "plat_handle_el3_ea" Except for special handling of lower EL's SError exception
|
||||||
|
which gets triggered in EL3 when PSTATE.A is unmasked. Its only applicable when lower
|
||||||
|
EL's EA is routed to EL3 (FFH_SUPPORT=1).
|
||||||
|
|
||||||
|
Lower EL Exceptions
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Applies to all the exceptions in both AArch64/AArch32 mode of lower EL.
|
||||||
|
|
||||||
|
Before handling any lower EL exception, we synchronize the errors at EL3 entry to ensure
|
||||||
|
that any errors pertaining to lower EL is isolated/identified. If we continue without
|
||||||
|
identifying these errors early on then these errors will trigger in EL3 (as SError from
|
||||||
|
current EL) any time after PSTATE.A is unmasked. This is wrong because the error originated
|
||||||
|
in lower EL but exception happened in EL3.
|
||||||
|
|
||||||
|
To solve this problem, synchronize the errors at EL3 entry and check for any pending
|
||||||
|
errors (async EA). If there is no pending error then continue with original exception.
|
||||||
|
If there is a pending error then, handle them based on routing model of EA's. Refer to
|
||||||
|
:ref:`Reliability, Availability, and Serviceability (RAS) Extensions` for details about
|
||||||
|
routing models.
|
||||||
|
|
||||||
|
- KFH : Reflect it back to lower EL using **reflect_pending_async_ea_to_lower_el()**
|
||||||
|
|
||||||
|
- FFH : Handle the synchronized error first using **handle_pending_async_ea()** after
|
||||||
|
that continue with original exception. It is the only scenario where EL3 is capable
|
||||||
|
of doing nested exception handling.
|
||||||
|
|
||||||
|
After synchronizing and handling lower EL SErrors, unmask EA (PSTATE.A) to ensure
|
||||||
|
that any further EA's caused by EL3 are caught.
|
||||||
|
|
||||||
Crash Reporting in BL31
|
Crash Reporting in BL31
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -2803,5 +2862,6 @@ kernel at boot time. These can be found in the ``fdts`` directory.
|
||||||
.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest
|
.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest
|
||||||
.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
|
.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
|
||||||
.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture
|
.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture
|
||||||
|
.. _AArch64 exception vector table: https://developer.arm.com/documentation/100933/0100/AArch64-exception-vector-table
|
||||||
|
|
||||||
.. |Image 1| image:: ../resources/diagrams/rt-svc-descs-layout.png
|
.. |Image 1| image:: ../resources/diagrams/rt-svc-descs-layout.png
|
||||||
|
|
|
@ -12,3 +12,10 @@ depends on certain options to be enabled or disabled.
|
||||||
interest when Armv8.4-SecEL2 or RME extension is implemented.
|
interest when Armv8.4-SecEL2 or RME extension is implemented.
|
||||||
Default is 0 (disabled). This option will be set to 1 (enabled) when ``SPD=spmd``
|
Default is 0 (disabled). This option will be set to 1 (enabled) when ``SPD=spmd``
|
||||||
and ``SPMD_SPM_AT_SEL2`` is set or when ``ENABLE_RME`` is set to 1 (enabled).
|
and ``SPMD_SPM_AT_SEL2`` is set or when ``ENABLE_RME`` is set to 1 (enabled).
|
||||||
|
|
||||||
|
- ``FFH_SUPPORT``: This boolean option provides support to enable Firmware First
|
||||||
|
handling (FFH) of External aborts and SError interrupts originating from lower
|
||||||
|
ELs which gets trapped in EL3. This option will be set to 1 (enabled) if
|
||||||
|
``HANDLE_EA_EL3_FIRST_NS`` is set. Currently only NS world routes EA to EL3 but
|
||||||
|
in future when Secure/Realm wants to use FFH then they can introduce new macros
|
||||||
|
which will enable this option implicitly.
|
||||||
|
|
|
@ -811,14 +811,12 @@ Common build options
|
||||||
- ``PSCI_OS_INIT_MODE``: Boolean flag to enable support for optional PSCI
|
- ``PSCI_OS_INIT_MODE``: Boolean flag to enable support for optional PSCI
|
||||||
OS-initiated mode. This option defaults to 0.
|
OS-initiated mode. This option defaults to 0.
|
||||||
|
|
||||||
- ``ENABLE_FEAT_RAS``: Numeric value to enable Armv8.2 RAS features. RAS features
|
- ``ENABLE_FEAT_RAS``: Boolean flag to enable Armv8.2 RAS features. RAS features
|
||||||
are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
|
are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
|
||||||
or later CPUs. This flag can take the values 0 to 2, to align with the
|
or later CPUs. This flag can take the values 0 or 1. The default value is 0.
|
||||||
``FEATURE_DETECTION`` mechanism.
|
NOTE: This flag enables use of IESB capability to reduce entry latency into
|
||||||
|
EL3 even when RAS error handling is not performed on the platform. Hence this
|
||||||
- ``RAS_FFH_SUPPORT``: Support to enable Firmware first handling of RAS errors
|
flag is recommended to be turned on Armv8.2 and later CPUs.
|
||||||
originating from NS world. When ``RAS_FFH_SUPPORT`` is set to ``1``,
|
|
||||||
``HANDLE_EA_EL3_FIRST_NS`` and ``ENABLE_FEAT_RAS`` must also be set to ``1``.
|
|
||||||
|
|
||||||
- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead
|
- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead
|
||||||
of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
|
of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
|
||||||
|
|
|
@ -3298,10 +3298,10 @@ Function : plat_ea_handler
|
||||||
Argument : uint64_t
|
Argument : uint64_t
|
||||||
Return : void
|
Return : void
|
||||||
|
|
||||||
This function is invoked by the RAS framework for the platform to handle an
|
This function is invoked by the runtime exception handling framework for the
|
||||||
External Abort received at EL3. The intention of the function is to attempt to
|
platform to handle an External Abort received at EL3. The intention of the
|
||||||
resolve the cause of External Abort and return; if that's not possible, to
|
function is to attempt to resolve the cause of External Abort and return;
|
||||||
initiate orderly shutdown of the system.
|
if that's not possible then an orderly shutdown of the system is initiated.
|
||||||
|
|
||||||
The first parameter (``int ea_reason``) indicates the reason for External Abort.
|
The first parameter (``int ea_reason``) indicates the reason for External Abort.
|
||||||
Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``.
|
Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``.
|
||||||
|
@ -3316,13 +3316,8 @@ The third parameter (``void *cookie``) is unused for now. The fourth parameter
|
||||||
(``uint64_t flags``) indicates the preempted security state. These parameters
|
(``uint64_t flags``) indicates the preempted security state. These parameters
|
||||||
are received from the top-level exception handler.
|
are received from the top-level exception handler.
|
||||||
|
|
||||||
If ``RAS_FFH_SUPPORT`` is set to ``1``, the default implementation of this
|
This function must be implemented if a platform expects Firmware First handling
|
||||||
function iterates through RAS handlers registered by the platform. If any of the
|
of External Aborts.
|
||||||
RAS handlers resolve the External Abort, no further action is taken.
|
|
||||||
|
|
||||||
If ``RAS_FFH_SUPPORT`` is set to ``0``, or if none of the platform RAS handlers
|
|
||||||
could resolve the External Abort, the default implementation prints an error
|
|
||||||
message, and panics.
|
|
||||||
|
|
||||||
Function : plat_handle_uncontainable_ea
|
Function : plat_handle_uncontainable_ea
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
|
@ -120,6 +120,14 @@
|
||||||
.endm
|
.endm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Macro for error synchronization */
|
||||||
|
.macro synchronize_errors
|
||||||
|
/* Complete any stores that may return an abort */
|
||||||
|
dsb sy
|
||||||
|
/* Synchronise the CPU context with the completion of the dsb */
|
||||||
|
isb
|
||||||
|
.endm
|
||||||
|
|
||||||
#if (ARM_ARCH_MAJOR == 7)
|
#if (ARM_ARCH_MAJOR == 7)
|
||||||
/* ARMv7 does not support stl instruction */
|
/* ARMv7 does not support stl instruction */
|
||||||
.macro stl _reg, _write_lock
|
.macro stl _reg, _write_lock
|
||||||
|
|
|
@ -962,6 +962,7 @@
|
||||||
#define EC_AARCH64_HVC U(0x16)
|
#define EC_AARCH64_HVC U(0x16)
|
||||||
#define EC_AARCH64_SMC U(0x17)
|
#define EC_AARCH64_SMC U(0x17)
|
||||||
#define EC_AARCH64_SYS U(0x18)
|
#define EC_AARCH64_SYS U(0x18)
|
||||||
|
#define EC_IMP_DEF_EL3 U(0x1f)
|
||||||
#define EC_IABORT_LOWER_EL U(0x20)
|
#define EC_IABORT_LOWER_EL U(0x20)
|
||||||
#define EC_IABORT_CUR_EL U(0x21)
|
#define EC_IABORT_CUR_EL U(0x21)
|
||||||
#define EC_PC_ALIGN U(0x22)
|
#define EC_PC_ALIGN U(0x22)
|
||||||
|
|
|
@ -292,4 +292,29 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro to unmask External Aborts by changing PSTATE.A bit.
|
||||||
|
* Put explicit synchronization event to ensure newly unmasked interrupt
|
||||||
|
* is taken immediately.
|
||||||
|
*/
|
||||||
|
.macro unmask_async_ea
|
||||||
|
msr daifclr, #DAIF_ABT_BIT
|
||||||
|
isb
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* Macro for error synchronization on exception boundries.
|
||||||
|
* With FEAT_RAS enabled, it is assumed that FEAT_IESB is also present
|
||||||
|
* and enabled.
|
||||||
|
* FEAT_IESB provides an implicit error synchronization event at exception
|
||||||
|
* entry and exception return, so there is no need for any explicit instruction.
|
||||||
|
*/
|
||||||
|
.macro synchronize_errors
|
||||||
|
#if !ENABLE_FEAT_RAS
|
||||||
|
/* Complete any stores that may return an abort */
|
||||||
|
dsb sy
|
||||||
|
/* Synchronise the CPU context with the completion of the dsb */
|
||||||
|
isb
|
||||||
|
#endif
|
||||||
|
.endm
|
||||||
|
|
||||||
#endif /* ASM_MACROS_S */
|
#endif /* ASM_MACROS_S */
|
||||||
|
|
|
@ -208,6 +208,10 @@
|
||||||
*/
|
*/
|
||||||
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
|
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
|
||||||
| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
|
| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
|
||||||
|
#if ENABLE_FEAT_RAS
|
||||||
|
/* If FEAT_RAS is present assume FEAT_IESB is also present */
|
||||||
|
orr x0, x0, #SCTLR_IESB_BIT
|
||||||
|
#endif
|
||||||
msr sctlr_el3, x0
|
msr sctlr_el3, x0
|
||||||
isb
|
isb
|
||||||
.endif /* _init_sctlr */
|
.endif /* _init_sctlr */
|
||||||
|
|
|
@ -21,4 +21,6 @@
|
||||||
/* RAS event signalled as peripheral interrupt */
|
/* RAS event signalled as peripheral interrupt */
|
||||||
#define ERROR_INTERRUPT 3
|
#define ERROR_INTERRUPT 3
|
||||||
|
|
||||||
|
#define ASYNC_EA_REPLAY_COUNTER U(100)
|
||||||
|
|
||||||
#endif /* EA_HANDLE_H */
|
#endif /* EA_HANDLE_H */
|
||||||
|
|
|
@ -63,7 +63,22 @@
|
||||||
#define CTX_PMCR_EL0 U(0x28)
|
#define CTX_PMCR_EL0 U(0x28)
|
||||||
#define CTX_IS_IN_EL3 U(0x30)
|
#define CTX_IS_IN_EL3 U(0x30)
|
||||||
#define CTX_MPAM3_EL3 U(0x38)
|
#define CTX_MPAM3_EL3 U(0x38)
|
||||||
#define CTX_EL3STATE_END U(0x40) /* Align to the next 16 byte boundary */
|
/* Constants required in supporting nested exception in EL3 */
|
||||||
|
#define CTX_SAVED_ELR_EL3 U(0x40)
|
||||||
|
/*
|
||||||
|
* General purpose flag, to save various EL3 states
|
||||||
|
* FFH mode : Used to identify if handling nested exception
|
||||||
|
* KFH mode : Used as counter value
|
||||||
|
*/
|
||||||
|
#define CTX_NESTED_EA_FLAG U(0x48)
|
||||||
|
#if FFH_SUPPORT
|
||||||
|
#define CTX_SAVED_ESR_EL3 U(0x50)
|
||||||
|
#define CTX_SAVED_SPSR_EL3 U(0x58)
|
||||||
|
#define CTX_SAVED_GPREG_LR U(0x60)
|
||||||
|
#define CTX_EL3STATE_END U(0x70) /* Align to the next 16 byte boundary */
|
||||||
|
#else
|
||||||
|
#define CTX_EL3STATE_END U(0x50) /* Align to the next 16 byte boundary */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Constants that allow assembler code to access members of and the
|
* Constants that allow assembler code to access members of and the
|
||||||
|
|
|
@ -774,7 +774,7 @@ MEASURED_BOOT
|
||||||
#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
|
#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
|
||||||
|
|
||||||
/* Priority levels for ARM platforms */
|
/* Priority levels for ARM platforms */
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
#define PLAT_RAS_PRI 0x10
|
#define PLAT_RAS_PRI 0x10
|
||||||
#endif
|
#endif
|
||||||
#define PLAT_SDEI_CRITICAL_PRI 0x60
|
#define PLAT_SDEI_CRITICAL_PRI 0x60
|
||||||
|
|
|
@ -649,23 +649,9 @@ sve_not_enabled:
|
||||||
1:
|
1:
|
||||||
#endif /* IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 */
|
#endif /* IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 */
|
||||||
|
|
||||||
/*
|
#if IMAGE_BL31
|
||||||
* This is a hot path, so we don't want to do some actual FEAT_RAS runtime
|
synchronize_errors
|
||||||
* detection here. The "esb" is a cheaper variant, so using "dsb" in the
|
#endif /* IMAGE_BL31 */
|
||||||
* ENABLE_FEAT_RAS==2 case is not ideal, but won't hurt.
|
|
||||||
*/
|
|
||||||
#if IMAGE_BL31 && ENABLE_FEAT_RAS == 1
|
|
||||||
/* ----------------------------------------------------------
|
|
||||||
* Issue Error Synchronization Barrier to synchronize SErrors
|
|
||||||
* before exiting EL3. We're running with EAs unmasked, so
|
|
||||||
* any synchronized errors would be taken immediately;
|
|
||||||
* therefore no need to inspect DISR_EL1 register.
|
|
||||||
* ----------------------------------------------------------
|
|
||||||
*/
|
|
||||||
esb
|
|
||||||
#else
|
|
||||||
dsb sy
|
|
||||||
#endif /* IMAGE_BL31 && ENABLE_FEAT_RAS */
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------
|
/* ----------------------------------------------------------
|
||||||
* Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
|
* Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
|
||||||
|
@ -689,7 +675,8 @@ sve_not_enabled:
|
||||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||||
|
|
||||||
#ifdef IMAGE_BL31
|
#ifdef IMAGE_BL31
|
||||||
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
|
/* Clear the EL3 flag as we are exiting el3 */
|
||||||
|
str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
|
||||||
#endif /* IMAGE_BL31 */
|
#endif /* IMAGE_BL31 */
|
||||||
|
|
||||||
exception_return
|
exception_return
|
||||||
|
|
|
@ -191,9 +191,6 @@ PSCI_EXTENDED_STATE_ID := 0
|
||||||
# Enable PSCI OS-initiated mode support
|
# Enable PSCI OS-initiated mode support
|
||||||
PSCI_OS_INIT_MODE := 0
|
PSCI_OS_INIT_MODE := 0
|
||||||
|
|
||||||
# Enable RAS Firmware First Handling Support
|
|
||||||
RAS_FFH_SUPPORT := 0
|
|
||||||
|
|
||||||
# By default, BL1 acts as the reset handler, not BL31
|
# By default, BL1 acts as the reset handler, not BL31
|
||||||
RESET_TO_BL31 := 0
|
RESET_TO_BL31 := 0
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ ifneq (${SPD}, tspd)
|
||||||
ENABLE_FEAT_RNG := 2
|
ENABLE_FEAT_RNG := 2
|
||||||
ENABLE_FEAT_TWED := 2
|
ENABLE_FEAT_TWED := 2
|
||||||
ENABLE_FEAT_GCS := 2
|
ENABLE_FEAT_GCS := 2
|
||||||
ENABLE_FEAT_RAS := 2
|
|
||||||
ifeq (${ARCH}, aarch64)
|
ifeq (${ARCH}, aarch64)
|
||||||
ifneq (${SPD}, spmd)
|
ifneq (${SPD}, spmd)
|
||||||
ifeq (${SPM_MM}, 0)
|
ifeq (${SPM_MM}, 0)
|
||||||
|
@ -398,8 +397,12 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (${RAS_FFH_SUPPORT},1)
|
ifeq (${HANDLE_EA_EL3_FIRST_NS},1)
|
||||||
|
ifeq (${ENABLE_FEAT_RAS},1)
|
||||||
BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c
|
BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c
|
||||||
|
else
|
||||||
|
BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (${ENABLE_STACK_PROTECTOR},0)
|
ifneq (${ENABLE_STACK_PROTECTOR},0)
|
||||||
|
@ -519,16 +522,19 @@ endif
|
||||||
# Test specific macros, keep them at bottom of this file
|
# Test specific macros, keep them at bottom of this file
|
||||||
$(eval $(call add_define,PLATFORM_TEST_EA_FFH))
|
$(eval $(call add_define,PLATFORM_TEST_EA_FFH))
|
||||||
ifeq (${PLATFORM_TEST_EA_FFH}, 1)
|
ifeq (${PLATFORM_TEST_EA_FFH}, 1)
|
||||||
ifeq (${HANDLE_EA_EL3_FIRST_NS}, 0)
|
ifeq (${FFH_SUPPORT}, 0)
|
||||||
$(error "PLATFORM_TEST_EA_FFH expects HANDLE_EA_EL3_FIRST_NS to be 1")
|
$(error "PLATFORM_TEST_EA_FFH expects FFH_SUPPORT to be 1")
|
||||||
endif
|
endif
|
||||||
BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(eval $(call add_define,PLATFORM_TEST_RAS_FFH))
|
$(eval $(call add_define,PLATFORM_TEST_RAS_FFH))
|
||||||
ifeq (${PLATFORM_TEST_RAS_FFH}, 1)
|
ifeq (${PLATFORM_TEST_RAS_FFH}, 1)
|
||||||
ifeq (${RAS_EXTENSION}, 0)
|
ifeq (${ENABLE_FEAT_RAS}, 0)
|
||||||
$(error "PLATFORM_TEST_RAS_FFH expects RAS_EXTENSION to be 1")
|
$(error "PLATFORM_TEST_RAS_FFH expects ENABLE_FEAT_RAS to be 1")
|
||||||
|
endif
|
||||||
|
ifeq (${HANDLE_EA_EL3_FIRST_NS}, 0)
|
||||||
|
$(error "PLATFORM_TEST_RAS_FFH expects HANDLE_EA_EL3_FIRST_NS to be 1")
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c
|
||||||
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
|
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (${RAS_FFH_SUPPORT},1)
|
ifeq (${ENABLE_FEAT_RAS}-${HANDLE_EA_EL3_FIRST_NS},1-1)
|
||||||
BL31_SOURCES += ${RDN2_BASE}/rdn2_ras.c \
|
BL31_SOURCES += ${RDN2_BASE}/rdn2_ras.c \
|
||||||
${CSS_ENT_BASE}/ras/sgi_ras_common.c \
|
${CSS_ENT_BASE}/ras/sgi_ras_common.c \
|
||||||
${CSS_ENT_BASE}/ras/sgi_ras_sram.c \
|
${CSS_ENT_BASE}/ras/sgi_ras_sram.c \
|
||||||
|
|
|
@ -137,7 +137,7 @@ void bl31_platform_setup(void)
|
||||||
|
|
||||||
sgi_bl31_common_platform_setup();
|
sgi_bl31_common_platform_setup();
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
sgi_ras_platform_setup(&ras_config);
|
sgi_ras_platform_setup(&ras_config);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
static const arm_tzc_regions_info_t tzc_regions[] = {
|
static const arm_tzc_regions_info_t tzc_regions[] = {
|
||||||
ARM_TZC_REGIONS_DEF,
|
ARM_TZC_REGIONS_DEF,
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
RDN2_TZC_CPER_REGION,
|
RDN2_TZC_CPER_REGION,
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -21,8 +21,6 @@ CSS_USE_SCMI_SDS_DRIVER := 1
|
||||||
|
|
||||||
ENABLE_FEAT_RAS := 1
|
ENABLE_FEAT_RAS := 1
|
||||||
|
|
||||||
RAS_FFH_SUPPORT := 0
|
|
||||||
|
|
||||||
SDEI_SUPPORT := 0
|
SDEI_SUPPORT := 0
|
||||||
|
|
||||||
EL3_EXCEPTION_HANDLING := 0
|
EL3_EXCEPTION_HANDLING := 0
|
||||||
|
|
|
@ -295,7 +295,7 @@ void arm_bl31_platform_setup(void)
|
||||||
/* Initialize power controller before setting up topology */
|
/* Initialize power controller before setting up topology */
|
||||||
plat_arm_pwrc_setup();
|
plat_arm_pwrc_setup();
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
ras_init();
|
ras_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -352,7 +352,7 @@ endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# RAS sources
|
# RAS sources
|
||||||
ifeq (${RAS_FFH_SUPPORT},1)
|
ifeq (${ENABLE_FEAT_RAS}-${HANDLE_EA_EL3_FIRST_NS},1-1)
|
||||||
BL31_SOURCES += lib/extensions/ras/std_err_record.c \
|
BL31_SOURCES += lib/extensions/ras/std_err_record.c \
|
||||||
lib/extensions/ras/ras_common.c
|
lib/extensions/ras/ras_common.c
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -41,7 +41,7 @@ static const uintptr_t *gicr_frames = gicr_base_addrs;
|
||||||
static const interrupt_prop_t arm_interrupt_props[] = {
|
static const interrupt_prop_t arm_interrupt_props[] = {
|
||||||
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
|
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
|
||||||
PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0),
|
PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0),
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
INTR_PROP_DESC(PLAT_CORE_FAULT_IRQ, PLAT_RAS_PRI, INTR_GROUP0,
|
INTR_PROP_DESC(PLAT_CORE_FAULT_IRQ, PLAT_RAS_PRI, INTR_GROUP0,
|
||||||
GIC_INTR_CFG_LEVEL)
|
GIC_INTR_CFG_LEVEL)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -204,13 +204,13 @@
|
||||||
SOC_CSS_DEVICE_SIZE, \
|
SOC_CSS_DEVICE_SIZE, \
|
||||||
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
|
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
#define PLAT_SP_PRI PLAT_RAS_PRI
|
#define PLAT_SP_PRI PLAT_RAS_PRI
|
||||||
#else
|
#else
|
||||||
#define PLAT_SP_PRI 0x10
|
#define PLAT_SP_PRI 0x10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)) && RAS_FFH_SUPPORT
|
#if (SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)) && ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
/*
|
/*
|
||||||
* CPER buffer memory of 128KB is reserved and it is placed adjacent to the
|
* CPER buffer memory of 128KB is reserved and it is placed adjacent to the
|
||||||
* memory shared between EL3 and S-EL0.
|
* memory shared between EL3 and S-EL0.
|
||||||
|
@ -239,7 +239,7 @@
|
||||||
*/
|
*/
|
||||||
#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
|
#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
|
||||||
PLAT_SP_IMAGE_NS_BUF_SIZE)
|
PLAT_SP_IMAGE_NS_BUF_SIZE)
|
||||||
#endif /* SPM_MM && RAS_FFH_SUPPORT */
|
#endif /* SPM_MM && ENABLE_FEAT_RAS && FFH_SUPPORT */
|
||||||
|
|
||||||
/* Platform ID address */
|
/* Platform ID address */
|
||||||
#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
|
#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
|
||||||
|
|
|
@ -10,8 +10,6 @@ CSS_ENT_BASE := plat/arm/css/sgi
|
||||||
|
|
||||||
ENABLE_FEAT_RAS := 1
|
ENABLE_FEAT_RAS := 1
|
||||||
|
|
||||||
RAS_FFH_SUPPORT := 0
|
|
||||||
|
|
||||||
SDEI_SUPPORT := 0
|
SDEI_SUPPORT := 0
|
||||||
|
|
||||||
EL3_EXCEPTION_HANDLING := 0
|
EL3_EXCEPTION_HANDLING := 0
|
||||||
|
|
|
@ -93,7 +93,7 @@ const mmap_region_t plat_arm_secure_partition_mmap[] = {
|
||||||
PLAT_ARM_SECURE_MAP_DEVICE,
|
PLAT_ARM_SECURE_MAP_DEVICE,
|
||||||
ARM_SP_IMAGE_MMAP,
|
ARM_SP_IMAGE_MMAP,
|
||||||
ARM_SP_IMAGE_NS_BUF_MMAP,
|
ARM_SP_IMAGE_NS_BUF_MMAP,
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
CSS_SGI_SP_CPER_BUF_MMAP,
|
CSS_SGI_SP_CPER_BUF_MMAP,
|
||||||
#endif
|
#endif
|
||||||
ARM_SP_IMAGE_RW_MMAP,
|
ARM_SP_IMAGE_RW_MMAP,
|
||||||
|
|
|
@ -87,7 +87,7 @@ const mmap_region_t plat_arm_secure_partition_mmap[] = {
|
||||||
SOC_PLATFORM_PERIPH_MAP_DEVICE_USER,
|
SOC_PLATFORM_PERIPH_MAP_DEVICE_USER,
|
||||||
ARM_SP_IMAGE_MMAP,
|
ARM_SP_IMAGE_MMAP,
|
||||||
ARM_SP_IMAGE_NS_BUF_MMAP,
|
ARM_SP_IMAGE_NS_BUF_MMAP,
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
CSS_SGI_SP_CPER_BUF_MMAP,
|
CSS_SGI_SP_CPER_BUF_MMAP,
|
||||||
#endif
|
#endif
|
||||||
ARM_SP_IMAGE_RW_MMAP,
|
ARM_SP_IMAGE_RW_MMAP,
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <arch_helpers.h>
|
#include <arch_helpers.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
#include <drivers/console.h>
|
#include <drivers/console.h>
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
#include <lib/extensions/ras.h>
|
#include <lib/extensions/ras.h>
|
||||||
#endif
|
#endif
|
||||||
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
||||||
|
@ -29,7 +29,9 @@
|
||||||
#pragma weak plat_sdei_validate_entry_point
|
#pragma weak plat_sdei_validate_entry_point
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FFH_SUPPORT
|
||||||
#pragma weak plat_ea_handler = plat_default_ea_handler
|
#pragma weak plat_ea_handler = plat_default_ea_handler
|
||||||
|
#endif
|
||||||
|
|
||||||
void bl31_plat_runtime_setup(void)
|
void bl31_plat_runtime_setup(void)
|
||||||
{
|
{
|
||||||
|
@ -77,11 +79,12 @@ const char *get_el_str(unsigned int el)
|
||||||
return "EL1";
|
return "EL1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FFH_SUPPORT
|
||||||
/* Handler for External Aborts from lower EL including RAS errors */
|
/* Handler for External Aborts from lower EL including RAS errors */
|
||||||
void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
||||||
void *handle, uint64_t flags)
|
void *handle, uint64_t flags)
|
||||||
{
|
{
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
/* Call RAS EA handler */
|
/* Call RAS EA handler */
|
||||||
int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
||||||
if (handled != 0)
|
if (handled != 0)
|
||||||
|
@ -99,3 +102,4 @@ void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *co
|
||||||
*/
|
*/
|
||||||
lower_el_panic();
|
lower_el_panic();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* Enumeration of priority levels on ARM platforms.
|
* Enumeration of priority levels on ARM platforms.
|
||||||
*/
|
*/
|
||||||
ehf_pri_desc_t plat_exceptions[] = {
|
ehf_pri_desc_t plat_exceptions[] = {
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
/* RAS Priority */
|
/* RAS Priority */
|
||||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI),
|
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI),
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,7 +26,7 @@ ehf_pri_desc_t plat_exceptions[] = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)
|
#if SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
#if (PLAT_SP_PRI != PLAT_RAS_PRI)
|
#if (PLAT_SP_PRI != PLAT_RAS_PRI)
|
||||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
|
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -154,7 +154,7 @@ int plat_sip_handler(uint32_t smc_fid,
|
||||||
void *handle,
|
void *handle,
|
||||||
uint64_t flags);
|
uint64_t flags);
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS && FFH_SUPPORT
|
||||||
void tegra194_ras_enable(void);
|
void tegra194_ras_enable(void);
|
||||||
void tegra194_ras_corrected_err_clear(uint64_t *cookie);
|
void tegra194_ras_corrected_err_clear(uint64_t *cookie);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -484,7 +484,7 @@ REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts);
|
||||||
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
||||||
void *handle, uint64_t flags)
|
void *handle, uint64_t flags)
|
||||||
{
|
{
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
||||||
#else
|
#else
|
||||||
plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
||||||
|
|
|
@ -254,7 +254,7 @@ void plat_early_platform_setup(void)
|
||||||
/* sanity check MCE firmware compatibility */
|
/* sanity check MCE firmware compatibility */
|
||||||
mce_verify_firmware_version();
|
mce_verify_firmware_version();
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
/* Enable Uncorrectable RAS error */
|
/* Enable Uncorrectable RAS error */
|
||||||
tegra194_ras_enable();
|
tegra194_ras_enable();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -71,7 +71,7 @@ int32_t plat_sip_handler(uint32_t smc_fid,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if RAS_FFH_SUPPORT
|
#if ENABLE_FEAT_RAS
|
||||||
case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS:
|
case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -37,7 +37,7 @@ $(eval $(call add_define,MAX_MMAP_REGIONS))
|
||||||
|
|
||||||
# enable RAS handling
|
# enable RAS handling
|
||||||
HANDLE_EA_EL3_FIRST_NS := 1
|
HANDLE_EA_EL3_FIRST_NS := 1
|
||||||
RAS_FFH_SUPPORT := 1
|
ENABLE_FEAT_RAS := 1
|
||||||
|
|
||||||
# platform files
|
# platform files
|
||||||
PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t194 \
|
PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t194 \
|
||||||
|
@ -71,7 +71,7 @@ BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# RAS sources
|
# RAS sources
|
||||||
ifeq (${RAS_FFH_SUPPORT},1)
|
ifeq (${ENABLE_FEAT_RAS}-${HANDLE_EA_EL3_FIRST_NS},1-1)
|
||||||
BL31_SOURCES += lib/extensions/ras/std_err_record.c \
|
BL31_SOURCES += lib/extensions/ras/std_err_record.c \
|
||||||
lib/extensions/ras/ras_common.c \
|
lib/extensions/ras/ras_common.c \
|
||||||
${SOC_DIR}/plat_ras.c
|
${SOC_DIR}/plat_ras.c
|
||||||
|
|
Loading…
Add table
Reference in a new issue