|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v5 3/7] xen/x86: support per-domain flag for xpti
On 06/04/18 15:16, Andrew Cooper wrote:
> On 06/04/18 08:52, Juergen Gross wrote:
>> Instead of switching XPTI globally on or off add a per-domain flag for
>> that purpose. This allows to modify the xpti boot parameter to support
>> running dom0 without Meltdown mitigations. Using "xpti=nodom0" as boot
>> parameter will achieve that.
>>
>> Move the xpti boot parameter handling to xen/arch/x86/pv/domain.c as
>> it is pv-domain specific.
>>
>> Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
>> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
>> ---
>> V3:
>> - latch get_cpu_info() return value in variable (Jan Beulich)
>> - call always xpti_domain_init() for pv dom0 (Jan Beulich)
>> - add __init annotations (Jan Beulich)
>> - drop per domain XPTI message (Jan Beulich)
>> - document xpti=default support (Jan Beulich)
>> - move domain xpti flag into a padding hole (Jan Beulich)
>> ---
>> docs/misc/xen-command-line.markdown | 10 ++++-
>> xen/arch/x86/domctl.c | 4 ++
>> xen/arch/x86/mm.c | 12 +++++-
>> xen/arch/x86/pv/dom0_build.c | 3 ++
>> xen/arch/x86/pv/domain.c | 77
>> +++++++++++++++++++++++++++++++++++++
>> xen/arch/x86/setup.c | 20 +---------
>> xen/arch/x86/smpboot.c | 4 +-
>> xen/arch/x86/x86_64/entry.S | 2 +
>> xen/include/asm-x86/current.h | 3 +-
>> xen/include/asm-x86/domain.h | 3 ++
>> xen/include/asm-x86/pv/domain.h | 4 ++
>> 11 files changed, 118 insertions(+), 24 deletions(-)
>>
>> diff --git a/docs/misc/xen-command-line.markdown
>> b/docs/misc/xen-command-line.markdown
>> index b353352adf..79be9a6ba5 100644
>> --- a/docs/misc/xen-command-line.markdown
>> +++ b/docs/misc/xen-command-line.markdown
>> @@ -1955,7 +1955,7 @@ clustered mode. The default, given no hint from the
>> **FADT**, is cluster
>> mode.
>>
>> ### xpti
>> -> `= <boolean>`
>> +> `= default | nodom0 | <boolean>`
>>
>> > Default: `false` on AMD hardware
>> > Default: `true` everywhere else
>> @@ -1963,6 +1963,14 @@ mode.
>> Override default selection of whether to isolate 64-bit PV guest page
>> tables.
>>
>> +`true` activates page table isolation even on AMD hardware.
>> +
>> +`false` deactivates page table isolation on all systems.
>> +
>> +`default` sets the default behaviour.
>> +
>> +`nodom0` deactivates page table isolation for dom0.
>
> Thinking more about this, a simple set of options like this is
> insufficiently expressive. What if I'd like to run domU's but not dom0
> with XPTI on AMD hardware?
Why would anyone want to do this?
My plan was to add a way to switch XPTI on per-domain basis in 4.12.
>
> How about `= List of [ <boolean>, dom0=bool ]`
>
> which allows for selecting dom0 independently of the general default.
> It also avoids the somewhat odd "nodom0" which doesn't match our
> prevailing style of "no-" prefixes for boolean options.
This reasoning makes more sense for me. :-)
>
> Also, the text should note that the dom0 option is ignored for non-PV
> dom0's.
It clearly states "64-bit PV guest". A non-pv dom0 clearly isn't subject
to this parameter.
>
>> +
>> ### xsave
>> > `= <boolean>`
>>
>> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
>> index 8fbbf3aeb3..0704f398c7 100644
>> --- a/xen/arch/x86/domctl.c
>> +++ b/xen/arch/x86/domctl.c
>> @@ -24,6 +24,7 @@
>> #include <asm/hvm/hvm.h>
>> #include <asm/hvm/support.h>
>> #include <asm/processor.h>
>> +#include <asm/pv/domain.h>
>> #include <asm/acpi.h> /* for hvm_acpi_power_button */
>> #include <xen/hypercall.h> /* for arch_do_domctl */
>> #include <xsm/xsm.h>
>> @@ -610,6 +611,9 @@ long arch_do_domctl(
>> ret = switch_compat(d);
>> else
>> ret = -EINVAL;
>> +
>> + if ( ret == 0 )
>> + xpti_domain_init(d);
>> break;
>>
>> case XEN_DOMCTL_get_address_size:
>> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
>> index cf2ccb07e6..131433af9b 100644
>> --- a/xen/arch/x86/mm.c
>> +++ b/xen/arch/x86/mm.c
>> @@ -505,13 +505,21 @@ void make_cr3(struct vcpu *v, mfn_t mfn)
>>
>> void write_ptbase(struct vcpu *v)
>> {
>> - if ( this_cpu(root_pgt) && is_pv_vcpu(v) && !is_pv_32bit_vcpu(v) )
>> + struct cpu_info *cpu_info = get_cpu_info();
>> +
>> + if ( is_pv_vcpu(v) && v->domain->arch.pv_domain.xpti )
>> {
>> - get_cpu_info()->root_pgt_changed = true;
>> + cpu_info->root_pgt_changed = true;
>> + cpu_info->pv_cr3 = __pa(this_cpu(root_pgt));
>> asm volatile ( "mov %0, %%cr3" : : "r" (v->arch.cr3) : "memory" );
>> }
>> else
>> + {
>> + /* Make sure to clear xen_cr3 before pv_cr3; write_cr3()
>> serializes. */
>> + cpu_info->xen_cr3 = 0;
>> write_cr3(v->arch.cr3);
>> + cpu_info->pv_cr3 = 0;
>> + }
>> }
>>
>> /*
>> diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
>> index 0bd2f1bf90..77186c19bd 100644
>> --- a/xen/arch/x86/pv/dom0_build.c
>> +++ b/xen/arch/x86/pv/dom0_build.c
>> @@ -19,6 +19,7 @@
>> #include <asm/dom0_build.h>
>> #include <asm/guest.h>
>> #include <asm/page.h>
>> +#include <asm/pv/domain.h>
>> #include <asm/pv/mm.h>
>> #include <asm/setup.h>
>>
>> @@ -707,6 +708,8 @@ int __init dom0_construct_pv(struct domain *d,
>> cpu = p->processor;
>> }
>>
>> + xpti_domain_init(d);
>> +
>> d->arch.paging.mode = 0;
>>
>> /* Set up CR3 value for write_ptbase */
>> diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
>> index 42522a2db3..2bef9c48bc 100644
>> --- a/xen/arch/x86/pv/domain.c
>> +++ b/xen/arch/x86/pv/domain.c
>> @@ -9,6 +9,8 @@
>> #include <xen/lib.h>
>> #include <xen/sched.h>
>>
>> +#include <asm/cpufeature.h>
>> +#include <asm/msr-index.h>
>> #include <asm/pv/domain.h>
>>
>> /* Override macros from asm/page.h to make them work with mfn_t */
>> @@ -17,6 +19,81 @@
>> #undef page_to_mfn
>> #define page_to_mfn(pg) _mfn(__page_to_mfn(pg))
>>
>> +static __read_mostly enum {
>> + XPTI_DEFAULT,
>> + XPTI_ON,
>> + XPTI_OFF,
>> + XPTI_NODOM0
>> +} opt_xpti = XPTI_DEFAULT;
>> +
>> +static __init int parse_xpti(const char *s)
>> +{
>> + int rc = 0;
>> +
>> + switch ( parse_bool(s, NULL) )
>> + {
>> + case 0:
>> + opt_xpti = XPTI_OFF;
>> + break;
>> + case 1:
>> + opt_xpti = XPTI_ON;
>> + break;
>> + default:
>> + if ( !strcmp(s, "default") )
>> + opt_xpti = XPTI_DEFAULT;
>> + else if ( !strcmp(s, "nodom0") )
>> + opt_xpti = XPTI_NODOM0;
>> + else
>> + rc = -EINVAL;
>> + break;
>> + }
>> +
>> + return rc;
>> +}
>> +custom_param("xpti", parse_xpti);
>> +
>> +void __init xpti_init(void)
>> +{
>> + uint64_t caps = 0;
>> +
>> + if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
>> + caps = ARCH_CAPABILITIES_RDCL_NO;
>> + else if ( boot_cpu_has(X86_FEATURE_ARCH_CAPS) )
>> + rdmsrl(MSR_ARCH_CAPABILITIES, caps);
>> +
>> + if ( opt_xpti != XPTI_ON && (caps & ARCH_CAPABILITIES_RDCL_NO) )
>> + opt_xpti = XPTI_OFF;
>> + else if ( opt_xpti == XPTI_DEFAULT )
>> + opt_xpti = XPTI_ON;
>> +
>> + if ( opt_xpti == XPTI_OFF )
>> + setup_force_cpu_cap(X86_FEATURE_NO_XPTI);
>> + else
>> + setup_clear_cpu_cap(X86_FEATURE_NO_XPTI);
>> +}
>
> Hmm - its probably arguable, but I'd say that init work for XPTI really
> does belong in spec_ctrl.c rather than pv/domain.c. This would also
> avoid having both a toplevel xpti_init() and
> init_speculation_migrations() call from __start_xen().
I don't mind either way.
>
>> +
>> +void xpti_domain_init(struct domain *d)
>> +{
>> + if ( !is_pv_domain(d) || is_pv_32bit_domain(d) )
>> + return;
>
> Nice, but nil pois. You've ended up with the same bug as my patch has,
> despite attempting to fix the 32bit case. This 32bit check causes an
> early exit and leaves xpti set.
Huh? The domain structure is zeroed on allocation. How would xpti
be true for 32-bit pv guests then?
>
> The least invasive way to fix is to have the switch statement fill in a
> local xpti boolean, then have
>
> d->arch.pv_domain.xpti = xpti && is_pv_32bit_domain(d);
Oh no. I want 32-bit pv domains to have xpti = false and 64-bit pv
domains may have xpti = true. Your suggestion is wrong in this regard.
>
> at the end.
>
>> +
>> + switch ( opt_xpti )
>> + {
>> + case XPTI_OFF:
>> + break;
>> + case XPTI_ON:
>> + d->arch.pv_domain.xpti = true;
>> + break;
>> + case XPTI_NODOM0:
>> + d->arch.pv_domain.xpti = d->domain_id != 0 &&
>> + d->domain_id != hardware_domid;
>> + break;
>
> Newlines after breaks please.
Okay.
>
> This wants to be is_hardware_domain(d), but that is liable to cause
> problems when constructing dom0. Instead, I'd suggest just the latter
> half of conditional, as hardware_domid is 0 until dom0 chooses to build
> a second hardware domain.
Okay.
Juergen
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |