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

[Xen-changelog] [xen staging] xen/domain: Allocate d->vcpu[] earlier during domain_create()



commit 344214c968ae8130564a34b31b6b0a63820f444f
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Tue Oct 2 14:02:55 2018 +0000
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Thu Nov 15 11:11:30 2018 +0000

    xen/domain: Allocate d->vcpu[] earlier during domain_create()
    
    The ARM code has a chicken-and-egg problem.  One of the vGICv3 emulations
    wants to know d->max_vcpus to be able to size itself appropriately, but the
    current order of initialisation requires the vGIC to be set up before the
    requested number of vcpus can be checked.
    
    Move the range checking of config->max_vcpus into sanitise_domain_config()
    path, which allows for the allocation of d->vcpu[] and d->max_vcpus to 
happen
    earlier during create, and in particular, before the call to
    arch_domain_create().
    
    The x86 side is fairly easy, and implements the logical equivalent of
    domain_max_vcpus() but using XEN_DOMCTL_CDF_hvm_guest rather than
    is_hvm_domain().
    
    For the ARM side, re-purpose vgic_max_vcpus() to take a domctl vGIC version,
    and return the maximum number of supported vCPUs, reusing 0 for "version not
    supported".  To avoid exporting the vgic_ops structures (which are in the
    process of being replaced), hard code the upper limits.
    
    This allows for the removal of the domain_max_vcpus() infrastructure, which 
is
    done to prevent it being reused incorrectly in the future.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Julien Grall <julien.grall@xxxxxxx>
---
 xen/arch/arm/domain.c         | 18 ++++++++++++++++++
 xen/arch/arm/vgic-v2.c        |  1 -
 xen/arch/arm/vgic-v3.c        |  5 -----
 xen/arch/arm/vgic.c           | 16 ++++++++++++++--
 xen/arch/arm/vgic/vgic-init.c |  3 ---
 xen/arch/arm/vgic/vgic.c      | 16 ++++++----------
 xen/arch/x86/domain.c         | 10 ++++++++++
 xen/common/domain.c           | 33 ++++++++++++++++++++-------------
 xen/include/asm-arm/config.h  |  4 ++--
 xen/include/asm-arm/domain.h  |  6 ------
 xen/include/asm-arm/vgic.h    |  5 ++---
 xen/include/asm-x86/domain.h  |  2 --
 12 files changed, 72 insertions(+), 47 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 71ad1f9653..1d926dcb29 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -601,6 +601,8 @@ void vcpu_switch_to_aarch64_mode(struct vcpu *v)
 
 int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
 {
+    unsigned int max_vcpus;
+
     if ( config->flags != (XEN_DOMCTL_CDF_hvm_guest | XEN_DOMCTL_CDF_hap) )
     {
         dprintk(XENLOG_INFO, "Unsupported configuration %#x\n", config->flags);
@@ -626,6 +628,22 @@ int arch_sanitise_domain_config(struct 
xen_domctl_createdomain *config)
         }
     }
 
+    /* max_vcpus depends on the GIC version, and Xen's compiled limit. */
+    max_vcpus = min(vgic_max_vcpus(config->arch.gic_version), MAX_VIRT_CPUS);
+
+    if ( max_vcpus == 0 )
+    {
+        dprintk(XENLOG_INFO, "Unsupported GIC version\n");
+        return -EINVAL;
+    }
+
+    if ( config->max_vcpus > max_vcpus )
+    {
+        dprintk(XENLOG_INFO, "Requested vCPUs (%u) exceeds max (%u)\n",
+                config->max_vcpus, max_vcpus);
+        return -EINVAL;
+    }
+
     return 0;
 }
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index bf77899dba..64b141fea5 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -725,7 +725,6 @@ static const struct vgic_ops vgic_v2_ops = {
     .domain_free = vgic_v2_domain_free,
     .lpi_to_pending = vgic_v2_lpi_to_pending,
     .lpi_get_priority = vgic_v2_lpi_get_priority,
-    .max_vcpus = 8,
 };
 
 int vgic_v2_init(struct domain *d, int *mmio_count)
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index c14bcd87b1..519cc728ab 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1822,11 +1822,6 @@ static const struct vgic_ops v3_ops = {
     .emulate_reg  = vgic_v3_emulate_reg,
     .lpi_to_pending = vgic_v3_lpi_to_pending,
     .lpi_get_priority = vgic_v3_lpi_get_priority,
-    /*
-     * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
-     * that can be supported is up to 4096(==256*16) in theory.
-     */
-    .max_vcpus = 4096,
 };
 
 int vgic_v3_init(struct domain *d, int *mmio_count)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5a4f082c16..f2608b042d 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -667,9 +667,21 @@ void vgic_free_virq(struct domain *d, unsigned int virq)
     clear_bit(virq, d->arch.vgic.allocated_irqs);
 }
 
-unsigned int vgic_max_vcpus(const struct domain *d)
+unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version)
 {
-    return min_t(unsigned int, MAX_VIRT_CPUS, d->arch.vgic.handler->max_vcpus);
+    switch ( domctl_vgic_version )
+    {
+    case XEN_DOMCTL_CONFIG_GIC_V2:
+        return 8;
+
+#ifdef CONFIG_GICV3
+    case XEN_DOMCTL_CONFIG_GIC_V3:
+        return 4096;
+#endif
+
+    default:
+        return 0;
+    }
 }
 
 /*
diff --git a/xen/arch/arm/vgic/vgic-init.c b/xen/arch/arm/vgic/vgic-init.c
index bfd3d09edb..62ae553699 100644
--- a/xen/arch/arm/vgic/vgic-init.c
+++ b/xen/arch/arm/vgic/vgic-init.c
@@ -112,9 +112,6 @@ int domain_vgic_register(struct domain *d, int *mmio_count)
         BUG();
     }
 
-    if ( d->max_vcpus > domain_max_vcpus(d) )
-        return -E2BIG;
-
     d->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
     d->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
     d->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
diff --git a/xen/arch/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
index 7c3cfc5182..e2844dcc20 100644
--- a/xen/arch/arm/vgic/vgic.c
+++ b/xen/arch/arm/vgic/vgic.c
@@ -949,20 +949,16 @@ void vgic_sync_hardware_irq(struct domain *d,
     spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-unsigned int vgic_max_vcpus(const struct domain *d)
+unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version)
 {
-    unsigned int vgic_vcpu_limit;
-
-    switch ( d->arch.vgic.version )
+    switch ( domctl_vgic_version )
     {
-    case GIC_V2:
-        vgic_vcpu_limit = VGIC_V2_MAX_CPUS;
-        break;
+    case XEN_DOMCTL_CONFIG_GIC_V2:
+        return VGIC_V2_MAX_CPUS;
+
     default:
-        BUG();
+        return 0;
     }
-
-    return min_t(unsigned int, MAX_VIRT_CPUS, vgic_vcpu_limit);
 }
 
 #ifdef CONFIG_GICV3
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 272fd84a3c..295b10c48c 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -421,6 +421,7 @@ void arch_vcpu_destroy(struct vcpu *v)
 int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
 {
     bool hvm = config->flags & XEN_DOMCTL_CDF_hvm_guest;
+    unsigned int max_vcpus;
 
     if ( hvm ? !hvm_enabled : !IS_ENABLED(CONFIG_PV) )
     {
@@ -428,6 +429,15 @@ int arch_sanitise_domain_config(struct 
xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    max_vcpus = hvm ? HVM_MAX_VCPUS : MAX_VIRT_CPUS;
+
+    if ( config->max_vcpus > max_vcpus )
+    {
+        dprintk(XENLOG_INFO, "Requested vCPUs (%u) exceeds max (%u)\n",
+                config->max_vcpus, max_vcpus);
+        return -EINVAL;
+    }
+
     return 0;
 }
 
diff --git a/xen/common/domain.c b/xen/common/domain.c
index f69f4055cd..78cc5249e8 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -300,6 +300,12 @@ static int sanitise_domain_config(struct 
xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    if ( config->max_vcpus < 1 )
+    {
+        dprintk(XENLOG_INFO, "No vCPUS\n");
+        return -EINVAL;
+    }
+
     return arch_sanitise_domain_config(config);
 }
 
@@ -345,6 +351,20 @@ struct domain *domain_create(domid_t domid,
 
     TRACE_1D(TRC_DOM0_DOM_ADD, d->domain_id);
 
+    /*
+     * Allocate d->vcpu[] and set ->max_vcpus up early.  Various per-domain
+     * resources want to be sized based on max_vcpus.
+     */
+    if ( !is_system_domain(d) )
+    {
+        err = -ENOMEM;
+        d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus);
+        if ( !d->vcpu )
+            goto fail;
+
+        d->max_vcpus = config->max_vcpus;
+    }
+
     lock_profile_register_struct(LOCKPROF_TYPE_PERDOM, d, domid, "Domain");
 
     if ( (err = xsm_alloc_security_domain(d)) != 0 )
@@ -396,19 +416,6 @@ struct domain *domain_create(domid_t domid,
 
     if ( !is_idle_domain(d) )
     {
-        /* Check d->max_vcpus and allocate d->vcpu[]. */
-        err = -EINVAL;
-        if ( config->max_vcpus < 1 ||
-             config->max_vcpus > domain_max_vcpus(d) )
-            goto fail;
-
-        err = -ENOMEM;
-        d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus);
-        if ( !d->vcpu )
-            goto fail;
-
-        d->max_vcpus = config->max_vcpus;
-
         watchdog_domain_init(d);
         init_status |= INIT_watchdog;
 
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index cdae8f64ff..bc89e84f4d 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -41,9 +41,9 @@
 #define OPT_CONSOLE_STR "dtuart"
 
 #ifdef CONFIG_ARM_64
-#define MAX_VIRT_CPUS 128
+#define MAX_VIRT_CPUS 128u
 #else
-#define MAX_VIRT_CPUS 8
+#define MAX_VIRT_CPUS 8u
 #endif
 
 #define INVALID_VCPU_ID MAX_VIRT_CPUS
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index d682307b27..175de44927 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -208,12 +208,6 @@ void vcpu_show_execution_state(struct vcpu *);
 void vcpu_show_registers(const struct vcpu *);
 void vcpu_switch_to_aarch64_mode(struct vcpu *);
 
-/* On ARM, the number of VCPUs is limited by the type of GIC emulated. */
-static inline unsigned int domain_max_vcpus(const struct domain *d)
-{
-    return vgic_max_vcpus(d);
-}
-
 /*
  * Due to the restriction of GICv3, the number of vCPUs in AFF0 is
  * limited to 16, thus only the first 4 bits of AFF0 are legal. We will
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 56ed5fe8fe..447d24ea59 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -234,8 +234,6 @@ struct vgic_ops {
     /* lookup the struct pending_irq for a given LPI interrupt */
     struct pending_irq *(*lpi_to_pending)(struct domain *d, unsigned int vlpi);
     int (*lpi_get_priority)(struct domain *d, uint32_t vlpi);
-    /* Maximum number of vCPU supported */
-    const unsigned int max_vcpus;
 };
 
 /* Number of ranks of interrupt registers for a domain */
@@ -350,7 +348,8 @@ extern void vgic_clear_pending_irqs(struct vcpu *v);
 
 extern bool vgic_emulate(struct cpu_user_regs *regs, union hsr hsr);
 
-unsigned int vgic_max_vcpus(const struct domain *d);
+/* Maximum vCPUs for a specific vGIC version, or 0 for unsupported. */
+unsigned int vgic_max_vcpus(unsigned int domctl_vgic_version);
 
 void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, paddr_t csize,
                       paddr_t vbase, uint32_t aliased_offset);
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 643e69acf9..277f99f633 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -664,8 +664,6 @@ unsigned long pv_guest_cr4_to_real_cr4(const struct vcpu 
*v);
              X86_CR4_OSXSAVE | X86_CR4_SMEP |               \
              X86_CR4_FSGSBASE | X86_CR4_SMAP | X86_CR4_PCIDE))
 
-#define domain_max_vcpus(d) (is_hvm_domain(d) ? HVM_MAX_VCPUS : MAX_VIRT_CPUS)
-
 static inline struct vcpu_guest_context *alloc_vcpu_guest_context(void)
 {
     return vmalloc(sizeof(struct vcpu_guest_context));
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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