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

[Xen-devel] [PATCH v1.5 20/20] xen/domain: Allocate d->vcpu[] in arch_domain_create()



On the ARM side, audit config->max_vcpus after the vgic has been initialised,
at which point we have a real upper bound to test against.  This allows for
the removal of the vgic_max_vcpus() juggling to cope with the call from
evtchn_init() before the vgic settings are known.

For each arch's dom0's, drop the temporary max_vcpus parameter, and allocation
of dom0->vcpu.

With arch_domain_create() now in charge of auditing config->max_vcpus, the
per-arch domain_max_vcpus() can be dropped.  Finally, evtchn_init() can be
updated to allocate a poll mask suitable for the domain, rather than suitable
for the worst case setting.

From this point on, d->max_vcpus and d->vcpus[] are valid for any domain which
can be looked up by ID.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
CC: Julien Grall <julien.grall@xxxxxxx>

v2:
 * Retain vgic_max_vcpus() on the ARM side, but remove the NULL special case.
---
 xen/arch/arm/domain.c        | 11 +++++++++++
 xen/arch/arm/domain_build.c  |  8 +-------
 xen/arch/arm/setup.c         |  2 +-
 xen/arch/arm/vgic.c          | 11 +----------
 xen/arch/x86/dom0_build.c    |  8 +-------
 xen/arch/x86/domain.c        | 11 +++++++++++
 xen/arch/x86/setup.c         |  2 +-
 xen/common/domctl.c          | 14 --------------
 xen/common/event_channel.c   |  4 ++--
 xen/include/asm-arm/domain.h |  6 ------
 xen/include/asm-x86/domain.h |  2 --
 xen/include/xen/domain.h     |  2 +-
 12 files changed, 30 insertions(+), 51 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 57a2b8b..7abe766 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -646,6 +646,17 @@ int arch_domain_create(struct domain *d,
     if ( (rc = domain_vtimer_init(d, &config->arch)) != 0 )
         goto fail;
 
+    rc = -EINVAL;
+    /* On ARM, the number of VCPUs is limited by the type of GIC emulated. */
+    if ( (config->max_vcpus < 1) || (config->max_vcpus > vgic_max_vcpus(d)) )
+        goto fail;
+
+    rc = -ENOMEM;
+    d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus);
+    if ( !d->vcpu )
+        goto fail;
+    d->max_vcpus = config->max_vcpus;
+
     update_domain_wallclock_time(d);
 
     /*
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 2e145d9..b13c47e 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -76,14 +76,8 @@ unsigned int __init dom0_max_vcpus(void)
     return opt_dom0_max_vcpus;
 }
 
-struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0,
-                                     unsigned int max_vcpus)
+struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
 {
-    dom0->vcpu = xzalloc_array(struct vcpu *, max_vcpus);
-    if ( !dom0->vcpu )
-        return NULL;
-    dom0->max_vcpus = max_vcpus;
-
     return alloc_vcpu(dom0, 0, 0);
 }
 
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index be24f20..0ada4d5 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -859,7 +859,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.max_vcpus = dom0_max_vcpus();
 
     dom0 = domain_create(0, &dom0_cfg);
-    if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0, dom0_cfg.max_vcpus) == NULL) )
+    if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
             panic("Error creating domain 0");
 
     dom0->is_privileged = 1;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 3fafdd0..4d2b00c 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -669,16 +669,7 @@ void vgic_free_virq(struct domain *d, unsigned int virq)
 
 unsigned int vgic_max_vcpus(const struct domain *d)
 {
-    /*
-     * Since evtchn_init would call domain_max_vcpus for poll_mask
-     * allocation when the vgic_ops haven't been initialised yet,
-     * we return MAX_VIRT_CPUS if d->arch.vgic.handler is null.
-     */
-    if ( !d->arch.vgic.handler )
-        return MAX_VIRT_CPUS;
-    else
-        return min_t(unsigned int, MAX_VIRT_CPUS,
-                     d->arch.vgic.handler->max_vcpus);
+    return min_t(unsigned int, MAX_VIRT_CPUS, d->arch.vgic.handler->max_vcpus);
 }
 
 /*
diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index e82bc48..4c25789 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -200,17 +200,11 @@ unsigned int __init dom0_max_vcpus(void)
     return max_vcpus;
 }
 
-struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0,
-                                     unsigned int max_vcpus)
+struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
 {
     dom0->node_affinity = dom0_nodes;
     dom0->auto_node_affinity = !dom0_nr_pxms;
 
-    dom0->vcpu = xzalloc_array(struct vcpu *, max_vcpus);
-    if ( !dom0->vcpu )
-        return NULL;
-    dom0->max_vcpus = max_vcpus;
-
     return dom0_setup_vcpu(dom0, 0,
                            cpumask_last(&dom0_cpus) /* so it wraps around to 
first pcpu */);
 }
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c4c34b4..90fe50a 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -504,6 +504,17 @@ int arch_domain_create(struct domain *d,
     HYPERVISOR_COMPAT_VIRT_START(d) =
         is_pv_domain(d) ? __HYPERVISOR_COMPAT_VIRT_START : ~0u;
 
+    if ( (config->max_vcpus < 1) ||
+         (config->max_vcpus >
+          (is_hvm_domain(d) ? HVM_MAX_VCPUS : MAX_VIRT_CPUS)) )
+        return -EINVAL;
+
+    rc = -ENOMEM;
+    d->vcpu = xzalloc_array(struct vcpu *, config->max_vcpus);
+    if ( !d->vcpu )
+        goto fail;
+    d->max_vcpus = config->max_vcpus;
+
     /* Need to determine if HAP is enabled before initialising paging */
     if ( is_hvm_domain(d) )
         d->arch.hvm_domain.hap_enabled =
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index b0e85b0..07e9893 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1649,7 +1649,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     /* Create initial domain 0. */
     dom0 = domain_create(get_initial_domain_id(), &dom0_cfg);
-    if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0, dom0_cfg.max_vcpus) == NULL) )
+    if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
         panic("Error creating domain 0");
 
     if ( !pv_shim )
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 2f9d993..1dc19ea 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -547,23 +547,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
         op->domain = d->domain_id;
         copyback = true;
 
-        ret = -EINVAL;
-        if ( vcpus > domain_max_vcpus(d) )
-            goto createdomain_fail_late;
-
         ret = -ENOMEM;
         online = cpupool_domain_cpumask(d);
 
-        BUG_ON(d->vcpu);
-        BUG_ON(d->max_vcpus);
-
-        d->vcpu = xzalloc_array(struct vcpu *, vcpus);
-        /* Install vcpu array /then/ update max_vcpus. */
-        smp_wmb();
-        if ( !d->vcpu )
-            goto createdomain_fail_late;
-        d->max_vcpus = vcpus;
-
         cpu = cpumask_any(online);
         for ( i = 0; i < vcpus; ++i )
         {
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 41cbbae..2e6f84b 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -1303,8 +1303,8 @@ int evtchn_init(struct domain *d, unsigned int max_port)
     evtchn_from_port(d, 0)->state = ECS_RESERVED;
 
 #if MAX_VIRT_CPUS > BITS_PER_LONG
-    d->poll_mask = xzalloc_array(unsigned long,
-                                 BITS_TO_LONGS(domain_max_vcpus(d)));
+    BUG_ON(d->max_vcpus == 0);
+    d->poll_mask = xzalloc_array(unsigned long, BITS_TO_LONGS(d->max_vcpus));
     if ( !d->poll_mask )
     {
         free_evtchn_bucket(d, d->evtchn);
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 7ba6528..2273b1b 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-x86/domain.h b/xen/include/asm-x86/domain.h
index 47aadc2..9a21e0f 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -624,8 +624,6 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *, 
unsigned long guest_cr4);
              X86_CR4_OSXSAVE | X86_CR4_SMEP |               \
              X86_CR4_FSGSBASE | X86_CR4_SMAP))
 
-#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));
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index dc022b4..3dcec06 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -17,7 +17,7 @@ struct vcpu *alloc_vcpu(
     struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
 
 unsigned int dom0_max_vcpus(void);
-struct vcpu *alloc_dom0_vcpu0(struct domain *dom0, unsigned int max_vcpus);
+struct vcpu *alloc_dom0_vcpu0(struct domain *dom0);
 
 int vcpu_reset(struct vcpu *);
 int vcpu_up(struct vcpu *v);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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