Module Name: src Committed By: maxv Date: Tue May 22 07:11:54 UTC 2018
Modified Files: src/sys/arch/x86/include: specialreg.h src/sys/arch/x86/x86: spectre.c x86_machdep.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/arch/x86/include/specialreg.h cvs rdiff -u -r1.11 -r1.12 src/sys/arch/x86/x86/spectre.c cvs rdiff -u -r1.112 -r1.113 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/x86/include/specialreg.h diff -u src/sys/arch/x86/include/specialreg.h:1.120 src/sys/arch/x86/include/specialreg.h:1.121 --- src/sys/arch/x86/include/specialreg.h:1.120 Fri Mar 30 19:49:49 2018 +++ src/sys/arch/x86/include/specialreg.h Tue May 22 07:11:53 2018 @@ -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 */ Index: src/sys/arch/x86/x86/spectre.c diff -u src/sys/arch/x86/x86/spectre.c:1.11 src/sys/arch/x86/x86/spectre.c:1.12 --- src/sys/arch/x86/x86/spectre.c:1.11 Tue May 22 06:31:05 2018 +++ src/sys/arch/x86/x86/spectre.c Tue May 22 07:11:53 2018 @@ -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 @@ sysctl_machdep_spectreV2_mitigated(SYSCT /* -------------------------------------------------------------------------- */ +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 @@ cpu_speculation_init(struct cpu_info *ci 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; */ + } } Index: src/sys/arch/x86/x86/x86_machdep.c diff -u src/sys/arch/x86/x86/x86_machdep.c:1.112 src/sys/arch/x86/x86/x86_machdep.c:1.113 --- src/sys/arch/x86/x86/x86_machdep.c:1.112 Tue May 22 06:31:05 2018 +++ src/sys/arch/x86/x86/x86_machdep.c Tue May 22 07:11:53 2018 @@ -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 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc #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 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc 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 */