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
diff --git a/Makefile b/Makefile
index 7f781a0..da9eb9f 100644
--- a/Makefile
+++ b/Makefile
@@ -809,6 +809,14 @@
BL2_RUNS_AT_EL3 := 0
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}))
ifeq (${ARM_ARCH_MAJOR},7)
@@ -970,18 +978,9 @@
# RAS_EXTENSION is deprecated, provide alternate build options
ifeq ($(RAS_EXTENSION),1)
$(error "RAS_EXTENSION is now deprecated, please use ENABLE_FEAT_RAS \
- and RAS_FFH_SUPPORT instead")
+ and HANDLE_EA_EL3_FIRST_NS instead")
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
ifeq ($(FAULT_INJECTION_SUPPORT),1)
@@ -1283,6 +1282,8 @@
ENABLE_RUNTIME_INSTRUMENTATION \
ENABLE_SME_FOR_SWD \
ENABLE_SVE_FOR_SWD \
+ ENABLE_FEAT_RAS \
+ FFH_SUPPORT \
ERROR_DEPRECATED \
FAULT_INJECTION_SUPPORT \
GENERATE_COT \
@@ -1337,7 +1338,6 @@
ERRATA_ABI_SUPPORT \
ERRATA_NON_ARM_INTERCONNECT \
CONDITIONAL_CMO \
- RAS_FFH_SUPPORT \
PSA_CRYPTO \
ENABLE_CONSOLE_GETC \
)))
@@ -1360,7 +1360,6 @@
ENABLE_FEAT_AMU \
ENABLE_FEAT_AMUv1p1 \
ENABLE_FEAT_CSV2_2 \
- ENABLE_FEAT_RAS \
ENABLE_FEAT_DIT \
ENABLE_FEAT_ECV \
ENABLE_FEAT_FGT \
@@ -1443,6 +1442,8 @@
ENABLE_SPE_FOR_NS \
ENABLE_SVE_FOR_NS \
ENABLE_SVE_FOR_SWD \
+ ENABLE_FEAT_RAS \
+ FFH_SUPPORT \
ENCRYPT_BL31 \
ENCRYPT_BL32 \
ERROR_DEPRECATED \
@@ -1460,8 +1461,6 @@
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
PSCI_OS_INIT_MODE \
- ENABLE_FEAT_RAS \
- RAS_FFH_SUPPORT \
RESET_TO_BL31 \
SEPARATE_CODE_AND_RODATA \
SEPARATE_BL2_NOLOAD_REGION \
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index dd6b4dc..28d2187 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -15,31 +15,11 @@
#include <cpu_macros.S>
#include <context.h>
- .globl handle_lower_el_ea_esb
.globl handle_lower_el_sync_ea
.globl handle_lower_el_async_ea
-
-
-/*
- * Function to delegate External Aborts synchronized by ESB instruction at EL3
- * 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
-
-
+ .globl handle_pending_async_ea
/*
- * 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.
+ * This function handles Synchronous External Aborts from lower EL.
*
* It delegates the handling of the EA to platform handler, and upon successfully
* handling the EA, exits EL3; otherwise panics.
@@ -57,27 +37,8 @@
cmp x30, #EC_DABORT_LOWER_EL
b.eq 1f
- /* 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, 2f
- mrs x1, esr_el3
- ubfx x1, x1, #ESR_EC_SHIFT, #ESR_EC_LENGTH
- blr x0
- b 2f
-
+ /* EA other than above are unhandled exceptions */
+ no_ret report_unhandled_exception
1:
/*
* Save general purpose and ARMv8.3-PAuth registers (if enabled).
@@ -98,14 +59,6 @@
/* el3_exit assumes SP_EL0 on entry */
msr spsel, #MODE_SP_EL0
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
@@ -140,6 +93,73 @@
b el3_exit
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
@@ -149,7 +169,7 @@
* x1: EA syndrome
*/
func delegate_sync_ea
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
/*
* Check for Uncontainable error type. If so, route to the platform
* fatal error handler rather than the generic EA one.
@@ -179,7 +199,7 @@
* x1: EA syndrome
*/
func delegate_async_ea
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
/* Check Exception Class to ensure SError, as this function should
* only be invoked for SError. If that is not the case, which implies
* either an HW error or programming error, panic.
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 8298696..ed48311 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -13,6 +13,7 @@
#include <bl31/sync_handle.h>
#include <common/runtime_svc.h>
#include <context.h>
+#include <cpu_macros.S>
#include <el3_common_macros.S>
#include <lib/el3_runtime/cpu_data.h>
#include <lib/smccc.h>
@@ -47,72 +48,30 @@
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
.endm
- /*
- * Macro that prepares entry to EL3 upon taking an exception.
- *
- * 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).
- * Also save PMCR_EL0 and set the PSTATE to a known state.
- */
- bl prepare_el3_entry
-
- bl handle_lower_el_ea_esb
-
- /* Restore general purpose, PMCR_EL0 and ARMv8.3-PAuth registers */
- bl restore_gp_pmcr_pauth_regs
-1:
-#else
- /*
- * Note 1: The explicit DSB at the entry of various exception vectors
- * 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.
- */
+ .macro restore_x30
+ ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+ .endm
/*
- * For SoCs which do not implement RAS, use DSB as a barrier to
- * synchronize pending external aborts.
+ * Macro that synchronizes errors (EA) and checks for pending SError.
+ * 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.
*/
- 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
+ .macro sync_and_handle_pending_serror
+ synchronize_errors
+ mrs x30, ISR_EL1
+ tbz x30, #ISR_A_SHIFT, 2f
+#if FFH_SUPPORT
+ mrs x30, scr_el3
+ tst x30, #SCR_EA_BIT
+ b.eq 1f
+ bl handle_pending_async_ea
+ b 2f
#endif
+1:
+ /* This function never returns, but need LR for decision making */
+ bl reflect_pending_async_ea_to_lower_el
+2:
.endm
/* ---------------------------------------------------------------------
@@ -147,9 +106,19 @@
cmp x30, #EC_AARCH64_SYS
b.eq sync_handler64
- /* Synchronous exceptions other than the above are assumed to be EA */
- ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+ cmp x30, #EC_IMP_DEF_EL3
+ 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
+#endif
+1:
+ /* Synchronous exceptions other than the above are unhandled */
+ b report_unhandled_exception
.endm
vector_base runtime_exceptions
@@ -217,22 +186,33 @@
end_vector_entry fiq_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
* 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
- ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3]
- cbnz x30, 1f
-
- /* Handle asynchronous external abort from lower EL */
+ ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_NESTED_EA_FLAG]
+ cbz x30, 1f
+ /*
+ * 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
1:
+ restore_x30
#endif
no_ret plat_handle_el3_ea
+
end_vector_entry serror_sp_elx
/* ---------------------------------------------------------------------
@@ -248,34 +228,41 @@
*/
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
handle_sync_exception
end_vector_entry sync_exception_aarch64
vector_entry irq_aarch64
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
b handle_interrupt_exception
end_vector_entry irq_aarch64
vector_entry fiq_aarch64
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
b handle_interrupt_exception
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
+#if FFH_SUPPORT
save_x30
apply_at_speculative_wa
-#if RAS_FFH_SUPPORT
- msr daifclr, #DAIF_ABT_BIT
+ sync_and_handle_pending_serror
+ unmask_async_ea
+ b handle_lower_el_async_ea
#else
- check_and_unmask_ea
+ b report_unhandled_exception
#endif
- b handle_lower_el_async_ea
-
end_vector_entry serror_aarch64
/* ---------------------------------------------------------------------
@@ -291,34 +278,41 @@
*/
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
handle_sync_exception
end_vector_entry sync_exception_aarch32
vector_entry irq_aarch32
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
b handle_interrupt_exception
end_vector_entry irq_aarch32
vector_entry fiq_aarch32
save_x30
apply_at_speculative_wa
- check_and_unmask_ea
+ sync_and_handle_pending_serror
+ unmask_async_ea
b handle_interrupt_exception
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
+#if FFH_SUPPORT
save_x30
apply_at_speculative_wa
-#if RAS_FFH_SUPPORT
- msr daifclr, #DAIF_ABT_BIT
+ sync_and_handle_pending_serror
+ unmask_async_ea
+ b handle_lower_el_async_ea
#else
- check_and_unmask_ea
+ b report_unhandled_exception
#endif
- b handle_lower_el_async_ea
-
end_vector_entry serror_aarch32
#ifdef MONITOR_TRAPS
@@ -608,6 +602,114 @@
b el3_exit
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.
* Following a BRK instruction, the only real valid cause of action is
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index a1fc12b..3359526 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -39,7 +39,6 @@
bl31/interrupt_mgmt.c \
bl31/aarch64/bl31_entrypoint.S \
bl31/aarch64/crash_reporting.S \
- bl31/aarch64/ea_delegate.S \
bl31/aarch64/runtime_exceptions.S \
bl31/bl31_context_mgmt.c \
bl31/bl31_traps.c \
@@ -67,6 +66,10 @@
BL31_SOURCES += bl31/ehf.c
endif
+ifeq (${FFH_SUPPORT},1)
+BL31_SOURCES += bl31/aarch64/ea_delegate.S
+endif
+
ifeq (${SDEI_SUPPORT},1)
ifeq (${EL3_EXCEPTION_HANDLING},0)
$(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support)
diff --git a/docs/components/ras.rst b/docs/components/ras.rst
index 8d00345..747367a 100644
--- a/docs/components/ras.rst
+++ b/docs/components/ras.rst
@@ -10,6 +10,9 @@
Reference Manual and `RAS Supplement`_. The rest of this document assumes
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
of view.
@@ -56,26 +59,87 @@
EA's originating/attributed to NS world are handled first in NS and Kernel navigates
the std error records directly.
+- KFH is the default handling mode if platform does not explicitly enable FFH mode.
+- KFH mode does not need any EL3 involvement except for the reflection of errors back
+ 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).
+
-**KFH can be supported in a platform without TF-A being aware of it but there are few
-corner cases where TF-A needs to have special handling, which is currently missing and
-will be added in future**
+|Image 1|
TF-A build options
==================
-- **ENABLE_FEAT_RAS**: Manage FEAT_RAS extension when switching the world.
-- **RAS_FFH_SUPPORT**: Pull in necessary framework and platform hooks for Firmware first
- handling(FFH) of RAS errors.
+- **ENABLE_FEAT_RAS**: Enable RAS extension feature at EL3.
+- **HANDLE_EA_EL3_FIRST_NS**: Required for FFH
- **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
- put together.
+- **RAS_EXTENSION**: Deprecated macro, equivalent to ENABLE_FEAT_RAS and
+ 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
- **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
+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
=============
@@ -238,7 +302,7 @@
Enabling RAS support is a platform choice
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
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
@@ -277,3 +341,6 @@
*Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.*
.. _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
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 879ddda..ff69b43 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1118,6 +1118,65 @@
``bl31_main()`` will set up the return to the normal world firmware BL33 and
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
-----------------------
@@ -2803,5 +2862,6 @@
.. _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
.. _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
diff --git a/docs/getting_started/build-internals.rst b/docs/getting_started/build-internals.rst
index a015d71..390c367 100644
--- a/docs/getting_started/build-internals.rst
+++ b/docs/getting_started/build-internals.rst
@@ -12,3 +12,10 @@
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``
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.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 347cf20..43b13d6 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -811,14 +811,12 @@
- ``PSCI_OS_INIT_MODE``: Boolean flag to enable support for optional PSCI
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
- or later CPUs. This flag can take the values 0 to 2, to align with the
- ``FEATURE_DETECTION`` mechanism.
-
-- ``RAS_FFH_SUPPORT``: Support to enable Firmware first handling of RAS errors
- 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``.
+ or later CPUs. This flag can take the values 0 or 1. The default value is 0.
+ 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
+ flag is recommended to be turned on Armv8.2 and later CPUs.
- ``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
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index f612e1c..082497c 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -3298,10 +3298,10 @@
Argument : uint64_t
Return : void
-This function is invoked by the RAS framework for the platform to handle an
-External Abort received at EL3. The intention of the function is to attempt to
-resolve the cause of External Abort and return; if that's not possible, to
-initiate orderly shutdown of the system.
+This function is invoked by the runtime exception handling framework for the
+platform to handle an External Abort received at EL3. The intention of the
+function is to attempt to resolve the cause of External Abort and return;
+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.
Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``.
@@ -3316,13 +3316,8 @@
(``uint64_t flags``) indicates the preempted security state. These parameters
are received from the top-level exception handler.
-If ``RAS_FFH_SUPPORT`` is set to ``1``, the default implementation of this
-function iterates through RAS handlers registered by the platform. If any of the
-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.
+This function must be implemented if a platform expects Firmware First handling
+of External Aborts.
Function : plat_handle_uncontainable_ea
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/resources/diagrams/bl31-exception-entry-error-synchronization.png b/docs/resources/diagrams/bl31-exception-entry-error-synchronization.png
new file mode 100644
index 0000000..cdfdcb9
--- /dev/null
+++ b/docs/resources/diagrams/bl31-exception-entry-error-synchronization.png
Binary files differ
diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S
index 83e94ca..3ba86e9 100644
--- a/include/arch/aarch32/asm_macros.S
+++ b/include/arch/aarch32/asm_macros.S
@@ -120,6 +120,14 @@
.endm
#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)
/* ARMv7 does not support stl instruction */
.macro stl _reg, _write_lock
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 13927bd..e9d22b6 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -962,6 +962,7 @@
#define EC_AARCH64_HVC U(0x16)
#define EC_AARCH64_SMC U(0x17)
#define EC_AARCH64_SYS U(0x18)
+#define EC_IMP_DEF_EL3 U(0x1f)
#define EC_IABORT_LOWER_EL U(0x20)
#define EC_IABORT_CUR_EL U(0x21)
#define EC_PC_ALIGN U(0x22)
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index 6091f62..d09ad0f 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -292,4 +292,29 @@
#endif
.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 */
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 9c9c00f..a78837f 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -208,6 +208,10 @@
*/
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_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
isb
.endif /* _init_sctlr */
diff --git a/include/bl31/ea_handle.h b/include/bl31/ea_handle.h
index 68f012c..7cd7b6a 100644
--- a/include/bl31/ea_handle.h
+++ b/include/bl31/ea_handle.h
@@ -21,4 +21,6 @@
/* RAS event signalled as peripheral interrupt */
#define ERROR_INTERRUPT 3
+#define ASYNC_EA_REPLAY_COUNTER U(100)
+
#endif /* EA_HANDLE_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 470d113..47d91de 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -63,7 +63,22 @@
#define CTX_PMCR_EL0 U(0x28)
#define CTX_IS_IN_EL3 U(0x30)
#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
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 314eb93..9176e88 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -774,7 +774,7 @@
#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
/* Priority levels for ARM platforms */
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
#define PLAT_RAS_PRI 0x10
#endif
#define PLAT_SDEI_CRITICAL_PRI 0x60
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 41b25d6..631094f 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -649,23 +649,9 @@
1:
#endif /* IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 */
-/*
- * This is a hot path, so we don't want to do some actual FEAT_RAS runtime
- * detection here. The "esb" is a cheaper variant, so using "dsb" in the
- * 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 */
+#if IMAGE_BL31
+ synchronize_errors
+#endif /* IMAGE_BL31 */
/* ----------------------------------------------------------
* Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
@@ -689,7 +675,8 @@
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
#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 */
exception_return
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index ea22655..e02917c 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -191,9 +191,6 @@
# Enable PSCI OS-initiated mode support
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
RESET_TO_BL31 := 0
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index f7c174f..2fdff34 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -56,7 +56,6 @@
ENABLE_FEAT_RNG := 2
ENABLE_FEAT_TWED := 2
ENABLE_FEAT_GCS := 2
- ENABLE_FEAT_RAS := 2
ifeq (${ARCH}, aarch64)
ifneq (${SPD}, spmd)
ifeq (${SPM_MM}, 0)
@@ -398,8 +397,12 @@
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
+else
+BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c
+endif
endif
ifneq (${ENABLE_STACK_PROTECTOR},0)
@@ -519,16 +522,19 @@
# Test specific macros, keep them at bottom of this file
$(eval $(call add_define,PLATFORM_TEST_EA_FFH))
ifeq (${PLATFORM_TEST_EA_FFH}, 1)
- ifeq (${HANDLE_EA_EL3_FIRST_NS}, 0)
- $(error "PLATFORM_TEST_EA_FFH expects HANDLE_EA_EL3_FIRST_NS to be 1")
+ ifeq (${FFH_SUPPORT}, 0)
+ $(error "PLATFORM_TEST_EA_FFH expects FFH_SUPPORT to be 1")
endif
-BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c
+
endif
$(eval $(call add_define,PLATFORM_TEST_RAS_FFH))
ifeq (${PLATFORM_TEST_RAS_FFH}, 1)
- ifeq (${RAS_EXTENSION}, 0)
- $(error "PLATFORM_TEST_RAS_FFH expects RAS_EXTENSION to be 1")
+ ifeq (${ENABLE_FEAT_RAS}, 0)
+ $(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
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 1506714..ef8f3d4 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -69,7 +69,7 @@
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
endif
-ifeq (${RAS_FFH_SUPPORT},1)
+ifeq (${ENABLE_FEAT_RAS}-${HANDLE_EA_EL3_FIRST_NS},1-1)
BL31_SOURCES += ${RDN2_BASE}/rdn2_ras.c \
${CSS_ENT_BASE}/ras/sgi_ras_common.c \
${CSS_ENT_BASE}/ras/sgi_ras_sram.c \
diff --git a/plat/arm/board/rdn2/rdn2_plat.c b/plat/arm/board/rdn2/rdn2_plat.c
index f117456..2a6c658 100644
--- a/plat/arm/board/rdn2/rdn2_plat.c
+++ b/plat/arm/board/rdn2/rdn2_plat.c
@@ -137,7 +137,7 @@
sgi_bl31_common_platform_setup();
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
sgi_ras_platform_setup(&ras_config);
#endif
}
diff --git a/plat/arm/board/rdn2/rdn2_security.c b/plat/arm/board/rdn2/rdn2_security.c
index b836a7f..7cd4a1c 100644
--- a/plat/arm/board/rdn2/rdn2_security.c
+++ b/plat/arm/board/rdn2/rdn2_security.c
@@ -15,7 +15,7 @@
static const arm_tzc_regions_info_t tzc_regions[] = {
ARM_TZC_REGIONS_DEF,
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
RDN2_TZC_CPER_REGION,
#endif
{}
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 8ca33ca..8db6f1d 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -21,8 +21,6 @@
ENABLE_FEAT_RAS := 1
-RAS_FFH_SUPPORT := 0
-
SDEI_SUPPORT := 0
EL3_EXCEPTION_HANDLING := 0
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index cfd1aac..f47bc3e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -295,7 +295,7 @@
/* Initialize power controller before setting up topology */
plat_arm_pwrc_setup();
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
ras_init();
#endif
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 421c8e9..bbb39d5 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -352,7 +352,7 @@
endif
# 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 \
lib/extensions/ras/ras_common.c
endif
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
index 8c16877..5becbcd 100644
--- a/plat/arm/common/arm_gicv3.c
+++ b/plat/arm/common/arm_gicv3.c
@@ -41,7 +41,7 @@
static const interrupt_prop_t arm_interrupt_props[] = {
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
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,
GIC_INTR_CFG_LEVEL)
#endif
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 8a13bf3..9dfe040 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -204,13 +204,13 @@
SOC_CSS_DEVICE_SIZE, \
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
#else
#define PLAT_SP_PRI 0x10
#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
* memory shared between EL3 and S-EL0.
@@ -239,7 +239,7 @@
*/
#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
PLAT_SP_IMAGE_NS_BUF_SIZE)
-#endif /* SPM_MM && RAS_FFH_SUPPORT */
+#endif /* SPM_MM && ENABLE_FEAT_RAS && FFH_SUPPORT */
/* Platform ID address */
#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 358316c..2cd7034 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -10,8 +10,6 @@
ENABLE_FEAT_RAS := 1
-RAS_FFH_SUPPORT := 0
-
SDEI_SUPPORT := 0
EL3_EXCEPTION_HANDLING := 0
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index 7f79d54..01b426e 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -93,7 +93,7 @@
PLAT_ARM_SECURE_MAP_DEVICE,
ARM_SP_IMAGE_MMAP,
ARM_SP_IMAGE_NS_BUF_MMAP,
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
CSS_SGI_SP_CPER_BUF_MMAP,
#endif
ARM_SP_IMAGE_RW_MMAP,
diff --git a/plat/arm/css/sgi/sgi_plat_v2.c b/plat/arm/css/sgi/sgi_plat_v2.c
index 85f99d4..624fed3 100644
--- a/plat/arm/css/sgi/sgi_plat_v2.c
+++ b/plat/arm/css/sgi/sgi_plat_v2.c
@@ -87,7 +87,7 @@
SOC_PLATFORM_PERIPH_MAP_DEVICE_USER,
ARM_SP_IMAGE_MMAP,
ARM_SP_IMAGE_NS_BUF_MMAP,
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
CSS_SGI_SP_CPER_BUF_MMAP,
#endif
ARM_SP_IMAGE_RW_MMAP,
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index eca81b1..ab99b15 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -11,7 +11,7 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/console.h>
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
#include <lib/extensions/ras.h>
#endif
#include <lib/xlat_tables/xlat_mmu_helpers.h>
@@ -29,7 +29,9 @@
#pragma weak plat_sdei_validate_entry_point
#endif
+#if FFH_SUPPORT
#pragma weak plat_ea_handler = plat_default_ea_handler
+#endif
void bl31_plat_runtime_setup(void)
{
@@ -77,11 +79,12 @@
return "EL1";
}
+#if FFH_SUPPORT
/* 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 *handle, uint64_t flags)
{
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
/* Call RAS EA handler */
int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
if (handled != 0)
@@ -99,3 +102,4 @@
*/
lower_el_panic();
}
+#endif
diff --git a/plat/common/aarch64/plat_ehf.c b/plat/common/aarch64/plat_ehf.c
index 41b175d..6100a20 100644
--- a/plat/common/aarch64/plat_ehf.c
+++ b/plat/common/aarch64/plat_ehf.c
@@ -12,7 +12,7 @@
* Enumeration of priority levels on ARM platforms.
*/
ehf_pri_desc_t plat_exceptions[] = {
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
/* RAS Priority */
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI),
#endif
@@ -26,7 +26,7 @@
#endif
#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)
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
#endif
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index f93585d..ad80596 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -154,7 +154,7 @@
void *handle,
uint64_t flags);
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS && FFH_SUPPORT
void tegra194_ras_enable(void);
void tegra194_ras_corrected_err_clear(uint64_t *cookie);
#endif
diff --git a/plat/nvidia/tegra/soc/t194/plat_ras.c b/plat/nvidia/tegra/soc/t194/plat_ras.c
index 2f438c3..841d70b 100644
--- a/plat/nvidia/tegra/soc/t194/plat_ras.c
+++ b/plat/nvidia/tegra/soc/t194/plat_ras.c
@@ -484,7 +484,7 @@
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
void *handle, uint64_t flags)
{
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
#else
plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index d3d09d3..6850330 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -254,7 +254,7 @@
/* sanity check MCE firmware compatibility */
mce_verify_firmware_version();
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
/* Enable Uncorrectable RAS error */
tegra194_ras_enable();
#endif
diff --git a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
index f0704ed..6e42e64 100644
--- a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
@@ -71,7 +71,7 @@
break;
-#if RAS_FFH_SUPPORT
+#if ENABLE_FEAT_RAS
case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS:
{
/*
diff --git a/plat/nvidia/tegra/soc/t194/platform_t194.mk b/plat/nvidia/tegra/soc/t194/platform_t194.mk
index 289e921..e6e0b5e 100644
--- a/plat/nvidia/tegra/soc/t194/platform_t194.mk
+++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk
@@ -37,7 +37,7 @@
# enable RAS handling
HANDLE_EA_EL3_FIRST_NS := 1
-RAS_FFH_SUPPORT := 1
+ENABLE_FEAT_RAS := 1
# platform files
PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t194 \
@@ -71,7 +71,7 @@
endif
# 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 \
lib/extensions/ras/ras_common.c \
${SOC_DIR}/plat_ras.c