All of lore.kernel.org
 help / color / mirror / Atom feed
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 3/3] x86/spec-ctrl: Add support for modifying SSBD AMD VIA LS_CFG MSR
Date: Fri, 20 Jul 2018 09:57:36 -0500	[thread overview]
Message-ID: <20180720145736.126487-4-brian.woods@amd.com> (raw)
In-Reply-To: <20180720145736.126487-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   |  10 +--
 xen/arch/x86/setup.c     |   2 +
 xen/arch/x86/smpboot.c   |   3 +
 xen/arch/x86/spec_ctrl.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 207 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 06c9e9661b..e7ec0d99a7 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -607,16 +607,10 @@ static void init_amd(struct cpuinfo_x86 *c)
 		case 0x17: bit = 10; break;
 		}
 
-		if (bit >= 0)
-			ssbd_amd_ls_cfg_mask = 1ull << bit;
-	}
 
-	if (ssbd_amd_ls_cfg_mask && !rdmsr_safe(MSR_AMD64_LS_CFG, value)) {
-		if (!boot_cpu_has(X86_FEATURE_SSBD_AMD_LS_CFG))
+		if (bit >= 0 && !rdmsr_safe(MSR_AMD64_LS_CFG, value)) {
+			ssbd_amd_ls_cfg_mask = 1ull << bit;
 			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);
 		}
 	}
 
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 419b46c033..b551852cbd 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1579,6 +1579,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     arch_init_memory();
 
+    ssbd_amd_ls_cfg_init();
+
     alternative_instructions();
 
     local_irq_enable();
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index d4478e6132..07760c920d 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 ( 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 baef907322..006e8fb14b 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -248,7 +248,7 @@ static void __init print_details(enum ind_thunk thunk, uint64_t caps)
            !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-",
+           xen_ssbd_amd_ls_cfg_en                    ? " SSBD+" : " SSBD-",
            opt_ibpb                                  ? " IBPB"  : "");
 
     /*
@@ -497,6 +497,201 @@ static __init int parse_xpti(const char *s)
 }
 custom_param("xpti", parse_xpti);
 
+/*
+ * For family 15h and 16h, there are no SMT enabled processors, so there
+ * is no need for locking, just need to set an MSR bit.   For 17h, it
+ * depends if SMT is enabled.  If SMT, are two threads share a single
+ * MSR so there needs to be a lock and a virtual bit for each thread.
+ */
+
+/* used for non SMT mitigations (no shared MSRs) */
+static void ssbd_amd_ls_cfg_set_nonsmt(bool enable_ssbd)
+{
+    unsigned long ls_cfg;
+
+    if ( enable_ssbd )
+    {
+        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
+    {
+        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);
+        }
+    }
+}
+
+/* used for family 17h with SMT enabled (shared MSRs) */
+static void ssbd_amd_ls_cfg_set_smt(bool enable_ssbd)
+{
+    __u32 socket, core, thread;
+    uint64_t enable_mask;
+    unsigned long ls_cfg;
+    struct ssbd_amd_ls_cfg_smt_status *status;
+    struct cpuinfo_x86  *c =  &current_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\n");
+        return;
+    }
+
+    if ( ssbd_amd_smt_en )
+        ssbd_amd_ls_cfg_set_smt(enable_ssbd);
+    else
+        ssbd_amd_ls_cfg_set_nonsmt(enable_ssbd);
+}
+
+/*
+ * used to init the boot cpu, we don't need to lock anything because
+ * it's just the boot CPU
+ */
+static __init void ssbd_amd_ls_cfg_set_init(void)
+{
+    __u32 socket, core, thread;
+    unsigned long long ls_cfg;
+    struct ssbd_amd_ls_cfg_smt_status *status;
+    struct cpuinfo_x86  *c =  &boot_cpu_data;
+
+    if ( ssbd_amd_smt_en )
+    {
+        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;
+        status->mask |= (1ull << thread);
+    }
+
+    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);
+    }
+}
+
+__init void ssbd_amd_ls_cfg_init(void)
+{
+    int cores_per_socket, threads_per_core;
+    struct cpuinfo_x86  *c =  &boot_cpu_data;
+    int 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 ( (cores_per_socket < 1) || (threads_per_core < 1) )
+        {
+            dprintk(XENLOG_ERR,
+                    "SSBD AMD LS CFG: error in topology decoding\n");
+            goto ssbd_amd_ls_cfg_init_fail;
+        }
+
+        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 ( xen_ssbd_amd_ls_cfg_en )
+        ssbd_amd_ls_cfg_set_init();
+
+    return;
+
+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);
+    xen_ssbd_amd_ls_cfg_en = false;
+
+    return;
+}
+
 void __init init_speculation_mitigations(void)
 {
     enum ind_thunk thunk = THUNK_DEFAULT;
@@ -599,6 +794,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 )
+         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
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-07-20 14:57 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-20 14:57 [PATCH 0/3] SSBD AMD via LS CFG Enablement Brian Woods
2018-07-20 14:57 ` [PATCH 1/3] x86/spec-ctrl: add AMD SSBD LS_CFG in init print Brian Woods
2018-07-31 10:47   ` Jan Beulich
2018-08-01 21:38     ` Brian Woods
2018-08-02  6:55       ` Jan Beulich
2018-07-20 14:57 ` [PATCH 2/3] x86/spec-ctrl: Add defines and variables for AMD SSBD support Brian Woods
2018-07-31 10:44   ` Jan Beulich
2018-08-01 21:25     ` Brian Woods
2018-07-20 14:57 ` Brian Woods [this message]
2018-07-31 11:25   ` [PATCH 3/3] x86/spec-ctrl: Add support for modifying SSBD AMD VIA LS_CFG MSR Jan Beulich
2018-08-01 22:20     ` Brian Woods
2018-08-02  7:09       ` Jan Beulich
2018-08-06 19:07         ` Brian Woods
2018-08-07  7:51           ` Jan Beulich
2018-08-08 16:43             ` Brian Woods
2018-08-09  6:53               ` 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=20180720145736.126487-4-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 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.