[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4 07/30] x86/spec-ctrl: introduce Address Space Isolation command line option



On Mon, Oct 19, 2026 at 08:42:38PM +0100, George Dunlap wrote:
> From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> 
> Introduce the `asi=` command line option, and the opt_vcpu_pt_hvm and
> opt_pvh_vcpu_pt_hwdom knobs plus the per-domain d->arch.asi.vcpu_pt
> setting they control.  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 adds a boot-time warning that the feature is not functional and
> is meant for development only.
> 
> The mechanisms this option controls apply to HVM domains: an HVM vCPU
> already runs on its own monitor table, so a per-vCPU per-domain area
> needs no work at context switch.  d->arch.asi.vcpu_pt is therefore only
> ever set for HVM domains, a PVH hardware domain included; PV domains,
> a PV hardware domain included, are unaffected.
> 
> Besides the plain boolean, `pv=`, `hvm=` and `dom0=` select the features
> for PV domains or HVM domains other than the hardware domain, or for the
> hardware domain, PV or PVH.  None of the features applies to PV domains,
> so `pv=` has no effect, and `dom0=` acts on a PVH hardware domain only.
> 
> The boot log gains "ASI features for ..." lines for Dom0 and HVM
> domains, so hardware-domain-only configurations remain visible.
> 
> 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, Claude 
> Code:claude-opus-5-5
> Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>

I don't have a strong opinion on the comments below, I think it would
be nice to adjust some as they likely lead to less churn in the
followup patches.

> ---
> Changes in v4:
> - Docs: "domains" throughout, not "guests" (Roger).
> - Group the per-domain settings as one-bit fields of d->arch.asi
>   (Roger).
> - Rename opt_vcpu_pt_hwdom to opt_pvh_vcpu_pt_hwdom: it acts on a PVH
>   hardware domain only (Jan).

I would leave opt_vcpu_pt_hwdom as-is.  The fact it only acts on a PVH
hardware domain is a transient implementation short-coming.  I don't
think it's worth introducing a separate opt_pv_vcpu_pt_hwdom when PV
dom0 support is added, or having to rename opt_pvh_vcpu_pt_hwdom ->
opt_vcpu_pt_hwdom.

> - parse_asi(): break in the success branch and fall through to
>   default:, rather than a default: label after an else (MISRA C:2012
>   Rule 16.2; Jan).
> - Message: enabling a knob adds a boot-time warning; it does not taint
>   (Roger).
> - Add the pv= and dom0= sub-options here, beside hvm= (Roger).
> 
> Changes in v3:
> - HVM only: drop the PV knob and its interaction with XPTI.  vCPU-PT
>   applies to HVM domains and to a PVH hardware domain; the Dom0 boot
>   log line says None for a PV one.
> 
> Changes in v2:
> - Added to the series
> 
> Changes since the previously posted version:
> - Include the hardware domain in the development warning and the boot
>    log summary.
> - Make the opt_vcpu_pt_* knobs plain booleans preinitialised to false,
>    dropping the late -1 resolution.
> - Documentation: mention possible protection against unmitigated
>    attacks, and state that hvm= does not affect the hardware domain.
> - Rewrite the commit message.
> ---
>  docs/misc/xen-command-line.pandoc    | 29 ++++++++++
>  xen/arch/x86/include/asm/domain.h    |  6 ++
>  xen/arch/x86/include/asm/spec_ctrl.h |  2 +
>  xen/arch/x86/spec_ctrl.c             | 82 ++++++++++++++++++++++++++++
>  4 files changed, 119 insertions(+)
> 
> diff --git a/docs/misc/xen-command-line.pandoc 
> b/docs/misc/xen-command-line.pandoc
> index a6f08463d1..839d06da26 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -202,6 +202,35 @@ 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,dom0}=<bool>,
> +>              vcpu-pt=<bool> | vcpu-pt=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.
> +
> +The mechanisms currently implemented apply to HVM domains, including a PVH
> +hardware domain.  PV domains, including a PV hardware domain, are unaffected.

I think we might want to drop this.  It's an incomplete in-development
feature: we don't need to mention explicitly what is and what is not
implemented in the command line documentation for the time being.

> +
> +* `pv=`, `hvm=` and `dom0=` enable the features for PV domains or HVM domains
> +  other than the hardware domain, or for the hardware domain, PV or PVH.  The
> +  plain boolean does all three: `asi=1,dom0=0` leaves the hardware domain
> +  out.  The forms naming no domain type (an un-suffixed `vcpu-pt=<bool>`)
> +  cover the hardware domain too.
> +
> +**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` gives each vCPU its own per-domain area: the per-domain slot of
> +  each vCPU's monitor table maps a region private to that vCPU.
> +
>  ### asid (x86)
>  > `= <boolean>`
>  
> diff --git a/xen/arch/x86/include/asm/domain.h 
> b/xen/arch/x86/include/asm/domain.h
> index 212daae1f5..12f79feb42 100644
> --- a/xen/arch/x86/include/asm/domain.h
> +++ b/xen/arch/x86/include/asm/domain.h
> @@ -474,6 +474,12 @@ struct arch_domain
>      /* Don't unconditionally inject #GP for unhandled MSRs. */
>      bool msr_relaxed;
>  
> +    /* Fine grained ASI related options. */
> +    struct {
> +        /* Give each vCPU its own per-domain area (HVM only). */

I would drop the HVM only part, it's a transient implementation
limitation, not a design one.

> +        bool vcpu_pt:1;
> +    } asi;
> +
>      /* 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..d84f985e82 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_pvh_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..66c878212a 100644
> --- a/xen/arch/x86/spec_ctrl.c
> +++ b/xen/arch/x86/spec_ctrl.c
> @@ -86,6 +86,10 @@ bool __ro_after_init opt_bp_spec_reduce = true;
>  
>  static bool __initdata opt_ibpb_alt;
>  
> +/* Give each vCPU of an HVM domain its own per-domain area (vCPU-PT). */
> +bool __ro_after_init opt_vcpu_pt_hvm;
> +bool __ro_after_init opt_pvh_vcpu_pt_hwdom;
> +
>  static int __init cf_check parse_spec_ctrl(const char *s)
>  {
>      const char *ss;
> @@ -487,6 +491,69 @@ 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_pvh_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_pvh_vcpu_pt_hwdom = opt_vcpu_pt_hvm = val;
> +            break;
> +
> +        default:
> +            if ( (val = parse_boolean("pv", s, ss)) >= 0 )
> +                /* PV domains are unaffected. */;

You might want to print a message saying that the option is ignored
for PV?  It will go into the console buffer at least.

> +            else if ( (val = parse_boolean("hvm", s, ss)) >= 0 )
> +                opt_vcpu_pt_hvm = val;
> +            else if ( (val = parse_boolean("dom0", s, ss)) >= 0 )
> +                opt_pvh_vcpu_pt_hwdom = val;
> +            else if ( (val = parse_boolean("vcpu-pt", s, ss)) != -1 )
> +            {
> +                switch ( val )
> +                {
> +                case 1:
> +                case 0:
> +                    opt_pvh_vcpu_pt_hwdom = opt_vcpu_pt_hvm = val;
> +                    break;
> +
> +                case -2:
> +                    s += strlen("vcpu-pt=");
> +                    if ( (val = parse_boolean("hvm", s, ss)) >= 0 )
> +                    {
> +                        opt_vcpu_pt_hvm = val;
> +                        break;
> +                    }
> +                    fallthrough;
> +                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 +747,13 @@ 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\n",
> +           opt_dom0_pvh && opt_pvh_vcpu_pt_hwdom ? " vCPU-PT" : " None");
> +#ifdef CONFIG_HVM
> +    printk("  ASI features for HVM VMs:%s\n",
> +           opt_vcpu_pt_hvm                       ? " vCPU-PT" : " None");
> +#endif

opt_vcpu_pt_hvm is defined unconditionally, so you might as well use:

if ( IS_ENABLED(CONFIG_HVM) )
    printk("  ASI features for HVM VMs:%s\n", ...

Which is a bit nicer than the ifdefs?

>  }
>  
>  static bool __init check_smt_enabled(void)
> @@ -1866,6 +1940,9 @@ 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.asi.vcpu_pt = !pv && (is_hardware_domain(d) ? 
> opt_pvh_vcpu_pt_hwdom
> +                                                        : opt_vcpu_pt_hvm);
>  }
>  
>  void __init init_speculation_mitigations(void)
> @@ -2158,6 +2235,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_pvh_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");

I wonder, could we add the warning in parse_asi() itself?  I know if
would then also trigger for asi=0, but would avoid having to remember
to expand the condition here every time a new option is added?

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.