diff --git a/Makefile b/Makefile index 23b48e8f4..c588931f9 100644 --- a/Makefile +++ b/Makefile @@ -388,6 +388,13 @@ ifneq (${SMCCC_MAJOR_VERSION},1) endif endif +# For RAS_EXTENSION, require that EAs are handled in EL3 first +ifeq ($(RAS_EXTENSION),1) + ifneq ($(HANDLE_EA_EL3_FIRST),1) + $(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1) + endif +endif + ################################################################################ # Process platform overrideable behaviour ################################################################################ @@ -525,6 +532,7 @@ $(eval $(call assert_boolean,NS_TIMER_SWITCH)) $(eval $(call assert_boolean,PL011_GENERIC_UART)) $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS)) $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID)) +$(eval $(call assert_boolean,RAS_EXTENSION)) $(eval $(call assert_boolean,RESET_TO_BL31)) $(eval $(call assert_boolean,SAVE_KEYS)) $(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA)) @@ -574,6 +582,7 @@ $(eval $(call add_define,PL011_GENERIC_UART)) $(eval $(call add_define,PLAT_${PLAT})) $(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS)) $(eval $(call add_define,PSCI_EXTENDED_STATE_ID)) +$(eval $(call add_define,RAS_EXTENSION)) $(eval $(call add_define,RESET_TO_BL31)) $(eval $(call add_define,SEPARATE_CODE_AND_RODATA)) $(eval $(call add_define,SMCCC_MAJOR_VERSION)) diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 494ccd797..346cd3b31 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -36,6 +36,50 @@ .globl fiq_aarch32 .globl serror_aarch32 + /* + * Macro that prepares entry to EL3 upon taking an exception. + * + * With RAS_EXTENSION, 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_EXTENSION, this macro just saves x30, and unmasks + * Asynchronous External Aborts. + */ + .macro check_and_unmask_ea +#if RAS_EXTENSION + /* Synchronize pending External Aborts */ + esb + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* + * Explicitly save x30 so as to free up a register and to enable + * branching + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Check for SErrors synchronized by the ESB instruction */ + mrs x30, DISR_EL1 + tbz x30, #DISR_A_BIT, 1f + + /* Save GP registers and restore them afterwards */ + bl save_gp_registers + mov x0, #ERROR_EA_ESB + mrs x1, DISR_EL1 + bl delegate_ea + bl restore_gp_registers + +1: +#else + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] +#endif + .endm + /* * Handle External Abort by delegating to the platform's EA handler. * Once the platform handler returns, the macro exits EL3 and returns to @@ -63,11 +107,6 @@ * --------------------------------------------------------------------- */ .macro handle_sync_exception - /* Enable the SError interrupt */ - msr daifclr, #DAIF_ABT_BIT - - str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] - #if ENABLE_RUNTIME_INSTRUMENTATION /* * Read the timestamp value and store it in per-cpu data. The value @@ -117,12 +156,7 @@ * --------------------------------------------------------------------- */ .macro handle_interrupt_exception label - /* Enable the SError interrupt */ - msr daifclr, #DAIF_ABT_BIT - - str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] bl save_gp_registers - /* Save the EL3 system registers needed to return from this exception */ mrs x0, spsr_el3 mrs x1, elr_el3 @@ -256,14 +290,17 @@ vector_entry sync_exception_aarch64 * to a valid cpu context where the general purpose and system register * state can be saved. */ + check_and_unmask_ea handle_sync_exception check_vector_size sync_exception_aarch64 vector_entry irq_aarch64 + check_and_unmask_ea handle_interrupt_exception irq_aarch64 check_vector_size irq_aarch64 vector_entry fiq_aarch64 + check_and_unmask_ea handle_interrupt_exception fiq_aarch64 check_vector_size fiq_aarch64 @@ -289,14 +326,17 @@ vector_entry sync_exception_aarch32 * to a valid cpu context where the general purpose and system register * state can be saved. */ + check_and_unmask_ea handle_sync_exception check_vector_size sync_exception_aarch32 vector_entry irq_aarch32 + check_and_unmask_ea handle_interrupt_exception irq_aarch32 check_vector_size irq_aarch32 vector_entry fiq_aarch32 + check_and_unmask_ea handle_interrupt_exception fiq_aarch32 check_vector_size fiq_aarch32 diff --git a/docs/user-guide.rst b/docs/user-guide.rst index aed54a631..880fe7d9b 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -531,6 +531,15 @@ Common build options smc function id. When this option is enabled on Arm platforms, the option ``ARM_RECOM_STATE_ID_ENC`` needs to be set to 1 as well. +- ``RAS_EXTENSION``: When set to ``1``, 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. + + When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be + set to ``1``. + + This option is disabled by default. + - ``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 entrypoint) or 1 (CPU reset to BL31 entrypoint). diff --git a/include/bl31/ea_handle.h b/include/bl31/ea_handle.h index 285132b7e..9dfe3e0a7 100644 --- a/include/bl31/ea_handle.h +++ b/include/bl31/ea_handle.h @@ -15,4 +15,7 @@ /* Synchronous External Abort received at Synchronous exception vector */ #define ERROR_EA_SYNC 1 +/* External Abort synchronized by ESB instruction */ +#define ERROR_EA_ESB 2 + #endif /* __EA_HANDLE_H__ */ diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S index 94a9df92d..7c8e643d1 100644 --- a/include/common/aarch64/asm_macros.S +++ b/include/common/aarch64/asm_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -192,4 +192,10 @@ .space SPINLOCK_ASM_SIZE .endm +#if RAS_EXTENSION + .macro esb + .inst 0xd503221f + .endm +#endif + #endif /* __ASM_MACROS_S__ */ diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index a44694126..5be4b4e9e 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -711,4 +711,10 @@ #define AMCGCR_EL0_CG1NC_LENGTH U(8) #define AMCGCR_EL0_CG1NC_MASK U(0xff) +/******************************************************************************* + * RAS system registers + *******************************************************************************/ +#define DISR_EL1 S3_0_C12_C1_1 +#define DISR_A_BIT 31 + #endif /* __ARCH_H__ */ diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 9a53b76c1..121ca4d30 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -364,6 +364,16 @@ endfunc restore_gp_registers func restore_gp_registers_eret bl restore_gp_registers ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +#if IMAGE_BL31 && RAS_EXTENSION + /* + * 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 +#endif eret endfunc restore_gp_registers_eret diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 00ac12687..791a9c086 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -124,6 +124,9 @@ PROGRAMMABLE_RESET_ADDRESS := 0 # Original format. PSCI_EXTENDED_STATE_ID := 0 +# Enable RAS support +RAS_EXTENSION := 0 + # By default, BL1 acts as the reset handler, not BL31 RESET_TO_BL31 := 0