From abbffe98ed6a2fff519cc5590b947c9751cdd235 Mon Sep 17 00:00:00 2001 From: Isla Mitchell Date: Thu, 3 Aug 2017 16:04:46 +0100 Subject: [PATCH 1/6] Add support for Cortex-Ares and Cortex-A76 CPUs Both Cortex-Ares and Cortex-A76 CPUs use the ARM DynamIQ Shared Unit (DSU). The power-down and power-up sequences are therefore mostly managed in hardware, and required software operations are simple. Change-Id: I3a9447b5bdbdbc5ed845b20f6564d086516fa161 Signed-off-by: Isla Mitchell --- include/lib/cpus/aarch64/cortex_a76.h | 22 +++++++++++ include/lib/cpus/aarch64/cortex_ares.h | 22 +++++++++++ lib/cpus/aarch64/cortex_a76.S | 51 ++++++++++++++++++++++++++ lib/cpus/aarch64/cortex_ares.S | 51 ++++++++++++++++++++++++++ plat/arm/board/fvp/platform.mk | 4 +- 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 include/lib/cpus/aarch64/cortex_a76.h create mode 100644 include/lib/cpus/aarch64/cortex_ares.h create mode 100644 lib/cpus/aarch64/cortex_a76.S create mode 100644 lib/cpus/aarch64/cortex_ares.S diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h new file mode 100644 index 0000000000..de6288d8f1 --- /dev/null +++ b/include/lib/cpus/aarch64/cortex_a76.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A76_H__ +#define __CORTEX_A76_H__ + +/* Cortex-A76 MIDR for revision 0 */ +#define CORTEX_A76_MIDR 0x410fd0b0 + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A76_CPUECTLR_EL1 S3_0_C15_C1_4 + +/* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */ +#define CORTEX_A76_CORE_PWRDN_EN_MASK 0x1 + +#endif /* __CORTEX_A76_H__ */ diff --git a/include/lib/cpus/aarch64/cortex_ares.h b/include/lib/cpus/aarch64/cortex_ares.h new file mode 100644 index 0000000000..680811cf2d --- /dev/null +++ b/include/lib/cpus/aarch64/cortex_ares.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_ARES_H__ +#define __CORTEX_ARES_H__ + +/* Cortex-ARES MIDR for revision 0 */ +#define CORTEX_ARES_MIDR 0x410fd0c0 + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_ARES_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_ARES_CPUECTLR_EL1 S3_0_C15_C1_4 + +/* Definitions of register field mask in CORTEX_ARES_CPUPWRCTLR_EL1 */ +#define CORTEX_ARES_CORE_PWRDN_EN_MASK 0x1 + +#endif /* __CORTEX_ARES_H__ */ diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S new file mode 100644 index 0000000000..3a41802f4e --- /dev/null +++ b/lib/cpus/aarch64/cortex_a76.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a76_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A76_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A76_CORE_PWRDN_EN_MASK + msr CORTEX_A76_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a76_core_pwr_dwn + + /* --------------------------------------------- + * This function provides cortex_a76 specific + * register information for crash reporting. + * It needs to return with x6 pointing to + * a list of register names in ascii and + * x8 - x15 having values of registers to be + * reported. + * --------------------------------------------- + */ +.section .rodata.cortex_a76_regs, "aS" +cortex_a76_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a76_cpu_reg_dump + adr x6, cortex_a76_regs + mrs x8, CORTEX_A76_CPUECTLR_EL1 + ret +endfunc cortex_a76_cpu_reg_dump + +declare_cpu_ops cortex_a76, CORTEX_A76_MIDR, \ + CPU_NO_RESET_FUNC, \ + cortex_a76_core_pwr_dwn diff --git a/lib/cpus/aarch64/cortex_ares.S b/lib/cpus/aarch64/cortex_ares.S new file mode 100644 index 0000000000..98e904406a --- /dev/null +++ b/lib/cpus/aarch64/cortex_ares.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_ares_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_ARES_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_ARES_CORE_PWRDN_EN_MASK + msr CORTEX_ARES_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_ares_core_pwr_dwn + + /* --------------------------------------------- + * This function provides cortex_ares specific + * register information for crash reporting. + * It needs to return with x6 pointing to + * a list of register names in ascii and + * x8 - x15 having values of registers to be + * reported. + * --------------------------------------------- + */ +.section .rodata.cortex_ares_regs, "aS" +cortex_ares_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_ares_cpu_reg_dump + adr x6, cortex_ares_regs + mrs x8, CORTEX_ARES_CPUECTLR_EL1 + ret +endfunc cortex_ares_cpu_reg_dump + +declare_cpu_ops cortex_ares, CORTEX_ARES_MIDR, \ + CPU_NO_RESET_FUNC, \ + cortex_ares_core_pwr_dwn diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index f807dc6e49..2a09bba56f 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -114,7 +114,9 @@ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a72.S \ lib/cpus/aarch64/cortex_a73.S \ - lib/cpus/aarch64/cortex_a75.S + lib/cpus/aarch64/cortex_a75.S \ + lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_ares.S else FVP_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S endif From 08268e27ab9dfe41b420f6aae33459adb6cd7f73 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 13 Feb 2018 11:28:02 +0000 Subject: [PATCH 2/6] Add AMU support for Cortex-Ares Change-Id: Ia170c12d3929a616ba80eb7645c301066641f5cc Signed-off-by: Dimitris Papastamos --- include/lib/cpus/aarch64/cortex_ares.h | 7 ++++++- lib/cpus/aarch64/cortex_ares.S | 29 ++++++++++++++++++++++---- lib/cpus/aarch64/cortex_ares_pubsub.c | 26 +++++++++++++++++++++++ plat/arm/board/fvp/platform.mk | 1 + 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 lib/cpus/aarch64/cortex_ares_pubsub.c diff --git a/include/lib/cpus/aarch64/cortex_ares.h b/include/lib/cpus/aarch64/cortex_ares.h index 680811cf2d..b2bb6331a9 100644 --- a/include/lib/cpus/aarch64/cortex_ares.h +++ b/include/lib/cpus/aarch64/cortex_ares.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -19,4 +19,9 @@ /* Definitions of register field mask in CORTEX_ARES_CPUPWRCTLR_EL1 */ #define CORTEX_ARES_CORE_PWRDN_EN_MASK 0x1 +#define CORTEX_ARES_ACTLR_AMEN_BIT (U(1) << 4) + +#define CORTEX_ARES_AMU_NR_COUNTERS U(5) +#define CORTEX_ARES_AMU_GROUP0_MASK U(0x1f) + #endif /* __CORTEX_ARES_H__ */ diff --git a/lib/cpus/aarch64/cortex_ares.S b/lib/cpus/aarch64/cortex_ares.S index 98e904406a..e1302019b7 100644 --- a/lib/cpus/aarch64/cortex_ares.S +++ b/lib/cpus/aarch64/cortex_ares.S @@ -1,15 +1,36 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include -#include #include +#include #include -#include + +func cortex_ares_reset_func +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #CORTEX_ARES_ACTLR_AMEN_BIT + msr actlr_el3, x0 + isb + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #CORTEX_ARES_ACTLR_AMEN_BIT + msr actlr_el2, x0 + isb + + /* Enable group0 counters */ + mov x0, #CORTEX_ARES_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 + isb +#endif + ret +endfunc cortex_ares_reset_func /* --------------------------------------------- * HW will do the cache maintenance while powering down @@ -47,5 +68,5 @@ func cortex_ares_cpu_reg_dump endfunc cortex_ares_cpu_reg_dump declare_cpu_ops cortex_ares, CORTEX_ARES_MIDR, \ - CPU_NO_RESET_FUNC, \ + cortex_ares_reset_func, \ cortex_ares_core_pwr_dwn diff --git a/lib/cpus/aarch64/cortex_ares_pubsub.c b/lib/cpus/aarch64/cortex_ares_pubsub.c new file mode 100644 index 0000000000..c7d850a009 --- /dev/null +++ b/lib/cpus/aarch64/cortex_ares_pubsub.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void *cortex_ares_context_save(const void *arg) +{ + if (midr_match(CORTEX_ARES_MIDR) != 0) + cpuamu_context_save(CORTEX_ARES_AMU_NR_COUNTERS); + return 0; +} + +static void *cortex_ares_context_restore(const void *arg) +{ + if (midr_match(CORTEX_ARES_MIDR) != 0) + cpuamu_context_restore(CORTEX_ARES_AMU_NR_COUNTERS); + return 0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_ares_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, cortex_ares_context_restore); diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 2a09bba56f..677beea045 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -208,6 +208,7 @@ ENABLE_AMU := 1 ifeq (${ENABLE_AMU},1) BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ + lib/cpus/aarch64/cortex_ares_pubsub.c \ lib/cpus/aarch64/cpuamu.c \ lib/cpus/aarch64/cpuamu_helpers.S endif From 040b546e94a2dc3f77bb16c79a5c887de8b80caf Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Mon, 26 Mar 2018 16:46:01 +0100 Subject: [PATCH 3/6] Implement Cortex-Ares 1043202 erratum workaround The workaround uses the instruction patching feature of the Ares cpu. Change-Id: I868fce0dc0e8e41853dcce311f01ee3867aabb59 Signed-off-by: Dimitris Papastamos --- include/lib/cpus/aarch64/cortex_ares.h | 6 +++ lib/cpus/aarch64/cortex_ares.S | 66 +++++++++++++++++++++++++- lib/cpus/cpu-ops.mk | 10 +++- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/include/lib/cpus/aarch64/cortex_ares.h b/include/lib/cpus/aarch64/cortex_ares.h index b2bb6331a9..84955b1815 100644 --- a/include/lib/cpus/aarch64/cortex_ares.h +++ b/include/lib/cpus/aarch64/cortex_ares.h @@ -24,4 +24,10 @@ #define CORTEX_ARES_AMU_NR_COUNTERS U(5) #define CORTEX_ARES_AMU_GROUP0_MASK U(0x1f) +/* Instruction patching registers */ +#define CPUPSELR_EL3 S3_6_C15_C8_0 +#define CPUPCR_EL3 S3_6_C15_C8_1 +#define CPUPOR_EL3 S3_6_C15_C8_2 +#define CPUPMR_EL3 S3_6_C15_C8_3 + #endif /* __CORTEX_ARES_H__ */ diff --git a/lib/cpus/aarch64/cortex_ares.S b/lib/cpus/aarch64/cortex_ares.S index e1302019b7..942b6f7056 100644 --- a/lib/cpus/aarch64/cortex_ares.S +++ b/lib/cpus/aarch64/cortex_ares.S @@ -10,7 +10,50 @@ #include #include +/* -------------------------------------------------- + * Errata Workaround for Cortex-Ares Errata + * This applies to revision r0p0 and r1p0 of Cortex-Ares. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_ares_1043202_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1043202 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x0 + msr CPUPSELR_EL3, x0 + ldr x0, =0xF3BF8F2F + msr CPUPOR_EL3, x0 + ldr x0, =0xFFFFFFFF + msr CPUPMR_EL3, x0 + ldr x0, =0x800200071 + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_ares_1043202_wa + +func check_errata_1043202 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1043202 + func cortex_ares_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_ARES_1043202 + mov x0, x18 + bl errata_ares_1043202_wa +#endif + #if ENABLE_AMU /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ mrs x0, actlr_el3 @@ -29,7 +72,7 @@ func cortex_ares_reset_func msr CPUAMCNTENSET_EL0, x0 isb #endif - ret + ret x19 endfunc cortex_ares_reset_func /* --------------------------------------------- @@ -48,6 +91,27 @@ func cortex_ares_core_pwr_dwn ret endfunc cortex_ares_core_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-Ares. Must follow AAPCS. + */ +func cortex_a72_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_ARES_1043202, cortex_ares, 1043202 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a72_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_ares specific * register information for crash reporting. diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk index 434c13ea06..456e3e5243 100644 --- a/lib/cpus/cpu-ops.mk +++ b/lib/cpus/cpu-ops.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -119,6 +119,10 @@ ERRATA_A57_859972 ?=0 # only to revision <= r0p3 of the Cortex A72 cpu. ERRATA_A72_859971 ?=0 +# Flag to apply T32 CLREX workaround during reset. This erratum applies +# only to r0p0 and r1p0 of the Ares cpu. +ERRATA_ARES_1043202 ?=1 + # Process ERRATA_A53_826319 flag $(eval $(call assert_boolean,ERRATA_A53_826319)) $(eval $(call add_define,ERRATA_A53_826319)) @@ -179,6 +183,10 @@ $(eval $(call add_define,ERRATA_A57_859972)) $(eval $(call assert_boolean,ERRATA_A72_859971)) $(eval $(call add_define,ERRATA_A72_859971)) +# Process ERRATA_ARES_1043202 flag +$(eval $(call assert_boolean,ERRATA_ARES_1043202)) +$(eval $(call add_define,ERRATA_ARES_1043202)) + # Errata build flags ifneq (${ERRATA_A53_843419},0) TF_LDFLAGS_aarch64 += --fix-cortex-a53-843419 From ee7cda31c759b39af7487ddd5ab799208f288c03 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 31 May 2018 14:10:06 +0100 Subject: [PATCH 4/6] Set DYNAMIC_WORKAROUND_CVE_2018_3639=1 on FVP by default The upcoming patch that adds dynamic mitigation for Cortex-A76 requires that DYNAMIC_WORKAROUND_CVE_2018_3639=1. On FVP, we pull in all the CPU files into the build which means there will be a build failure if DYNAMIC_WORKAROUND_CVE_2018_3639=0. Change-Id: I2e781cbeafbf5d16eaabf76a1677e0c9f81269d2 Signed-off-by: Dimitris Papastamos --- plat/arm/board/fvp/platform.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 677beea045..3a2873339e 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -206,6 +206,9 @@ ENABLE_PLAT_COMPAT := 0 # Enable Activity Monitor Unit extensions by default ENABLE_AMU := 1 +# Enable dynamic mitigation support by default +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + ifeq (${ENABLE_AMU},1) BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ lib/cpus/aarch64/cortex_ares_pubsub.c \ From d6b798097e23bc98814ced8406f4dc63df4078c5 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Wed, 16 May 2018 09:59:54 +0100 Subject: [PATCH 5/6] Implement dynamic mitigation for CVE-2018-3639 on Cortex-A76 The Cortex-A76 implements SMCCC_ARCH_WORKAROUND_2 as defined in "Firmware interfaces for mitigating cache speculation vulnerabilities System Software on Arm Systems"[0]. Dynamic mitigation for CVE-2018-3639 is enabled/disabled by setting/clearning bit 16 (Disable load pass store) of `CPUACTLR2_EL1`. NOTE: The generic code that implements dynamic mitigation does not currently implement the expected semantics when dispatching an SDEI event to a lower EL. This will be fixed in a separate patch. [0] https://developer.arm.com/cache-speculation-vulnerability-firmware-specification Change-Id: I8fb2862b9ab24d55a0e9693e48e8be4df32afb5a Signed-off-by: Dimitris Papastamos --- include/lib/cpus/aarch64/cortex_a76.h | 7 + lib/cpus/aarch64/cortex_a76.S | 243 +++++++++++++++++++++++++- 2 files changed, 248 insertions(+), 2 deletions(-) diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h index de6288d8f1..1cb774763c 100644 --- a/include/lib/cpus/aarch64/cortex_a76.h +++ b/include/lib/cpus/aarch64/cortex_a76.h @@ -16,6 +16,13 @@ #define CORTEX_A76_CPUPWRCTLR_EL1 S3_0_C15_C2_7 #define CORTEX_A76_CPUECTLR_EL1 S3_0_C15_C1_4 +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE (1 << 16) + /* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */ #define CORTEX_A76_CORE_PWRDN_EN_MASK 0x1 diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S index 3a41802f4e..14705d7b24 100644 --- a/lib/cpus/aarch64/cortex_a76.S +++ b/lib/cpus/aarch64/cortex_a76.S @@ -5,12 +5,228 @@ */ #include +#include #include #include +#include #include #include #include +#if !DYNAMIC_WORKAROUND_CVE_2018_3639 +#error Cortex A76 requires DYNAMIC_WORKAROUND_CVE_2018_3639=1 +#endif + +#define ESR_EL3_A64_SMC0 0x5e000000 +#define ESR_EL3_A32_SMC0 0x4e000000 + + /* + * This macro applies the mitigation for CVE-2018-3639. + * It implements a fash path where `SMCCC_ARCH_WORKAROUND_2` + * SMC calls from a lower EL running in AArch32 or AArch64 + * will go through the fast and return early. + * + * The macro saves x2-x3 to the context. In the fast path + * x0-x3 registers do not need to be restored as the calling + * context will have saved them. + */ + .macro apply_cve_2018_3639_wa _is_sync_exception _esr_el3_val + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + + .if \_is_sync_exception + /* + * Ensure SMC is coming from A64/A32 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_2 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_2) ? (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + */ + orr w2, wzr, #SMCCC_ARCH_WORKAROUND_2 + cmp x0, x2 + mrs x3, esr_el3 + mov_imm w2, \_esr_el3_val + ccmp w2, w3, #0, eq + /* + * Static predictor will predict a fall-through, optimizing + * the `SMCCC_ARCH_WORKAROUND_2` fast path. + */ + bne 1f + + /* + * The sequence below implements the `SMCCC_ARCH_WORKAROUND_2` + * fast path. + */ + cmp x1, xzr /* enable/disable check */ + + /* + * When the calling context wants mitigation disabled, + * we program the mitigation disable function in the + * CPU context, which gets invoked on subsequent exits from + * EL3 via the `el3_exit` function. Otherwise NULL is + * programmed in the CPU context, which results in caller's + * inheriting the EL3 mitigation state (enabled) on subsequent + * `el3_exit`. + */ + mov x0, xzr + adr x1, cortex_a76_disable_wa_cve_2018_3639 + csel x1, x1, x0, eq + str x1, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] + + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + bic x3, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + csel x3, x3, x1, eq + msr CORTEX_A76_CPUACTLR2_EL1, x3 + eret /* ERET implies ISB */ + .endif +1: + /* + * Always enable v4 mitigation during EL3 execution. This is not + * required for the fast path above because it does not perform any + * memory loads. + */ + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x2, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x2 + isb + + /* + * The caller may have passed arguments to EL3 via x2-x3. + * Restore these registers from the context before jumping to the + * main runtime vector table entry. + */ + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .endm + +vector_base cortex_a76_wa_cve_2018_3639_a76_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_el0 + b sync_exception_sp_el0 + check_vector_size cortex_a76_sync_exception_sp_el0 + +vector_entry cortex_a76_irq_sp_el0 + b irq_sp_el0 + check_vector_size cortex_a76_irq_sp_el0 + +vector_entry cortex_a76_fiq_sp_el0 + b fiq_sp_el0 + check_vector_size cortex_a76_fiq_sp_el0 + +vector_entry cortex_a76_serror_sp_el0 + b serror_sp_el0 + check_vector_size cortex_a76_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_elx + b sync_exception_sp_elx + check_vector_size cortex_a76_sync_exception_sp_elx + +vector_entry cortex_a76_irq_sp_elx + b irq_sp_elx + check_vector_size cortex_a76_irq_sp_elx + +vector_entry cortex_a76_fiq_sp_elx + b fiq_sp_elx + check_vector_size cortex_a76_fiq_sp_elx + +vector_entry cortex_a76_serror_sp_elx + b serror_sp_elx + check_vector_size cortex_a76_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch64 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0 + b sync_exception_aarch64 + check_vector_size cortex_a76_sync_exception_aarch64 + +vector_entry cortex_a76_irq_aarch64 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b irq_aarch64 + check_vector_size cortex_a76_irq_aarch64 + +vector_entry cortex_a76_fiq_aarch64 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b fiq_aarch64 + check_vector_size cortex_a76_fiq_aarch64 + +vector_entry cortex_a76_serror_aarch64 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b serror_aarch64 + check_vector_size cortex_a76_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch32 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0 + b sync_exception_aarch32 + check_vector_size cortex_a76_sync_exception_aarch32 + +vector_entry cortex_a76_irq_aarch32 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b irq_aarch32 + check_vector_size cortex_a76_irq_aarch32 + +vector_entry cortex_a76_fiq_aarch32 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b fiq_aarch32 + check_vector_size cortex_a76_fiq_aarch32 + +vector_entry cortex_a76_serror_aarch32 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b serror_aarch32 + check_vector_size cortex_a76_serror_aarch32 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func cortex_a76_disable_wa_cve_2018_3639 + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + bic x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb + ret +endfunc cortex_a76_disable_wa_cve_2018_3639 + +func cortex_a76_reset_func +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + orr x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2018_3639 + /* + * The Cortex-A76 generic vectors are overwritten to use the vectors + * defined above. This is required in order to apply mitigation + * against CVE-2018-3639 on exception entry from lower ELs. + */ + adr x0, cortex_a76_wa_cve_2018_3639_a76_vbar + msr vbar_el3, x0 + isb +#endif + ret +endfunc cortex_a76_reset_func + /* --------------------------------------------- * HW will do the cache maintenance while powering down * --------------------------------------------- @@ -27,6 +243,27 @@ func cortex_a76_core_pwr_dwn ret endfunc cortex_a76_core_pwr_dwn +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Cortex A76. Must follow AAPCS. + */ +func cortex_a76_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a76_errata_report +#endif + /* --------------------------------------------- * This function provides cortex_a76 specific * register information for crash reporting. @@ -46,6 +283,8 @@ func cortex_a76_cpu_reg_dump ret endfunc cortex_a76_cpu_reg_dump -declare_cpu_ops cortex_a76, CORTEX_A76_MIDR, \ - CPU_NO_RESET_FUNC, \ +declare_cpu_ops_wa cortex_a76, CORTEX_A76_MIDR, \ + cortex_a76_reset_func, \ + CPU_NO_EXTRA1_FUNC, \ + cortex_a76_disable_wa_cve_2018_3639, \ cortex_a76_core_pwr_dwn From 6f03bc7753a22485ad2b531a11e96756147facbe Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Thu, 7 Jun 2018 11:29:15 +0100 Subject: [PATCH 6/6] SDEI: Ensure SDEI handler executes with CVE-2018-3639 mitigation enabled When dynamic mitigation is used, the SDEI handler is required to execute with the mitigation enabled by default, regardless of the mitigation state for lower ELs. This means that if the kernel or hypervisor explicitly disables the mitigation and then later when the event is dispatched, the dispatcher will remember the mitigation state for the lower ELs but force the mitigation to be on during the SDEI handler execution. When the SDEI handler returns, it will restore the mitigation state. This behaviour is described in "Firmware interfaces for mitigating cache speculation vulnerabilities System Software on Arm Systems"[0]. [0] https://developer.arm.com/cache-speculation-vulnerability-firmware-specification Change-Id: I8dd60b736be0aa9e832b0f92d67a401fdeb417f4 Signed-off-by: Dimitris Papastamos --- include/lib/el3_runtime/aarch64/context.h | 1 + services/std_svc/sdei/sdei_intr_mgmt.c | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index a4f3ea1bbe..a2ce9f8284 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -271,6 +271,7 @@ typedef struct cpu_context { #endif #define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx) #define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) +#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx) /* * Compile time assertions related to the 'cpu_context' structure to diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c index 2717ea43bd..c0bd9de6bf 100644 --- a/services/std_svc/sdei/sdei_intr_mgmt.c +++ b/services/std_svc/sdei/sdei_intr_mgmt.c @@ -39,6 +39,11 @@ typedef struct sdei_dispatch_context { /* Exception state registers */ uint64_t elr_el3; uint64_t spsr_el3; + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* CVE-2018-3639 mitigation state */ + uint64_t disable_cve_2018_3639; +#endif } sdei_dispatch_context_t; /* Per-CPU SDEI state data */ @@ -170,6 +175,18 @@ static void save_event_ctx(sdei_ev_map_t *map, void *tgt_ctx, int sec_state, memcpy(disp_ctx->x, tgt_gpregs, sizeof(disp_ctx->x)); disp_ctx->spsr_el3 = read_ctx_reg(tgt_el3, CTX_SPSR_EL3); disp_ctx->elr_el3 = read_ctx_reg(tgt_el3, CTX_ELR_EL3); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx); + + /* Save CVE-2018-3639 mitigation state */ + disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639, + CTX_CVE_2018_3639_DISABLE); + + /* Force SDEI handler to execute with mitigation enabled by default */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0); +#endif } static void restore_event_ctx(sdei_dispatch_context_t *disp_ctx, void *tgt_ctx) @@ -188,6 +205,15 @@ static void restore_event_ctx(sdei_dispatch_context_t *disp_ctx, void *tgt_ctx) memcpy(tgt_gpregs, disp_ctx->x, sizeof(disp_ctx->x)); write_ctx_reg(tgt_el3, CTX_SPSR_EL3, disp_ctx->spsr_el3); write_ctx_reg(tgt_el3, CTX_ELR_EL3, disp_ctx->elr_el3); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx); + + /* Restore CVE-2018-3639 mitigation state */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, + disp_ctx->disable_cve_2018_3639); +#endif } static void save_secure_context(void)