Date: Mon, 21 May 2018 21:08:19 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334005 - in head/sys: amd64/amd64 amd64/include dev/cpuctl x86/acpica x86/include x86/x86 Message-ID: <201805212108.w4LL8J8J007563@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Mon May 21 21:08:19 2018 New Revision: 334005 URL: https://svnweb.freebsd.org/changeset/base/334005 Log: Add Intel Spec Store Bypass Disable control. Speculative Store Bypass (SSB) is a speculative execution side channel vulnerability identified by Jann Horn of Google Project Zero (GPZ) and Ken Johnson of the Microsoft Security Response Center (MSRC) https://bugs.chromium.org/p/project-zero/issues/detail?id=1528. Updated Intel microcode introduces a MSR bit to disable SSB as a mitigation for the vulnerability. Introduce a sysctl hw.spec_store_bypass_disable to provide global control over the SSBD bit, akin to the existing sysctl that controls IBRS. The sysctl can be set to one of three values: 0: off 1: on 2: auto Future work will enable applications to control SSBD on a per-process basis (when it is not enabled globally). SSBD bit detection and control was verified with prerelease microcode. Security: CVE-2018-3639 Tested by: emaste (previous version, without updated microcode) Sponsored by: The FreeBSD Foundation MFC after: 3 days Modified: head/sys/amd64/amd64/initcpu.c head/sys/amd64/amd64/machdep.c head/sys/amd64/include/md_var.h head/sys/dev/cpuctl/cpuctl.c head/sys/x86/acpica/acpi_wakeup.c head/sys/x86/include/x86_var.h head/sys/x86/x86/cpu_machdep.c Modified: head/sys/amd64/amd64/initcpu.c ============================================================================== --- head/sys/amd64/amd64/initcpu.c Mon May 21 21:07:13 2018 (r334004) +++ head/sys/amd64/amd64/initcpu.c Mon May 21 21:08:19 2018 (r334005) @@ -224,6 +224,7 @@ initializecpu(void) pg_nx = PG_NX; } hw_ibrs_recalculate(); + hw_ssb_recalculate(false); switch (cpu_vendor_id) { case CPU_VENDOR_AMD: init_amd(); Modified: head/sys/amd64/amd64/machdep.c ============================================================================== --- head/sys/amd64/amd64/machdep.c Mon May 21 21:07:13 2018 (r334004) +++ head/sys/amd64/amd64/machdep.c Mon May 21 21:08:19 2018 (r334005) @@ -1843,6 +1843,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) thread0.td_critnest = 0; TUNABLE_INT_FETCH("hw.ibrs_disable", &hw_ibrs_disable); + TUNABLE_INT_FETCH("hw.spec_store_bypass_disable", &hw_ssb_disable); TSEXIT(); Modified: head/sys/amd64/include/md_var.h ============================================================================== --- head/sys/amd64/include/md_var.h Mon May 21 21:07:13 2018 (r334004) +++ head/sys/amd64/include/md_var.h Mon May 21 21:08:19 2018 (r334005) @@ -39,6 +39,7 @@ extern uint64_t *vm_page_dump; extern int hw_lower_amd64_sharedpage; extern int hw_ibrs_disable; +extern int hw_ssb_disable; /* * The file "conf/ldscript.amd64" defines the symbol "kernphys". Its Modified: head/sys/dev/cpuctl/cpuctl.c ============================================================================== --- head/sys/dev/cpuctl/cpuctl.c Mon May 21 21:07:13 2018 (r334004) +++ head/sys/dev/cpuctl/cpuctl.c Mon May 21 21:08:19 2018 (r334005) @@ -529,6 +529,7 @@ cpuctl_do_eval_cpu_features(int cpu, struct thread *td identify_cpu2(); hw_ibrs_recalculate(); restore_cpu(oldcpu, is_bound, td); + hw_ssb_recalculate(true); printcpuinfo(); return (0); } Modified: head/sys/x86/acpica/acpi_wakeup.c ============================================================================== --- head/sys/x86/acpica/acpi_wakeup.c Mon May 21 21:07:13 2018 (r334004) +++ head/sys/x86/acpica/acpi_wakeup.c Mon May 21 21:08:19 2018 (r334005) @@ -244,6 +244,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) #endif #ifdef __amd64__ hw_ibrs_active = 0; + hw_ssb_active = 0; cpu_stdext_feature3 = 0; CPU_FOREACH(i) { pc = pcpu_find(i); Modified: head/sys/x86/include/x86_var.h ============================================================================== --- head/sys/x86/include/x86_var.h Mon May 21 21:07:13 2018 (r334004) +++ head/sys/x86/include/x86_var.h Mon May 21 21:08:19 2018 (r334005) @@ -85,6 +85,7 @@ extern uint64_t xsave_mask; extern u_int max_apic_id; extern int pti; extern int hw_ibrs_active; +extern int hw_ssb_active; struct pcb; struct thread; @@ -137,6 +138,7 @@ int isa_nmi(int cd); void handle_ibrs_entry(void); void handle_ibrs_exit(void); void hw_ibrs_recalculate(void); +void hw_ssb_recalculate(bool all_cpus); void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame); void nmi_call_kdb_smp(u_int type, struct trapframe *frame); void nmi_handle_intr(u_int type, struct trapframe *frame); Modified: head/sys/x86/x86/cpu_machdep.c ============================================================================== --- head/sys/x86/x86/cpu_machdep.c Mon May 21 21:07:13 2018 (r334004) +++ head/sys/x86/x86/cpu_machdep.c Mon May 21 21:08:19 2018 (r334005) @@ -150,6 +150,7 @@ void acpi_cpu_idle_mwait(uint32_t mwait_hint) { int *state; + uint64_t v; /* * A comment in Linux patch claims that 'CPUs run faster with @@ -166,13 +167,26 @@ acpi_cpu_idle_mwait(uint32_t mwait_hint) KASSERT(atomic_load_int(state) == STATE_SLEEPING, ("cpu_mwait_cx: wrong monitorbuf state")); atomic_store_int(state, STATE_MWAIT); - handle_ibrs_exit(); + if (PCPU_GET(ibpb_set) || hw_ssb_active) { + v = rdmsr(MSR_IA32_SPEC_CTRL); + wrmsr(MSR_IA32_SPEC_CTRL, v & ~(IA32_SPEC_CTRL_IBRS | + IA32_SPEC_CTRL_STIBP | IA32_SPEC_CTRL_SSBD)); + } else { + v = 0; + } cpu_monitor(state, 0, 0); if (atomic_load_int(state) == STATE_MWAIT) cpu_mwait(MWAIT_INTRBREAK, mwait_hint); - handle_ibrs_entry(); /* + * SSB cannot be disabled while we sleep, or rather, if it was + * disabled, the sysctl thread will bind to our cpu to tweak + * MSR. + */ + if (v != 0) + wrmsr(MSR_IA32_SPEC_CTRL, v); + + /* * We should exit on any event that interrupts mwait, because * that event might be a wanted interrupt. */ @@ -803,6 +817,95 @@ hw_ibrs_disable_handler(SYSCTL_HANDLER_ARGS) SYSCTL_PROC(_hw, OID_AUTO, ibrs_disable, CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NOFETCH | CTLFLAG_MPSAFE, NULL, 0, hw_ibrs_disable_handler, "I", "Disable Indirect Branch Restricted Speculation"); + +int hw_ssb_active; +int hw_ssb_disable; + +SYSCTL_INT(_hw, OID_AUTO, spec_store_bypass_disable_active, CTLFLAG_RD, + &hw_ssb_active, 0, + "Speculative Store Bypass Disable active"); + +static void +hw_ssb_set_one(bool enable) +{ + uint64_t v; + + v = rdmsr(MSR_IA32_SPEC_CTRL); + if (enable) + v |= (uint64_t)IA32_SPEC_CTRL_SSBD; + else + v &= ~(uint64_t)IA32_SPEC_CTRL_SSBD; + wrmsr(MSR_IA32_SPEC_CTRL, v); +} + +static void +hw_ssb_set(bool enable, bool for_all_cpus) +{ + struct thread *td; + int bound_cpu, i, is_bound; + + if ((cpu_stdext_feature3 & CPUID_STDEXT3_SSBD) == 0) { + hw_ssb_active = 0; + return; + } + hw_ssb_active = enable; + if (for_all_cpus) { + td = curthread; + thread_lock(td); + is_bound = sched_is_bound(td); + bound_cpu = td->td_oncpu; + CPU_FOREACH(i) { + sched_bind(td, i); + hw_ssb_set_one(enable); + } + if (is_bound) + sched_bind(td, bound_cpu); + else + sched_unbind(td); + thread_unlock(td); + } else { + hw_ssb_set_one(enable); + } +} + +void +hw_ssb_recalculate(bool all_cpus) +{ + + switch (hw_ssb_disable) { + default: + hw_ssb_disable = 0; + /* FALLTHROUGH */ + case 0: /* off */ + hw_ssb_set(false, all_cpus); + break; + case 1: /* on */ + hw_ssb_set(true, all_cpus); + break; + case 2: /* auto */ + hw_ssb_set((cpu_ia32_arch_caps & IA32_ARCH_CAP_SSBD_NO) != 0 ? + false : true, all_cpus); + break; + } +} + +static int +hw_ssb_disable_handler(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = hw_ssb_disable; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + hw_ssb_disable = val; + hw_ssb_recalculate(true); + return (0); +} +SYSCTL_PROC(_hw, OID_AUTO, spec_store_bypass_disable, CTLTYPE_INT | + CTLFLAG_RWTUN | CTLFLAG_NOFETCH | CTLFLAG_MPSAFE, NULL, 0, + hw_ssb_disable_handler, "I", + "Speculative Store Bypass Disable (0 - off, 1 - on, 2 - auto"); /* * Enable and restore kernel text write permissions.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805212108.w4LL8J8J007563>