Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86 Mitigation for SpectreV4, based on...
details: https://anonhg.NetBSD.org/src/rev/a2823d0c5d21
branches: trunk
changeset: 319224:a2823d0c5d21
user: maxv <maxv%NetBSD.org@localhost>
date: Tue May 22 07:11:53 2018 +0000
description:
Mitigation for SpectreV4, based on SSBD. The following sysctl branches
are added:
machdep.spectre_v4.mitigated = {0/1} user-settable
machdep.spectre_v4.affected = {0/1} set by the kernel
The mitigation is not enabled by default yet. It is not tested either,
because no microcode update has been published yet.
On current CPUs a microcode/bios update must be applied for SSBD to be
available. The user can then set mitigated=1. Even with an update applied
the kernel will set affected=1.
On future CPUs, where the problem will presumably be fixed by default,
the CPU will report SSB_NO, and the kernel will set affected=0. In this
case we also have mitigated=0, but the mitigation is not needed.
For now the feature is system-wide. Perhaps we will want a more
fine-grained, per-process approach in the future.
diffstat:
sys/arch/x86/include/specialreg.h | 12 +-
sys/arch/x86/x86/spectre.c | 149 +++++++++++++++++++++++++++++++++++++-
sys/arch/x86/x86/x86_machdep.c | 29 ++++++-
3 files changed, 181 insertions(+), 9 deletions(-)
diffs (275 lines):
diff -r 5245b9277fd9 -r a2823d0c5d21 sys/arch/x86/include/specialreg.h
--- a/sys/arch/x86/include/specialreg.h Tue May 22 06:31:05 2018 +0000
+++ b/sys/arch/x86/include/specialreg.h Tue May 22 07:11:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: specialreg.h,v 1.120 2018/03/30 19:49:49 maxv Exp $ */
+/* $NetBSD: specialreg.h,v 1.121 2018/05/22 07:11:53 maxv Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@@ -405,11 +405,11 @@
#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"
+#define CPUID_SEF_FLAGS2 \
+ "\20" "\3" "AVX512_4VNNIW" "\4" "AVX512_4FMAPS" \
+ "\33" "IBRS" "\34" "STIBP" "\36" "ARCH_CAP" "\38" "SSBD"
/*
* CPUID Processor extended state Enumeration Fn0000000d
@@ -643,6 +643,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 +661,7 @@
#define MSR_IA32_ARCH_CAPABILITIES 0x10a
#define IA32_ARCH_RDCL_NO 0x01
#define IA32_ARCH_IBRS_ALL 0x02
+#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 */
diff -r 5245b9277fd9 -r a2823d0c5d21 sys/arch/x86/x86/spectre.c
--- a/sys/arch/x86/x86/spectre.c Tue May 22 06:31:05 2018 +0000
+++ b/sys/arch/x86/x86/spectre.c Tue May 22 07:11:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: spectre.c,v 1.11 2018/05/22 06:31:05 maxv Exp $ */
+/* $NetBSD: spectre.c,v 1.12 2018/05/22 07:11:53 maxv Exp $ */
/*
* Copyright (c) 2018 NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.11 2018/05/22 06:31:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.12 2018/05/22 07:11:53 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -347,6 +347,140 @@
/* -------------------------------------------------------------------------- */
+bool spec_v4_mitigation_enabled __read_mostly = false;
+bool spec_v4_affected __read_mostly = true;
+
+int sysctl_machdep_spectreV4_mitigated(SYSCTLFN_ARGS);
+
+static bool ssbd_needed(void)
+{
+ uint64_t msr;
+
+ 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.
+ */
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool ssbd_supported(void)
+{
+ u_int descs[4];
+
+ if (cpu_vendor == CPUVENDOR_INTEL) {
+ if (cpuid_level >= 7) {
+ x86_cpuid(7, descs);
+ if (descs[3] & CPUID_SEF_SSBD) {
+ /* descs[3] = %edx */
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void
+mitigation_v4_apply_cpu(bool enabled)
+{
+ uint64_t msr;
+
+ msr = rdmsr(MSR_IA32_SPEC_CTRL);
+
+ if (enabled) {
+ msr |= IA32_SPEC_CTRL_SSBD;
+ } else {
+ msr &= ~IA32_SPEC_CTRL_SSBD;
+ }
+
+ wrmsr(MSR_IA32_SPEC_CTRL, 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;
+
+ if (!ssbd_supported()) {
+ printf("[!] No mitigation available\n");
+ return EOPNOTSUPP;
+ }
+
+ 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;
+ }
+ }
+
+ printf("[+] %s SpectreV4 Mitigation...",
+ enabled ? "Enabling" : "Disabling");
+ xc = xc_broadcast(0, mitigation_v4_change_cpu,
+ (void *)enabled, NULL);
+ xc_wait(xc);
+ printf(" done!\n");
+ spec_v4_mitigation_enabled = enabled;
+ mutex_exit(&cpu_lock);
+
+ return 0;
+}
+
+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 == 0) {
+ if (!spec_v4_mitigation_enabled)
+ error = 0;
+ else
+ error = mitigation_v4_change(false);
+ } else {
+ if (spec_v4_mitigation_enabled)
+ error = 0;
+ else
+ error = mitigation_v4_change(true);
+ }
+
+ return error;
+}
+
+/* -------------------------------------------------------------------------- */
+
void speculation_barrier(struct lwp *, struct lwp *);
void
@@ -393,4 +527,15 @@
if (mitigation_v2_method != MITIGATION_NONE) {
mitigation_v2_apply_cpu(ci, true);
}
+
+ /*
+ * Spectre V4.
+ */
+ if (ssbd_needed()) {
+ if (ci == &cpu_info_primary) {
+ spec_v4_affected = true;
+ }
+ /* mitigation_v4_apply_cpu(true); */
+ /* spec_v4_mitigation_enabled = true; */
+ }
}
diff -r 5245b9277fd9 -r a2823d0c5d21 sys/arch/x86/x86/x86_machdep.c
--- a/sys/arch/x86/x86/x86_machdep.c Tue May 22 06:31:05 2018 +0000
+++ b/sys/arch/x86/x86/x86_machdep.c Tue May 22 07:11:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: x86_machdep.c,v 1.112 2018/05/22 06:31:05 maxv Exp $ */
+/* $NetBSD: x86_machdep.c,v 1.113 2018/05/22 07:11:53 maxv 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.112 2018/05/22 06:31:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.113 2018/05/22 07:11:53 maxv Exp $");
#include "opt_modular.h"
#include "opt_physmem.h"
@@ -1273,8 +1273,11 @@
#ifndef XEN
int sysctl_machdep_spectreV2_mitigated(SYSCTLFN_ARGS);
+ int sysctl_machdep_spectreV4_mitigated(SYSCTLFN_ARGS);
extern bool spec_v2_mitigation_enabled;
+ extern bool spec_v4_mitigation_enabled;
extern char spec_v2_mitigation_name[];
+ extern bool spec_v4_affected;
const struct sysctlnode *spec_rnode;
/* SpectreV1 */
@@ -1312,6 +1315,28 @@
NULL, 0,
spec_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,
+ &spec_v4_mitigation_enabled, 0,
+ CTL_CREATE, CTL_EOL);
+ sysctl_createv(clog, 0, &spec_rnode, NULL,
+ CTLFLAG_PERMANENT,
+ CTLTYPE_BOOL, "affected",
+ SYSCTL_DESCR("Whether the CPU is affected by SpectreV4"),
+ NULL, 0,
+ &spec_v4_affected, 0,
+ CTL_CREATE, CTL_EOL);
#endif
/* None of these can ever change once the system has booted */
Home |
Main Index |
Thread Index |
Old Index