Thread (39 messages) 39 messages, 5 authors, 2018-05-25
STALE2935d

[PATCH 09/14] ARM: spectre-v2: add PSCI based hardening

From: Marc Zyngier <hidden>
Date: 2018-05-23 07:25:31
Also in: kvmarm

On Tue, 22 May 2018 18:57:18 +0100,
Russell King wrote:
On Tue, May 22, 2018 at 06:24:13PM +0100, Marc Zyngier wrote:
quoted
On 21/05/18 12:45, Russell King wrote:
quoted
Add PSCI based hardening for cores that require more complex handling in
firmware.

Signed-off-by: Russell King <redacted>
Acked-by: Marc Zyngier <redacted>
---
 arch/arm/mm/proc-v7-bugs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-v7.S      | 21 +++++++++++++++++++
 2 files changed, 71 insertions(+)
diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index 65a9b8141f86..0c37e6a2830d 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -1,9 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/arm-smccc.h>
 #include <linux/kernel.h>
+#include <linux/psci.h>
 #include <linux/smp.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
+#include <asm/proc-fns.h>
 #include <asm/system_misc.h>
 
 void cpu_v7_bugs_init(void);
@@ -39,6 +42,9 @@ void cpu_v7_ca15_ibe(void)
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 void (*harden_branch_predictor)(void);
 
+extern void cpu_v7_smc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
+extern void cpu_v7_hvc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
+
 static void harden_branch_predictor_bpiall(void)
 {
 	write_sysreg(0, BPIALL);
@@ -49,6 +55,18 @@ static void harden_branch_predictor_iciallu(void)
 	write_sysreg(0, ICIALLU);
 }
 
+#ifdef CONFIG_ARM_PSCI
+static void call_smc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+
+static void call_hvc_arch_workaround_1(void)
+{
+	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
+}
+#endif
+
 void cpu_v7_bugs_init(void)
 {
 	const char *spectre_v2_method = NULL;
@@ -73,6 +91,38 @@ void cpu_v7_bugs_init(void)
 		spectre_v2_method = "ICIALLU";
 		break;
 	}
+
+#ifdef CONFIG_ARM_PSCI
+	if (psci_ops.smccc_version != SMCCC_VERSION_1_0) {
+		struct arm_smccc_res res;
+
+		switch (psci_ops.conduit) {
+		case PSCI_CONDUIT_HVC:
+			arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+			if ((int)res.a0 < 0)
+				break;
I just realised that there is a small, but significant difference
between this and the arm64 version: On arm64, we have a table of
vulnerable implementations, and we try the mitigation on a per-cpu
basis. Here, you entirely rely on the firmware to discover whether the
CPU needs mitigation or not. You then need to check for a return value
of 1, which indicates that although the mitigation is implemented, it is
not required on this particular CPU.

But that's probably moot if you don't support BL systems.
quoted
+			harden_branch_predictor = call_hvc_arch_workaround_1;
+			processor.switch_mm = cpu_v7_hvc_switch_mm;
+			spectre_v2_method = "hypervisor";
+			break;
+
+		case PSCI_CONDUIT_SMC:
+			arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+			if ((int)res.a0 < 0)
+				break;
+			harden_branch_predictor = call_smc_arch_workaround_1;
+			processor.switch_mm = cpu_v7_smc_switch_mm;
+			spectre_v2_method = "firmware PSCI";
My previous remark still stands: this is not really PSCI.
Sorry, no.  Your comment was for the HVC call, not the SMC.  You said
nothing about this one.
My bad then. For all intents and purposes, they are the same thing,
just serviced by a different exception level.

	M.

-- 
Jazz is not dead, it just smell funny.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help