From d55d52961d13d4fcd1441fcfca98f690e687b941 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Mon, 12 Feb 2024 17:50:43 +0000 Subject: [PATCH 43/67] x86/spec-ctrl: Rename VERW related options VERW is going to be used for a 3rd purpose, and the existing nomenclature didn't survive the Stale MMIO issues terribly well. Rename the command line option from `md-clear=` to `verw=`. This is more consistent with other options which tend to be named based on what they're doing, not which feature enumeration they use behind the scenes. Retain `md-clear=` as a deprecated alias. Rename opt_md_clear_{pv,hvm} and opt_fb_clear_mmio to opt_verw_{pv,hvm,mmio}, which has a side effect of making spec_ctrl_init_domain() rather clearer to follow. No functional change. This is part of XSA-452 / CVE-2023-28746. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich (cherry picked from commit f7603ca252e4226739eb3129a5290ee3da3f8ea4) --- docs/misc/xen-command-line.pandoc | 15 ++++---- xen/arch/x86/spec_ctrl.c | 62 ++++++++++++++++--------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 2006697226..d909ec94fe 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -2324,7 +2324,7 @@ By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`). ### spec-ctrl (x86) > `= List of [ , xen=, {pv,hvm}=, -> {msr-sc,rsb,md-clear,ibpb-entry}=|{pv,hvm}=, +> {msr-sc,rsb,verw,ibpb-entry}=|{pv,hvm}=, > bti-thunk=retpoline|lfence|jmp, {ibrs,ibpb,ssbd,psfd, > eager-fpu,l1d-flush,branch-harden,srb-lock, > unpriv-mmio,gds-mit,div-scrub}= ]` @@ -2349,7 +2349,7 @@ in place for guests to use. Use of a positive boolean value for either of these options is invalid. -The `pv=`, `hvm=`, `msr-sc=`, `rsb=`, `md-clear=` and `ibpb-entry=` options +The `pv=`, `hvm=`, `msr-sc=`, `rsb=`, `verw=` and `ibpb-entry=` options offer fine grained control over the primitives by Xen. These impact Xen's ability to protect itself, and/or Xen's ability to virtualise support for guests to use. @@ -2366,11 +2366,12 @@ guests to use. guests and if disabled, guests will be unable to use IBRS/STIBP/SSBD/etc. * `rsb=` offers control over whether to overwrite the Return Stack Buffer / Return Address Stack on entry to Xen and on idle. -* `md-clear=` offers control over whether to use VERW to flush - microarchitectural buffers on idle and exit from Xen. *Note: For - compatibility with development versions of this fix, `mds=` is also accepted - on Xen 4.12 and earlier as an alias. Consult vendor documentation in - preference to here.* +* `verw=` offers control over whether to use VERW for its scrubbing side + effects at appropriate privilege transitions. The exact side effects are + microarchitecture and microcode specific. *Note: `md-clear=` is accepted as + a deprecated alias. For compatibility with development versions of XSA-297, + `mds=` is also accepted on Xen 4.12 and earlier as an alias. Consult vendor + documentation in preference to here.* * `ibpb-entry=` offers control over whether IBPB (Indirect Branch Prediction Barrier) is used on entry to Xen. This is used by default on hardware vulnerable to Branch Type Confusion, and hardware vulnerable to Speculative diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c index 25a18ac598..e12ec9930c 100644 --- a/xen/arch/x86/spec_ctrl.c +++ b/xen/arch/x86/spec_ctrl.c @@ -37,8 +37,8 @@ static bool __initdata opt_msr_sc_pv = true; static bool __initdata opt_msr_sc_hvm = true; static int8_t __initdata opt_rsb_pv = -1; static bool __initdata opt_rsb_hvm = true; -static int8_t __ro_after_init opt_md_clear_pv = -1; -static int8_t __ro_after_init opt_md_clear_hvm = -1; +static int8_t __ro_after_init opt_verw_pv = -1; +static int8_t __ro_after_init opt_verw_hvm = -1; static int8_t __ro_after_init opt_ibpb_entry_pv = -1; static int8_t __ro_after_init opt_ibpb_entry_hvm = -1; @@ -78,7 +78,7 @@ static bool __initdata cpu_has_bug_mds; /* Any other M{LP,SB,FB}DS combination. static int8_t __initdata opt_srb_lock = -1; static bool __initdata opt_unpriv_mmio; -static bool __ro_after_init opt_fb_clear_mmio; +static bool __ro_after_init opt_verw_mmio; static int8_t __initdata opt_gds_mit = -1; static int8_t __initdata opt_div_scrub = -1; @@ -120,8 +120,8 @@ static int __init cf_check parse_spec_ctrl(const char *s) disable_common: opt_rsb_pv = false; opt_rsb_hvm = false; - opt_md_clear_pv = 0; - opt_md_clear_hvm = 0; + opt_verw_pv = 0; + opt_verw_hvm = 0; opt_ibpb_entry_pv = 0; opt_ibpb_entry_hvm = 0; opt_ibpb_entry_dom0 = false; @@ -152,14 +152,14 @@ static int __init cf_check parse_spec_ctrl(const char *s) { opt_msr_sc_pv = val; opt_rsb_pv = val; - opt_md_clear_pv = val; + opt_verw_pv = val; opt_ibpb_entry_pv = val; } else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) { opt_msr_sc_hvm = val; opt_rsb_hvm = val; - opt_md_clear_hvm = val; + opt_verw_hvm = val; opt_ibpb_entry_hvm = val; } else if ( (val = parse_boolean("msr-sc", s, ss)) != -1 ) @@ -204,21 +204,22 @@ static int __init cf_check parse_spec_ctrl(const char *s) break; } } - else if ( (val = parse_boolean("md-clear", s, ss)) != -1 ) + else if ( (val = parse_boolean("verw", s, ss)) != -1 || + (val = parse_boolean("md-clear", s, ss)) != -1 ) { switch ( val ) { case 0: case 1: - opt_md_clear_pv = opt_md_clear_hvm = val; + opt_verw_pv = opt_verw_hvm = val; break; case -2: - s += strlen("md-clear="); + s += (*s == 'v') ? strlen("verw=") : strlen("md-clear="); if ( (val = parse_boolean("pv", s, ss)) >= 0 ) - opt_md_clear_pv = val; + opt_verw_pv = val; else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) - opt_md_clear_hvm = val; + opt_verw_hvm = val; else default: rc = -EINVAL; @@ -540,8 +541,8 @@ static void __init print_details(enum ind_thunk thunk) opt_srb_lock ? " SRB_LOCK+" : " SRB_LOCK-", opt_ibpb_ctxt_switch ? " IBPB-ctxt" : "", opt_l1d_flush ? " L1D_FLUSH" : "", - opt_md_clear_pv || opt_md_clear_hvm || - opt_fb_clear_mmio ? " VERW" : "", + opt_verw_pv || opt_verw_hvm || + opt_verw_mmio ? " VERW" : "", opt_div_scrub ? " DIV" : "", opt_branch_harden ? " BRANCH_HARDEN" : ""); @@ -562,13 +563,13 @@ static void __init print_details(enum ind_thunk thunk) boot_cpu_has(X86_FEATURE_SC_RSB_HVM) || boot_cpu_has(X86_FEATURE_IBPB_ENTRY_HVM) || amd_virt_spec_ctrl || - opt_eager_fpu || opt_md_clear_hvm) ? "" : " None", + opt_eager_fpu || opt_verw_hvm) ? "" : " None", boot_cpu_has(X86_FEATURE_SC_MSR_HVM) ? " MSR_SPEC_CTRL" : "", (boot_cpu_has(X86_FEATURE_SC_MSR_HVM) || amd_virt_spec_ctrl) ? " MSR_VIRT_SPEC_CTRL" : "", boot_cpu_has(X86_FEATURE_SC_RSB_HVM) ? " RSB" : "", opt_eager_fpu ? " EAGER_FPU" : "", - opt_md_clear_hvm ? " MD_CLEAR" : "", + opt_verw_hvm ? " VERW" : "", boot_cpu_has(X86_FEATURE_IBPB_ENTRY_HVM) ? " IBPB-entry" : ""); #endif @@ -577,11 +578,11 @@ static void __init print_details(enum ind_thunk thunk) (boot_cpu_has(X86_FEATURE_SC_MSR_PV) || boot_cpu_has(X86_FEATURE_SC_RSB_PV) || boot_cpu_has(X86_FEATURE_IBPB_ENTRY_PV) || - opt_eager_fpu || opt_md_clear_pv) ? "" : " None", + opt_eager_fpu || opt_verw_pv) ? "" : " None", boot_cpu_has(X86_FEATURE_SC_MSR_PV) ? " MSR_SPEC_CTRL" : "", boot_cpu_has(X86_FEATURE_SC_RSB_PV) ? " RSB" : "", opt_eager_fpu ? " EAGER_FPU" : "", - opt_md_clear_pv ? " MD_CLEAR" : "", + opt_verw_pv ? " VERW" : "", boot_cpu_has(X86_FEATURE_IBPB_ENTRY_PV) ? " IBPB-entry" : ""); printk(" XPTI (64-bit PV only): Dom0 %s, DomU %s (with%s PCID)\n", @@ -1514,8 +1515,8 @@ void spec_ctrl_init_domain(struct domain *d) { bool pv = is_pv_domain(d); - bool verw = ((pv ? opt_md_clear_pv : opt_md_clear_hvm) || - (opt_fb_clear_mmio && is_iommu_enabled(d))); + bool verw = ((pv ? opt_verw_pv : opt_verw_hvm) || + (opt_verw_mmio && is_iommu_enabled(d))); bool ibpb = ((pv ? opt_ibpb_entry_pv : opt_ibpb_entry_hvm) && (d->domain_id != 0 || opt_ibpb_entry_dom0)); @@ -1878,19 +1879,20 @@ void __init init_speculation_mitigations(void) * the return-to-guest path. */ if ( opt_unpriv_mmio ) - opt_fb_clear_mmio = cpu_has_fb_clear; + opt_verw_mmio = cpu_has_fb_clear; /* * By default, enable PV and HVM mitigations on MDS-vulnerable hardware. * This will only be a token effort for MLPDS/MFBDS when HT is enabled, * but it is somewhat better than nothing. */ - if ( opt_md_clear_pv == -1 ) - opt_md_clear_pv = ((cpu_has_bug_mds || cpu_has_bug_msbds_only) && - boot_cpu_has(X86_FEATURE_MD_CLEAR)); - if ( opt_md_clear_hvm == -1 ) - opt_md_clear_hvm = ((cpu_has_bug_mds || cpu_has_bug_msbds_only) && - boot_cpu_has(X86_FEATURE_MD_CLEAR)); + if ( opt_verw_pv == -1 ) + opt_verw_pv = ((cpu_has_bug_mds || cpu_has_bug_msbds_only) && + cpu_has_md_clear); + + if ( opt_verw_hvm == -1 ) + opt_verw_hvm = ((cpu_has_bug_mds || cpu_has_bug_msbds_only) && + cpu_has_md_clear); /* * Enable MDS/MMIO defences as applicable. The Idle blocks need using if @@ -1903,12 +1905,12 @@ void __init init_speculation_mitigations(void) * MDS mitigations. L1D_FLUSH is not safe for MMIO mitigations.) * * After calculating the appropriate idle setting, simplify - * opt_md_clear_hvm to mean just "should we VERW on the way into HVM + * opt_verw_hvm to mean just "should we VERW on the way into HVM * guests", so spec_ctrl_init_domain() can calculate suitable settings. */ - if ( opt_md_clear_pv || opt_md_clear_hvm || opt_fb_clear_mmio ) + if ( opt_verw_pv || opt_verw_hvm || opt_verw_mmio ) setup_force_cpu_cap(X86_FEATURE_SC_VERW_IDLE); - opt_md_clear_hvm &= !cpu_has_skip_l1dfl && !opt_l1d_flush; + opt_verw_hvm &= !cpu_has_skip_l1dfl && !opt_l1d_flush; /* * Warn the user if they are on MLPDS/MFBDS-vulnerable hardware with HT -- 2.44.0