WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] New dom0_op to set max vcpus for a domain.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] New dom0_op to set max vcpus for a domain.
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 13 Oct 2005 12:30:11 +0000
Delivery-date: Thu, 13 Oct 2005 12:27:43 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 52b9aca1916ace16c60955ee598bfc29ba45b9a6
# Parent  29db5bded574aa378a15f85a4ceb5653c3ed1837
New dom0_op to set max vcpus for a domain.

Signed-off-by: Ryan Harper <ryanh@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 29db5bded574 -r 52b9aca1916a tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Wed Oct 12 15:15:02 2005
+++ b/tools/libxc/xc_domain.c   Wed Oct 12 15:34:49 2005
@@ -329,6 +329,15 @@
     return err;
 }
 
+int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_MAX_VCPUS;
+    op.u.max_vcpus.domain = (domid_t)domid;
+    op.u.max_vcpus.max    = max;
+    return do_dom0_op(xc_handle, &op);
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 29db5bded574 -r 52b9aca1916a tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Oct 12 15:15:02 2005
+++ b/tools/libxc/xenctrl.h     Wed Oct 12 15:34:49 2005
@@ -147,6 +147,17 @@
                        uint32_t domid,
                        const char *corename);
 
+/*
+ * This function sets the maximum number vcpus that a domian may create.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface.
+ * @parm domid the domain id in which vcpus are to be created.
+ * @parm max the maximum number of vcpus that the domain may create.
+ * @return 0 on success, -1 on failure.
+ */
+int xc_domain_max_vcpus(int xc_handle,
+                        uint32_t domid, 
+                        unsigned int max);
 
 /**
  * This function pauses a domain. A paused domain still exists in memory
diff -r 29db5bded574 -r 52b9aca1916a tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Wed Oct 12 15:15:02 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Wed Oct 12 15:34:49 2005
@@ -91,6 +91,26 @@
         return PyErr_SetFromErrno(xc_error);
 
     return PyInt_FromLong(dom);
+}
+
+static PyObject *pyxc_domain_max_vcpus(PyObject *self,
+                                            PyObject *args,
+                                            PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+
+    uint32_t dom, max;
+
+    static char *kwd_list[] = { "dom", "max", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, &dom, &max) )
+        return NULL;
+
+    if ( xc_domain_max_vcpus(xc->xc_handle, dom, max) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+    
+    Py_INCREF(zero);
+    return zero;
 }
 
 static PyObject *pyxc_domain_pause(PyObject *self,
@@ -783,6 +803,14 @@
       " dom    [int, 0]:        Domain identifier to use (allocated if 
zero).\n"
       "Returns: [int] new domain identifier; -1 on error.\n" },
 
+    { "domain_max_vcpus", 
+      (PyCFunction)pyxc_domain_max_vcpus,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Set the maximum number of VCPUs a domain may create.\n"
+      " dom       [int, 0]:      Domain identifier to use.\n"
+      " max     [int, 0]:      New maximum number of VCPUs in domain.\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
     { "domain_dumpcore", 
       (PyCFunction)pyxc_domain_dumpcore, 
       METH_VARARGS | METH_KEYWORDS, "\n"
diff -r 29db5bded574 -r 52b9aca1916a tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Oct 12 15:15:02 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Wed Oct 12 15:34:49 2005
@@ -1030,6 +1030,10 @@
             self.image.handleBootloading()
 
         xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
+
+        # Set maximum number of vcpus in domain
+        xc.domain_max_vcpus(self.domid, int(self.info['vcpus']));
+
         # XXX Merge with configure_maxmem?
         m = self.image.getDomainMemory(self.info['memory_KiB'])
         xc.domain_setmaxmem(self.domid, m)
diff -r 29db5bded574 -r 52b9aca1916a xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Wed Oct 12 15:15:02 2005
+++ b/xen/arch/ia64/xen/domain.c        Wed Oct 12 15:34:49 2005
@@ -149,14 +149,24 @@
        continue_cpu_idle_loop();
 }
 
-struct vcpu *arch_alloc_vcpu_struct(void)
-{
-       /* Per-vp stack is used here. So we need keep vcpu
-        * same page as per-vp stack */
-       return alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER);
-}
-
-void arch_free_vcpu_struct(struct vcpu *v)
+struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+{
+       struct vcpu *v;
+
+       if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL)
+               return NULL;
+
+       memset(v, 0, sizeof(*v)); 
+        memcpy(&v->arch, &idle0_vcpu.arch, sizeof(v->arch));
+       v->arch.privregs = 
+               alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
+       printf("arch_vcpu_info=%p\n", v->arch.privregs);
+       memset(v->arch.privregs, 0, PAGE_SIZE);
+
+       return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
 {
        free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
 }
@@ -194,12 +204,6 @@
                while (1);
        }
        memset(d->shared_info, 0, PAGE_SIZE);
-#if 0
-       d->vcpu[0].arch.privregs = 
-                       alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
-       printf("arch_vcpu_info=%p\n", d->vcpu[0].arch.privregs);
-       memset(d->vcpu.arch.privregs, 0, PAGE_SIZE);
-#endif
        v->vcpu_info = &(d->shared_info->vcpu_data[0]);
 
        d->max_pages = (128UL*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
@@ -249,13 +253,6 @@
        printf("arch_getdomaininfo_ctxt\n");
        c->regs = *regs;
        c->vcpu.evtchn_vector = v->vcpu_info->arch.evtchn_vector;
-#if 0
-       if (c->vcpu.privregs && copy_to_user(c->vcpu.privregs,
-                       v->vcpu_info->arch.privregs, sizeof(mapped_regs_t))) {
-               printk("Bad ctxt address: 0x%lx\n", c->vcpu.privregs);
-               return -EFAULT;
-       }
-#endif
 
        c->shared = v->domain->shared_info->arch;
 }
@@ -279,12 +276,7 @@
 
            vmx_setup_platform(v, c);
        }
-    else{
-       v->arch.privregs =
-                       alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
-           printf("arch_vcpu_info=%p\n", v->arch.privregs);
-       memset(v->arch.privregs, 0, PAGE_SIZE);
-    }
+
        *regs = c->regs;
        new_thread(v, regs->cr_iip, 0, 0);
 
@@ -302,18 +294,6 @@
        /* Don't redo final setup */
        set_bit(_VCPUF_initialised, &v->vcpu_flags);
        return 0;
-}
-
-void arch_do_boot_vcpu(struct vcpu *v)
-{
-       struct domain *d = v->domain;
-       printf("arch_do_boot_vcpu: not implemented\n");
-
-       d->vcpu[v->vcpu_id]->arch.privregs = 
-                       alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
-       printf("arch_vcpu_info=%p\n", d->vcpu[v->vcpu_id]->arch.privregs);
-       memset(d->vcpu[v->vcpu_id]->arch.privregs, 0, PAGE_SIZE);
-       return;
 }
 
 void domain_relinquish_resources(struct domain *d)
@@ -824,12 +804,12 @@
        unsigned long ret, progress = 0;
 
 //printf("construct_dom0: starting\n");
+
+#ifndef CLONE_DOMAIN0
        /* Sanity! */
-#ifndef CLONE_DOMAIN0
-       if ( d != dom0 ) 
-           BUG();
-       if ( test_bit(_DOMF_constructed, &d->domain_flags) ) 
-           BUG();
+       BUG_ON(d != dom0);
+       BUG_ON(d->vcpu[0] == NULL);
+       BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags));
 #endif
 
        memset(&dsi, 0, sizeof(struct domain_setup_info));
@@ -992,14 +972,8 @@
        printk("Dom0: 0x%lx, domain: 0x%lx\n", (u64)dom0, (u64)d);
        if (vmx_dom0)
            vmx_final_setup_domain(dom0);
-    else{
-       d->vcpu[0]->arch.privregs = 
-                       alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
-           printf("arch_vcpu_info=%p\n", d->vcpu[0]->arch.privregs);
-       memset(d->vcpu[0]->arch.privregs, 0, PAGE_SIZE);
-    }
-
-       set_bit(_DOMF_constructed, &d->domain_flags);
+
+       set_bit(_VCPUF_initialised, &v->vcpu_flags);
 
        new_thread(v, pkern_entry, 0, 0);
        physdev_init_dom0(d);
@@ -1031,7 +1005,7 @@
        unsigned long pkern_entry;
 
 #ifndef DOMU_AUTO_RESTART
-       if ( test_bit(_DOMF_constructed, &d->domain_flags) ) BUG();
+       BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags));
 #endif
 
        printk("*** LOADING DOMAIN %d ***\n",d->domain_id);
@@ -1051,7 +1025,7 @@
        loaddomainelfimage(d,image_start);
        printk("loaddomainelfimage returns\n");
 
-       set_bit(_DOMF_constructed, &d->domain_flags);
+       set_bit(_VCPUF_initialised, &v->vcpu_flags);
 
        printk("calling new_thread, entry=%p\n",pkern_entry);
 #ifdef DOMU_AUTO_RESTART
diff -r 29db5bded574 -r 52b9aca1916a xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Oct 12 15:15:02 2005
+++ b/xen/arch/x86/domain.c     Wed Oct 12 15:34:49 2005
@@ -212,21 +212,35 @@
            page->u.inuse.type_info);
 }
 
-struct vcpu *arch_alloc_vcpu_struct(void)
-{
-    return xmalloc(struct vcpu);
-}
-
-/* We assume that vcpu 0 is always the last one to be freed in a
-   domain i.e. if v->vcpu_id == 0, the domain should be
-   single-processor. */
-void arch_free_vcpu_struct(struct vcpu *v)
-{
-    struct vcpu *p;
-    for_each_vcpu(v->domain, p) {
-        if (p->next_in_list == v)
-            p->next_in_list = v->next_in_list;
-    }
+struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+{
+    struct vcpu *v;
+
+    if ( (v = xmalloc(struct vcpu)) == NULL )
+        return NULL;
+
+    memset(v, 0, sizeof(*v));
+
+    memcpy(&v->arch, &idle0_vcpu.arch, sizeof(v->arch));
+    v->arch.flags = TF_kernel_mode;
+
+    if ( (v->vcpu_id = vcpu_id) != 0 )
+    {
+        v->arch.schedule_tail = d->vcpu[0]->arch.schedule_tail;
+        v->arch.perdomain_ptes =
+            d->arch.mm_perdomain_pt + (vcpu_id << PDPT_VCPU_SHIFT);
+        v->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] =
+            l1e_from_page(virt_to_page(gdt_table), PAGE_HYPERVISOR);
+    }
+
+    return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+    BUG_ON(v->next_in_list != NULL);
+    if ( v->vcpu_id != 0 )
+        v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
     xfree(v);
 }
 
@@ -242,8 +256,6 @@
 void arch_do_createdomain(struct vcpu *v)
 {
     struct domain *d = v->domain;
-
-    v->arch.flags = TF_kernel_mode;
 
     if ( is_idle_task(d) )
         return;
@@ -291,20 +303,6 @@
     INIT_LIST_HEAD(&d->arch.free_shadow_frames);
 }
 
-void arch_do_boot_vcpu(struct vcpu *v)
-{
-    struct domain *d = v->domain;
-
-    v->arch.flags = TF_kernel_mode;
-
-    v->arch.schedule_tail = d->vcpu[0]->arch.schedule_tail;
-
-    v->arch.perdomain_ptes =
-        d->arch.mm_perdomain_pt + (v->vcpu_id << PDPT_VCPU_SHIFT);
-    v->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] =
-        l1e_from_page(virt_to_page(gdt_table), PAGE_HYPERVISOR);
-}
-
 void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
 {
     if ( v->processor == newcpu )
diff -r 29db5bded574 -r 52b9aca1916a xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Wed Oct 12 15:15:02 2005
+++ b/xen/arch/x86/domain_build.c       Wed Oct 12 15:34:49 2005
@@ -14,6 +14,7 @@
 #include <xen/event.h>
 #include <xen/elf.h>
 #include <xen/kernel.h>
+#include <xen/domain.h>
 #include <asm/regs.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -146,10 +147,9 @@
         struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn);
 
     /* Sanity! */
-    if ( d->domain_id != 0 ) 
-        BUG();
-    if ( test_bit(_DOMF_constructed, &d->domain_flags) ) 
-        BUG();
+    BUG_ON(d->domain_id != 0);
+    BUG_ON(d->vcpu[0] == NULL);
+    BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags));
 
     memset(&dsi, 0, sizeof(struct domain_setup_info));
     dsi.image_addr = (unsigned long)image_start;
@@ -559,6 +559,9 @@
         d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
     d->shared_info->n_vcpu = num_online_cpus();
 
+    for ( i = 1; i < d->shared_info->n_vcpu; i++ )
+        (void)alloc_vcpu(d, i);
+
     /* Set up monitor table */
     update_pagetables(v);
 
@@ -657,7 +660,7 @@
 
     init_domain_time(d);
 
-    set_bit(_DOMF_constructed, &d->domain_flags);
+    set_bit(_VCPUF_initialised, &v->vcpu_flags);
 
     new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
 
diff -r 29db5bded574 -r 52b9aca1916a xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Oct 12 15:15:02 2005
+++ b/xen/arch/x86/mm.c Wed Oct 12 15:34:49 2005
@@ -185,7 +185,7 @@
      * Any Xen-heap pages that we will allow to be mapped will have
      * their domain field set to dom_xen.
      */
-    dom_xen = alloc_domain_struct();
+    dom_xen = alloc_domain();
     atomic_set(&dom_xen->refcnt, 1);
     dom_xen->domain_id = DOMID_XEN;
 
@@ -194,7 +194,7 @@
      * This domain owns I/O pages that are within the range of the pfn_info
      * array. Mappings occur at the priv of the caller.
      */
-    dom_io = alloc_domain_struct();
+    dom_io = alloc_domain();
     atomic_set(&dom_io->refcnt, 1);
     dom_io->domain_id = DOMID_IO;
 
diff -r 29db5bded574 -r 52b9aca1916a xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Wed Oct 12 15:15:02 2005
+++ b/xen/arch/x86/vmx.c        Wed Oct 12 15:34:49 2005
@@ -1674,7 +1674,7 @@
             store_cpu_user_regs(&regs);
             __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, PENDING_DEBUG_EXC_BS);
 
-            set_bit(_VCPUF_ctrl_pause, &current->vcpu_flags);
+            domain_pause_for_debugger();
             do_sched_op(SCHEDOP_yield);
 
             break;
diff -r 29db5bded574 -r 52b9aca1916a xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Wed Oct 12 15:15:02 2005
+++ b/xen/common/dom0_ops.c     Wed Oct 12 15:34:49 2005
@@ -44,28 +44,24 @@
     struct vcpu   *v;
     u64 cpu_time = 0;
     int vcpu_count = 0;
-    int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
+    int flags = DOMFLAGS_BLOCKED;
     
     info->domain = d->domain_id;
     
     memset(&info->vcpu_to_cpu, -1, sizeof(info->vcpu_to_cpu));
     memset(&info->cpumap, 0, sizeof(info->cpumap));
-    
+
     /* 
-     * - domain is marked as paused or blocked only if all its vcpus 
-     *   are paused or blocked 
+     * - domain is marked as blocked only if all its vcpus are blocked
      * - domain is marked as running if any of its vcpus is running
      * - only map vcpus that aren't down.  Note, at some point we may
      *   wish to demux the -1 value to indicate down vs. not-ever-booted
-     *   
      */
     for_each_vcpu ( d, v ) {
         /* only map vcpus that are up */
         if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
             info->vcpu_to_cpu[v->vcpu_id] = v->processor;
         info->cpumap[v->vcpu_id] = v->cpumap;
-        if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
-            flags &= ~DOMFLAGS_PAUSED;
         if ( !(v->vcpu_flags & VCPUF_blocked) )
             flags &= ~DOMFLAGS_BLOCKED;
         if ( v->vcpu_flags & VCPUF_running )
@@ -78,8 +74,9 @@
     info->n_vcpu = vcpu_count;
     
     info->flags = flags |
-        ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
-        ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
+        ((d->domain_flags & DOMF_dying)      ? DOMFLAGS_DYING    : 0) |
+        ((d->domain_flags & DOMF_shutdown)   ? DOMFLAGS_SHUTDOWN : 0) |
+        ((d->domain_flags & DOMF_ctrl_pause) ? DOMFLAGS_PAUSED   : 0) |
         d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
 
     if (d->ssid != NULL)
@@ -97,6 +94,7 @@
     long ret = 0;
     dom0_op_t curop, *op = &curop;
     void *ssid = NULL; /* save security ptr between pre and post/fail hooks */
+    static spinlock_t dom0_lock = SPIN_LOCK_UNLOCKED;
 
     if ( !IS_PRIV(current->domain) )
         return -EPERM;
@@ -109,6 +107,8 @@
 
     if ( acm_pre_dom0_op(op, &ssid) )
         return -EACCES;
+
+    spin_lock(&dom0_lock);
 
     switch ( op->cmd )
     {
@@ -150,7 +150,7 @@
         {
             ret = -EINVAL;
             if ( (d != current->domain) && 
-                 test_bit(_DOMF_constructed, &d->domain_flags) )
+                 test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) )
             {
                 domain_unpause_by_systemcontroller(d);
                 ret = 0;
@@ -167,17 +167,14 @@
         domid_t        dom;
         struct vcpu   *v;
         unsigned int   i, cnt[NR_CPUS] = { 0 };
-        static spinlock_t alloc_lock = SPIN_LOCK_UNLOCKED;
         static domid_t rover = 0;
-
-        spin_lock(&alloc_lock);
 
         dom = op->u.createdomain.domain;
         if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) )
         {
             ret = -EINVAL;
             if ( !is_free_domid(dom) )
-                goto alloc_out;
+                break;
         }
         else
         {
@@ -191,7 +188,7 @@
 
             ret = -ENOMEM;
             if ( dom == rover )
-                goto alloc_out;
+                break;
 
             rover = dom;
         }
@@ -215,15 +212,51 @@
 
         ret = -ENOMEM;
         if ( (d = do_createdomain(dom, pro)) == NULL )
-            goto alloc_out;
+            break;
 
         ret = 0;
 
         op->u.createdomain.domain = d->domain_id;
         copy_to_user(u_dom0_op, op, sizeof(*op));
-
-    alloc_out:
-        spin_unlock(&alloc_lock);
+    }
+    break;
+
+    case DOM0_MAX_VCPUS:
+    {
+        struct domain *d;
+        unsigned int i, max = op->u.max_vcpus.max;
+
+        ret = -EINVAL;
+        if ( max > MAX_VIRT_CPUS )
+            break;
+
+        ret = -ESRCH;
+        if ( (d = find_domain_by_id(op->u.max_vcpus.domain)) == NULL )
+            break;
+
+        /*
+         * Can only create new VCPUs while the domain is not fully constructed
+         * (and hence not runnable). Xen needs auditing for races before
+         * removing this check.
+         */
+        ret = -EINVAL;
+        if ( test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) )
+            goto maxvcpu_out;
+
+        /* We cannot reduce maximum VCPUs. */
+        ret = -EINVAL;
+        if ( (max != MAX_VIRT_CPUS) && (d->vcpu[max] != NULL) )
+            goto maxvcpu_out;
+
+        ret = -ENOMEM;
+        for ( i = 0; i < max; i++ )
+            if ( (d->vcpu[i] == NULL) && (alloc_vcpu(d, i) == NULL) )
+                goto maxvcpu_out;
+
+        ret = 0;
+
+    maxvcpu_out:
+        put_domain(d);
     }
     break;
 
@@ -535,10 +568,14 @@
         ret = arch_do_dom0_op(op,u_dom0_op);
 
     }
+
+    spin_unlock(&dom0_lock);
+
     if (!ret)
         acm_post_dom0_op(op, ssid);
     else
         acm_fail_dom0_op(op, ssid);
+
     return ret;
 }
 
diff -r 29db5bded574 -r 52b9aca1916a xen/common/domain.c
--- a/xen/common/domain.c       Wed Oct 12 15:15:02 2005
+++ b/xen/common/domain.c       Wed Oct 12 15:34:49 2005
@@ -33,7 +33,7 @@
     struct domain *d, **pd;
     struct vcpu *v;
 
-    if ( (d = alloc_domain_struct()) == NULL )
+    if ( (d = alloc_domain()) == NULL )
         return NULL;
 
     v = d->vcpu[0];
@@ -52,12 +52,14 @@
 
     if ( d->domain_id == IDLE_DOMAIN_ID )
         set_bit(_DOMF_idle_domain, &d->domain_flags);
+    else
+        set_bit(_DOMF_ctrl_pause, &d->domain_flags);
 
     if ( !is_idle_task(d) &&
          ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) )
     {
         evtchn_destroy(d);
-        free_domain_struct(d);
+        free_domain(d);
         return NULL;
     }
     
@@ -224,11 +226,9 @@
      * must issue a PAUSEDOMAIN command to ensure that all execution
      * has ceased and guest state is committed to memory.
      */
+    set_bit(_DOMF_ctrl_pause, &d->domain_flags);
     for_each_vcpu ( d, v )
-    {
-        set_bit(_VCPUF_ctrl_pause, &v->vcpu_flags);
         vcpu_sleep_nosync(v);
-    }
 
     send_guest_virq(dom0->vcpu[0], VIRQ_DEBUGGER);
 }
@@ -267,7 +267,7 @@
     free_perdomain_pt(d);
     free_xenheap_page(d->shared_info);
 
-    free_domain_struct(d);
+    free_domain(d);
 
     send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
 }
@@ -310,10 +310,11 @@
 {
     struct vcpu *v;
 
-    for_each_vcpu ( d, v )
-    {
-        BUG_ON(v == current);
-        if ( !test_and_set_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) )
+    BUG_ON(current->domain == d);
+
+    if ( !test_and_set_bit(_DOMF_ctrl_pause, &d->domain_flags) )
+    {
+        for_each_vcpu ( d, v )
             vcpu_sleep_sync(v);
     }
 }
@@ -322,9 +323,9 @@
 {
     struct vcpu *v;
 
-    for_each_vcpu ( d, v )
-    {
-        if ( test_and_clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) )
+    if ( test_and_clear_bit(_DOMF_ctrl_pause, &d->domain_flags) )
+    {
+        for_each_vcpu ( d, v )
             vcpu_wake(v);
     }
 }
@@ -345,61 +346,32 @@
     if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
         return -EINVAL;
     
-    if (test_bit(_DOMF_constructed, &d->domain_flags) && 
-        !test_bit(_VCPUF_ctrl_pause, &v->vcpu_flags))
+    if ( !test_bit(_DOMF_ctrl_pause, &d->domain_flags) )
         return -EINVAL;
 
     if ( (c = xmalloc(struct vcpu_guest_context)) == NULL )
         return -ENOMEM;
 
-    if ( copy_from_user(c, setdomaininfo->ctxt, sizeof(*c)) )
-    {
-        rc = -EFAULT;
-        goto out;
-    }
-    
-    if ( (rc = arch_set_info_guest(v, c)) != 0 )
-        goto out;
-
-    set_bit(_DOMF_constructed, &d->domain_flags);
-
- out:    
+    rc = -EFAULT;
+    if ( copy_from_user(c, setdomaininfo->ctxt, sizeof(*c)) == 0 )
+        rc = arch_set_info_guest(v, c);
+
     xfree(c);
     return rc;
 }
 
 int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt) 
 {
-    struct vcpu *v;
+    struct vcpu *v = d->vcpu[vcpuid];
     int rc;
 
-    ASSERT(d->vcpu[vcpuid] == NULL);
-
-    if ( alloc_vcpu_struct(d, vcpuid) == NULL )
-        return -ENOMEM;
-
-    v = d->vcpu[vcpuid];
-
-    atomic_set(&v->pausecnt, 0);
-    v->cpumap = CPUMAP_RUNANYWHERE;
-
-    memcpy(&v->arch, &idle0_vcpu.arch, sizeof(v->arch));
-
-    arch_do_boot_vcpu(v);
+    BUG_ON(test_bit(_VCPUF_initialised, &v->vcpu_flags));
 
     if ( (rc = arch_set_info_guest(v, ctxt)) != 0 )
-        goto out;
+        return rc;
 
     sched_add_domain(v);
 
-    set_bit(_VCPUF_down, &v->vcpu_flags);
-    clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags);
-
-    return 0;
-
- out:
-    arch_free_vcpu_struct(d->vcpu[vcpuid]);
-    d->vcpu[vcpuid] = NULL;
     return rc;
 }
 
@@ -413,7 +385,7 @@
     if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) )
         return -EINVAL;
 
-    if ( ((v = d->vcpu[vcpuid]) == NULL) && (cmd != VCPUOP_initialise) )
+    if ( (v = d->vcpu[vcpuid]) == NULL )
         return -ENOENT;
 
     switch ( cmd )
@@ -433,7 +405,9 @@
         }
 
         LOCK_BIGLOCK(d);
-        rc = (d->vcpu[vcpuid] == NULL) ? boot_vcpu(d, vcpuid, ctxt) : -EEXIST;
+        rc = -EEXIST;
+        if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
+            rc = boot_vcpu(d, vcpuid, ctxt);
         UNLOCK_BIGLOCK(d);
 
         xfree(ctxt);
diff -r 29db5bded574 -r 52b9aca1916a xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Wed Oct 12 15:15:02 2005
+++ b/xen/common/sched_sedf.c   Wed Oct 12 15:34:49 2005
@@ -1122,10 +1122,10 @@
 void sedf_wake(struct vcpu *d) {
     s_time_t              now = NOW();
     struct sedf_vcpu_info* inf = EDOM_INFO(d);
- 
+
     PRINT(3, "sedf_wake was called, domain-id %i.%i\n",d->domain->domain_id,
           d->vcpu_id);
- 
+
     if (unlikely(is_idle_task(d->domain)))
         return;
    
diff -r 29db5bded574 -r 52b9aca1916a xen/common/schedule.c
--- a/xen/common/schedule.c     Wed Oct 12 15:15:02 2005
+++ b/xen/common/schedule.c     Wed Oct 12 15:34:49 2005
@@ -80,69 +80,59 @@
 /* Per-CPU periodic timer sends an event to the currently-executing domain. */
 static struct ac_timer t_timer[NR_CPUS]; 
 
-void free_domain_struct(struct domain *d)
+void free_domain(struct domain *d)
 {
     int i;
 
     SCHED_OP(free_task, d);
-    /* vcpu 0 has to be the last one destructed. */
-    for (i = MAX_VIRT_CPUS-1; i >= 0; i--)
-        if ( d->vcpu[i] )
-            arch_free_vcpu_struct(d->vcpu[i]);
+
+    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
+        if ( d->vcpu[i] != NULL )
+            free_vcpu_struct(d->vcpu[i]);
 
     xfree(d);
 }
 
-struct vcpu *alloc_vcpu_struct(
-    struct domain *d, unsigned long vcpu)
-{
-    struct vcpu *v, *vc;
-
-    ASSERT( d->vcpu[vcpu] == NULL );
-
-    if ( (v = arch_alloc_vcpu_struct()) == NULL )
+struct vcpu *alloc_vcpu(struct domain *d, unsigned int vcpu_id)
+{
+    struct vcpu *v;
+
+    BUG_ON(d->vcpu[vcpu_id] != NULL);
+
+    if ( (v = alloc_vcpu_struct(d, vcpu_id)) == NULL )
         return NULL;
 
-    memset(v, 0, sizeof(*v));
-
-    d->vcpu[vcpu] = v;
     v->domain = d;
-    v->vcpu_id = vcpu;
+    v->vcpu_id = vcpu_id;
+    atomic_set(&v->pausecnt, 0);
+    v->cpumap = CPUMAP_RUNANYWHERE;
+
+    d->vcpu[vcpu_id] = v;
 
     if ( SCHED_OP(alloc_task, v) < 0 )
-        goto out;
-
-    if ( vcpu != 0 )
-    {
-        v->vcpu_info = &d->shared_info->vcpu_data[v->vcpu_id];
-
-        for_each_vcpu( d, vc )
-        {
-            if ( (vc->next_in_list == NULL) ||
-                 (vc->next_in_list->vcpu_id > vcpu) )
-                break;
-        }
-        v->next_in_list  = vc->next_in_list;
-        vc->next_in_list = v;
-
-        if (test_bit(_VCPUF_cpu_pinned, &vc->vcpu_flags)) {
-            v->processor = (vc->processor + 1) % num_online_cpus();
-            set_bit(_VCPUF_cpu_pinned, &v->vcpu_flags);
-        } else {
-            v->processor = (vc->processor + 1) % num_online_cpus();
-        }
-    }
+    {
+        d->vcpu[vcpu_id] = NULL;
+        free_vcpu_struct(v);
+        return NULL;
+    }
+
+    if ( vcpu_id == 0 )
+        return v;
+
+    v->vcpu_info = &d->shared_info->vcpu_data[vcpu_id];
+
+    d->vcpu[v->vcpu_id-1]->next_in_list = v;
+
+    v->processor = (d->vcpu[0]->processor + 1) % num_online_cpus();
+    if ( test_bit(_VCPUF_cpu_pinned, &d->vcpu[0]->vcpu_flags) )
+        set_bit(_VCPUF_cpu_pinned, &v->vcpu_flags);
+
+    set_bit(_VCPUF_down, &v->vcpu_flags);
 
     return v;
-
- out:
-    d->vcpu[vcpu] = NULL;
-    arch_free_vcpu_struct(v);
-
-    return NULL;
-}
-
-struct domain *alloc_domain_struct(void)
+}
+
+struct domain *alloc_domain(void)
 {
     struct domain *d;
 
@@ -151,7 +141,7 @@
     
     memset(d, 0, sizeof(*d));
 
-    if ( alloc_vcpu_struct(d, 0) == NULL )
+    if ( alloc_vcpu(d, 0) == NULL )
         goto out;
 
     return d;
@@ -176,11 +166,6 @@
         schedule_data[v->processor].curr = v;
         schedule_data[v->processor].idle = v;
         set_bit(_VCPUF_running, &v->vcpu_flags);
-    }
-    else
-    {
-        /* Must be unpaused by control software to start execution. */
-        set_bit(_VCPUF_ctrl_pause, &v->vcpu_flags);
     }
 
     SCHED_OP(add_task, v);
diff -r 29db5bded574 -r 52b9aca1916a xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Wed Oct 12 15:15:02 2005
+++ b/xen/include/public/dom0_ops.h     Wed Oct 12 15:34:49 2005
@@ -386,6 +386,13 @@
         int is_ram;
     } *memory_map;
 } dom0_physical_memory_map_t;
+
+#define DOM0_MAX_VCPUS 41
+typedef struct {
+    domid_t domain;             /* domain to be affected */
+    unsigned int max;           /* maximum number of vcpus */
+} dom0_max_vcpus_t;
+
 
 typedef struct {
     uint32_t cmd;
@@ -422,6 +429,7 @@
         dom0_getdomaininfolist_t getdomaininfolist;
         dom0_platform_quirk_t    platform_quirk;
         dom0_physical_memory_map_t physical_memory_map;
+        dom0_max_vcpus_t         max_vcpus;
     } u;
 } dom0_op_t;
 
diff -r 29db5bded574 -r 52b9aca1916a xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Wed Oct 12 15:15:02 2005
+++ b/xen/include/xen/domain.h  Wed Oct 12 15:34:49 2005
@@ -1,18 +1,19 @@
 
 #ifndef __XEN_DOMAIN_H__
 #define __XEN_DOMAIN_H__
+
+extern int boot_vcpu(
+    struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt);
 
 /*
  * Arch-specifics.
  */
 
-struct vcpu *arch_alloc_vcpu_struct(void);
+struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id);
 
-extern void arch_free_vcpu_struct(struct vcpu *v);
+extern void free_vcpu_struct(struct vcpu *v);
 
 extern void arch_do_createdomain(struct vcpu *v);
-
-extern void arch_do_boot_vcpu(struct vcpu *v);
 
 extern int  arch_set_info_guest(
     struct vcpu *v, struct vcpu_guest_context *c);
diff -r 29db5bded574 -r 52b9aca1916a xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Oct 12 15:15:02 2005
+++ b/xen/include/xen/sched.h   Wed Oct 12 15:34:49 2005
@@ -61,7 +61,8 @@
     vcpu_info_t     *vcpu_info;
 
     struct domain   *domain;
-    struct vcpu *next_in_list;
+
+    struct vcpu     *next_in_list;
 
     struct ac_timer  timer;         /* one-shot timer for timeout values */
     unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
@@ -166,11 +167,10 @@
 #define IDLE_DOMAIN_ID   (0x7FFFU)
 #define is_idle_task(_d) (test_bit(_DOMF_idle_domain, &(_d)->domain_flags))
 
-struct vcpu *alloc_vcpu_struct(struct domain *d,
-                                             unsigned long vcpu);
-
-void free_domain_struct(struct domain *d);
-struct domain *alloc_domain_struct();
+struct vcpu *alloc_vcpu(struct domain *d, unsigned int vcpu_id);
+
+struct domain *alloc_domain(void);
+void free_domain(struct domain *d);
 
 #define DOMAIN_DESTRUCTED (1<<31) /* assumes atomic_t is >= 32 bits */
 #define put_domain(_d) \
@@ -327,13 +327,15 @@
 extern struct domain *domain_hash[DOMAIN_HASH_SIZE];
 extern struct domain *domain_list;
 
-#define for_each_domain(_d) \
- for ( (_d) = domain_list; (_d) != NULL; (_d) = (_d)->next_in_list )
-
-#define for_each_vcpu(_d,_ed) \
- for ( (_ed) = (_d)->vcpu[0]; \
-       (_ed) != NULL;                \
-       (_ed) = (_ed)->next_in_list )
+#define for_each_domain(_d)                     \
+ for ( (_d) = domain_list;                      \
+       (_d) != NULL;                            \
+       (_d) = (_d)->next_in_list )
+
+#define for_each_vcpu(_d,_v)                    \
+ for ( (_v) = (_d)->vcpu[0];                    \
+       (_v) != NULL;                            \
+       (_v) = (_v)->next_in_list )
 
 /*
  * Per-VCPU flags (vcpu_flags).
@@ -345,57 +347,55 @@
 #define _VCPUF_fpu_dirtied     1
 #define VCPUF_fpu_dirtied      (1UL<<_VCPUF_fpu_dirtied)
  /* Domain is blocked waiting for an event. */
-#define _VCPUF_blocked         3
+#define _VCPUF_blocked         2
 #define VCPUF_blocked          (1UL<<_VCPUF_blocked)
- /* Domain is paused by controller software. */
-#define _VCPUF_ctrl_pause      4
-#define VCPUF_ctrl_pause       (1UL<<_VCPUF_ctrl_pause)
  /* Currently running on a CPU? */
-#define _VCPUF_running         5
+#define _VCPUF_running         3
 #define VCPUF_running          (1UL<<_VCPUF_running)
  /* Disables auto-migration between CPUs. */
-#define _VCPUF_cpu_pinned      6
+#define _VCPUF_cpu_pinned      4
 #define VCPUF_cpu_pinned       (1UL<<_VCPUF_cpu_pinned)
  /* Domain migrated between CPUs. */
-#define _VCPUF_cpu_migrated    7
+#define _VCPUF_cpu_migrated    5
 #define VCPUF_cpu_migrated     (1UL<<_VCPUF_cpu_migrated)
  /* Initialization completed. */
-#define _VCPUF_initialised     8
+#define _VCPUF_initialised     6
 #define VCPUF_initialised      (1UL<<_VCPUF_initialised)
  /* VCPU is not-runnable */
-#define _VCPUF_down            9
+#define _VCPUF_down            7
 #define VCPUF_down             (1UL<<_VCPUF_down)
 
 /*
  * Per-domain flags (domain_flags).
  */
- /* Has the guest OS been fully built yet? */
-#define _DOMF_constructed      0
-#define DOMF_constructed       (1UL<<_DOMF_constructed)
  /* Is this one of the per-CPU idle domains? */
-#define _DOMF_idle_domain      1
+#define _DOMF_idle_domain      0
 #define DOMF_idle_domain       (1UL<<_DOMF_idle_domain)
  /* Is this domain privileged? */
-#define _DOMF_privileged       2
+#define _DOMF_privileged       1
 #define DOMF_privileged        (1UL<<_DOMF_privileged)
  /* May this domain do IO to physical devices? */
-#define _DOMF_physdev_access   3
+#define _DOMF_physdev_access   2
 #define DOMF_physdev_access    (1UL<<_DOMF_physdev_access)
  /* Guest shut itself down for some reason. */
-#define _DOMF_shutdown         4
+#define _DOMF_shutdown         3
 #define DOMF_shutdown          (1UL<<_DOMF_shutdown)
  /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
-#define _DOMF_shuttingdown     5
+#define _DOMF_shuttingdown     4
 #define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
  /* Death rattle. */
-#define _DOMF_dying            6
+#define _DOMF_dying            5
 #define DOMF_dying             (1UL<<_DOMF_dying)
+ /* Domain is paused by controller software. */
+#define _DOMF_ctrl_pause       6
+#define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
 
 static inline int domain_runnable(struct vcpu *v)
 {
     return ( (atomic_read(&v->pausecnt) == 0) &&
-             !(v->vcpu_flags & (VCPUF_blocked|VCPUF_ctrl_pause|VCPUF_down)) &&
-             !(v->domain->domain_flags & (DOMF_shutdown|DOMF_shuttingdown)) );
+             !(v->vcpu_flags & (VCPUF_blocked|VCPUF_down)) &&
+             !(v->domain->domain_flags &
+               (DOMF_shutdown|DOMF_shuttingdown|DOMF_ctrl_pause)) );
 }
 
 void vcpu_pause(struct vcpu *v);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] New dom0_op to set max vcpus for a domain., Xen patchbot -unstable <=