From 9801d13d6bc4bf83ef5efdd9c68c26f164d15fff Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 26 Nov 2015 18:56:43 +0000 Subject: [PATCH] x86/pv: Provide custom cpumasks for PV domains And use them in preference to cpumask_defaults on context switch. HVM domains must not be masked (to avoid interfering with cpuid calls within the guest), so always lazily context switch to the host default. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich Reviewed-by: Konrad Rzeszutek Wilk --- xen/arch/x86/cpu/amd.c | 4 +++- xen/arch/x86/cpu/intel.c | 5 ++++- xen/arch/x86/domain.c | 14 ++++++++++++++ xen/include/asm-x86/domain.h | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c index 3e2f4a8f45..d5afc3ea0e 100644 --- a/xen/arch/x86/cpu/amd.c +++ b/xen/arch/x86/cpu/amd.c @@ -206,7 +206,9 @@ static void __init noinline probe_masking_msrs(void) static void amd_ctxt_switch_levelling(const struct domain *nextd) { struct cpuidmasks *these_masks = &this_cpu(cpuidmasks); - const struct cpuidmasks *masks = &cpuidmask_defaults; + const struct cpuidmasks *masks = + (nextd && is_pv_domain(nextd) && nextd->arch.pv_domain.cpuidmasks) + ? nextd->arch.pv_domain.cpuidmasks : &cpuidmask_defaults; #define LAZY(cap, msr, field) \ ({ \ diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c index e21c32d695..fe4736edc7 100644 --- a/xen/arch/x86/cpu/intel.c +++ b/xen/arch/x86/cpu/intel.c @@ -154,7 +154,7 @@ static void __init probe_masking_msrs(void) static void intel_ctxt_switch_levelling(const struct domain *nextd) { struct cpuidmasks *these_masks = &this_cpu(cpuidmasks); - const struct cpuidmasks *masks = &cpuidmask_defaults; + const struct cpuidmasks *masks; if (cpu_has_cpuid_faulting) { /* @@ -178,6 +178,9 @@ static void intel_ctxt_switch_levelling(const struct domain *nextd) return; } + masks = (nextd && is_pv_domain(nextd) && nextd->arch.pv_domain.cpuidmasks) + ? nextd->arch.pv_domain.cpuidmasks : &cpuidmask_defaults; + #define LAZY(msr, field) \ ({ \ if (unlikely(these_masks->field != masks->field) && \ diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index d7b6c2bf45..e93ff2056a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -577,6 +577,14 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags, goto fail; clear_page(d->arch.pv_domain.gdt_ldt_l1tab); + if ( levelling_caps & ~LCAP_faulting ) + { + d->arch.pv_domain.cpuidmasks = xmalloc(struct cpuidmasks); + if ( !d->arch.pv_domain.cpuidmasks ) + goto fail; + *d->arch.pv_domain.cpuidmasks = cpuidmask_defaults; + } + rc = create_perdomain_mapping(d, GDT_LDT_VIRT_START, GDT_LDT_MBYTES << (20 - PAGE_SHIFT), NULL, NULL); @@ -672,7 +680,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags, paging_final_teardown(d); free_perdomain_mappings(d); if ( is_pv_domain(d) ) + { + xfree(d->arch.pv_domain.cpuidmasks); free_xenheap_page(d->arch.pv_domain.gdt_ldt_l1tab); + } psr_domain_free(d); return rc; } @@ -692,7 +703,10 @@ void arch_domain_destroy(struct domain *d) free_perdomain_mappings(d); if ( is_pv_domain(d) ) + { free_xenheap_page(d->arch.pv_domain.gdt_ldt_l1tab); + xfree(d->arch.pv_domain.cpuidmasks); + } free_xenheap_page(d->shared_info); cleanup_domain_irq_mapping(d); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 5f2f27f354..d393ed24aa 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -252,6 +252,8 @@ struct pv_domain /* map_domain_page() mapping cache. */ struct mapcache_domain mapcache; + + struct cpuidmasks *cpuidmasks; }; struct monitor_write_data { -- 2.30.2