From: Brian Woods <brian.woods@amd.com>
To: xen-devel@lists.xen.org
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
Brian Woods <brian.woods@amd.com>,
Jan Beulich <jbeulich@suse.com>
Subject: [PATCH v2 2/2] x86/spec-ctrl: add support for modifying SSBD VIA LS_CFG MSR
Date: Thu, 9 Aug 2018 14:42:13 -0500 [thread overview]
Message-ID: <20180809194213.56671-3-brian.woods@amd.com> (raw)
In-Reply-To: <20180809194213.56671-1-brian.woods@amd.com>
Adds support for modifying the LS_CFG MSR to enable SSBD on supporting
AMD CPUs. There needs to be locking logic for family 17h with SMT
enabled since both threads share the same MSR. Otherwise, a core just
needs to write to the LS_CFG MSR. For more information see:
https://developer.amd.com/wp-content/resources/124441_AMD64_SpeculativeStoreBypassDisable_Whitepaper_final.pdf
Signed-off-by: Brian Woods <brian.woods@amd.com>
---
xen/arch/x86/cpu/amd.c | 7 +-
xen/arch/x86/smpboot.c | 3 +
xen/arch/x86/spec_ctrl.c | 174 +++++++++++++++++++++++++++++++++++++++-
xen/include/asm-x86/spec_ctrl.h | 2 +
4 files changed, 178 insertions(+), 8 deletions(-)
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 06c9e9661b..6a5fbcae22 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -611,14 +611,9 @@ static void init_amd(struct cpuinfo_x86 *c)
ssbd_amd_ls_cfg_mask = 1ull << bit;
}
- if (ssbd_amd_ls_cfg_mask && !rdmsr_safe(MSR_AMD64_LS_CFG, value)) {
+ if (ssbd_amd_ls_cfg_mask && !rdmsr_safe(MSR_AMD64_LS_CFG, value))
if (!boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG))
setup_force_cpu_cap(X86_FEATURE_SSBD_AMD_LS_CFG);
- if (opt_ssbd) {
- value |= ssbd_amd_ls_cfg_mask;
- wrmsr_safe(MSR_AMD64_LS_CFG, value);
- }
- }
/* MFENCE stops RDTSC speculation */
if (!cpu_has_lfence_dispatch)
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index d4478e6132..af881ba30a 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -366,6 +366,9 @@ void start_secondary(void *unused)
if ( boot_cpu_has(X86_FEATURE_IBRSB) )
wrmsrl(MSR_SPEC_CTRL, default_xen_spec_ctrl);
+ if ( default_xen_ssbd_amd_ls_cfg_en )
+ ssbd_amd_ls_cfg_set(true);
+
if ( xen_guest )
hypervisor_ap_setup();
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 62e6519d93..ff14b8f985 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -19,6 +19,7 @@
#include <xen/errno.h>
#include <xen/init.h>
#include <xen/lib.h>
+#include <xen/spinlock.h>
#include <asm/microcode.h>
#include <asm/msr.h>
@@ -50,7 +51,16 @@ bool __initdata bsp_delay_spec_ctrl;
uint8_t __read_mostly default_xen_spec_ctrl;
uint8_t __read_mostly default_spec_ctrl_flags;
+/* for SSBD support for AMD via LS_CFG */
+#define SSBD_AMD_MAX_SOCKET 2
+struct ssbd_amd_ls_cfg_smt_status {
+ spinlock_t lock;
+ uint32_t mask;
+} __attribute__ ((aligned (64)));
+bool __read_mostly ssbd_amd_smt_en = false;
+bool __read_mostly default_xen_ssbd_amd_ls_cfg_en = false;
uint64_t __read_mostly ssbd_amd_ls_cfg_mask = 0ull;
+struct ssbd_amd_ls_cfg_smt_status *ssbd_amd_smt_status[SSBD_AMD_MAX_SOCKET] = {NULL};
static int __init parse_bti(const char *s)
{
@@ -237,8 +247,8 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
(default_xen_spec_ctrl & SPEC_CTRL_IBRS) ? "IBRS+" : "IBRS-",
!boot_cpu_has(X86_FEATURE_SSBD) ? "" :
(default_xen_spec_ctrl & SPEC_CTRL_SSBD) ? " SSBD+" : " SSBD-",
- !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG)? "" :
- (opt_ssbd && ssbd_amd_ls_cfg_mask) ? " SSBD+" : " SSBD-",
+ !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) ? "" :
+ default_xen_ssbd_amd_ls_cfg_en ? " SSBD+" : " SSBD-",
opt_ibpb ? " IBPB" : "");
/*
@@ -487,6 +497,162 @@ static __init int parse_xpti(const char *s)
}
custom_param("xpti", parse_xpti);
+/*
+ * Enabling SSBD on AMD processers via the LS_CFG MSR
+ *
+ * For family 15h and 16h, there are no SMT enabled processors, so there
+ * is no need for locking, just setting an MSR bit. For 17h, it depends
+ * if SMT is enabled. If SMT, are two threads that share a single MSR
+ * so there needs to be a lock and a virtual bit for each thread,
+ * otherwise it's the same as family 15h/16h.
+ */
+
+static void ssbd_amd_ls_cfg_set_nonsmt(bool enable_ssbd)
+{
+ uint64_t ls_cfg, new_ls_cfg;
+
+ rdmsrl(MSR_AMD64_LS_CFG, ls_cfg);
+
+ if ( enable_ssbd )
+ new_ls_cfg = ls_cfg | ssbd_amd_ls_cfg_mask;
+ else
+ new_ls_cfg = ls_cfg & ~ssbd_amd_ls_cfg_mask;
+
+ if ( new_ls_cfg != ls_cfg )
+ wrmsrl(MSR_AMD64_LS_CFG, new_ls_cfg);
+}
+
+static void ssbd_amd_ls_cfg_set_smt(bool enable_ssbd)
+{
+ uint32_t socket, core, thread;
+ uint64_t enable_mask;
+ uint64_t ls_cfg;
+ struct ssbd_amd_ls_cfg_smt_status *status;
+ const struct cpuinfo_x86 *c = ¤t_cpu_data;
+
+ socket = c->phys_proc_id;
+ core = c->cpu_core_id;
+ thread = c->apicid & (c->x86_num_siblings - 1);
+ status = ssbd_amd_smt_status[socket] + core;
+ enable_mask = (1ull << thread);
+
+ spin_lock(&status->lock);
+
+ if ( enable_ssbd )
+ {
+ if ( !(status->mask & enable_mask) )
+ {
+ status->mask |= enable_mask;
+ rdmsrl(MSR_AMD64_LS_CFG, ls_cfg);
+ if ( !(ls_cfg & ssbd_amd_ls_cfg_mask) )
+ {
+ ls_cfg |= ssbd_amd_ls_cfg_mask;
+ wrmsrl(MSR_AMD64_LS_CFG, ls_cfg);
+ }
+ }
+ }
+ else
+ {
+ if ( status->mask & enable_mask )
+ {
+ status->mask &= ~enable_mask;
+ rdmsrl(MSR_AMD64_LS_CFG, ls_cfg);
+ if ( (ls_cfg & ssbd_amd_ls_cfg_mask) && (status->mask == 0) )
+ {
+ ls_cfg &= ~ssbd_amd_ls_cfg_mask;
+ wrmsrl(MSR_AMD64_LS_CFG, ls_cfg);
+ }
+ }
+ }
+
+ spin_unlock(&status->lock);
+}
+
+void ssbd_amd_ls_cfg_set(bool enable_ssbd)
+{
+ if ( !ssbd_amd_ls_cfg_mask ||
+ !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) ) {
+ dprintk(XENLOG_ERR, "SSBD AMD LS CFG: invalid mask or missing feature\n");
+ return;
+ }
+
+ if ( ssbd_amd_smt_en )
+ ssbd_amd_ls_cfg_set_smt(enable_ssbd);
+ else
+ ssbd_amd_ls_cfg_set_nonsmt(enable_ssbd);
+}
+
+static int __init ssbd_amd_ls_cfg_init(void)
+{
+ uint32_t cores_per_socket, threads_per_core;
+ const struct cpuinfo_x86 *c = &boot_cpu_data;
+ uint32_t core, socket;
+
+ if ( !ssbd_amd_ls_cfg_mask ||
+ !boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) )
+ goto ssbd_amd_ls_cfg_init_fail;
+
+ switch ( c->x86 )
+ {
+ case 0x15:
+ case 0x16:
+ break;
+
+ case 0x17:
+ cores_per_socket = c->x86_max_cores;
+ threads_per_core = c->x86_num_siblings;
+
+ if ( threads_per_core > 1 )
+ {
+ ssbd_amd_smt_en = true;
+ for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
+ {
+ ssbd_amd_smt_status[socket] =
+ (struct ssbd_amd_ls_cfg_smt_status *)
+ xmalloc_array(struct ssbd_amd_ls_cfg_smt_status,
+ cores_per_socket);
+ if ( ssbd_amd_smt_status[socket] == NULL )
+ {
+ dprintk(XENLOG_ERR,
+ "SSBD AMD LS CFG: error in status allocing\n");
+ goto ssbd_amd_ls_cfg_init_fail;
+ }
+ }
+
+ for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
+ {
+ for ( core = 0; core < cores_per_socket; core++ )
+ {
+ spin_lock_init(&ssbd_amd_smt_status[socket][core].lock);
+ ssbd_amd_smt_status[socket][core].mask = 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ goto ssbd_amd_ls_cfg_init_fail;
+ }
+
+ if ( default_xen_ssbd_amd_ls_cfg_en )
+ ssbd_amd_ls_cfg_set(true);
+
+ return 0;
+
+ ssbd_amd_ls_cfg_init_fail:
+ for ( socket = 0; socket < SSBD_AMD_MAX_SOCKET; socket++ )
+ if ( ssbd_amd_smt_status[socket] != NULL )
+ xfree(ssbd_amd_smt_status[socket]);
+
+ setup_clear_cpu_cap(X86_FEATURE_SSBD_AMD_LS_CFG);
+ default_xen_ssbd_amd_ls_cfg_en = false;
+
+ dprintk(XENLOG_ERR, "SSBD AMD LS CFG: disalbing SSBD due to errors\n");
+
+ return 1;
+}
+presmp_initcall(ssbd_amd_ls_cfg_init);
+
void __init init_speculation_mitigations(void)
{
enum ind_thunk thunk = THUNK_DEFAULT;
@@ -589,6 +755,10 @@ void __init init_speculation_mitigations(void)
if ( boot_cpu_has(X86_FEATURE_SSBD) && opt_ssbd )
default_xen_spec_ctrl |= SPEC_CTRL_SSBD;
+ /* if we have SSBD LS_CFG available, see whether we should use it. */
+ if ( boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG) && opt_ssbd )
+ default_xen_ssbd_amd_ls_cfg_en = true;
+
/*
* PV guests can poison the RSB to any virtual address from which
* they can execute a call instruction. This is necessarily outside
diff --git a/xen/include/asm-x86/spec_ctrl.h b/xen/include/asm-x86/spec_ctrl.h
index 6aebfa9e4f..e48c76ac4f 100644
--- a/xen/include/asm-x86/spec_ctrl.h
+++ b/xen/include/asm-x86/spec_ctrl.h
@@ -39,6 +39,8 @@ extern uint8_t opt_xpti;
#define OPT_XPTI_DOMU 0x02
extern uint64_t ssbd_amd_ls_cfg_mask;
+extern bool default_xen_ssbd_amd_ls_cfg_en;
+extern void ssbd_amd_ls_cfg_set(bool enable_ssbd);
static inline void init_shadow_spec_ctrl_state(void)
{
--
2.11.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
next prev parent reply other threads:[~2018-08-09 19:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-09 19:42 [PATCH v2 0/2] SSBD AMD via LS CFG Enablement Brian Woods
2018-08-09 19:42 ` [PATCH v2 1/2] x86/spec-ctrl: add AMD SSBD LS_CFG in init print Brian Woods
2018-08-15 15:38 ` Jan Beulich
2018-08-09 19:42 ` Brian Woods [this message]
2018-08-09 19:49 ` [PATCH v2 2/2] x86/spec-ctrl: add support for modifying SSBD VIA LS_CFG MSR Brian Woods
2018-08-15 16:00 ` Jan Beulich
2018-08-16 20:02 ` Brian Woods
2018-08-17 6:59 ` Jan Beulich
2018-08-17 18:45 ` Brian Woods
2018-08-20 7:32 ` Jan Beulich
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=20180809194213.56671-3-brian.woods@amd.com \
--to=brian.woods@amd.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).