Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Jul 2018 12:53:27 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r336967 - in head/sys: arm64/arm64 arm64/include dev/psci
Message-ID:  <201807311253.w6VCrR6Y080209@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Tue Jul 31 12:53:27 2018
New Revision: 336967
URL: https://svnweb.freebsd.org/changeset/base/336967

Log:
  Implement the SSBD (CVE-2018-3639) workaround on arm64
  
  This calls into the Arm Trusted Firmware to enable and disable the
  workaround for the Speculative Store Bypass Disable (SSBD) issue, also
  known as Spectre Variant 4.
  
  As this may have a large performance overhead, and how exploitable SSBD is
  is unknown we follow the Linux lead of allowing the administrator to select
  between always on, always off, or only enabled in the kernel, with the
  latter being the default.
  
  PR:		228955
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D15819

Modified:
  head/sys/arm64/arm64/cpu_errata.c
  head/sys/arm64/arm64/exception.S
  head/sys/arm64/arm64/genassym.c
  head/sys/arm64/include/pcpu.h
  head/sys/dev/psci/smccc.c
  head/sys/dev/psci/smccc.h

Modified: head/sys/arm64/arm64/cpu_errata.c
==============================================================================
--- head/sys/arm64/arm64/cpu_errata.c	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/arm64/arm64/cpu_errata.c	Tue Jul 31 12:53:27 2018	(r336967)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/pcpu.h>
+#include <sys/systm.h>
 
 #include <machine/cpu.h>
 
@@ -50,7 +51,14 @@ struct cpu_quirks {
 	u_int		midr_value;
 };
 
+static enum {
+	SSBD_FORCE_ON,
+	SSBD_FORCE_OFF,
+	SSBD_KERNEL,
+} ssbd_method = SSBD_KERNEL;
+
 static cpu_quirk_install install_psci_bp_hardening;
+static cpu_quirk_install install_ssbd_workaround;
 
 static struct cpu_quirks cpu_quirks[] = {
 	{
@@ -79,6 +87,11 @@ static struct cpu_quirks cpu_quirks[] = {
 		    CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0,0),
 		.quirk_install = install_psci_bp_hardening,
 	},
+	{
+		.midr_mask = 0,
+		.midr_value = 0,
+		.quirk_install = install_ssbd_workaround,
+	},
 };
 
 static void
@@ -89,6 +102,40 @@ install_psci_bp_hardening(void)
 		return;
 
 	PCPU_SET(bp_harden, smccc_arch_workaround_1);
+}
+
+static void
+install_ssbd_workaround(void)
+{
+	char *env;
+
+	if (PCPU_GET(cpuid) == 0) {
+		env = kern_getenv("kern.cfg.ssbd");
+		if (env != NULL) {
+			if (strcmp(env, "force-on") == 0) {
+				ssbd_method = SSBD_FORCE_ON;
+			} else if (strcmp(env, "force-off") == 0) {
+				ssbd_method = SSBD_FORCE_OFF;
+			}
+		}
+	}
+
+	/* Enable the workaround on this CPU if it's enabled in the firmware */
+	if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_2) != SMCCC_RET_SUCCESS)
+		return;
+
+	switch(ssbd_method) {
+	case SSBD_FORCE_ON:
+		smccc_arch_workaround_2(true);
+		break;
+	case SSBD_FORCE_OFF:
+		smccc_arch_workaround_2(false);
+		break;
+	case SSBD_KERNEL:
+	default:
+		PCPU_SET(ssbd, smccc_arch_workaround_2);
+		break;
+	}
 }
 
 void

Modified: head/sys/arm64/arm64/exception.S
==============================================================================
--- head/sys/arm64/arm64/exception.S	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/arm64/arm64/exception.S	Tue Jul 31 12:53:27 2018	(r336967)
@@ -66,6 +66,14 @@ __FBSDID("$FreeBSD$");
 	stp	x18,  lr, [sp, #(TF_SP)]
 	mrs	x18, tpidr_el1
 	add	x29, sp, #(TF_SIZE)
+.if \el == 0
+	/* Apply the SSBD (CVE-2018-3639) workaround if needed */
+	ldr	x1, [x18, #PC_SSBD]
+	cbz	x1, 1f
+	mov	w0, #1
+	blr	x1
+1:
+.endif
 .endm
 
 .macro	restore_registers el
@@ -75,6 +83,14 @@ __FBSDID("$FreeBSD$");
 	 * Disable interrupts, x18 may change in the interrupt exception
 	 * handler.  For EL0 exceptions, do_ast already did this.
 	 */
+.endif
+.if \el == 0
+	/* Remove the SSBD (CVE-2018-3639) workaround if needed */
+	ldr	x1, [x18, #PC_SSBD]
+	cbz	x1, 1f
+	mov	w0, #0
+	blr	x1
+1:
 .endif
 	ldp	x18,  lr, [sp, #(TF_SP)]
 	ldp	x10, x11, [sp, #(TF_ELR)]

Modified: head/sys/arm64/arm64/genassym.c
==============================================================================
--- head/sys/arm64/arm64/genassym.c	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/arm64/arm64/genassym.c	Tue Jul 31 12:53:27 2018	(r336967)
@@ -43,6 +43,7 @@ ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
 ASSYM(PCPU_SIZE, sizeof(struct pcpu));
 ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
 ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
+ASSYM(PC_SSBD, offsetof(struct pcpu, pc_ssbd));
 
 /* Size of pcb, rounded to keep stack alignment */
 ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1));

Modified: head/sys/arm64/include/pcpu.h
==============================================================================
--- head/sys/arm64/include/pcpu.h	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/arm64/include/pcpu.h	Tue Jul 31 12:53:27 2018	(r336967)
@@ -36,13 +36,15 @@
 #define	ALT_STACK_SIZE	128
 
 typedef int (*pcpu_bp_harden)(void);
+typedef int (*pcpu_ssbd)(bool);
 
 #define	PCPU_MD_FIELDS							\
 	u_int	pc_acpi_id;	/* ACPI CPU id */		\
 	u_int	pc_midr;	/* stored MIDR value */	\
 	uint64_t pc_clock;						\
 	pcpu_bp_harden pc_bp_harden;					\
-	char __pad[233]
+	pcpu_ssbd pc_ssbd;						\
+	char __pad[225]
 
 #ifdef _KERNEL
 

Modified: head/sys/dev/psci/smccc.c
==============================================================================
--- head/sys/dev/psci/smccc.c	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/dev/psci/smccc.c	Tue Jul 31 12:53:27 2018	(r336967)
@@ -91,3 +91,12 @@ smccc_arch_workaround_1(void)
 	    ("SMCCC arch workaround 1 called with an invalid SMCCC interface"));
 	return (psci_call(SMCCC_ARCH_WORKAROUND_1, 0, 0, 0));
 }
+
+int
+smccc_arch_workaround_2(bool enable)
+{
+
+	KASSERT(smccc_version != SMCCC_VERSION_1_0,
+	    ("SMCCC arch workaround 2 called with an invalid SMCCC interface"));
+	return (psci_call(SMCCC_ARCH_WORKAROUND_2, enable ? 1 : 0, 0, 0));
+}

Modified: head/sys/dev/psci/smccc.h
==============================================================================
--- head/sys/dev/psci/smccc.h	Tue Jul 31 12:44:28 2018	(r336966)
+++ head/sys/dev/psci/smccc.h	Tue Jul 31 12:53:27 2018	(r336967)
@@ -59,6 +59,8 @@
     SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 1)
 #define	SMCCC_ARCH_WORKAROUND_1						\
     SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 0x8000)
+#define	SMCCC_ARCH_WORKAROUND_2						\
+    SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 0x7fff)
 
 /* The return values from ARM DEN 0070A. */
 #define	SMCCC_RET_SUCCESS		0
@@ -67,6 +69,7 @@
 
 int32_t smccc_arch_features(uint32_t);
 int smccc_arch_workaround_1(void);
+int smccc_arch_workaround_2(bool);
 
 
 #endif /* _PSCI_SMCCC_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807311253.w6VCrR6Y080209>