mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-15 17:14:21 +00:00
Merge changes from topic "mp/exceptions" into integration
* changes: docs(ras): update RAS documentation docs(el3-runtime): update BL31 exception vector handling fix(el3-runtime): restrict lower el EA handlers in FFH mode fix(ras): remove RAS_FFH_SUPPORT and introduce FFH_SUPPORT fix(ras): restrict ENABLE_FEAT_RAS to have only two states feat(ras): use FEAT_IESB for error synchronization feat(el3-runtime): modify vector entry paths
This commit is contained in:
commit
6f802c44e9
38 changed files with 536 additions and 240 deletions
27
Makefile
27
Makefile
|
@ -809,6 +809,14 @@ else
|
|||
BL2_RUNS_AT_EL3 := 0
|
||||
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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
.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.
|
||||
|
|
|
@ -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
|
||||
.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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 @@ 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue