[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 2/2] x86/spec-ctrl: add support for modifying SSBD VIA LS_CFG MSR
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@xxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |