diff --git a/Makefile b/Makefile index 7f781a09a..da9eb9f53 100644 --- a/Makefile +++ b/Makefile @@ -809,6 +809,14 @@ else 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 @@ endif # 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 @@ $(eval $(call assert_booleans,\ 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 @@ $(eval $(call assert_booleans,\ ERRATA_ABI_SUPPORT \ ERRATA_NON_ARM_INTERCONNECT \ CONDITIONAL_CMO \ - RAS_FFH_SUPPORT \ PSA_CRYPTO \ ENABLE_CONSOLE_GETC \ ))) @@ -1360,7 +1360,6 @@ $(eval $(call assert_numerics,\ 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 @@ $(eval $(call add_defines,\ 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 @@ $(eval $(call add_defines,\ 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 dd6b4dc9c..28d218737 100644 --- a/bl31/aarch64/ea_delegate.S +++ b/bl31/aarch64/ea_delegate.S @@ -15,31 +15,11 @@ #include #include - .globl handle_lower_el_ea_esb .globl handle_lower_el_sync_ea .globl handle_lower_el_async_ea - - + .globl handle_pending_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 - - -/* - * 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 @@ func handle_lower_el_sync_ea 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 @@ func handle_lower_el_sync_ea /* 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 @@ func handle_lower_el_async_ea 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 @@ endfunc handle_lower_el_async_ea * 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 @@ endfunc delegate_sync_ea * 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 82986966c..ed483111c 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -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 + .macro restore_x30 + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + .endm /* - * Save general purpose and ARMv8.3-PAuth registers (if enabled). - * Also save PMCR_EL0 and set the PSTATE to a known state. + * 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. */ - 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. - */ - - /* - * 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 + .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 @@ vector_entry fiq_sp_elx 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 @@ vector_entry sync_exception_aarch64 */ 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 -#else - check_and_unmask_ea -#endif + sync_and_handle_pending_serror + unmask_async_ea b handle_lower_el_async_ea - +#else + b report_unhandled_exception +#endif end_vector_entry serror_aarch64 /* --------------------------------------------------------------------- @@ -291,34 +278,41 @@ vector_entry sync_exception_aarch32 */ 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 -#else - check_and_unmask_ea -#endif + sync_and_handle_pending_serror + unmask_async_ea b handle_lower_el_async_ea - +#else + b report_unhandled_exception +#endif end_vector_entry serror_aarch32 #ifdef MONITOR_TRAPS @@ -608,6 +602,114 @@ interrupt_exit: 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 a1fc12be8..335952672 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -39,7 +39,6 @@ BL31_SOURCES += bl31/bl31_main.c \ 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 @@ ifeq (${EL3_EXCEPTION_HANDLING},1) 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 8d003452c..747367a4c 100644 --- a/docs/components/ras.rst +++ b/docs/components/ras.rst @@ -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 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 @@ Introduction EA's originating/attributed to NS world are handled first in NS and Kernel navigates the std error records directly. -**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** +- 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). + +|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 @@ Engaging the RAS framework 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 @@ for non-interrupt exceptions, they're explicit using :ref:`EHF APIs *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 879ddda41..ff69b43cf 100644 --- a/docs/design/firmware-design.rst +++ b/docs/design/firmware-design.rst @@ -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 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 @@ kernel at boot time. These can be found in the ``fdts`` directory. .. _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 a015d7167..390c3671d 100644 --- a/docs/getting_started/build-internals.rst +++ b/docs/getting_started/build-internals.rst @@ -12,3 +12,10 @@ depends on certain options to be enabled or disabled. 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 347cf20bc..43b13d613 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -811,14 +811,12 @@ Common build options - ``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 f612e1ca5..082497cea 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -3298,10 +3298,10 @@ Function : plat_ea_handler 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 @@ The third parameter (``void *cookie``) is unused for now. The fourth parameter (``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 000000000..cdfdcb910 Binary files /dev/null and b/docs/resources/diagrams/bl31-exception-entry-error-synchronization.png differ diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S index 83e94caa4..3ba86e956 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 13927bd50..e9d22b61d 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 6091f6294..d09ad0f0d 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 9c9c00f1a..a78837f23 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 68f012c14..7cd7b6a1c 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 470d11300..47d91de0d 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 314eb93e7..9176e8887 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -774,7 +774,7 @@ MEASURED_BOOT #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 41b25d6f9..631094f73 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -649,23 +649,9 @@ sve_not_enabled: 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 @@ sve_not_enabled: 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 ea22655ce..e02917c8a 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -191,9 +191,6 @@ PSCI_EXTENDED_STATE_ID := 0 # 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 f7c174f78..2fdff3488 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -56,7 +56,6 @@ ifneq (${SPD}, tspd) 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 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ 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 @@ endif # 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 1506714b9..ef8f3d477 100644 --- a/plat/arm/board/rdn2/platform.mk +++ b/plat/arm/board/rdn2/platform.mk @@ -69,7 +69,7 @@ BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c 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 f1174562c..2a6c658bc 100644 --- a/plat/arm/board/rdn2/rdn2_plat.c +++ b/plat/arm/board/rdn2/rdn2_plat.c @@ -137,7 +137,7 @@ void bl31_platform_setup(void) 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 b836a7f04..7cd4a1c81 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 8ca33cac4..8db6f1d6b 100644 --- a/plat/arm/board/tc/platform.mk +++ b/plat/arm/board/tc/platform.mk @@ -21,8 +21,6 @@ CSS_USE_SCMI_SDS_DRIVER := 1 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 cfd1aac08..f47bc3e02 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -295,7 +295,7 @@ void arm_bl31_platform_setup(void) /* 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 421c8e98f..bbb39d580 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -352,7 +352,7 @@ endif 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 8c16877ce..5becbcd5c 100644 --- a/plat/arm/common/arm_gicv3.c +++ b/plat/arm/common/arm_gicv3.c @@ -41,7 +41,7 @@ static const uintptr_t *gicr_frames = gicr_base_addrs; 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 8a13bf33e..9dfe040d5 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 358316caa..2cd703422 100644 --- a/plat/arm/css/sgi/sgi-common.mk +++ b/plat/arm/css/sgi/sgi-common.mk @@ -10,8 +10,6 @@ CSS_ENT_BASE := plat/arm/css/sgi 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 7f79d5409..01b426e88 100644 --- a/plat/arm/css/sgi/sgi_plat.c +++ b/plat/arm/css/sgi/sgi_plat.c @@ -93,7 +93,7 @@ const mmap_region_t plat_arm_secure_partition_mmap[] = { 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 85f99d44d..624fed34f 100644 --- a/plat/arm/css/sgi/sgi_plat_v2.c +++ b/plat/arm/css/sgi/sgi_plat_v2.c @@ -87,7 +87,7 @@ const mmap_region_t plat_arm_secure_partition_mmap[] = { 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 eca81b11f..ab99b1589 100644 --- a/plat/common/aarch64/plat_common.c +++ b/plat/common/aarch64/plat_common.c @@ -11,7 +11,7 @@ #include #include #include -#if RAS_FFH_SUPPORT +#if ENABLE_FEAT_RAS #include #endif #include @@ -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 @@ const char *get_el_str(unsigned int el) 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 @@ void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *co */ lower_el_panic(); } +#endif diff --git a/plat/common/aarch64/plat_ehf.c b/plat/common/aarch64/plat_ehf.c index 41b175d56..6100a2009 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 @@ ehf_pri_desc_t plat_exceptions[] = { #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 f93585d9d..ad80596b7 100644 --- a/plat/nvidia/tegra/include/tegra_private.h +++ b/plat/nvidia/tegra/include/tegra_private.h @@ -154,7 +154,7 @@ int plat_sip_handler(uint32_t smc_fid, 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 2f438c3c0..841d70b2f 100644 --- a/plat/nvidia/tegra/soc/t194/plat_ras.c +++ b/plat/nvidia/tegra/soc/t194/plat_ras.c @@ -484,7 +484,7 @@ REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts); 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 d3d09d3dc..68503301e 100644 --- a/plat/nvidia/tegra/soc/t194/plat_setup.c +++ b/plat/nvidia/tegra/soc/t194/plat_setup.c @@ -254,7 +254,7 @@ void plat_early_platform_setup(void) /* 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 f0704edb1..6e42e6458 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 @@ int32_t plat_sip_handler(uint32_t smc_fid, 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 289e9210f..e6e0b5eea 100644 --- a/plat/nvidia/tegra/soc/t194/platform_t194.mk +++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk @@ -37,7 +37,7 @@ $(eval $(call add_define,MAX_MMAP_REGIONS)) # 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 @@ BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S 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