From: Thomas Gleixner <tglx@linutronix.de>
To: speck@linutronix.de
Subject: [patch V3 6/9] MDS basics 6
Date: Fri, 22 Feb 2019 00:44:37 +0100 [thread overview]
Message-ID: <20190221235534.926465092@linutronix.de> (raw)
In-Reply-To: 20190221234431.922117624@linutronix.de
Subject: [patch V3 6/9] x86/speculation/mds: Conditionally clear CPU buffers on idle entry
From: Thomas Gleixner <tglx@linutronix.de>
Add a static key which controls the invocation of the CPU buffer clear
mechanism on idle entry. This is independent of other MDS mitigations
because the idle entry invocation to mitigate the potential leakage due to
store buffer repartitioning is only necessary on SMT systems.
Add the actual invocations to the different halt/mwait variants which
covers all usage sites. mwaitx is not patched as it's not available on
Intel CPUs.
The buffer clear is only invoked before entering the C-State to prevent
that stale data from the idling CPU is spilled to the Hyper-Thread sibling
after the Store buffer got repartitioned and all entries are available to
the non idle sibling.
When coming out of idle the store buffer is partitioned again so each
sibling has half of it available. Now CPU which returned from idle could be
speculatively exposed to contents of the sibling, but the buffers are
flushed either on exit to user space or on VMENTER.
When later on conditional buffer clearing is implemented on top of this,
then there is no action required either because before returning to user
space the context switch will set the condition flag which causes a flush
on the return to user path.
This intentionaly does not handle the case in the acpi/processor_idle
driver which uses the legacy IO port interface for C-State transitions for
two reasons:
- The acpi/processor_idle driver was replaced by the intel_idle driver
almost a decade ago. Anything Nehalem upwards supports it and defaults
to that new driver.
- The legacy IO port interface is likely to be used on older and therefore
unaffected CPUs or on systems which do not receive microcode updates
anymore, so there is no point in adding that.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
---
V3: Adjust document wording
---
Documentation/x86/mds.rst | 35 +++++++++++++++++++++++++++++++++++
arch/x86/include/asm/irqflags.h | 4 ++++
arch/x86/include/asm/mwait.h | 7 +++++++
arch/x86/include/asm/nospec-branch.h | 12 ++++++++++++
arch/x86/kernel/cpu/bugs.c | 2 ++
5 files changed, 60 insertions(+)
--- a/Documentation/x86/mds.rst
+++ b/Documentation/x86/mds.rst
@@ -125,3 +125,38 @@ Mitigation points
There is one non maskable exception which returns through paranoid exit
and is not mitigated: #DF. If user space is able to trigger a double
fault the possible MDS leakage is the least problem to worry about.
+
+
+2. C-State transition
+^^^^^^^^^^^^^^^^^^^^^
+
+ When a CPU goes idle and enters a C-State the CPU buffers need to be
+ cleared on affected CPUs when SMT is active. This addresses the
+ repartitioning of the store buffer when one of the Hyper-Threads enters
+ a C-State.
+
+ When SMT is inactive, i.e. either the CPU does not support it or all
+ sibling threads are offline CPU buffer clearing is not required.
+
+ The invocation is controlled by the static key mds_idle_clear which is
+ switched depending on the chosen mitigation mode and the SMT state of
+ the system.
+
+ The buffer clear is only invoked before entering the C-State to prevent
+ that stale data from the idling CPU can be spilled to the Hyper-Thread
+ sibling after the store buffer got repartitioned and all entries are
+ available to the non idle sibling.
+
+ When coming out of idle the store buffer is partitioned again so each
+ sibling has half of it available. The back from idle CPU could be then
+ speculatively exposed to contents of the sibling. The buffers are
+ flushed either on exit to user space or on VMENTER so malicious code
+ in user space or the guest cannot speculatively access them.
+
+ The mitigation is hooked into all variants of halt()/mwait(), but does
+ not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
+ has been superseded by the intel_idle driver around 2010 and is
+ preferred on all affected CPUs which are expected to gain the MD_CLEAR
+ functionality in microcode. Aside of that the IO-Port mechanism is a
+ legacy interface which is only used on older systems which are either
+ not affected or do not receive microcode updates anymore.
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -6,6 +6,8 @@
#ifndef __ASSEMBLY__
+#include <asm/nospec-branch.h>
+
/* Provide __cpuidle; we can't safely include <linux/cpu.h> */
#define __cpuidle __attribute__((__section__(".cpuidle.text")))
@@ -54,11 +56,13 @@ static inline void native_irq_enable(voi
static inline __cpuidle void native_safe_halt(void)
{
+ mds_idle_clear_cpu_buffers();
asm volatile("sti; hlt": : :"memory");
}
static inline __cpuidle void native_halt(void)
{
+ mds_idle_clear_cpu_buffers();
asm volatile("hlt": : :"memory");
}
--- a/arch/x86/include/asm/mwait.h
+++ b/arch/x86/include/asm/mwait.h
@@ -6,6 +6,7 @@
#include <linux/sched/idle.h>
#include <asm/cpufeature.h>
+#include <asm/nospec-branch.h>
#define MWAIT_SUBSTATE_MASK 0xf
#define MWAIT_CSTATE_MASK 0xf
@@ -40,6 +41,8 @@ static inline void __monitorx(const void
static inline void __mwait(unsigned long eax, unsigned long ecx)
{
+ mds_idle_clear_cpu_buffers();
+
/* "mwait %eax, %ecx;" */
asm volatile(".byte 0x0f, 0x01, 0xc9;"
:: "a" (eax), "c" (ecx));
@@ -74,6 +77,8 @@ static inline void __mwait(unsigned long
static inline void __mwaitx(unsigned long eax, unsigned long ebx,
unsigned long ecx)
{
+ /* No MDS buffer clear as this is AMD/HYGON only */
+
/* "mwaitx %eax, %ebx, %ecx;" */
asm volatile(".byte 0x0f, 0x01, 0xfb;"
:: "a" (eax), "b" (ebx), "c" (ecx));
@@ -81,6 +86,8 @@ static inline void __mwaitx(unsigned lon
static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
{
+ mds_idle_clear_cpu_buffers();
+
trace_hardirqs_on();
/* "mwait %eax, %ecx;" */
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -319,6 +319,7 @@ DECLARE_STATIC_KEY_FALSE(switch_mm_cond_
DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
DECLARE_STATIC_KEY_FALSE(mds_user_clear);
+DECLARE_STATIC_KEY_FALSE(mds_idle_clear);
#include <asm/segment.h>
@@ -343,6 +344,17 @@ static inline void mds_clear_cpu_buffers
asm volatile("verw %[ds]" : : [ds] "m" (ds) : "cc");
}
+/**
+ * mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability
+ *
+ * Clear CPU buffers if the corresponding static key is enabled
+ */
+static inline void mds_idle_clear_cpu_buffers(void)
+{
+ if (static_branch_likely(&mds_idle_clear))
+ mds_clear_cpu_buffers();
+}
+
#endif /* __ASSEMBLY__ */
/*
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -65,6 +65,8 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_always
/* Control MDS CPU buffer clear before returning to user space */
DEFINE_STATIC_KEY_FALSE(mds_user_clear);
+/* Control MDS CPU buffer clear before idling (halt, mwait) */
+DEFINE_STATIC_KEY_FALSE(mds_idle_clear);
void __init check_bugs(void)
{
next prev parent reply other threads:[~2019-02-22 0:31 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-21 23:44 [patch V3 0/9] MDS basics 0 Thomas Gleixner
2019-02-21 23:44 ` [patch V3 1/9] MDS basics 1 Thomas Gleixner
2019-02-22 6:53 ` [MODERATED] " Greg KH
2019-02-22 7:30 ` Borislav Petkov
2019-02-21 23:44 ` [patch V3 2/9] MDS basics 2 Thomas Gleixner
2019-02-21 23:44 ` [patch V3 3/9] MDS basics 3 Thomas Gleixner
2019-02-21 23:44 ` [patch V3 4/9] MDS basics 4 Thomas Gleixner
2019-02-22 6:58 ` [MODERATED] " Greg KH
2019-02-22 10:44 ` Thomas Gleixner
2019-02-22 14:36 ` [MODERATED] " Greg KH
2019-02-22 22:38 ` Thomas Gleixner
2019-02-22 7:45 ` [MODERATED] Encrypted Message Jon Masters
2019-02-22 17:16 ` [MODERATED] " Linus Torvalds
2019-02-22 17:40 ` Thomas Gleixner
2019-02-22 7:50 ` [MODERATED] Re: [patch V3 4/9] MDS basics 4 Borislav Petkov
2019-02-21 23:44 ` [patch V3 5/9] MDS basics 5 Thomas Gleixner
2019-02-22 0:46 ` [MODERATED] " Andrew Cooper
2019-02-22 7:00 ` Thomas Gleixner
2019-02-22 9:20 ` [MODERATED] " Peter Zijlstra
2019-02-22 10:23 ` Thomas Gleixner
2019-02-21 23:44 ` Thomas Gleixner [this message]
2019-02-21 23:44 ` [patch V3 7/9] MDS basics 7 Thomas Gleixner
2019-02-22 7:08 ` [MODERATED] " Greg KH
2019-02-21 23:44 ` [patch V3 8/9] MDS basics 8 Thomas Gleixner
2019-02-22 7:14 ` [MODERATED] " Greg KH
2019-02-22 8:55 ` Borislav Petkov
2019-02-21 23:44 ` [patch V3 9/9] MDS basics 9 Thomas Gleixner
2019-02-22 7:50 ` [MODERATED] " Greg KH
2019-02-22 10:38 ` Thomas Gleixner
2019-02-22 14:44 ` [MODERATED] " Greg KH
2019-02-22 15:53 ` [MODERATED] " Borislav Petkov
2019-02-22 15:54 ` [MODERATED] " Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190221235534.926465092@linutronix.de \
--to=tglx@linutronix.de \
--cc=speck@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.