xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Wei Liu <wei.liu2@citrix.com>, Jan Beulich <JBeulich@suse.com>
Subject: [PATCH v2 12/12] xen/domain: Allocate d->vcpu[] in domain_create()
Date: Mon, 13 Aug 2018 11:01:09 +0100	[thread overview]
Message-ID: <1534154469-6076-13-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1534154469-6076-1-git-send-email-andrew.cooper3@citrix.com>

For ARM, the call to arch_domain_create() needs to have completed before
domain_max_vcpus() will return the correct upper bound.

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

With d->max_vcpus now correctly configured before evtchn_init(), the poll mask
can be constructed suitably for the domain, rather than for the worst-case
setting.

Due to the evtchn_init() fixes, it no longer calls domain_max_vcpus(), and
ARM's two implementations of vgic_max_vcpus() no longer need work around the
out-of-order call.

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

The XEN_DOMCTL_max_vcpus hypercall is modified to reject any call attempt with
max != d->max_vcpus, which does match the older semantics (not that it is
obvious from the code).  The logic to allocate d->vcpu[] is dropped, but at
this point the hypercall still needs making to allocate each vcpu.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@arm.com>
CC: Wei Liu <wei.liu2@citrix.com>

v2:
 * Allocate in domain_create() rather than arch_domain_create().
 * Retain domain_max_vcpus().
---
 xen/arch/arm/domain_build.c |  8 +-------
 xen/arch/arm/setup.c        |  2 +-
 xen/arch/arm/vgic.c         | 11 +----------
 xen/arch/arm/vgic/vgic.c    | 22 +---------------------
 xen/arch/x86/dom0_build.c   |  8 +-------
 xen/arch/x86/setup.c        |  2 +-
 xen/common/domain.c         | 18 ++++++++++++++++++
 xen/common/domctl.c         | 39 +--------------------------------------
 xen/common/event_channel.c  |  3 +--
 xen/include/xen/domain.h    |  2 +-
 10 files changed, 27 insertions(+), 88 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f4a1225..6f45e56 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -72,14 +72,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 72e42e8..a3e1ef7 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -863,7 +863,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.max_vcpus = dom0_max_vcpus();
 
     dom0 = domain_create(0, &dom0_cfg, true);
-    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 ( construct_dom0(dom0) != 0)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 7a2c455..5a4f082 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/arm/vgic/vgic.c b/xen/arch/arm/vgic/vgic.c
index 832632a..4124817 100644
--- a/xen/arch/arm/vgic/vgic.c
+++ b/xen/arch/arm/vgic/vgic.c
@@ -951,27 +951,7 @@ void vgic_sync_hardware_irq(struct domain *d,
 
 unsigned int vgic_max_vcpus(const struct domain *d)
 {
-    unsigned int vgic_vcpu_limit;
-
-    switch ( d->arch.vgic.version )
-    {
-    case GIC_INVALID:
-        /*
-         * Since evtchn_init would call domain_max_vcpus for poll_mask
-         * allocation before the VGIC has been initialised, we need to
-         * return some safe value in this case. As this is for allocation
-         * purposes, go with the maximum value.
-         */
-        vgic_vcpu_limit = MAX_VIRT_CPUS;
-        break;
-    case GIC_V2:
-        vgic_vcpu_limit = VGIC_V2_MAX_CPUS;
-        break;
-    default:
-        BUG();
-    }
-
-    return min_t(unsigned int, MAX_VIRT_CPUS, vgic_vcpu_limit);
+    return min_t(unsigned int, MAX_VIRT_CPUS, d->arch.vgic.handler->max_vcpus);
 }
 
 #ifdef CONFIG_GICV3
diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index b42eac3..423fdec 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -199,17 +199,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/setup.c b/xen/arch/x86/setup.c
index 46dcc71..532aca7 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1693,7 +1693,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     /* Create initial domain 0. */
     dom0 = domain_create(get_initial_domain_id(), &dom0_cfg, !pv_shim);
-    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");
 
     /* Grab the DOM0 command line. */
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 0c44f27..902276d 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -339,6 +339,19 @@ 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;
 
@@ -423,6 +436,11 @@ struct domain *domain_create(domid_t domid,
 
     sched_destroy_domain(d);
 
+    if ( d->max_vcpus )
+    {
+        d->max_vcpus = 0;
+        XFREE(d->vcpu);
+    }
     if ( init_status & INIT_arch )
         arch_domain_destroy(d);
     if ( init_status & INIT_gnttab )
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 58e51b2..ee0983d 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -554,16 +554,9 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
 
         ret = -EINVAL;
         if ( (d == current->domain) || /* no domain_pause() */
-             (max > domain_max_vcpus(d)) )
+             (max != d->max_vcpus) )   /* max_vcpus set up in createdomain */
             break;
 
-        /* Until Xenoprof can dynamically grow its vcpu-s array... */
-        if ( d->xenoprof )
-        {
-            ret = -EAGAIN;
-            break;
-        }
-
         /* Needed, for example, to ensure writable p.t. state is synced. */
         domain_pause(d);
 
@@ -581,38 +574,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
             }
         }
 
-        /* We cannot reduce maximum VCPUs. */
-        ret = -EINVAL;
-        if ( (max < d->max_vcpus) && (d->vcpu[max] != NULL) )
-            goto maxvcpu_out;
-
-        /*
-         * For now don't allow increasing the vcpu count from a non-zero
-         * value: This code and all readers of d->vcpu would otherwise need
-         * to be converted to use RCU, but at present there's no tools side
-         * code path that would issue such a request.
-         */
-        ret = -EBUSY;
-        if ( (d->max_vcpus > 0) && (max > d->max_vcpus) )
-            goto maxvcpu_out;
-
         ret = -ENOMEM;
         online = cpupool_domain_cpumask(d);
-        if ( max > d->max_vcpus )
-        {
-            struct vcpu **vcpus;
-
-            BUG_ON(d->vcpu != NULL);
-            BUG_ON(d->max_vcpus != 0);
-
-            if ( (vcpus = xzalloc_array(struct vcpu *, max)) == NULL )
-                goto maxvcpu_out;
-
-            /* Install vcpu array /then/ update max_vcpus. */
-            d->vcpu = vcpus;
-            smp_wmb();
-            d->max_vcpus = max;
-        }
 
         for ( i = 0; i < max; i++ )
         {
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 41cbbae..381f30e 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -1303,8 +1303,7 @@ 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)));
+    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/xen/domain.h b/xen/include/xen/domain.h
index 651205d..ce31999 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@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply	other threads:[~2018-08-13 10:01 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-13 10:00 [PATCH v2 00/12] Improvements to domain creation Andrew Cooper
2018-08-13 10:00 ` [PATCH v2 01/12] tools/ocaml: Pass a full domctl_create_config into stub_xc_domain_create() Andrew Cooper
2018-08-13 10:00 ` [PATCH v2 02/12] tools: Rework xc_domain_create() to take a full xen_domctl_createdomain Andrew Cooper
2018-08-13 10:01 ` [PATCH v2 03/12] xen/domctl: Merge set_max_evtchn into createdomain Andrew Cooper
2018-08-14 13:58   ` Roger Pau Monné
2018-08-13 10:01 ` [PATCH v2 04/12] xen/evtchn: Pass max_evtchn_port into evtchn_init() Andrew Cooper
2018-08-14 14:07   ` Roger Pau Monné
2018-08-15 12:45   ` Jan Beulich
2018-08-15 12:57   ` Julien Grall
2018-08-13 10:01 ` [PATCH v2 05/12] tools: Pass grant table limits to XEN_DOMCTL_set_gnttab_limits Andrew Cooper
2018-08-13 10:01 ` [PATCH v2 06/12] xen/gnttab: Pass max_{grant, maptrack}_frames into grant_table_create() Andrew Cooper
2018-08-14 14:17   ` Roger Pau Monné
2018-08-15 12:51   ` Jan Beulich
2018-08-15 13:04   ` Julien Grall
2018-08-15 13:08     ` Andrew Cooper
2018-08-15 13:32       ` Julien Grall
2018-08-15 19:03         ` Andrew Cooper
2018-08-16  8:59           ` Julien Grall
2018-08-29  9:38   ` [PATCH v3 6/12] " Andrew Cooper
2018-08-30 19:40     ` Julien Grall
2018-08-13 10:01 ` [PATCH v2 07/12] xen/domctl: Remove XEN_DOMCTL_set_gnttab_limits Andrew Cooper
2018-08-14 14:19   ` Roger Pau Monné
2018-08-13 10:01 ` [PATCH v2 08/12] xen/gnttab: Fold grant_table_{create, set_limits}() into grant_table_init() Andrew Cooper
2018-08-14 14:31   ` Roger Pau Monné
2018-08-15 12:54   ` Jan Beulich
2018-08-13 10:01 ` [PATCH v2 09/12] xen/domain: Call arch_domain_create() as early as possible in domain_create() Andrew Cooper
2018-08-14 14:37   ` Roger Pau Monné
2018-08-15 12:56   ` Jan Beulich
2018-09-04 18:44   ` Rats nest with domain pirq initialisation Andrew Cooper
2018-09-05  7:24     ` Jan Beulich
2018-09-05 11:38       ` Jan Beulich
2018-09-05 12:04       ` Andrew Cooper
2018-09-05 12:25         ` Jan Beulich
2018-09-05 12:39           ` Andrew Cooper
2018-09-05 15:44             ` Roger Pau Monné
2018-08-13 10:01 ` [PATCH v2 10/12] tools: Pass max_vcpus to XEN_DOMCTL_createdomain Andrew Cooper
2018-08-13 10:01 ` [PATCH v2 11/12] xen/dom0: Arrange for dom0_cfg to contain the real max_vcpus value Andrew Cooper
2018-08-14 15:05   ` Roger Pau Monné
2018-08-15 12:59   ` Jan Beulich
2018-08-13 10:01 ` Andrew Cooper [this message]
2018-08-14 15:17   ` [PATCH v2 12/12] xen/domain: Allocate d->vcpu[] in domain_create() Roger Pau Monné
2018-08-15 13:17     ` Julien Grall
2018-08-15 13:50       ` Andrew Cooper
2018-08-15 13:52         ` Julien Grall
2018-08-15 13:56           ` Andrew Cooper
2018-08-15 13:11   ` Jan Beulich
2018-08-15 14:03     ` Andrew Cooper
2018-08-15 15:18       ` Jan Beulich
2018-08-29 10:36         ` Andrew Cooper
2018-08-29 12:10           ` Jan Beulich
2018-08-29 12:29             ` Andrew Cooper
2018-08-29 12:49               ` Jan Beulich
2018-08-29 14:40   ` [PATCH v3 " Andrew Cooper
2018-08-29 15:03     ` Jan Beulich
2018-08-31 10:33       ` Wei Liu
2018-08-31 10:42         ` Jan Beulich
2018-08-31 10:57           ` Julien Grall
2018-08-31 11:00             ` Juergen Gross
2018-08-31 10:58           ` Andrew Cooper
2018-08-30 19:46     ` Julien Grall
2018-08-30 20:04       ` Andrew Cooper
2018-08-14 13:12 ` [PATCH v2 00/12] Improvements to domain creation Christian Lindig
2018-08-14 13:34   ` Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1534154469-6076-13-git-send-email-andrew.cooper3@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).