Module Name:    src
Committed By:   martin
Date:           Sat Jun  9 15:12:21 UTC 2018

Modified Files:
        src/sys/arch/amd64/amd64 [netbsd-8]: machdep.c
        src/sys/arch/amd64/conf [netbsd-8]: GENERIC files.amd64
        src/sys/arch/i386/conf [netbsd-8]: GENERIC files.i386
        src/sys/arch/i386/i386 [netbsd-8]: machdep.c
        src/sys/arch/x86/include [netbsd-8]: cpu.h specialreg.h
        src/sys/arch/x86/x86 [netbsd-8]: x86_machdep.c
Added Files:
        src/sys/arch/x86/x86 [netbsd-8]: spectre.c

Log Message:
Pullup the following revisions, requested by maxv in ticket #865:

        sys/arch/amd64/amd64/machdep.c          1.303 (patch)
        sys/arch/amd64/conf/GENERIC             1.492 (patch)
        sys/arch/amd64/conf/files.amd64         1.103 (patch)
        sys/arch/i386/i386/machdep.c            1.806 (patch)
        sys/arch/i386/conf/GENERIC              1.1179 (patch)
        sys/arch/i386/conf/files.i386           1.393 (patch)
        sys/arch/x86/include/cpu.h              1.91 (patch)
        sys/arch/x86/include/specialreg.h       upto 1.126 (patch)
        sys/arch/x86/x86/x86_machdep.c          upto 1.115 (patch, adapted)
        sys/arch/x86/x86/spectre.c              upto 1.19 (patch, adapted,
                                                no IBRS,
                                                SpectreV2 mitigations not
                                                enabled by default)

Backport the hardware SpectreV2 and SpectreV4 mitigations.


To generate a diff of this commit:
cvs rdiff -u -r1.255.6.6 -r1.255.6.7 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.459.2.9 -r1.459.2.10 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.88.8.3 -r1.88.8.4 src/sys/arch/amd64/conf/files.amd64
cvs rdiff -u -r1.1156.2.9 -r1.1156.2.10 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.378.6.2 -r1.378.6.3 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r1.782.6.5 -r1.782.6.6 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.71.2.5 -r1.71.2.6 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.98.2.4 -r1.98.2.5 src/sys/arch/x86/include/specialreg.h
cvs rdiff -u -r0 -r1.19.2.2 src/sys/arch/x86/x86/spectre.c
cvs rdiff -u -r1.91.4.2 -r1.91.4.3 src/sys/arch/x86/x86/x86_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.255.6.6 src/sys/arch/amd64/amd64/machdep.c:1.255.6.7
--- src/sys/arch/amd64/amd64/machdep.c:1.255.6.6	Thu Mar 22 16:59:03 2018
+++ src/sys/arch/amd64/amd64/machdep.c	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.255.6.6 2018/03/22 16:59:03 martin Exp $	*/
+/*	$NetBSD: machdep.c,v 1.255.6.7 2018/06/09 15:12:21 martin Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.6 2018/03/22 16:59:03 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255.6.7 2018/06/09 15:12:21 martin Exp $");
 
 /* #define XENDEBUG_LOW  */
 
@@ -1549,6 +1549,9 @@ init_x86_64(paddr_t first_avail)
 	svs_init();
 #endif
 	cpu_init_msrs(&cpu_info_primary, true);
+#ifndef XEN
+	cpu_speculation_init(&cpu_info_primary);
+#endif
 
 	use_pae = 1; /* PAE always enabled in long mode */
 

Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.459.2.9 src/sys/arch/amd64/conf/GENERIC:1.459.2.10
--- src/sys/arch/amd64/conf/GENERIC:1.459.2.9	Wed Apr 18 14:45:08 2018
+++ src/sys/arch/amd64/conf/GENERIC	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.459.2.9 2018/04/18 14:45:08 martin Exp $
+# $NetBSD: GENERIC,v 1.459.2.10 2018/06/09 15:12:21 martin Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.459.2.9 $"
+#ident		"GENERIC-$Revision: 1.459.2.10 $"
 
 maxusers	64		# estimated number of users
 
@@ -77,6 +77,7 @@ options 	SYSCTL_INCLUDE_DESCR	# Include 
 options 	SVS		# Separate Virtual Space
 makeoptions	SPECTRE_V2_GCC_MITIGATION=1	# GCC Spectre variant 2
 						# migitation
+options 	SPECTRE_V2_GCC_MITIGATION
 
 # CPU features
 acpicpu*	at cpu?		# ACPI CPU (including frequency scaling)

Index: src/sys/arch/amd64/conf/files.amd64
diff -u src/sys/arch/amd64/conf/files.amd64:1.88.8.3 src/sys/arch/amd64/conf/files.amd64:1.88.8.4
--- src/sys/arch/amd64/conf/files.amd64:1.88.8.3	Wed Apr 11 14:23:30 2018
+++ src/sys/arch/amd64/conf/files.amd64	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: files.amd64,v 1.88.8.3 2018/04/11 14:23:30 martin Exp $
+#	$NetBSD: files.amd64,v 1.88.8.4 2018/06/09 15:12:21 martin Exp $
 #
 # new style config file for amd64 architecture
 #
@@ -54,6 +54,7 @@ file	arch/amd64/amd64/machdep.c		machdep
 file	arch/amd64/amd64/process_machdep.c	machdep
 file	arch/amd64/amd64/trap.c			machdep
 file	arch/x86/x86/fpu.c			machdep
+file	arch/x86/x86/spectre.c			machdep
 file	arch/x86/x86/dbregs.c			machdep
 file	arch/x86/x86/convert_xmm_s87.c		machdep
 file	arch/amd64/amd64/lock_stubs.S		machdep

Index: src/sys/arch/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.1156.2.9 src/sys/arch/i386/conf/GENERIC:1.1156.2.10
--- src/sys/arch/i386/conf/GENERIC:1.1156.2.9	Wed Apr 18 14:45:08 2018
+++ src/sys/arch/i386/conf/GENERIC	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.1156.2.9 2018/04/18 14:45:08 martin Exp $
+# $NetBSD: GENERIC,v 1.1156.2.10 2018/06/09 15:12:21 martin Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/i386/conf/std.i386"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.1156.2.9 $"
+#ident		"GENERIC-$Revision: 1.1156.2.10 $"
 
 maxusers	64		# estimated number of users
 
@@ -32,6 +32,7 @@ options 	USER_LDT	# user-settable LDT; u
 #options 	PAE		# PAE mode (36 bits physical addressing)
 makeoptions	SPECTRE_V2_GCC_MITIGATION=1	# GCC Spectre variant 2
 						# migitation
+options 	SPECTRE_V2_GCC_MITIGATION
 
 # CPU features
 acpicpu*	at cpu?		# ACPI CPU (including frequency scaling)

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.378.6.2 src/sys/arch/i386/conf/files.i386:1.378.6.3
--- src/sys/arch/i386/conf/files.i386:1.378.6.2	Wed Apr 11 14:23:30 2018
+++ src/sys/arch/i386/conf/files.i386	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i386,v 1.378.6.2 2018/04/11 14:23:30 martin Exp $
+#	$NetBSD: files.i386,v 1.378.6.3 2018/06/09 15:12:21 martin Exp $
 #
 # new style config file for i386 architecture
 #
@@ -85,6 +85,7 @@ file	arch/i386/i386/trap.c
 file	dev/cons.c
 file	arch/x86/x86/fpu.c
 file	arch/x86/x86/dbregs.c
+file	arch/x86/x86/spectre.c
 
 file	arch/i386/i386/mptramp.S	multiprocessor
 

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.782.6.5 src/sys/arch/i386/i386/machdep.c:1.782.6.6
--- src/sys/arch/i386/i386/machdep.c:1.782.6.5	Thu Apr  5 18:15:02 2018
+++ src/sys/arch/i386/i386/machdep.c	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.782.6.5 2018/04/05 18:15:02 martin Exp $	*/
+/*	$NetBSD: machdep.c,v 1.782.6.6 2018/06/09 15:12:21 martin Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.782.6.5 2018/04/05 18:15:02 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.782.6.6 2018/06/09 15:12:21 martin Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_ibcs2.h"
@@ -1187,6 +1187,9 @@ init386(paddr_t first_avail)
 
 	cpu_probe(&cpu_info_primary);
 	cpu_init_msrs(&cpu_info_primary, true);
+#ifndef XEN
+	cpu_speculation_init(&cpu_info_primary);
+#endif
 
 #ifdef PAE
 	use_pae = 1;

Index: src/sys/arch/x86/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.71.2.5 src/sys/arch/x86/include/cpu.h:1.71.2.6
--- src/sys/arch/x86/include/cpu.h:1.71.2.5	Sun Apr  1 08:51:47 2018
+++ src/sys/arch/x86/include/cpu.h	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.71.2.5 2018/04/01 08:51:47 martin Exp $	*/
+/*	$NetBSD: cpu.h,v 1.71.2.6 2018/06/09 15:12:21 martin Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -357,6 +357,7 @@ void cpu_kick(struct cpu_info *);
 
 void cpu_pcpuarea_init(struct cpu_info *);
 void cpu_svs_init(struct cpu_info *);
+void cpu_speculation_init(struct cpu_info *);
 
 #define	curcpu()		x86_curcpu()
 #define	curlwp			x86_curlwp()

Index: src/sys/arch/x86/include/specialreg.h
diff -u src/sys/arch/x86/include/specialreg.h:1.98.2.4 src/sys/arch/x86/include/specialreg.h:1.98.2.5
--- src/sys/arch/x86/include/specialreg.h:1.98.2.4	Wed Apr 18 14:14:17 2018
+++ src/sys/arch/x86/include/specialreg.h	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: specialreg.h,v 1.98.2.4 2018/04/18 14:14:17 martin Exp $	*/
+/*	$NetBSD: specialreg.h,v 1.98.2.5 2018/06/09 15:12:21 martin Exp $	*/
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -104,10 +104,8 @@
 #define XCR0_Hi16_ZMM	0x00000080	/* AVX-512 512 bits upper registers */
 
 /*
- * Known fpu bits - only these get enabled
- * I think the XCR0_BNDREGS and XCR0_BNDCSR would need saving on
- * every context switch.
- * The save are is sized for all the fields below (max 2680 bytes).
+ * Known fpu bits - only these get enabled. The save area is sized for all the
+ * fields below (max 2680 bytes).
  */
 #define XCR0_FPU	(XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \
 			XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM)
@@ -405,11 +403,12 @@
 #define CPUID_SEF_IBRS		__BIT(26) /* IBRS / IBPB Speculation Control */
 #define CPUID_SEF_STIBP		__BIT(27) /* STIBP Speculation Control */
 #define CPUID_SEF_ARCH_CAP	__BIT(29) /* IA32_ARCH_CAPABILITIES */
+#define CPUID_SEF_SSBD		__BIT(31) /* Speculative Store Bypass Disable */
 
 #define CPUID_SEF_FLAGS2	"\20" \
 				"\3" "AVX512_4VNNIW" "\4" "AVX512_4FMAPS" \
 					"\33" "IBRS"	"\34" "STIBP"	\
-			"\36" "ARCH_CAP"
+			"\36" "ARCH_CAP"		"\40" "SSBD"
 
 /*
  * CPUID Processor extended state Enumeration Fn0000000d
@@ -643,6 +642,7 @@
 #define MSR_IA32_SPEC_CTRL	0x048
 #define 	IA32_SPEC_CTRL_IBRS	0x01
 #define 	IA32_SPEC_CTRL_STIBP	0x02
+#define 	IA32_SPEC_CTRL_SSBD	0x04
 #define MSR_IA32_PRED_CMD	0x049
 #define 	IA32_PRED_CMD_IBPB	0x01
 #define MSR_BIOS_UPDT_TRIG	0x079
@@ -660,6 +660,8 @@
 #define MSR_IA32_ARCH_CAPABILITIES 0x10a
 #define 	IA32_ARCH_RDCL_NO	0x01
 #define 	IA32_ARCH_IBRS_ALL	0x02
+#define 	IA32_ARCH_RSBA		0x04
+#define 	IA32_ARCH_SSB_NO	0x10
 #define MSR_BBL_CR_ADDR		0x116	/* PII+ only */
 #define MSR_BBL_CR_DECC		0x118	/* PII+ only */
 #define MSR_BBL_CR_CTL		0x119	/* PII+ only */
@@ -855,6 +857,9 @@
 
 #define MSR_LS_CFG	0xc0011020
 #define 	LS_CFG_DIS_LS2_SQUISH	0x02000000
+#define 	LS_CFG_DIS_SSB_F15H	0x0040000000000000ULL
+#define 	LS_CFG_DIS_SSB_F16H	0x0000000200000000ULL
+#define 	LS_CFG_DIS_SSB_F17H	0x0000000000000400ULL
 
 #define MSR_IC_CFG	0xc0011021
 #define 	IC_CFG_DIS_SEQ_PREFETCH	0x00000800

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.91.4.2 src/sys/arch/x86/x86/x86_machdep.c:1.91.4.3
--- src/sys/arch/x86/x86/x86_machdep.c:1.91.4.2	Thu Mar 22 16:59:04 2018
+++ src/sys/arch/x86/x86/x86_machdep.c	Sat Jun  9 15:12:21 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.91.4.2 2018/03/22 16:59:04 martin Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.91.4.3 2018/06/09 15:12:21 martin Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.91.4.2 2018/03/22 16:59:04 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.91.4.3 2018/06/09 15:12:21 martin Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -1196,6 +1196,11 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc
 		       CTL_CREATE, CTL_EOL);
 #endif
 
+#ifndef XEN
+	void sysctl_speculation_init(struct sysctllog **);
+	sysctl_speculation_init(clog);
+#endif
+
 	/* None of these can ever change once the system has booted */
 	const_sysctl(clog, "fpu_present", CTLTYPE_INT, i386_fpu_present,
 	    CPU_FPU_PRESENT);

Added files:

Index: src/sys/arch/x86/x86/spectre.c
diff -u /dev/null src/sys/arch/x86/x86/spectre.c:1.19.2.2
--- /dev/null	Sat Jun  9 15:12:21 2018
+++ src/sys/arch/x86/x86/spectre.c	Sat Jun  9 15:12:21 2018
@@ -0,0 +1,546 @@
+/*	$NetBSD: spectre.c,v 1.19.2.2 2018/06/09 15:12:21 martin Exp $	*/
+
+/*
+ * Copyright (c) 2018 NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Maxime Villard.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Mitigations for the SpectreV2 and SpectreV4 CPU flaws.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.19.2.2 2018/06/09 15:12:21 martin Exp $");
+
+#include "opt_spectre.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cpu.h>
+#include <sys/sysctl.h>
+#include <sys/xcall.h>
+
+#include <machine/cpufunc.h>
+#include <machine/cpuvar.h>
+#include <machine/specialreg.h>
+#include <machine/frameasm.h>
+
+#include <x86/cputypes.h>
+
+enum v2_mitigation {
+	V2_MITIGATION_NONE,
+	V2_MITIGATION_AMD_DIS_IND,
+};
+
+enum v4_mitigation {
+	V4_MITIGATION_NONE,
+	V4_MITIGATION_INTEL_SSBD,
+	V4_MITIGATION_INTEL_SSB_NO,
+	V4_MITIGATION_AMD_NONARCH_F15H,
+	V4_MITIGATION_AMD_NONARCH_F16H,
+	V4_MITIGATION_AMD_NONARCH_F17H
+};
+
+static enum v2_mitigation v2_mitigation_method = V2_MITIGATION_NONE;
+static enum v4_mitigation v4_mitigation_method = V4_MITIGATION_NONE;
+
+static bool v2_mitigation_enabled __read_mostly = false;
+static bool v4_mitigation_enabled __read_mostly = false;
+
+static char v2_mitigation_name[64] = "(none)";
+static char v4_mitigation_name[64] = "(none)";
+
+/* --------------------------------------------------------------------- */
+
+static void
+v2_set_name(void)
+{
+	char name[64] = "";
+	size_t nmitig = 0;
+
+#if defined(SPECTRE_V2_GCC_MITIGATION)
+	strlcat(name, "[GCC retpoline]", sizeof(name));
+	nmitig++;
+#endif
+
+	if (!v2_mitigation_enabled) {
+		if (nmitig == 0)
+			strlcat(name, "(none)", sizeof(name));
+	} else {
+		if (nmitig)
+			strlcat(name, " + ", sizeof(name));
+		switch (v2_mitigation_method) {
+		case V2_MITIGATION_AMD_DIS_IND:
+			strlcat(name, "[AMD DIS_IND]", sizeof(name));
+			break;
+		default:
+			panic("%s: impossible", __func__);
+		}
+	}
+
+	strlcpy(v2_mitigation_name, name,
+	    sizeof(v2_mitigation_name));
+}
+
+static void
+v2_detect_method(void)
+{
+	struct cpu_info *ci = curcpu();
+
+	if (cpu_vendor == CPUVENDOR_INTEL) {
+		v2_mitigation_method = V2_MITIGATION_NONE;
+	} else if (cpu_vendor == CPUVENDOR_AMD) {
+		/*
+		 * The AMD Family 10h manual documents the IC_CFG.DIS_IND bit.
+		 * This bit disables the Indirect Branch Predictor.
+		 *
+		 * Families 12h and 16h are believed to have this bit too, but
+		 * their manuals don't document it.
+		 */
+		switch (CPUID_TO_FAMILY(ci->ci_signature)) {
+		case 0x10:
+		case 0x12:
+		case 0x16:
+			v2_mitigation_method = V2_MITIGATION_AMD_DIS_IND;
+			break;
+		default:
+			v2_mitigation_method = V2_MITIGATION_NONE;
+			break;
+		}
+	} else {
+		v2_mitigation_method = V2_MITIGATION_NONE;
+	}
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void
+mitigation_v2_apply_cpu(bool enabled)
+{
+	uint64_t msr;
+
+	switch (v2_mitigation_method) {
+	case V2_MITIGATION_NONE:
+		panic("impossible");
+	case V2_MITIGATION_AMD_DIS_IND:
+		msr = rdmsr(MSR_IC_CFG);
+		if (enabled) {
+			msr |= IC_CFG_DIS_IND;
+		} else {
+			msr &= ~IC_CFG_DIS_IND;
+		}
+		wrmsr(MSR_IC_CFG, msr);
+		break;
+	}
+}
+
+static void
+mitigation_v2_change_cpu(void *arg1, void *arg2)
+{
+	bool enabled = (bool)arg1;
+
+	mitigation_v2_apply_cpu(enabled);
+}
+
+static int
+mitigation_v2_change(bool enabled)
+{
+	struct cpu_info *ci = NULL;
+	CPU_INFO_ITERATOR cii;
+	uint64_t xc;
+
+	v2_detect_method();
+
+	mutex_enter(&cpu_lock);
+
+	/*
+	 * We expect all the CPUs to be online.
+	 */
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		struct schedstate_percpu *spc = &ci->ci_schedstate;
+		if (spc->spc_flags & SPCF_OFFLINE) {
+			printf("[!] cpu%d offline, SpectreV2 not changed\n",
+			    cpu_index(ci));
+			mutex_exit(&cpu_lock);
+			return EOPNOTSUPP;
+		}
+	}
+
+	switch (v2_mitigation_method) {
+	case V2_MITIGATION_NONE:
+		printf("[!] No mitigation available\n");
+		mutex_exit(&cpu_lock);
+		return EOPNOTSUPP;
+	case V2_MITIGATION_AMD_DIS_IND:
+		printf("[+] %s SpectreV2 Mitigation...",
+		    enabled ? "Enabling" : "Disabling");
+		xc = xc_broadcast(0, mitigation_v2_change_cpu,
+		    (void *)enabled, NULL);
+		xc_wait(xc);
+		printf(" done!\n");
+		v2_mitigation_enabled = enabled;
+		mutex_exit(&cpu_lock);
+		v2_set_name();
+		return 0;
+	default:
+		panic("impossible");
+	}
+}
+
+static int
+sysctl_machdep_spectreV2_mitigated(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error;
+	bool val;
+
+	val = *(bool *)rnode->sysctl_data;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	if (val == v2_mitigation_enabled)
+		return 0;
+	return mitigation_v2_change(val);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void
+v4_set_name(void)
+{
+	char name[64] = "";
+
+	if (!v4_mitigation_enabled) {
+		strlcat(name, "(none)", sizeof(name));
+	} else {
+		switch (v4_mitigation_method) {
+		case V4_MITIGATION_NONE:
+			panic("%s: impossible", __func__);
+		case V4_MITIGATION_INTEL_SSBD:
+			strlcat(name, "[Intel SSBD]", sizeof(name));
+			break;
+		case V4_MITIGATION_INTEL_SSB_NO:
+			strlcat(name, "[Intel SSB_NO]", sizeof(name));
+			break;
+		case V4_MITIGATION_AMD_NONARCH_F15H:
+		case V4_MITIGATION_AMD_NONARCH_F16H:
+		case V4_MITIGATION_AMD_NONARCH_F17H:
+			strlcat(name, "[AMD NONARCH]", sizeof(name));
+			break;
+		}
+	}
+
+	strlcpy(v4_mitigation_name, name,
+	    sizeof(v4_mitigation_name));
+}
+
+static void
+v4_detect_method(void)
+{
+	struct cpu_info *ci = curcpu();
+	u_int descs[4];
+	uint64_t msr;
+
+	if (cpu_vendor == CPUVENDOR_INTEL) {
+		if (cpu_info_primary.ci_feat_val[7] & CPUID_SEF_ARCH_CAP) {
+			msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
+			if (msr & IA32_ARCH_SSB_NO) {
+				/*
+				 * The processor indicates it is not vulnerable
+				 * to the Speculative Store Bypass (SpectreV4)
+				 * flaw.
+				 */
+				v4_mitigation_method = V4_MITIGATION_INTEL_SSB_NO;
+				return;
+			}
+		}
+		if (cpuid_level >= 7) {
+			x86_cpuid(7, descs);
+			if (descs[3] & CPUID_SEF_SSBD) {
+				/* descs[3] = %edx */
+				v4_mitigation_method = V4_MITIGATION_INTEL_SSBD;
+				return;
+			}
+		}
+	} else if (cpu_vendor == CPUVENDOR_AMD) {
+		switch (CPUID_TO_FAMILY(ci->ci_signature)) {
+		case 0x15:
+			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F15H;
+			return;
+		case 0x16:
+			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F16H;
+			return;
+		case 0x17:
+			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F17H;
+			return;
+		default:
+			break;
+		}
+	}
+
+	v4_mitigation_method = V4_MITIGATION_NONE;
+}
+
+static void
+mitigation_v4_apply_cpu(bool enabled)
+{
+	uint64_t msr, msrval = 0, msrbit = 0;
+
+	switch (v4_mitigation_method) {
+	case V4_MITIGATION_NONE:
+	case V4_MITIGATION_INTEL_SSB_NO:
+		panic("impossible");
+	case V4_MITIGATION_INTEL_SSBD:
+		msrval = MSR_IA32_SPEC_CTRL;
+		msrbit = IA32_SPEC_CTRL_SSBD;
+		break;
+	case V4_MITIGATION_AMD_NONARCH_F15H:
+		msrval = MSR_LS_CFG;
+		msrbit = LS_CFG_DIS_SSB_F15H;
+		break;
+	case V4_MITIGATION_AMD_NONARCH_F16H:
+		msrval = MSR_LS_CFG;
+		msrbit = LS_CFG_DIS_SSB_F16H;
+		break;
+	case V4_MITIGATION_AMD_NONARCH_F17H:
+		msrval = MSR_LS_CFG;
+		msrbit = LS_CFG_DIS_SSB_F17H;
+		break;
+	}
+
+	msr = rdmsr(msrval);
+	if (enabled) {
+		msr |= msrbit;
+	} else {
+		msr &= ~msrbit;
+	}
+	wrmsr(msrval, msr);
+}
+
+static void
+mitigation_v4_change_cpu(void *arg1, void *arg2)
+{
+	bool enabled = (bool)arg1;
+
+	mitigation_v4_apply_cpu(enabled);
+}
+
+static int mitigation_v4_change(bool enabled)
+{
+	struct cpu_info *ci = NULL;
+	CPU_INFO_ITERATOR cii;
+	uint64_t xc;
+
+	v4_detect_method();
+
+	mutex_enter(&cpu_lock);
+
+	/*
+	 * We expect all the CPUs to be online.
+	 */
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		struct schedstate_percpu *spc = &ci->ci_schedstate;
+		if (spc->spc_flags & SPCF_OFFLINE) {
+			printf("[!] cpu%d offline, SpectreV4 not changed\n",
+			    cpu_index(ci));
+			mutex_exit(&cpu_lock);
+			return EOPNOTSUPP;
+		}
+	}
+
+	switch (v4_mitigation_method) {
+	case V4_MITIGATION_NONE:
+		printf("[!] No mitigation available\n");
+		mutex_exit(&cpu_lock);
+		return EOPNOTSUPP;
+	case V4_MITIGATION_INTEL_SSBD:
+	case V4_MITIGATION_AMD_NONARCH_F15H:
+	case V4_MITIGATION_AMD_NONARCH_F16H:
+	case V4_MITIGATION_AMD_NONARCH_F17H:
+		printf("[+] %s SpectreV4 Mitigation...",
+		    enabled ? "Enabling" : "Disabling");
+		xc = xc_broadcast(0, mitigation_v4_change_cpu,
+		    (void *)enabled, NULL);
+		xc_wait(xc);
+		printf(" done!\n");
+		v4_mitigation_enabled = enabled;
+		mutex_exit(&cpu_lock);
+		v4_set_name();
+		return 0;
+	case V4_MITIGATION_INTEL_SSB_NO:
+		printf("[+] The CPU is not affected by SpectreV4\n");
+		mutex_exit(&cpu_lock);
+		return 0;
+	default:
+		panic("impossible");
+	}
+}
+
+static int
+sysctl_machdep_spectreV4_mitigated(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error;
+	bool val;
+
+	val = *(bool *)rnode->sysctl_data;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	if (val == v4_mitigation_enabled)
+		return 0;
+	return mitigation_v4_change(val);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void
+cpu_speculation_init(struct cpu_info *ci)
+{
+	/*
+	 * Spectre V2.
+	 *
+	 * cpu0 is the one that detects the method and sets the global
+	 * variable.
+	 */
+#if 0
+	if (ci == &cpu_info_primary) {
+		v2_detect_method();
+		v2_mitigation_enabled =
+		    (v2_mitigation_method != V2_MITIGATION_NONE);
+		v2_set_name();
+	}
+	if (v2_mitigation_method != V2_MITIGATION_NONE) {
+		mitigation_v2_apply_cpu(ci, true);
+	}
+#endif
+
+	/*
+	 * Spectre V4.
+	 *
+	 * cpu0 is the one that detects the method and sets the global
+	 * variable.
+	 */
+#if 0
+	if (ci == &cpu_info_primary) {
+		v4_detect_method();
+		v4_mitigation_enabled =
+		    (v4_mitigation_method != V4_MITIGATION_NONE);
+		v4_set_name();
+	}
+	if (v4_mitigation_method != V4_MITIGATION_NONE) {
+		mitigation_v4_apply_cpu(ci, true);
+	}
+#endif
+}
+
+void sysctl_speculation_init(struct sysctllog **);
+
+void
+sysctl_speculation_init(struct sysctllog **clog)
+{
+	const struct sysctlnode *spec_rnode;
+
+	/* SpectreV1 */
+	spec_rnode = NULL;
+	sysctl_createv(clog, 0, NULL, &spec_rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "spectre_v1", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_MACHDEP, CTL_CREATE);
+	sysctl_createv(clog, 0, &spec_rnode, &spec_rnode,
+		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
+		       CTLTYPE_BOOL, "mitigated",
+		       SYSCTL_DESCR("Whether Spectre Variant 1 is mitigated"),
+		       NULL, 0 /* mitigated=0 */, NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	/* SpectreV2 */
+	spec_rnode = NULL;
+	sysctl_createv(clog, 0, NULL, &spec_rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "spectre_v2", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_MACHDEP, CTL_CREATE);
+	sysctl_createv(clog, 0, &spec_rnode, NULL,
+		       CTLFLAG_READWRITE,
+		       CTLTYPE_BOOL, "hwmitigated",
+		       SYSCTL_DESCR("Whether Spectre Variant 2 is HW-mitigated"),
+		       sysctl_machdep_spectreV2_mitigated, 0,
+		       &v2_mitigation_enabled, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &spec_rnode, NULL,
+		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
+		       CTLTYPE_BOOL, "swmitigated",
+		       SYSCTL_DESCR("Whether Spectre Variant 2 is SW-mitigated"),
+#if defined(SPECTRE_V2_GCC_MITIGATION)
+		       NULL, 1,
+#else
+		       NULL, 0,
+#endif
+		       NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &spec_rnode, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_STRING, "method",
+		       SYSCTL_DESCR("Mitigation method in use"),
+		       NULL, 0,
+		       v2_mitigation_name, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	/* SpectreV4 */
+	spec_rnode = NULL;
+	sysctl_createv(clog, 0, NULL, &spec_rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "spectre_v4", NULL,
+		       NULL, 0, NULL, 0,
+		       CTL_MACHDEP, CTL_CREATE);
+	sysctl_createv(clog, 0, &spec_rnode, NULL,
+		       CTLFLAG_READWRITE,
+		       CTLTYPE_BOOL, "mitigated",
+		       SYSCTL_DESCR("Whether Spectre Variant 4 is mitigated"),
+		       sysctl_machdep_spectreV4_mitigated, 0,
+		       &v4_mitigation_enabled, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &spec_rnode, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_STRING, "method",
+		       SYSCTL_DESCR("Mitigation method in use"),
+		       NULL, 0,
+		       v4_mitigation_name, 0,
+		       CTL_CREATE, CTL_EOL);
+}

Reply via email to