No functional change, as the option is not used. Introduced new so newly added functionality is keyed on the option being enabled, even if the feature is non-functional.
When ASI is enabled for PV domains, printing the usage of XPTI might be omitted if it must be uniformly disabled given the usage of ASI. Signed-off-by: Roger Pau Monné <roger....@citrix.com> --- Changes since v1: - Improve comments and documentation about what ASI provides. - Do not print the XPTI information if ASI is used for pv domUs and dom0 is PVH, or if ASI is used for both domU and dom0. FWIW, I would print the state of XPTI uniformly, as otherwise I find the output might be confusing for user expecting to assert the state of XPTI. --- docs/misc/xen-command-line.pandoc | 19 +++++ xen/arch/x86/include/asm/domain.h | 3 + xen/arch/x86/include/asm/spec_ctrl.h | 2 + xen/arch/x86/spec_ctrl.c | 115 +++++++++++++++++++++++++-- 4 files changed, 133 insertions(+), 6 deletions(-) diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 08b0053f9ced..3c1ad7b5fe7d 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -202,6 +202,25 @@ to appropriate auditing by Xen. Argo is disabled by default. This option is disabled by default, to protect domains from a DoS by a buggy or malicious other domain spamming the ring. +### asi (x86) +> `= List of [ <bool>, {pv,hvm}=<bool>, + {vcpu-pt}=<bool>|{pv,hvm}=<bool> ]` + +Offers control over whether the hypervisor will engage in Address Space +Isolation, by not having potentially sensitive information permanently mapped +in the VMM page-tables. Using this option might avoid the need to apply +mitigations for certain speculative related attacks, at the cost of mapping +sensitive information on-demand. + +* `pv=` and `hvm=` sub-options allow enabling for specific guest types. + +**WARNING: manual de-selection of enabled options will invalidate any +protection offered by the feature. The fine grained options provided below are +meant to be used for debugging purposes only.** + +* `vcpu-pt` ensure each vCPU uses a unique top-level page-table and setup a + virtual address space region to map memory on a per-vCPU basis. + ### asid (x86) > `= <boolean>` diff --git a/xen/arch/x86/include/asm/domain.h b/xen/arch/x86/include/asm/domain.h index 5af414fa64ac..fb92a10bf3b7 100644 --- a/xen/arch/x86/include/asm/domain.h +++ b/xen/arch/x86/include/asm/domain.h @@ -456,6 +456,9 @@ struct arch_domain /* Don't unconditionally inject #GP for unhandled MSRs. */ bool msr_relaxed; + /* Use a per-vCPU root pt, and switch per-domain slot to per-vCPU. */ + bool vcpu_pt; + /* Emulated devices enabled bitmap. */ uint32_t emulation_flags; } __cacheline_aligned; diff --git a/xen/arch/x86/include/asm/spec_ctrl.h b/xen/arch/x86/include/asm/spec_ctrl.h index 077225418956..c58afbaab671 100644 --- a/xen/arch/x86/include/asm/spec_ctrl.h +++ b/xen/arch/x86/include/asm/spec_ctrl.h @@ -88,6 +88,8 @@ extern uint8_t default_scf; extern int8_t opt_xpti_hwdom, opt_xpti_domu; +extern int8_t opt_vcpu_pt_pv, opt_vcpu_pt_hwdom, opt_vcpu_pt_hvm; + extern bool cpu_has_bug_l1tf; extern int8_t opt_pv_l1tf_hwdom, opt_pv_l1tf_domu; extern bool opt_bp_spec_reduce; diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c index ced84750015c..9463a8624701 100644 --- a/xen/arch/x86/spec_ctrl.c +++ b/xen/arch/x86/spec_ctrl.c @@ -85,6 +85,11 @@ static int8_t __initdata opt_gds_mit = -1; static int8_t __initdata opt_div_scrub = -1; bool __ro_after_init opt_bp_spec_reduce = true; +/* Use a per-vCPU root page-table and switch the per-domain slot to per-vCPU. */ +int8_t __ro_after_init opt_vcpu_pt_hvm = -1; +int8_t __ro_after_init opt_vcpu_pt_hwdom = -1; +int8_t __ro_after_init opt_vcpu_pt_pv = -1; + static int __init cf_check parse_spec_ctrl(const char *s) { const char *ss; @@ -384,6 +389,13 @@ int8_t __ro_after_init opt_xpti_domu = -1; static __init void xpti_init_default(void) { + ASSERT(opt_vcpu_pt_pv >= 0 && opt_vcpu_pt_hwdom >= 0); + if ( (opt_xpti_hwdom == 1 || opt_xpti_domu == 1) && opt_vcpu_pt_pv == 1 ) + { + printk(XENLOG_ERR + "XPTI incompatible with per-vCPU page-tables, disabling ASI\n"); + opt_vcpu_pt_pv = 0; + } if ( (boot_cpu_data.x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) || cpu_has_rdcl_no ) { @@ -395,9 +407,9 @@ static __init void xpti_init_default(void) else { if ( opt_xpti_hwdom < 0 ) - opt_xpti_hwdom = 1; + opt_xpti_hwdom = !opt_vcpu_pt_hwdom; if ( opt_xpti_domu < 0 ) - opt_xpti_domu = 1; + opt_xpti_domu = !opt_vcpu_pt_pv; } } @@ -488,6 +500,66 @@ static int __init cf_check parse_pv_l1tf(const char *s) } custom_param("pv-l1tf", parse_pv_l1tf); +static int __init cf_check parse_asi(const char *s) +{ + const char *ss; + int val, rc = 0; + + /* Interpret 'asi' alone in its positive boolean form. */ + if ( *s == '\0' ) + opt_vcpu_pt_pv = opt_vcpu_pt_hwdom = opt_vcpu_pt_hvm = 1; + + do { + ss = strchr(s, ','); + if ( !ss ) + ss = strchr(s, '\0'); + + val = parse_bool(s, ss); + switch ( val ) + { + case 0: + case 1: + opt_vcpu_pt_pv = opt_vcpu_pt_hwdom = opt_vcpu_pt_hvm = val; + break; + + default: + if ( (val = parse_boolean("pv", s, ss)) >= 0 ) + opt_vcpu_pt_pv = val; + else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) + opt_vcpu_pt_hvm = val; + else if ( (val = parse_boolean("vcpu-pt", s, ss)) != -1 ) + { + switch ( val ) + { + case 1: + case 0: + opt_vcpu_pt_pv = opt_vcpu_pt_hvm = opt_vcpu_pt_hwdom = val; + break; + + case -2: + s += strlen("vcpu-pt="); + if ( (val = parse_boolean("pv", s, ss)) >= 0 ) + opt_vcpu_pt_pv = val; + else if ( (val = parse_boolean("hvm", s, ss)) >= 0 ) + opt_vcpu_pt_hvm = val; + else + default: + rc = -EINVAL; + break; + } + } + else if ( *s ) + rc = -EINVAL; + break; + } + + s = ss + 1; + } while ( *ss ); + + return rc; +} +custom_param("asi", parse_asi); + static void __init print_details(enum ind_thunk thunk) { unsigned int _7d0 = 0, _7d2 = 0, e8b = 0, e21a = 0, max = 0, tmp; @@ -668,15 +740,29 @@ static void __init print_details(enum ind_thunk thunk) boot_cpu_has(X86_FEATURE_IBPB_ENTRY_PV) ? " IBPB-entry" : "", opt_bhb_entry_pv ? " BHB-entry" : ""); - printk(" XPTI (64-bit PV only): Dom0 %s, DomU %s (with%s PCID)\n", - opt_xpti_hwdom ? "enabled" : "disabled", - opt_xpti_domu ? "enabled" : "disabled", - xpti_pcid_enabled() ? "" : "out"); + if ( !opt_vcpu_pt_pv || (!opt_dom0_pvh && !opt_vcpu_pt_hwdom) ) + printk(" XPTI (64-bit PV only): Dom0 %s, DomU %s (with%s PCID)\n", + opt_xpti_hwdom ? "enabled" : "disabled", + opt_xpti_domu ? "enabled" : "disabled", + xpti_pcid_enabled() ? "" : "out"); printk(" PV L1TF shadowing: Dom0 %s, DomU %s\n", opt_pv_l1tf_hwdom ? "enabled" : "disabled", opt_pv_l1tf_domu ? "enabled" : "disabled"); #endif + +#ifdef CONFIG_HVM + printk(" ASI features for HVM VMs:%s%s\n", + opt_vcpu_pt_hvm ? "" : " None", + opt_vcpu_pt_hvm ? " vCPU-PT" : ""); + +#endif +#ifdef CONFIG_PV + printk(" ASI features for PV VMs:%s%s\n", + opt_vcpu_pt_pv ? "" : " None", + opt_vcpu_pt_pv ? " vCPU-PT" : ""); + +#endif } static bool __init check_smt_enabled(void) @@ -1779,6 +1865,10 @@ void spec_ctrl_init_domain(struct domain *d) if ( pv ) d->arch.pv.xpti = is_hardware_domain(d) ? opt_xpti_hwdom : opt_xpti_domu; + + d->arch.vcpu_pt = is_hardware_domain(d) ? opt_vcpu_pt_hwdom + : pv ? opt_vcpu_pt_pv + : opt_vcpu_pt_hvm; } void __init init_speculation_mitigations(void) @@ -2075,6 +2165,19 @@ void __init init_speculation_mitigations(void) hw_smt_enabled && default_xen_spec_ctrl ) setup_force_cpu_cap(X86_FEATURE_SC_MSR_IDLE); + /* Disable all ASI options by default until feature is finished. */ + if ( opt_vcpu_pt_pv == -1 ) + opt_vcpu_pt_pv = 0; + if ( opt_vcpu_pt_hwdom == -1 ) + opt_vcpu_pt_hwdom = 0; + if ( opt_vcpu_pt_hvm == -1 ) + opt_vcpu_pt_hvm = 0; + + if ( opt_vcpu_pt_pv || opt_vcpu_pt_hvm ) + warning_add( + "Address Space Isolation is not functional, this option is\n" + "intended to be used only for development purposes.\n"); + xpti_init_default(); l1tf_calculations(); -- 2.46.0