From 5378d30323828d32243a867b245d855562e0829b Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 30 Nov 2017 14:53:53 +0000 Subject: Workaround for CVE-2017-5715 on Cortex A57 and A72 Invalidate the Branch Target Buffer (BTB) on entry to EL3 by disabling and enabling the MMU. To achieve this without performing any branch instruction, a per-cpu vbar is installed which executes the workaround and then branches off to the corresponding vector entry in the main vector table. A side effect of this change is that the main vbar is configured before any reset handling. This is to allow the per-cpu reset function to override the vbar setting. This workaround is enabled by default on the affected CPUs. Signed-off-by: Dimitris Papastamos Change-Id: I135c4173b4f5a16186c8b2e85dc5adb21e041b0b [Resolve conflicts] Signed-off-by: Marcin Wojtas Reviewed-on: http://vgitil04.il.marvell.com:8080/48855 Tested-by: iSoC Platform CI Reviewed-by: Igal Liberman --- bl31/aarch64/runtime_exceptions.S | 20 +++++ bl31/bl31.mk | 4 + include/common/aarch64/el3_common_macros.S | 20 ++--- lib/cpus/aarch64/cortex_a57.S | 5 ++ lib/cpus/aarch64/cortex_a72.S | 6 ++ lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S | 114 ++++++++++++++++++++++++ lib/cpus/cpu-ops.mk | 5 ++ 7 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 799062ef..ca9eee90 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -37,6 +37,26 @@ .globl runtime_exceptions + .globl sync_exception_sp_el0 + .globl irq_sp_el0 + .globl fiq_sp_el0 + .globl serror_sp_el0 + + .globl sync_exception_sp_elx + .globl irq_sp_elx + .globl fiq_sp_elx + .globl serror_sp_elx + + .globl sync_exception_aarch64 + .globl irq_aarch64 + .globl fiq_aarch64 + .globl serror_aarch64 + + .globl sync_exception_aarch32 + .globl irq_aarch32 + .globl fiq_aarch32 + .globl serror_aarch32 + /* ----------------------------------------------------- * Handle SMC exceptions separately from other sync. * exceptions. diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 4de511b6..4be3e600 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -44,6 +44,10 @@ ifeq (${ENABLE_PMF}, 1) BL31_SOURCES += lib/pmf/pmf_main.c endif +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL31_SOURCES += lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S +endif + BL31_LINKERFILE := bl31/bl31.ld.S # Flag used to indicate if Crash reporting via console should be included diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S index 9b22a734..be82bd1e 100644 --- a/include/common/aarch64/el3_common_macros.S +++ b/include/common/aarch64/el3_common_macros.S @@ -37,7 +37,7 @@ /* * Helper macro to initialise EL3 registers we care about. */ - .macro el3_arch_init_common _exception_vectors + .macro el3_arch_init_common /* --------------------------------------------------------------------- * Enable the instruction cache, stack pointer and data access alignment * checks @@ -61,14 +61,6 @@ bl init_cpu_data_ptr #endif /* IMAGE_BL31 */ - /* --------------------------------------------------------------------- - * Set the exception vectors. - * --------------------------------------------------------------------- - */ - adr x0, \_exception_vectors - msr vbar_el3, x0 - isb - /* --------------------------------------------------------------------- * Early set RES1 bits in SCR_EL3. Set EA bit to catch both * External Aborts and SError Interrupts in EL3 and also the SIF bit @@ -179,6 +171,14 @@ do_cold_boot: .endif /* _warm_boot_mailbox */ + /* --------------------------------------------------------------------- + * Set the exception vectors. + * --------------------------------------------------------------------- + */ + adr x0, \_exception_vectors + msr vbar_el3, x0 + isb + /* --------------------------------------------------------------------- * It is a cold boot. * Perform any processor specific actions upon reset e.g. cache, TLB @@ -187,7 +187,7 @@ */ bl reset_handler - el3_arch_init_common \_exception_vectors + el3_arch_init_common .if \_secondary_cold_boot /* ------------------------------------------------------------- diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S index d6b181d0..d1ed5158 100644 --- a/lib/cpus/aarch64/cortex_a57.S +++ b/lib/cpus/aarch64/cortex_a57.S @@ -361,6 +361,11 @@ func cortex_a57_reset_func bl errata_a57_833471_wa #endif +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + adr x0, workaround_mmu_runtime_exceptions + msr vbar_el3, x0 +#endif + /* --------------------------------------------- * Enable the SMP bit. * --------------------------------------------- diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S index 9f04fb72..ba40d467 100644 --- a/lib/cpus/aarch64/cortex_a72.S +++ b/lib/cpus/aarch64/cortex_a72.S @@ -102,6 +102,12 @@ endfunc cortex_a72_disable_ext_debug * ------------------------------------------------- */ func cortex_a72_reset_func + +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + adr x0, workaround_mmu_runtime_exceptions + msr vbar_el3, x0 +#endif + /* --------------------------------------------- * As a bare minimum enable the SMP bit. * --------------------------------------------- diff --git a/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S b/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S new file mode 100644 index 00000000..f4781484 --- /dev/null +++ b/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl workaround_mmu_runtime_exceptions + +vector_base workaround_mmu_runtime_exceptions + + .macro apply_workaround + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + mrs x0, sctlr_el3 + /* Disable MMU */ + bic x1, x0, #SCTLR_M_BIT + msr sctlr_el3, x1 + isb + /* Restore MMU config */ + msr sctlr_el3, x0 + isb + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + .endm + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry workaround_mmu_sync_exception_sp_el0 + b sync_exception_sp_el0 + check_vector_size workaround_mmu_sync_exception_sp_el0 + +vector_entry workaround_mmu_irq_sp_el0 + b irq_sp_el0 + check_vector_size workaround_mmu_irq_sp_el0 + +vector_entry workaround_mmu_fiq_sp_el0 + b fiq_sp_el0 + check_vector_size workaround_mmu_fiq_sp_el0 + +vector_entry workaround_mmu_serror_sp_el0 + b serror_sp_el0 + check_vector_size workaround_mmu_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry workaround_mmu_sync_exception_sp_elx + b sync_exception_sp_elx + check_vector_size workaround_mmu_sync_exception_sp_elx + +vector_entry workaround_mmu_irq_sp_elx + b irq_sp_elx + check_vector_size workaround_mmu_irq_sp_elx + +vector_entry workaround_mmu_fiq_sp_elx + b fiq_sp_elx + check_vector_size workaround_mmu_fiq_sp_elx + +vector_entry workaround_mmu_serror_sp_elx + b serror_sp_elx + check_vector_size workaround_mmu_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry workaround_mmu_sync_exception_aarch64 + apply_workaround + b sync_exception_aarch64 + check_vector_size workaround_mmu_sync_exception_aarch64 + +vector_entry workaround_mmu_irq_aarch64 + apply_workaround + b irq_aarch64 + check_vector_size workaround_mmu_irq_aarch64 + +vector_entry workaround_mmu_fiq_aarch64 + apply_workaround + b fiq_aarch64 + check_vector_size workaround_mmu_fiq_aarch64 + +vector_entry workaround_mmu_serror_aarch64 + apply_workaround + b serror_aarch64 + check_vector_size workaround_mmu_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry workaround_mmu_sync_exception_aarch32 + apply_workaround + b sync_exception_aarch32 + check_vector_size workaround_mmu_sync_exception_aarch32 + +vector_entry workaround_mmu_irq_aarch32 + apply_workaround + b irq_aarch32 + check_vector_size workaround_mmu_irq_aarch32 + +vector_entry workaround_mmu_fiq_aarch32 + apply_workaround + b fiq_aarch32 + check_vector_size workaround_mmu_fiq_aarch32 + +vector_entry workaround_mmu_serror_aarch32 + apply_workaround + b serror_aarch32 + check_vector_size workaround_mmu_serror_aarch32 diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk index 0659bff9..d1144247 100644 --- a/lib/cpus/cpu-ops.mk +++ b/lib/cpus/cpu-ops.mk @@ -40,6 +40,8 @@ A53_DISABLE_NON_TEMPORAL_HINT ?=1 # It is enabled by default. A57_DISABLE_NON_TEMPORAL_HINT ?=1 +WORKAROUND_CVE_2017_5715 ?=1 + # Process SKIP_A57_L1_FLUSH_PWR_DWN flag $(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN)) $(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN)) @@ -52,6 +54,9 @@ $(eval $(call add_define,A53_DISABLE_NON_TEMPORAL_HINT)) $(eval $(call assert_boolean,A57_DISABLE_NON_TEMPORAL_HINT)) $(eval $(call add_define,A57_DISABLE_NON_TEMPORAL_HINT)) +# Process WORKAROUND_CVE_2017_5715 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2017_5715)) +$(eval $(call add_define,WORKAROUND_CVE_2017_5715)) # CPU Errata Build flags. # These should be enabled by the platform if the erratum workaround needs to be -- cgit