diff --git a/Makefile b/Makefile index 5c4f36c..9972362 100644 --- a/Makefile +++ b/Makefile @@ -891,6 +891,7 @@ $(eval $(call assert_boolean,USE_SPINLOCK_CAS)) $(eval $(call assert_boolean,ENCRYPT_BL31)) $(eval $(call assert_boolean,ENCRYPT_BL32)) +$(eval $(call assert_boolean,ERRATA_SPECULATIVE_AT)) $(eval $(call assert_numeric,ARM_ARCH_MAJOR)) $(eval $(call assert_numeric,ARM_ARCH_MINOR)) @@ -967,6 +968,7 @@ $(eval $(call add_define,BL2_IN_XIP_MEM)) $(eval $(call add_define,BL2_INV_DCACHE)) $(eval $(call add_define,USE_SPINLOCK_CAS)) +$(eval $(call add_define,ERRATA_SPECULATIVE_AT)) ifeq (${SANITIZE_UB},trap) $(eval $(call add_define,MONITOR_TRAPS)) diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 90fe83f..6f3b605 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -673,6 +673,29 @@ default value of this flag is ``no``. Note this option must be enabled only for ARM architecture greater than Armv8.5-A. +- ``ERRATA_SPECULATIVE_AT``: This flag enables/disables page table walk during + context restore as speculative AT instructions using an out-of-context + translation regime could cause subsequent requests to generate an incorrect + translation. + System registers are not updated during context save, hence this workaround + need not be applied in the context save path. + + This boolean option enables errata for all below CPUs. + + +---------+--------------+ + | Errata | CPU | + +=========+==============+ + | 1165522 | Cortex-A76 | + +---------+--------------+ + | 1319367 | Cortex-A72 | + +---------+--------------+ + | 1319537 | Cortex-A57 | + +---------+--------------+ + | 1530923 | Cortex-A55 | + +---------+--------------+ + | 1530924 | Cortex-A53 | + +---------+--------------+ + GICv3 driver options -------------------- diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index e45a594..81e0f27 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -381,6 +381,7 @@ /* HCR definitions */ #define HCR_API_BIT (ULL(1) << 41) #define HCR_APK_BIT (ULL(1) << 40) +#define HCR_E2H_BIT (ULL(1) << 34) #define HCR_TGE_BIT (ULL(1) << 27) #define HCR_RW_SHIFT U(31) #define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT) diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 221f33e..984468a 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -234,6 +234,21 @@ */ func el2_sysregs_context_restore +#if ERRATA_SPECULATIVE_AT +/* Clear EPD0 and EPD1 bit and M bit to disable PTW */ + mrs x9, hcr_el2 + tst x9, #HCR_E2H_BIT + bne 1f + mrs x9, tcr_el2 + orr x9, x9, #TCR_EPD0_BIT + orr x9, x9, #TCR_EPD1_BIT + msr tcr_el2, x9 +1: mrs x9, sctlr_el2 + bic x9, x9, #SCTLR_M_BIT + msr sctlr_el2, x9 + isb +#endif + ldp x9, x10, [x0, #CTX_ACTLR_EL2] msr actlr_el2, x9 msr afsr0_el2, x10 @@ -282,17 +297,15 @@ msr mair_el2, x15 msr mdcr_el2, x16 - ldp x17, x9, [x0, #CTX_PMSCR_EL2] + ldr x17, [x0, #CTX_PMSCR_EL2] msr PMSCR_EL2, x17 - msr sctlr_el2, x9 ldp x10, x11, [x0, #CTX_SPSR_EL2] msr spsr_el2, x10 msr sp_el2, x11 - ldp x12, x13, [x0, #CTX_TCR_EL2] - msr tcr_el2, x12 - msr tpidr_el2, x13 + ldr x12, [x0, #CTX_TPIDR_EL2] + msr tpidr_el2, x12 ldp x14, x15, [x0, #CTX_TTBR0_EL2] msr ttbr0_el2, x14 @@ -404,6 +417,19 @@ msr scxtnum_el2, x9 #endif +#if ERRATA_SPECULATIVE_AT +/* + * Make sure all registers are stored successfully except + * SCTLR_EL2 and TCR_EL2 + */ + isb +#endif + + ldr x9, [x0, #CTX_SCTLR_EL2] + msr sctlr_el2, x9 + ldr x9, [x0, #CTX_TCR_EL2] + msr tcr_el2, x9 + ret endfunc el2_sysregs_context_restore @@ -515,12 +541,22 @@ */ func el1_sysregs_context_restore +#if ERRATA_SPECULATIVE_AT + mrs x9, tcr_el1 + orr x9, x9, #TCR_EPD0_BIT + orr x9, x9, #TCR_EPD1_BIT + msr tcr_el1, x9 + mrs x9, sctlr_el1 + bic x9, x9, #SCTLR_M_BIT + msr sctlr_el1, x9 + isb +#endif + ldp x9, x10, [x0, #CTX_SPSR_EL1] msr spsr_el1, x9 msr elr_el1, x10 - ldp x15, x16, [x0, #CTX_SCTLR_EL1] - msr sctlr_el1, x15 + ldr x16, [x0, #CTX_ACTLR_EL1] msr actlr_el1, x16 ldp x17, x9, [x0, #CTX_CPACR_EL1] @@ -539,9 +575,8 @@ msr mair_el1, x14 msr amair_el1, x15 - ldp x16, x17, [x0, #CTX_TCR_EL1] - msr tcr_el1, x16 - msr tpidr_el1, x17 + ldr x16,[x0, #CTX_TPIDR_EL1] + msr tpidr_el1, x16 ldp x9, x10, [x0, #CTX_TPIDR_EL0] msr tpidr_el0, x9 @@ -597,6 +632,19 @@ msr GCR_EL1, x14 #endif +#if ERRATA_SPECULATIVE_AT +/* + * Make sure all registers are stored successfully except + * SCTLR_EL1 and TCR_EL1 + */ + isb +#endif + + ldr x9, [x0, #CTX_SCTLR_EL1] + msr sctlr_el1, x9 + ldr x9, [x0, #CTX_TCR_EL1] + msr tcr_el1, x9 + /* No explict ISB required here as ERET covers it */ ret endfunc el1_sysregs_context_restore diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 590a800..608e963 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -293,3 +293,6 @@ # than Armv8.5-A # By default it is set to "no" SUPPORT_STACK_MEMTAG := no + +# Select workaround for AT speculative behaviour. +ERRATA_SPECULATIVE_AT := 0