x86/cpuid: Allocate a CPUID policy for every domain
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 11 Jan 2017 11:59:02 +0000 (11:59 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 11 Jan 2017 11:59:02 +0000 (11:59 +0000)
Introduce init_domain_cpuid_policy() to allocate an appropriate cpuid policy
for the domain (currently the domains maximum applicable policy), and call it
during domain construction.

init_guest_cpuid() now needs calling before dom0 is constructed.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/cpuid.c
xen/arch/x86/domain.c
xen/arch/x86/setup.c
xen/include/asm-x86/cpuid.h
xen/include/asm-x86/domain.h

index fa73fc137794c6847333cda1d5655de157d63e51..fcd9acc14d86be117a37c74542f7086cc617b632 100644 (file)
@@ -262,6 +262,18 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
     return NULL;
 }
 
+int init_domain_cpuid_policy(struct domain *d)
+{
+    d->arch.cpuid = xmalloc(struct cpuid_policy);
+
+    if ( !d->arch.cpuid )
+        return -ENOMEM;
+
+    *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
+
+    return 0;
+}
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res)
 {
index 939318718f30dbcb8c96bddd5d45ae5f6b5befe4..c1f95ccaffc49922fc2c86053bb76479650ee8ca 100644 (file)
@@ -532,6 +532,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( is_idle_domain(d) )
     {
         d->arch.emulation_flags = 0;
+        d->arch.cpuid = ZERO_BLOCK_PTR; /* Catch stray misuses. */
     }
     else
     {
@@ -601,6 +602,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
             goto fail;
         paging_initialised = 1;
 
+        if ( (rc = init_domain_cpuid_policy(d)) )
+            goto fail;
+
         d->arch.cpuids = xmalloc_array(cpuid_input_t, MAX_CPUID_INPUT);
         rc = -ENOMEM;
         if ( d->arch.cpuids == NULL )
@@ -674,6 +678,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     cleanup_domain_irq_mapping(d);
     free_xenheap_page(d->shared_info);
     xfree(d->arch.cpuids);
+    xfree(d->arch.cpuid);
     if ( paging_initialised )
         paging_final_teardown(d);
     free_perdomain_mappings(d);
@@ -692,6 +697,7 @@ void arch_domain_destroy(struct domain *d)
 
     xfree(d->arch.e820);
     xfree(d->arch.cpuids);
+    xfree(d->arch.cpuid);
 
     free_domain_pirqs(d);
     if ( !is_idle_domain(d) )
index 94db5142ecdcb324a2da17b497e4f574a2715c16..0ccef1dcd72c5a942106f718d2efe34f182191a3 100644 (file)
@@ -1540,6 +1540,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( !tboot_protect_mem_regions() )
         panic("Could not protect TXT memory regions");
 
+    init_guest_cpuid();
+
     if ( opt_dom0pvh )
         domcr_flags |= DOMCRF_pvh | DOMCRF_hap;
 
@@ -1590,8 +1592,6 @@ void __init noreturn __start_xen(unsigned long mbi_p)
                "Multiple initrd candidates, picking module #%u\n",
                initrdidx);
 
-    init_guest_cpuid();
-
     /*
      * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0().
      * This saves a large number of corner cases interactions with
index 0d0ac5297e2cdc82417bbc957f831768082819b5..77a467a6e877bc69df06a24bb14c03b3be20665d 100644 (file)
@@ -84,6 +84,16 @@ struct cpuid_policy
      * - Guest accurate:
      *   - All FEATURESET_* words
      *
+     * Per-domain objects:
+     *
+     * - Host accurate:
+     *   - max_{,sub}leaf
+     *   - {xcr0,xss}_{high,low}
+     *   - All FEATURESET_* words
+     *
+     * - Guest accurate:
+     *   - Nothing
+     *
      * Everything else should be considered inaccurate, and not necesserily 0.
      */
 
@@ -189,6 +199,9 @@ extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
 #define pv_featureset pv_max_policy.fs
 #define hvm_featureset hvm_max_policy.fs
 
+/* Allocate and initialise a CPUID policy suitable for the domain. */
+int init_domain_cpuid_policy(struct domain *d);
+
 void guest_cpuid(const struct vcpu *v, uint32_t leaf,
                  uint32_t subleaf, struct cpuid_leaf *res);
 
index 95762cf6a78c358e4ca0901a9f242bd9b3163e3d..780f31164b20821cf7cb010f2fd02dcf017a961d 100644 (file)
@@ -362,6 +362,9 @@ struct arch_domain
 
     cpuid_input_t *cpuids;
 
+    /* CPUID Policy. */
+    struct cpuid_policy *cpuid;
+
     struct PITState vpit;
 
     /* TSC management (emulation, pv, scaling, stats) */