|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 12/14] x86/spec-ctrl: introduce Address Space Isolation command line option
From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Introduce the `asi=` command line option, and the opt_vcpu_pt_{pv,hwdom,hvm}
knobs plus the per-domain d->arch.vcpu_pt setting it controls. The option is
introduced ahead of the functionality it enables, so that the newly added
code can be keyed on it from the start; all knobs currently default to off,
and enabling any of them taints the boot with a "not functional, development
purposes only" warning.
XPTI and per-vCPU page-tables are mutually exclusive (they are different
answers to the same problem, and the entry paths can only be built for one of
them at a time), so an explicit XPTI request takes precedence over vCPU-PT,
per axis: xpti=dom0 clears the hardware domain vCPU-PT knob (when dom0 is
PV), and xpti=domu clears the PV domU one. When XPTI is left to default, it
is turned off for those domain kinds that use vCPU-PT instead.
The boot log gains "ASI features for ..." lines for Dom0, HVM and PV
domains, so hardware-domain-only configurations remain visible, and the XPTI
line is printed unconditionally: users expecting to assert the state of XPTI
should not need to derive it from the ASI configuration.
Further per-mechanism tokens arrive with their mechanisms in later
patches.
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Assisted-by: Claude Code:claude-fable-5, Claude Code:claude-opus-4-8
Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>
---
Changes in v2:
- Added to the series
Changes since the previously posted version:
- Make the XPTI exclusion per-axis: an explicit xpti=dom0 previously
cleared only the PV domU vCPU-PT knob, leaving dom0 with both XPTI
and vCPU-PT enabled.
- Include the hardware domain in the development warning and the boot
log summary.
- Print the XPTI status line unconditionally.
- Make the opt_vcpu_pt_* knobs plain booleans preinitialised to false,
dropping the late -1 resolution.
- Documentation: mention possible protection against unmitigated
attacks, use {pv,hvm} notation in the synopsis, and state that
pv=/hvm= do not affect the hardware domain.
- Rewrite the commit message.
---
docs/misc/xen-command-line.pandoc | 24 ++++++
xen/arch/x86/include/asm/domain.h | 3 +
xen/arch/x86/include/asm/spec_ctrl.h | 2 +
xen/arch/x86/spec_ctrl.c | 107 ++++++++++++++++++++++++++-
4 files changed, 134 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc
b/docs/misc/xen-command-line.pandoc
index 1c711fa980..834f6c57f2 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -202,6 +202,30 @@ 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=<bool>, hvm=<bool>,
+> vcpu-pt=<bool> | vcpu-pt={pv,hvm}=<bool> ]`
+
+> Default: `false`
+
+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. It might also offer some protection against
+unmitigated speculation-related attacks.
+
+* `pv=` and `hvm=` sub-options allow enabling for specific guest types; they
+ do not affect the hardware domain, which follows the whole-feature forms
+ (the plain boolean, or an un-suffixed `vcpu-pt=<bool>`).
+
+**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` ensures each vCPU uses a unique top-level page-table and sets up
+ 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 38df5c376e..fdf7b205ea 100644
--- a/xen/arch/x86/include/asm/domain.h
+++ b/xen/arch/x86/include/asm/domain.h
@@ -472,6 +472,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 8f82533c41..770c24f6a0 100644
--- a/xen/arch/x86/include/asm/spec_ctrl.h
+++ b/xen/arch/x86/include/asm/spec_ctrl.h
@@ -87,6 +87,8 @@ extern uint8_t default_scf;
extern int8_t opt_xpti_hwdom, opt_xpti_domu;
+extern bool 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 bc8538a56f..55a02212a9 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -86,6 +86,14 @@ bool __ro_after_init opt_bp_spec_reduce = true;
static bool __initdata opt_ibpb_alt;
+/*
+ * Use a per-vCPU root page-table and switch the per-domain slot to per-vCPU.
+ * Off by default until the feature is complete.
+ */
+bool __ro_after_init opt_vcpu_pt_hvm;
+bool __ro_after_init opt_vcpu_pt_hwdom;
+bool __ro_after_init opt_vcpu_pt_pv;
+
static int __init cf_check parse_spec_ctrl(const char *s)
{
const char *ss;
@@ -383,6 +391,18 @@ int8_t __ro_after_init opt_xpti_domu = -1;
static __init void xpti_init_default(void)
{
+ if ( !opt_dom0_pvh && opt_xpti_hwdom == 1 && opt_vcpu_pt_hwdom )
+ {
+ printk(XENLOG_ERR
+ "XPTI incompatible with per-vCPU page-tables, disabling Dom0
vCPU-PT\n");
+ opt_vcpu_pt_hwdom = false;
+ }
+ if ( opt_xpti_domu == 1 && opt_vcpu_pt_pv )
+ {
+ printk(XENLOG_ERR
+ "XPTI incompatible with per-vCPU page-tables, disabling PV DomU
vCPU-PT\n");
+ opt_vcpu_pt_pv = false;
+ }
if ( (boot_cpu_data.vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) ||
cpu_has_rdcl_no )
{
@@ -394,9 +414,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;
}
}
@@ -487,6 +507,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 = true;
+
+ 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, e21c = 0, max = 0, tmp;
@@ -680,6 +760,20 @@ static void __init print_details(enum ind_thunk thunk)
opt_pv_l1tf_hwdom ? "enabled" : "disabled",
opt_pv_l1tf_domu ? "enabled" : "disabled");
#endif
+
+ printk(" ASI features for Dom0:%s%s\n",
+ opt_vcpu_pt_hwdom ? "" : "
None",
+ opt_vcpu_pt_hwdom ? " vCPU-PT" : "");
+#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)
@@ -1866,6 +1960,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)
@@ -2158,6 +2256,11 @@ void __init init_speculation_mitigations(void)
hw_smt_enabled && default_xen_spec_ctrl )
setup_force_cpu_cap(X86_FEATURE_SC_MSR_IDLE);
+ if ( opt_vcpu_pt_pv || opt_vcpu_pt_hwdom || 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.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |