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

[Xen-changelog] [xen-unstable] x86_64: allow more vCPU-s per guest



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1245316456 -3600
# Node ID 2f9e1348aa98f7e0a3e08913a47a59a8261b9ba4
# Parent  cecc76506afc76e6f34b994d06abd35c753baf64
x86_64: allow more vCPU-s per guest

Since the shared info layout is fixed, guests are required to use
VCPUOP_register_vcpu_info prior to booting any vCPU beyond the
traditional limit of 32.

MAX_VIRT_CPUS, being an implemetation detail of the hypervisor, is no
longer being exposed in the public headers.

The tools changes are clearly incomplete (and done only so things
would
build again), and the current state of the tools (using scalar
variables all over the place to represent vCPU bitmaps) very likely
doesn't permit booting DomU-s with more than the traditional number of
vCPU-s. Testing of the extended functionality was done with Dom0 (96
vCPU-s, as well as 128 vCPU-s out of which the kernel elected - by way
of a simple kernel side patch - to use only some, resulting in a
sparse
bitmap).

ia64 changes only to make things build, and build-tested only (and the
tools part only as far as the build would go without encountering
unrelated problems in the blktap code).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 docs/src/interface.tex                   |    2 
 tools/debugger/xenitp/xenitp.c           |   20 ++++-
 tools/include/xen-foreign/structs.py     |    2 
 tools/libxc/ia64/xc_ia64_linux_restore.c |    2 
 tools/libxc/ia64/xc_ia64_linux_save.c    |    4 -
 tools/libxc/xc_core.c                    |   11 ++-
 tools/libxc/xc_core_ia64.c               |   21 +++++-
 tools/libxc/xc_core_ia64.h               |    2 
 tools/libxc/xc_dom_ia64.c                |    2 
 tools/libxc/xc_dom_x86.c                 |    4 -
 tools/libxc/xc_domain_restore.c          |    2 
 tools/libxc/xc_private.h                 |    5 -
 tools/libxc/xc_ptrace.c                  |   27 ++++++-
 tools/libxc/xc_ptrace.h                  |    5 +
 tools/libxc/xc_ptrace_core.c             |  105 ++++++++++++++++++-------------
 xen/arch/ia64/xen/dom_fw_common.c        |    1 
 xen/arch/ia64/xen/domain.c               |   25 +++++--
 xen/arch/ia64/xen/xensetup.c             |    8 +-
 xen/arch/x86/domain.c                    |   28 +++++---
 xen/arch/x86/domain_build.c              |   24 +++++--
 xen/arch/x86/domctl.c                    |    7 +-
 xen/arch/x86/hvm/hvm.c                   |    8 +-
 xen/arch/x86/hvm/mtrr.c                  |    5 -
 xen/arch/x86/hvm/vioapic.c               |   12 ++-
 xen/arch/x86/hvm/vlapic.c                |    6 -
 xen/arch/x86/hvm/vmx/vmx.c               |    9 +-
 xen/arch/x86/hvm/vpic.c                  |    4 -
 xen/arch/x86/mm.c                        |    6 -
 xen/arch/x86/mm/paging.c                 |    2 
 xen/arch/x86/mm/shadow/common.c          |    4 -
 xen/arch/x86/nmi.c                       |    3 
 xen/arch/x86/setup.c                     |   14 ++--
 xen/arch/x86/traps.c                     |    6 -
 xen/common/compat/domain.c               |    2 
 xen/common/domain.c                      |   32 +++------
 xen/common/domctl.c                      |   38 +++++++++--
 xen/common/event_channel.c               |   41 +++++++++---
 xen/common/keyhandler.c                  |    6 +
 xen/common/sched_sedf.c                  |    3 
 xen/common/xenoprof.c                    |   13 +++
 xen/include/asm-ia64/config.h            |    1 
 xen/include/asm-x86/config.h             |   15 +++-
 xen/include/asm-x86/paging.h             |    2 
 xen/include/asm-x86/shared.h             |    4 -
 xen/include/public/arch-ia64.h           |    2 
 xen/include/public/arch-x86/xen.h        |    4 -
 xen/include/public/xen.h                 |    2 
 xen/include/xen/domain.h                 |    1 
 xen/include/xen/numa.h                   |    3 
 xen/include/xen/sched.h                  |   10 ++
 xen/include/xen/shared.h                 |   17 ++---
 xen/include/xen/xenoprof.h               |    2 
 52 files changed, 395 insertions(+), 189 deletions(-)

diff -r cecc76506afc -r 2f9e1348aa98 docs/src/interface.tex
--- a/docs/src/interface.tex    Thu Jun 18 10:05:23 2009 +0100
+++ b/docs/src/interface.tex    Thu Jun 18 10:14:16 2009 +0100
@@ -462,7 +462,7 @@ The structure is declared in {\bf xen/in
 \scriptsize
 \begin{verbatim}
 typedef struct shared_info {
-    vcpu_info_t vcpu_info[MAX_VIRT_CPUS];
+    vcpu_info_t vcpu_info[XEN_LEGACY_MAX_VCPUS];
 
     /*
      * A domain can create "event channels" on which it can send and receive
diff -r cecc76506afc -r 2f9e1348aa98 tools/debugger/xenitp/xenitp.c
--- a/tools/debugger/xenitp/xenitp.c    Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/debugger/xenitp/xenitp.c    Thu Jun 18 10:14:16 2009 +0100
@@ -955,7 +955,7 @@ char *parse_arg (char **buf)
     return res;
 }
 
-vcpu_guest_context_any_t vcpu_ctx_any[MAX_VIRT_CPUS];
+vcpu_guest_context_any_t *vcpu_ctx_any;
 
 int vcpu_setcontext (int vcpu)
 {
@@ -1584,10 +1584,22 @@ void xenitp (int vcpu)
 {
     int ret;
     struct sigaction sa;
-
+    xc_dominfo_t dominfo;
+
+    xc_handle = xc_interface_open (); /* for accessing control interface */
+
+    ret = xc_domain_getinfo (xc_handle, domid, 1, &dominfo);
+    if (ret < 0) {
+        perror ("xc_domain_getinfo");
+        exit (-1);
+    }
+
+    vcpu_ctx_any = calloc (sizeof(vcpu_ctx_any), dominfo.max_vcpu_id + 1);
+    if (!vcpu_ctx_any) {
+        perror ("vcpu context array alloc");
+        exit (-1);
+    }
     cur_ctx = &vcpu_ctx_any[vcpu].c;
-
-    xc_handle = xc_interface_open (); /* for accessing control interface */
 
     if (xc_domain_setdebugging (xc_handle, domid, 1) != 0)
         perror ("setdebugging");
diff -r cecc76506afc -r 2f9e1348aa98 tools/include/xen-foreign/structs.py
--- a/tools/include/xen-foreign/structs.py      Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/include/xen-foreign/structs.py      Thu Jun 18 10:14:16 2009 +0100
@@ -53,6 +53,6 @@ defines = [ "__i386__",
 
             # all archs
             "xen_pfn_to_cr3",
-            "MAX_VIRT_CPUS",
+            "XEN_LEGACY_MAX_VCPUS",
             "MAX_GUEST_CMDLINE" ];
 
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c  Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c  Thu Jun 18 10:14:16 2009 +0100
@@ -174,7 +174,7 @@ xc_ia64_recv_shared_info(int xc_handle, 
     /* clear any pending events and the selector */
     memset(&(shared_info->evtchn_pending[0]), 0,
            sizeof (shared_info->evtchn_pending));
-    for (i = 0; i < MAX_VIRT_CPUS; i++)
+    for (i = 0; i < XEN_LEGACY_MAX_VCPUS; i++)
         shared_info->vcpu_info[i].evtchn_pending_sel = 0;
 
     if (start_info_pfn != NULL)
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/ia64/xc_ia64_linux_save.c
--- a/tools/libxc/ia64/xc_ia64_linux_save.c     Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c     Thu Jun 18 10:14:16 2009 +0100
@@ -238,7 +238,7 @@ xc_ia64_pv_send_context(int xc_handle, i
 
     /* vcpu map */
     uint64_t *vcpumap = NULL;
-    if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, MAX_VIRT_CPUS,
+    if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, XEN_LEGACY_MAX_VCPUS,
                              &vcpumap))
         goto out;
 
@@ -308,7 +308,7 @@ xc_ia64_hvm_send_context(int xc_handle, 
         return -1;
 
     /* vcpu map */
-    if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, MAX_VIRT_CPUS,
+    if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, XEN_LEGACY_MAX_VCPUS,
                              &vcpumap))
         goto out;
 
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c     Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_core.c     Thu Jun 18 10:14:16 2009 +0100
@@ -430,7 +430,7 @@ xc_domain_dumpcore_via_callback(int xc_h
 
     int nr_vcpus = 0;
     char *dump_mem, *dump_mem_start = NULL;
-    vcpu_guest_context_any_t  ctxt[MAX_VIRT_CPUS];
+    vcpu_guest_context_any_t *ctxt = NULL;
     struct xc_core_arch_context arch_ctxt;
     char dummy[PAGE_SIZE];
     int dummy_len;
@@ -492,6 +492,13 @@ xc_domain_dumpcore_via_callback(int xc_h
     if ( domid != info.domid )
     {
         PERROR("Domain %d does not exist", domid);
+        goto out;
+    }
+
+    ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
+    if ( !ctxt )
+    {
+        PERROR("Could not allocate vcpu context array", domid);
         goto out;
     }
 
@@ -900,6 +907,8 @@ out:
         xc_core_shdr_free(sheaders);
     if ( strtab != NULL )
         xc_core_strtab_free(strtab);
+    if ( ctxt != NULL )
+        free(ctxt);
     if ( dump_mem_start != NULL )
         free(dump_mem_start);
     if ( live_shinfo != NULL )
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_core_ia64.c
--- a/tools/libxc/xc_core_ia64.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_core_ia64.c        Thu Jun 18 10:14:16 2009 +0100
@@ -251,13 +251,10 @@ void
 void
 xc_core_arch_context_init(struct xc_core_arch_context* arch_ctxt)
 {
-    int i;
-
     arch_ctxt->mapped_regs_size =
         (XMAPPEDREGS_SIZE < PAGE_SIZE) ? PAGE_SIZE: XMAPPEDREGS_SIZE;
     arch_ctxt->nr_vcpus = 0;
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-        arch_ctxt->mapped_regs[i] = NULL;
+    arch_ctxt->mapped_regs = NULL;
 
     xc_ia64_p2m_init(&arch_ctxt->p2m_table);
 }
@@ -269,6 +266,7 @@ xc_core_arch_context_free(struct xc_core
     for ( i = 0; i < arch_ctxt->nr_vcpus; i++ )
         if ( arch_ctxt->mapped_regs[i] != NULL )
             munmap(arch_ctxt->mapped_regs[i], arch_ctxt->mapped_regs_size);
+    free(arch_ctxt->mapped_regs);
     xc_ia64_p2m_unmap(&arch_ctxt->p2m_table);
 }
 
@@ -289,6 +287,21 @@ xc_core_arch_context_get(struct xc_core_
         errno = ENOENT;
         return -1;
     }
+    if ( !(arch_ctxt->nr_vcpus & (arch_ctxt->nr_vcpus - 1)) ) {
+        unsigned int nr = arch_ctxt->nr_vcpus ? arch_ctxt->nr_vcpus << 1 : 1;
+        mapped_regs_t** new = realloc(arch_ctxt->mapped_regs,
+                                      nr * sizeof(*new));
+
+        if ( !new )
+        {
+            PERROR("Could not alloc mapped regs pointer array");
+            return -1;
+        }
+        memset(new + arch_ctxt->nr_vcpus, 0,
+               (nr - arch_ctxt->nr_vcpus) * sizeof(*new));
+        arch_ctxt->mapped_regs = new;
+    }
+
     mapped_regs = xc_map_foreign_range(xc_handle, domid,
                                        arch_ctxt->mapped_regs_size,
                                        PROT_READ, ctxt->privregs_pfn);
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_core_ia64.h
--- a/tools/libxc/xc_core_ia64.h        Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_core_ia64.h        Thu Jun 18 10:14:16 2009 +0100
@@ -29,7 +29,7 @@ struct xc_core_arch_context {
 struct xc_core_arch_context {
     size_t mapped_regs_size;
     int nr_vcpus;
-    mapped_regs_t* mapped_regs[MAX_VIRT_CPUS];
+    mapped_regs_t** mapped_regs;
 
     struct xen_ia64_p2m_table p2m_table;
 };
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_dom_ia64.c
--- a/tools/libxc/xc_dom_ia64.c Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_dom_ia64.c Thu Jun 18 10:14:16 2009 +0100
@@ -87,7 +87,7 @@ int shared_info_ia64(struct xc_dom_image
     xc_dom_printf("%s: called\n", __FUNCTION__);
 
     memset(shared_info, 0, sizeof(*shared_info));
-    for (i = 0; i < MAX_VIRT_CPUS; i++)
+    for (i = 0; i < XEN_LEGACY_MAX_VCPUS; i++)
         shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
     shared_info->arch.start_info_pfn = dom->start_info_pfn;
     shared_info->arch.memmap_info_num_pages = 1; //XXX
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_dom_x86.c
--- a/tools/libxc/xc_dom_x86.c  Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_dom_x86.c  Thu Jun 18 10:14:16 2009 +0100
@@ -498,7 +498,7 @@ static int shared_info_x86_32(struct xc_
     xc_dom_printf("%s: called\n", __FUNCTION__);
 
     memset(shared_info, 0, sizeof(*shared_info));
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+    for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
         shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
     return 0;
 }
@@ -511,7 +511,7 @@ static int shared_info_x86_64(struct xc_
     xc_dom_printf("%s: called\n", __FUNCTION__);
 
     memset(shared_info, 0, sizeof(*shared_info));
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+    for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
         shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
     return 0;
 }
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_domain_restore.c   Thu Jun 18 10:14:16 2009 +0100
@@ -1146,7 +1146,7 @@ int xc_domain_restore(int xc_handle, int
 
     /* clear any pending events and the selector */
     MEMSET_ARRAY_FIELD(new_shared_info, evtchn_pending, 0);
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+    for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
            SET_FIELD(new_shared_info, vcpu_info[i].evtchn_pending_sel, 0);
 
     /* mask event channels */
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h  Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_private.h  Thu Jun 18 10:14:16 2009 +0100
@@ -190,11 +190,6 @@ void *xc_map_foreign_ranges(int xc_handl
 void *xc_map_foreign_ranges(int xc_handle, uint32_t dom,
                             size_t size, int prot, size_t chunksize,
                             privcmd_mmap_entry_t entries[], int nentries);
-
-void *map_domain_va_core(unsigned long domfd, int cpu, void *guest_va,
-                         vcpu_guest_context_any_t *ctxt);
-int xc_waitdomain_core(int xc_handle, int domain, int *status,
-    int options, vcpu_guest_context_any_t *ctxt);
 
 void bitmap_64_to_byte(uint8_t *bp, const uint64_t *lp, int nbits);
 void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits);
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_ptrace.c   Thu Jun 18 10:14:16 2009 +0100
@@ -42,7 +42,8 @@ static int current_is_hvm;
 
 static uint64_t                         online_cpumap;
 static uint64_t                         regs_valid;
-static vcpu_guest_context_any_t      ctxt[MAX_VIRT_CPUS];
+static unsigned int                     nr_vcpu_ids;
+static vcpu_guest_context_any_t        *ctxt;
 
 #define FOREACH_CPU(cpumap, i)  for ( cpumap = online_cpumap; (i = 
xc_ffs64(cpumap)); cpumap &= ~(1 << (index - 1)) )
 
@@ -101,6 +102,21 @@ paging_enabled(vcpu_guest_context_any_t 
     return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
 }
 
+vcpu_guest_context_any_t *xc_ptrace_get_vcpu_ctxt(unsigned int nr_cpus)
+{
+    if (nr_cpus > nr_vcpu_ids) {
+        vcpu_guest_context_any_t *new;
+
+        new = realloc(ctxt, nr_cpus * sizeof(*ctxt));
+        if (!new)
+            return NULL;
+        ctxt = new;
+        nr_vcpu_ids = nr_cpus;
+    }
+
+    return ctxt;
+}
+
 /*
  * Fetch registers for all online cpus and set the cpumap
  * to indicate which cpus are online
@@ -112,6 +128,9 @@ get_online_cpumap(int xc_handle, struct 
                   uint64_t *cpumap)
 {
     int i, online;
+
+    if (!xc_ptrace_get_vcpu_ctxt(d->max_vcpu_id + 1))
+        return -ENOMEM;
 
     *cpumap = 0;
     for (i = 0; i <= d->max_vcpu_id; i++) {
@@ -261,7 +280,7 @@ xc_ptrace(
     case PTRACE_PEEKDATA:
         if (current_isfile)
             guest_va = (unsigned long *)map_domain_va_core(
-                current_domid, cpu, addr, ctxt);
+                current_domid, cpu, addr);
         else
             guest_va = (unsigned long *)map_domain_va(
                 xc_handle, cpu, addr, PROT_READ);
@@ -277,7 +296,7 @@ xc_ptrace(
         /* XXX assume that all CPUs have the same address space */
         if (current_isfile)
             guest_va = (unsigned long *)map_domain_va_core(
-                current_domid, cpu, addr, ctxt);
+                current_domid, cpu, addr);
         else
             guest_va = (unsigned long *)map_domain_va(
                 xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
@@ -433,7 +452,7 @@ xc_waitdomain(
     int options)
 {
     if (current_isfile)
-        return xc_waitdomain_core(xc_handle, domain, status, options, ctxt);
+        return xc_waitdomain_core(xc_handle, domain, status, options);
     return __xc_waitdomain(xc_handle, domain, status, options);
 }
 
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_ptrace.h
--- a/tools/libxc/xc_ptrace.h   Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_ptrace.h   Thu Jun 18 10:14:16 2009 +0100
@@ -157,4 +157,9 @@ struct gdb_regs {
 }
 #endif
 
+void *map_domain_va_core(unsigned long domfd, int cpu, void *guest_va);
+int xc_waitdomain_core(int xc_handle, int domain, int *status, int options);
+vcpu_guest_context_any_t *xc_ptrace_get_vcpu_ctxt(unsigned int nr_cpus);
+
+
 #endif /* XC_PTRACE */
diff -r cecc76506afc -r 2f9e1348aa98 tools/libxc/xc_ptrace_core.c
--- a/tools/libxc/xc_ptrace_core.c      Thu Jun 18 10:05:23 2009 +0100
+++ b/tools/libxc/xc_ptrace_core.c      Thu Jun 18 10:14:16 2009 +0100
@@ -12,6 +12,44 @@
 #include <time.h>
 #include <inttypes.h>
 
+static unsigned int    max_nr_vcpus;
+static unsigned long  *cr3;
+static unsigned long  *cr3_phys;
+static unsigned long **cr3_virt;
+static unsigned long  *pde_phys;
+static unsigned long **pde_virt;
+static unsigned long  *page_phys;
+static unsigned long **page_virt;
+
+static vcpu_guest_context_t *
+ptrace_core_get_vcpu_ctxt(unsigned int nr_vcpus)
+{
+    if (nr_vcpus > max_nr_vcpus) {
+        void *new;
+
+#define REALLOC(what) \
+        new = realloc(what, nr_vcpus * sizeof(*what)); \
+        if (!new) \
+            return NULL; \
+        memset(what + max_nr_vcpus, 0, \
+              (nr_vcpus - max_nr_vcpus) * sizeof(*what)); \
+        what = new
+
+        REALLOC(cr3);
+        REALLOC(cr3_phys);
+        REALLOC(cr3_virt);
+        REALLOC(pde_phys);
+        REALLOC(pde_virt);
+        REALLOC(page_phys);
+        REALLOC(page_virt);
+
+#undef REALLOC
+        max_nr_vcpus = nr_vcpus;
+    }
+
+    return &xc_ptrace_get_vcpu_ctxt(nr_vcpus)->c;
+}
+
 /* Leave the code for the old format as is. */
 /* --- compatible layer for old format ------------------------------------- */
 /* XXX application state */
@@ -21,7 +59,6 @@ static unsigned long  *p2m_array_compat 
 static unsigned long  *p2m_array_compat = NULL;
 static unsigned long  *m2p_array_compat = NULL;
 static unsigned long   pages_offset_compat;
-static unsigned long   cr3_compat[MAX_VIRT_CPUS];
 
 /* --------------------- */
 
@@ -34,23 +71,15 @@ map_mtop_offset_compat(unsigned long ma)
 
 
 static void *
-map_domain_va_core_compat(unsigned long domfd, int cpu, void *guest_va,
-                          vcpu_guest_context_t *ctxt)
+map_domain_va_core_compat(unsigned long domfd, int cpu, void *guest_va)
 {
     unsigned long pde, page;
     unsigned long va = (unsigned long)guest_va;
     void *v;
 
-    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
-    static unsigned long *cr3_virt[MAX_VIRT_CPUS];
-    static unsigned long  pde_phys[MAX_VIRT_CPUS];
-    static unsigned long *pde_virt[MAX_VIRT_CPUS];
-    static unsigned long  page_phys[MAX_VIRT_CPUS];
-    static unsigned long *page_virt[MAX_VIRT_CPUS];
-
-    if (cr3_compat[cpu] != cr3_phys[cpu])
+    if (cr3[cpu] != cr3_phys[cpu])
     {
-        cr3_phys[cpu] = cr3_compat[cpu];
+        cr3_phys[cpu] = cr3[cpu];
         if (cr3_virt[cpu])
             munmap(cr3_virt[cpu], PAGE_SIZE);
         v = mmap(
@@ -93,7 +122,7 @@ map_domain_va_core_compat(unsigned long 
             map_mtop_offset_compat(page_phys[cpu]));
         if (v == MAP_FAILED)
         {
-            IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3_compat[cpu], 
pde, page, l1_table_offset_i386(va));
+            IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, 
l1_table_offset_i386(va));
             page_phys[cpu] = 0;
             return NULL;
         }
@@ -107,11 +136,11 @@ xc_waitdomain_core_compat(
     int xc_handle,
     int domfd,
     int *status,
-    int options,
-    vcpu_guest_context_t *ctxt)
+    int options)
 {
     int nr_vcpus;
     int i;
+    vcpu_guest_context_t *ctxt;
     xc_core_header_t header;
 
     if ( nr_pages_compat == 0 )
@@ -132,12 +161,18 @@ xc_waitdomain_core_compat(
         nr_vcpus = header.xch_nr_vcpus;
         pages_offset_compat = header.xch_pages_offset;
 
+        if ((ctxt = ptrace_core_get_vcpu_ctxt(nr_vcpus)) == NULL)
+        {
+            IPRINTF("Could not allocate vcpu context array\n");
+            return -1;
+        }
+
         if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
             sizeof(vcpu_guest_context_t)*nr_vcpus)
             return -1;
 
         for (i = 0; i < nr_vcpus; i++)
-            cr3_compat[i] = ctxt[i].ctrlreg[3];
+            cr3[i] = ctxt[i].ctrlreg[3];
 
         if ((p2m_array_compat = malloc(nr_pages_compat * sizeof(unsigned 
long))) == NULL)
         {
@@ -375,7 +410,6 @@ static uint64_t pfn_array_size = 0;
 static uint64_t pfn_array_size = 0;
 static long nr_pages = 0;
 static uint64_t pages_offset;
-static unsigned long cr3[MAX_VIRT_CPUS];
 
 static const struct xen_dumpcore_elfnote_format_version_desc
 known_format_version[] =
@@ -413,20 +447,12 @@ map_gmfn_to_offset_elf(unsigned long gmf
 }
 
 static void *
-map_domain_va_core_elf(unsigned long domfd, int cpu, void *guest_va,
-                       vcpu_guest_context_t *ctxt)
+map_domain_va_core_elf(unsigned long domfd, int cpu, void *guest_va)
 {
     unsigned long pde, page;
     unsigned long va = (unsigned long)guest_va;
     unsigned long offset;
     void *v;
-
-    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
-    static unsigned long *cr3_virt[MAX_VIRT_CPUS];
-    static unsigned long  pde_phys[MAX_VIRT_CPUS];
-    static unsigned long *pde_virt[MAX_VIRT_CPUS];
-    static unsigned long  page_phys[MAX_VIRT_CPUS];
-    static unsigned long *page_virt[MAX_VIRT_CPUS];
 
     if (cr3[cpu] != cr3_phys[cpu])
     {
@@ -498,10 +524,10 @@ xc_waitdomain_core_elf(
     int xc_handle,
     int domfd,
     int *status,
-    int options,
-    vcpu_guest_context_t *ctxt)
+    int options)
 {
     int i;
+    vcpu_guest_context_t *ctxt;
     struct elf_core ecore;
 
     struct xen_dumpcore_elfnote_none *none;
@@ -527,14 +553,13 @@ xc_waitdomain_core_elf(
     if ((header->header.xch_magic != XC_CORE_MAGIC &&
          header->header.xch_magic != XC_CORE_MAGIC_HVM) ||
         header->header.xch_nr_vcpus == 0 ||
-        header->header.xch_nr_vcpus >= MAX_VIRT_CPUS ||
         header->header.xch_nr_pages == 0 ||
         header->header.xch_page_size != PAGE_SIZE)
         goto out;
     current_is_auto_translated_physmap =
         (header->header.xch_magic == XC_CORE_MAGIC_HVM);
     nr_pages = header->header.xch_nr_pages;
-    
+
     /* .note.Xen: xen_version */
     if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME,
                              XEN_ELFNOTE_DUMPCORE_XEN_VERSION,
@@ -560,6 +585,9 @@ xc_waitdomain_core_elf(
         IPRINTF("warning:unknown format version. %"PRIx64"\n",
                 format_version->format_version.version);
     }
+
+    if ((ctxt = ptrace_core_get_vcpu_ctxt(header->header.xch_nr_vcpus)) == 
NULL)
+        goto out;
 
     /* .xen_prstatus: read vcpu_guest_context_t*/
     if (elf_core_read_sec_by_name(&ecore, XEN_DUMPCORE_SEC_PRSTATUS,
@@ -621,12 +649,10 @@ typedef int (*xc_waitdomain_core_t)(int 
 typedef int (*xc_waitdomain_core_t)(int xc_handle,
                                     int domfd,
                                     int *status,
-                                    int options,
-                                    vcpu_guest_context_t *ctxt);
+                                    int options);
 typedef void *(*map_domain_va_core_t)(unsigned long domfd,
                                       int cpu,
-                                      void *guest_va,
-                                      vcpu_guest_context_t *ctxt);
+                                      void *guest_va);
 struct xc_core_format_type {
     xc_waitdomain_core_t waitdomain_core;
     map_domain_va_core_t map_domain_va_core;
@@ -642,25 +668,22 @@ static const struct xc_core_format_type*
 static const struct xc_core_format_type* current_format_type = NULL;
 
 void *
-map_domain_va_core(unsigned long domfd, int cpu, void *guest_va,
-                   vcpu_guest_context_any_t *ctxt)
+map_domain_va_core(unsigned long domfd, int cpu, void *guest_va)
 {
     if (current_format_type == NULL)
         return NULL;
-    return (current_format_type->map_domain_va_core)(domfd, cpu, guest_va,
-                                                     &ctxt->c);
+    return (current_format_type->map_domain_va_core)(domfd, cpu, guest_va);
 }
 
 int
-xc_waitdomain_core(int xc_handle, int domfd, int *status, int options,
-                   vcpu_guest_context_any_t *ctxt)
+xc_waitdomain_core(int xc_handle, int domfd, int *status, int options)
 {
     int ret;
     int i;
 
     for (i = 0; i < NR_FORMAT_TYPE; i++) {
         ret = (format_type[i].waitdomain_core)(xc_handle, domfd, status,
-                                               options, &ctxt->c);
+                                               options);
         if (ret == 0) {
             current_format_type = &format_type[i];
             break;
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/ia64/xen/dom_fw_common.c
--- a/xen/arch/ia64/xen/dom_fw_common.c Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/ia64/xen/dom_fw_common.c Thu Jun 18 10:14:16 2009 +0100
@@ -28,6 +28,7 @@
 #include "ia64/xc_dom_ia64_util.h"
 
 #define ia64_fc(addr)   asm volatile ("fc %0" :: "r"(addr) : "memory")
+#define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS /* XXX */
 #endif /* __XEN__ */
 
 #include <xen/acpi.h>
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/ia64/xen/domain.c        Thu Jun 18 10:14:16 2009 +0100
@@ -2225,13 +2225,6 @@ int __init construct_dom0(struct domain 
        for ( i = 1; i < MAX_VIRT_CPUS; i++ )
            d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
 
-       if (dom0_max_vcpus == 0)
-           dom0_max_vcpus = MAX_VIRT_CPUS;
-       if (dom0_max_vcpus > num_online_cpus())
-           dom0_max_vcpus = num_online_cpus();
-       if (dom0_max_vcpus > MAX_VIRT_CPUS)
-           dom0_max_vcpus = MAX_VIRT_CPUS;
-       
        printk ("Dom0 max_vcpus=%d\n", dom0_max_vcpus);
        for ( i = 1; i < dom0_max_vcpus; i++ )
            if (alloc_vcpu(d, i, i) == NULL)
@@ -2304,6 +2297,24 @@ int __init construct_dom0(struct domain 
        physdev_init_dom0(d);
 
        return 0;
+}
+
+struct vcpu *__init alloc_dom0_vcpu0(void)
+{
+       if (dom0_max_vcpus == 0)
+           dom0_max_vcpus = MAX_VIRT_CPUS;
+       if (dom0_max_vcpus > num_online_cpus())
+           dom0_max_vcpus = num_online_cpus();
+       if (dom0_max_vcpus > MAX_VIRT_CPUS)
+           dom0_max_vcpus = MAX_VIRT_CPUS;
+
+       dom0->vcpu = xmalloc_array(struct vcpu *, dom0_max_vcpus);
+       if ( !dom0->vcpu )
+               return NULL;
+       memset(dom0->vcpu, 0, dom0_max_vcpus * sizeof(*dom0->vcpu));
+       dom0->max_vcpus = dom0_max_vcpus;
+
+       return alloc_vcpu(dom0, 0, 0);
 }
 
 void machine_restart(unsigned int delay_millisecs)
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/ia64/xen/xensetup.c      Thu Jun 18 10:14:16 2009 +0100
@@ -570,7 +570,11 @@ skip_move:
     scheduler_init();
     idle_vcpu[0] = (struct vcpu*) ia64_r13;
     idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
-    if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
+    if ( idle_domain == NULL )
+        BUG();
+    idle_domain->vcpu = idle_vcpu;
+    idle_domain->max_vcpus = NR_CPUS;
+    if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
         BUG();
 
     alloc_dom_xen_and_dom_io();
@@ -657,7 +661,7 @@ printk("num_online_cpus=%d, max_cpus=%d\
     if (dom0 == NULL)
         panic("Error creating domain 0\n");
     domain_set_vhpt_size(dom0, dom0_vhpt_size_log2);
-    dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
+    dom0_vcpu0 = alloc_dom0_vcpu0();
     if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
         panic("Cannot allocate dom0 vcpu 0\n");
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/domain.c     Thu Jun 18 10:14:16 2009 +0100
@@ -263,7 +263,7 @@ int switch_native(struct domain *d)
 
     d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 0;
 
-    for ( vcpuid = 0; vcpuid < MAX_VIRT_CPUS; vcpuid++ )
+    for ( vcpuid = 0; vcpuid < d->max_vcpus; vcpuid++ )
     {
         if (d->vcpu[vcpuid])
             release_compat_l4(d->vcpu[vcpuid]);
@@ -285,7 +285,7 @@ int switch_compat(struct domain *d)
 
     d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 1;
 
-    for ( vcpuid = 0; vcpuid < MAX_VIRT_CPUS; vcpuid++ )
+    for ( vcpuid = 0; vcpuid < d->max_vcpus; vcpuid++ )
     {
         if ( (d->vcpu[vcpuid] != NULL) &&
              (setup_compat_l4(d->vcpu[vcpuid]) != 0) )
@@ -423,12 +423,13 @@ int arch_domain_create(struct domain *d,
 
 #else /* __x86_64__ */
 
-    d->arch.mm_perdomain_pt_pages = xmalloc_array(struct page_info *,
-                                                  PDPT_L2_ENTRIES);
-    if ( !d->arch.mm_perdomain_pt_pages )
+    BUILD_BUG_ON(PDPT_L2_ENTRIES * sizeof(*d->arch.mm_perdomain_pt_pages)
+                 != PAGE_SIZE);
+    pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
+    if ( !pg )
         goto fail;
-    memset(d->arch.mm_perdomain_pt_pages, 0,
-           PDPT_L2_ENTRIES * sizeof(*d->arch.mm_perdomain_pt_pages));
+    d->arch.mm_perdomain_pt_pages = page_to_virt(pg);
+    clear_page(d->arch.mm_perdomain_pt_pages);
 
     pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
     if ( pg == NULL )
@@ -523,7 +524,8 @@ int arch_domain_create(struct domain *d,
         free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
     if ( d->arch.mm_perdomain_l3 )
         free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
-    xfree(d->arch.mm_perdomain_pt_pages);
+    if ( d->arch.mm_perdomain_pt_pages )
+        free_domheap_page(virt_to_page(d->arch.mm_perdomain_pt_pages));
 #else
     free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
 #endif
@@ -556,7 +558,7 @@ void arch_domain_destroy(struct domain *
         if ( perdomain_pt_page(d, i) )
             free_domheap_page(perdomain_pt_page(d, i));
     }
-    xfree(d->arch.mm_perdomain_pt_pages);
+    free_domheap_page(virt_to_page(d->arch.mm_perdomain_pt_pages));
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
 #endif
@@ -872,7 +874,13 @@ map_vcpu_info(struct vcpu *v, unsigned l
 
     new_info = (vcpu_info_t *)(mapping + offset);
 
-    memcpy(new_info, v->vcpu_info, sizeof(*new_info));
+    if ( v->vcpu_info )
+        memcpy(new_info, v->vcpu_info, sizeof(*new_info));
+    else
+    {
+        memset(new_info, 0, sizeof(*new_info));
+        __vcpu_info(v, new_info, evtchn_upcall_mask) = 1;
+    }
 
     v->vcpu_info = new_info;
     v->arch.vcpu_info_mfn = mfn;
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/domain_build.c       Thu Jun 18 10:14:16 2009 +0100
@@ -82,8 +82,24 @@ static void __init parse_dom0_mem(const 
 }
 custom_param("dom0_mem", parse_dom0_mem);
 
-static unsigned int opt_dom0_max_vcpus;
+static unsigned int __initdata opt_dom0_max_vcpus;
 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
+
+struct vcpu *__init alloc_dom0_vcpu0(void)
+{
+    if ( opt_dom0_max_vcpus == 0 )
+        opt_dom0_max_vcpus = num_online_cpus();
+    if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )
+        opt_dom0_max_vcpus = MAX_VIRT_CPUS;
+
+    dom0->vcpu = xmalloc_array(struct vcpu *, opt_dom0_max_vcpus);
+    if ( !dom0->vcpu )
+        return NULL;
+    memset(dom0->vcpu, 0, opt_dom0_max_vcpus * sizeof(*dom0->vcpu));
+    dom0->max_vcpus = opt_dom0_max_vcpus;
+
+    return alloc_vcpu(dom0, 0, 0);
+}
 
 static unsigned int opt_dom0_shadow;
 boolean_param("dom0_shadow", opt_dom0_shadow);
@@ -701,13 +717,9 @@ int __init construct_dom0(
 #endif /* __x86_64__ */
 
     /* Mask all upcalls... */
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+    for ( i = 0; i < XEN_LEGACY_MAX_VCPUS; i++ )
         shared_info(d, vcpu_info[i].evtchn_upcall_mask) = 1;
 
-    if ( opt_dom0_max_vcpus == 0 )
-        opt_dom0_max_vcpus = num_online_cpus();
-    if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )
-        opt_dom0_max_vcpus = MAX_VIRT_CPUS;
     printk("Dom0 has maximum %u VCPUs\n", opt_dom0_max_vcpus);
 
     for ( i = 1; i < opt_dom0_max_vcpus; i++ )
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/domctl.c     Thu Jun 18 10:14:16 2009 +0100
@@ -574,7 +574,8 @@ long arch_do_domctl(
             goto sendtrigger_out;
 
         ret = -ESRCH;
-        if ( (v = d->vcpu[domctl->u.sendtrigger.vcpu]) == NULL )
+        if ( domctl->u.sendtrigger.vcpu >= d->max_vcpus ||
+             (v = d->vcpu[domctl->u.sendtrigger.vcpu]) == NULL )
             goto sendtrigger_out;
 
         switch ( domctl->u.sendtrigger.trigger )
@@ -963,7 +964,7 @@ long arch_do_domctl(
             goto ext_vcpucontext_out;
 
         ret = -ESRCH;
-        if ( (evc->vcpu >= MAX_VIRT_CPUS) ||
+        if ( (evc->vcpu >= d->max_vcpus) ||
              ((v = d->vcpu[evc->vcpu]) == NULL) )
             goto ext_vcpucontext_out;
 
@@ -1085,7 +1086,7 @@ long arch_do_domctl(
             break;
 
         ret = -EINVAL;
-        if ( (domctl->u.debug_op.vcpu >= MAX_VIRT_CPUS) ||
+        if ( (domctl->u.debug_op.vcpu >= d->max_vcpus) ||
              ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) )
             goto debug_op_out;
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Thu Jun 18 10:14:16 2009 +0100
@@ -367,7 +367,7 @@ void hvm_domain_relinquish_resources(str
 
     /* Stop all asynchronous timer actions. */
     rtc_deinit(d);
-    if ( d->vcpu[0] != NULL )
+    if ( d->vcpu != NULL && d->vcpu[0] != NULL )
     {
         pit_deinit(d);
         pmtimer_deinit(d);
@@ -507,7 +507,7 @@ static int hvm_load_cpu_ctxt(struct doma
 
     /* Which vcpu is this? */
     vcpuid = hvm_load_instance(h);
-    if ( vcpuid >= MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
     {
         gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid);
         return -EINVAL;
@@ -2285,7 +2285,7 @@ static void hvm_s3_suspend(struct domain
     domain_pause(d);
     domain_lock(d);
 
-    if ( d->is_dying || (d->vcpu[0] == NULL) ||
+    if ( d->is_dying || (d->vcpu == NULL) || (d->vcpu[0] == NULL) ||
          test_and_set_bool(d->arch.hvm_domain.is_s3_suspended) )
     {
         domain_unlock(d);
@@ -2660,7 +2660,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
             goto param_fail2;
 
         rc = -EINVAL;
-        if ( d->vcpu[0] == NULL )
+        if ( d->vcpu == NULL || d->vcpu[0] == NULL )
             goto param_fail2;
 
         if ( shadow_mode_enabled(d) )
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/mtrr.c
--- a/xen/arch/x86/hvm/mtrr.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/mtrr.c   Thu Jun 18 10:14:16 2009 +0100
@@ -676,7 +676,7 @@ static int hvm_load_mtrr_msr(struct doma
     struct hvm_hw_mtrr hw_mtrr;
 
     vcpuid = hvm_load_instance(h);
-    if ( vcpuid >= MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
     {
         gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid);
         return -EINVAL;
@@ -720,7 +720,8 @@ uint8_t epte_get_entry_emt(
 
     *igmt = 0;
 
-    if ( (current->domain != d) && ((v = d->vcpu[0]) == NULL) )
+    if ( (current->domain != d) &&
+         ((d->vcpu == NULL) || ((v = d->vcpu[0]) == NULL)) )
         return MTRR_TYPE_WRBACK;
 
     if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_IDENT_PT] )
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/vioapic.c        Thu Jun 18 10:14:16 2009 +0100
@@ -339,7 +339,8 @@ static void vioapic_deliver(struct hvm_h
         /* Force round-robin to pick VCPU 0 */
         if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
         {
-            v = vioapic_domain(vioapic)->vcpu[0];
+            v = vioapic_domain(vioapic)->vcpu ?
+                vioapic_domain(vioapic)->vcpu[0] : NULL;
             target = v ? vcpu_vlapic(v) : NULL;
         }
         else
@@ -367,12 +368,14 @@ static void vioapic_deliver(struct hvm_h
             if ( !(deliver_bitmask & (1 << bit)) )
                 continue;
             deliver_bitmask &= ~(1 << bit);
+            if ( vioapic_domain(vioapic)->vcpu == NULL )
+                v = NULL;
 #ifdef IRQ0_SPECIAL_ROUTING
             /* Do not deliver timer interrupts to VCPU != 0 */
-            if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
+            else if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() 
)
                 v = vioapic_domain(vioapic)->vcpu[0];
+#endif
             else
-#endif
                 v = vioapic_domain(vioapic)->vcpu[bit];
             if ( v != NULL )
             {
@@ -392,7 +395,8 @@ static void vioapic_deliver(struct hvm_h
             if ( !(deliver_bitmask & (1 << bit)) )
                 continue;
             deliver_bitmask &= ~(1 << bit);
-            if ( ((v = vioapic_domain(vioapic)->vcpu[bit]) != NULL) &&
+            if ( (vioapic_domain(vioapic)->vcpu != NULL) &&
+                 ((v = vioapic_domain(vioapic)->vcpu[bit]) != NULL) &&
                  !test_and_set_bool(v->nmi_pending) )
                 vcpu_kick(v);
         }
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Thu Jun 18 10:14:16 2009 +0100
@@ -384,7 +384,7 @@ struct vlapic *apic_lowest_prio(struct d
     struct vlapic *vlapic, *target = NULL;
     struct vcpu *v;
 
-    if ( unlikely((v = d->vcpu[old]) == NULL) )
+    if ( unlikely(!d->vcpu) || unlikely((v = d->vcpu[old]) == NULL) )
         return NULL;
 
     do {
@@ -913,7 +913,7 @@ static int lapic_load_hidden(struct doma
     
     /* Which vlapic to load? */
     vcpuid = hvm_load_instance(h); 
-    if ( vcpuid >= MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
     {
         gdprintk(XENLOG_ERR, "HVM restore: domain has no vlapic %u\n", vcpuid);
         return -EINVAL;
@@ -936,7 +936,7 @@ static int lapic_load_regs(struct domain
     
     /* Which vlapic to load? */
     vcpuid = hvm_load_instance(h); 
-    if ( vcpuid >= MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
     {
         gdprintk(XENLOG_ERR, "HVM restore: domain has no vlapic %u\n", vcpuid);
         return -EINVAL;
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Jun 18 10:14:16 2009 +0100
@@ -1221,7 +1221,7 @@ void ept_sync_domain(struct domain *d)
 void ept_sync_domain(struct domain *d)
 {
     /* Only if using EPT and this domain has some VCPUs to dirty. */
-    if ( d->arch.hvm_domain.hap_enabled && d->vcpu[0] )
+    if ( d->arch.hvm_domain.hap_enabled && d->vcpu && d->vcpu[0] )
     {
         ASSERT(local_irq_is_enabled());
         on_each_cpu(__ept_sync_domain, d, 1);
@@ -1399,7 +1399,7 @@ static struct hvm_function_table vmx_fun
 };
 
 static unsigned long *vpid_bitmap;
-#define VPID_BITMAP_SIZE ((1u << VMCS_VPID_WIDTH) / MAX_VIRT_CPUS)
+#define VPID_BITMAP_SIZE ((1u << VMCS_VPID_WIDTH) / XEN_LEGACY_MAX_VCPUS)
 
 void start_vmx(void)
 {
@@ -1921,7 +1921,7 @@ static int vmx_alloc_vpid(struct domain 
     }
     while ( test_and_set_bit(idx, vpid_bitmap) );
 
-    d->arch.hvm_domain.vmx.vpid_base = idx * MAX_VIRT_CPUS;
+    d->arch.hvm_domain.vmx.vpid_base = idx * XEN_LEGACY_MAX_VCPUS;
     return 0;
 }
 
@@ -1930,7 +1930,8 @@ static void vmx_free_vpid(struct domain 
     if ( !cpu_has_vmx_vpid )
         return;
 
-    clear_bit(d->arch.hvm_domain.vmx.vpid_base / MAX_VIRT_CPUS, vpid_bitmap);
+    clear_bit(d->arch.hvm_domain.vmx.vpid_base / XEN_LEGACY_MAX_VCPUS,
+              vpid_bitmap);
 }
 
 static void vmx_install_vlapic_mapping(struct vcpu *v)
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/hvm/vpic.c   Thu Jun 18 10:14:16 2009 +0100
@@ -110,7 +110,9 @@ static void vpic_update_int_output(struc
         if ( vpic->is_master )
         {
             /* Master INT line is connected to VCPU0's VLAPIC LVT0. */
-            struct vcpu *v = vpic_domain(vpic)->vcpu[0];
+            struct vcpu *v = vpic_domain(vpic)->vcpu ?
+                vpic_domain(vpic)->vcpu[0] : NULL;
+
             if ( (v != NULL) && vlapic_accept_pic_intr(v) )
                 vcpu_kick(v);
         }
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/mm.c Thu Jun 18 10:14:16 2009 +0100
@@ -1336,7 +1336,7 @@ static int alloc_l3_table(struct page_in
      */
     if ( (pfn >= 0x100000) &&
          unlikely(!VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3)) &&
-         d->vcpu[0] && d->vcpu[0]->is_initialised )
+         d->vcpu && d->vcpu[0] && d->vcpu[0]->is_initialised )
     {
         MEM_LOG("PAE pgd must be below 4GB (0x%lx >= 0x100000)", pfn);
         return -EINVAL;
@@ -2575,7 +2575,7 @@ static inline int vcpumask_to_pcpumask(
     for ( vmask = 0, offs = 0; ; ++offs)
     {
         vcpu_bias = offs * (is_native ? BITS_PER_LONG : 32);
-        if ( vcpu_bias >= MAX_VIRT_CPUS )
+        if ( vcpu_bias >= d->max_vcpus )
             return 0;
 
         if ( unlikely(is_native ?
@@ -2592,7 +2592,7 @@ static inline int vcpumask_to_pcpumask(
             vcpu_id = find_first_set_bit(vmask);
             vmask &= ~(1UL << vcpu_id);
             vcpu_id += vcpu_bias;
-            if ( (vcpu_id >= MAX_VIRT_CPUS) )
+            if ( (vcpu_id >= d->max_vcpus) )
                 return 0;
             if ( ((v = d->vcpu[vcpu_id]) != NULL) )
                 cpus_or(*pmask, *pmask, v->vcpu_dirty_cpumask);
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c  Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/mm/paging.c  Thu Jun 18 10:14:16 2009 +0100
@@ -684,7 +684,7 @@ int paging_domctl(struct domain *d, xen_
         return 0;
     }
 
-    if ( unlikely(d->vcpu[0] == NULL) )
+    if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) )
     {
         PAGING_ERROR("Paging op on a domain (%u) with no vcpus\n",
                      d->domain_id);
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Thu Jun 18 10:14:16 2009 +0100
@@ -1452,7 +1452,7 @@ static void shadow_blow_tables(struct do
 
 void shadow_blow_tables_per_domain(struct domain *d)
 {
-    if ( shadow_mode_enabled(d) && d->vcpu[0] != NULL ) {
+    if ( shadow_mode_enabled(d) && d->vcpu != NULL && d->vcpu[0] != NULL ) {
         shadow_lock(d);
         shadow_blow_tables(d);
         shadow_unlock(d);
@@ -1470,7 +1470,7 @@ static void shadow_blow_all_tables(unsig
     rcu_read_lock(&domlist_read_lock);
     for_each_domain(d)
     {
-        if ( shadow_mode_enabled(d) && d->vcpu[0] != NULL )
+        if ( shadow_mode_enabled(d) && d->vcpu != NULL && d->vcpu[0] != NULL )
         {
             shadow_lock(d);
             shadow_blow_tables(d);
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/nmi.c
--- a/xen/arch/x86/nmi.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/nmi.c        Thu Jun 18 10:14:16 2009 +0100
@@ -463,7 +463,8 @@ static void do_nmi_stats(unsigned char k
     for_each_cpu ( i )
         printk("%3d\t%3d\n", i, nmi_count(i));
 
-    if ( ((d = dom0) == NULL) || ((v = d->vcpu[0]) == NULL) )
+    if ( ((d = dom0) == NULL) || (d->vcpu == NULL) ||
+         ((v = d->vcpu[0]) == NULL) )
         return;
 
     if ( v->nmi_pending || (v->trap_priority >= VCPU_TRAP_NMI) )
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/setup.c      Thu Jun 18 10:14:16 2009 +0100
@@ -234,11 +234,15 @@ static void __init init_idle_domain(void
     scheduler_init();
 
     idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
-    if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
+    if ( idle_domain == NULL )
         BUG();
-
-    set_current(idle_domain->vcpu[0]);
-    idle_vcpu[0] = this_cpu(curr_vcpu) = current;
+    idle_domain->vcpu = idle_vcpu;
+    idle_domain->max_vcpus = NR_CPUS;
+    if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
+        BUG();
+
+    set_current(idle_vcpu[0]);
+    this_cpu(curr_vcpu) = current;
 
     setup_idle_pagetable();
 }
@@ -998,7 +1002,7 @@ void __init __start_xen(unsigned long mb
 
     /* Create initial domain 0. */
     dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
-    if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
+    if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
         panic("Error creating domain 0\n");
 
     dom0->is_privileged = 1;
diff -r cecc76506afc -r 2f9e1348aa98 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/arch/x86/traps.c      Thu Jun 18 10:14:16 2009 +0100
@@ -2868,7 +2868,7 @@ static void nmi_dom0_report(unsigned int
 {
     struct domain *d = dom0;
 
-    if ( (d == NULL) || (d->vcpu[0] == NULL) )
+    if ( (d == NULL) || (d->vcpu == NULL) || (d->vcpu[0] == NULL) )
         return;
 
     set_bit(reason_idx, nmi_reason(d));
@@ -3205,7 +3205,7 @@ int guest_has_trap_callback(struct domai
     struct trap_info *t;
 
     BUG_ON(d == NULL);
-    BUG_ON(vcpuid >= MAX_VIRT_CPUS);
+    BUG_ON(vcpuid >= d->max_vcpus);
 
     /* Sanity check - XXX should be more fine grained. */
     BUG_ON(trap_nr > TRAP_syscall);
@@ -3223,7 +3223,7 @@ int send_guest_trap(struct domain *d, ui
     struct softirq_trap *st;
 
     BUG_ON(d == NULL);
-    BUG_ON(vcpuid >= MAX_VIRT_CPUS);
+    BUG_ON(vcpuid >= d->max_vcpus);
     v = d->vcpu[vcpuid];
 
     switch (trap_nr) {
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/compat/domain.c
--- a/xen/common/compat/domain.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/compat/domain.c        Thu Jun 18 10:14:16 2009 +0100
@@ -24,7 +24,7 @@ int compat_vcpu_op(int cmd, int vcpuid, 
     if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) )
         return -EINVAL;
 
-    if ( (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
         return -ENOENT;
 
     switch ( cmd )
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/domain.c
--- a/xen/common/domain.c       Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/domain.c       Thu Jun 18 10:14:16 2009 +0100
@@ -134,7 +134,7 @@ struct vcpu *alloc_vcpu(
 {
     struct vcpu *v;
 
-    BUG_ON(d->vcpu[vcpu_id] != NULL);
+    BUG_ON((!is_idle_domain(d) || vcpu_id) && d->vcpu[vcpu_id]);
 
     if ( (v = alloc_vcpu_struct()) == NULL )
         return NULL;
@@ -153,7 +153,8 @@ struct vcpu *alloc_vcpu(
         v->runstate.state = RUNSTATE_offline;        
         v->runstate.state_entry_time = NOW();
         set_bit(_VPF_down, &v->pause_flags);
-        v->vcpu_info = (void *)&shared_info(d, vcpu_info[vcpu_id]);
+        if ( vcpu_id < XEN_LEGACY_MAX_VCPUS )
+            v->vcpu_info = (void *)&shared_info(d, vcpu_info[vcpu_id]);
     }
 
     if ( sched_init_vcpu(v, cpu_id) != 0 )
@@ -181,22 +182,8 @@ struct vcpu *alloc_vcpu(
 
 struct vcpu *alloc_idle_vcpu(unsigned int cpu_id)
 {
-    struct domain *d;
-    struct vcpu *v;
-    unsigned int vcpu_id = cpu_id % MAX_VIRT_CPUS;
-
-    if ( (v = idle_vcpu[cpu_id]) != NULL )
-        return v;
-
-    d = (vcpu_id == 0) ?
-        domain_create(IDLE_DOMAIN_ID, 0, 0) :
-        idle_vcpu[cpu_id - vcpu_id]->domain;
-    BUG_ON(d == NULL);
-
-    v = alloc_vcpu(d, vcpu_id, cpu_id);
-    idle_vcpu[cpu_id] = v;
-
-    return v;
+    return idle_vcpu[cpu_id] ?: alloc_vcpu(idle_vcpu[0]->domain,
+                                           cpu_id, cpu_id);
 }
 
 static unsigned int extra_dom0_irqs, extra_domU_irqs = 8;
@@ -575,7 +562,7 @@ static void complete_domain_destroy(stru
     struct vcpu *v;
     int i;
 
-    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
+    for ( i = d->max_vcpus - 1; i >= 0; i-- )
     {
         if ( (v = d->vcpu[i]) == NULL )
             continue;
@@ -594,7 +581,7 @@ static void complete_domain_destroy(stru
     /* Free page used by xen oprofile buffer. */
     free_xenoprof_pages(d);
 
-    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
+    for ( i = d->max_vcpus - 1; i >= 0; i-- )
         if ( (v = d->vcpu[i]) != NULL )
             free_vcpu_struct(v);
 
@@ -742,12 +729,15 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
     if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) )
         return -EINVAL;
 
-    if ( (v = d->vcpu[vcpuid]) == NULL )
+    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
         return -ENOENT;
 
     switch ( cmd )
     {
     case VCPUOP_initialise:
+        if ( !v->vcpu_info )
+            return -EINVAL;
+
         if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
             return -ENOMEM;
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/domctl.c
--- a/xen/common/domctl.c       Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/domctl.c       Thu Jun 18 10:14:16 2009 +0100
@@ -253,7 +253,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
 
         ret = -EINVAL;
         if ( (d == current->domain) || /* no domain_pause() */
-             (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
+             (vcpu >= d->max_vcpus) || ((v = d->vcpu[vcpu]) == NULL) )
             goto svc_out;
 
         if ( guest_handle_is_null(op->u.vcpucontext.ctxt) )
@@ -433,7 +433,8 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
 
         ret = -EINVAL;
         if ( (d == current->domain) || /* no domain_pause() */
-             (max > MAX_VIRT_CPUS) )
+             (max > MAX_VIRT_CPUS) ||
+             (is_hvm_domain(d) && max > XEN_LEGACY_MAX_VCPUS) )
         {
             rcu_unlock_domain(d);
             break;
@@ -443,6 +444,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
         if ( ret )
         {
             rcu_unlock_domain(d);
+            break;
+        }
+
+        /* Until Xenoprof can dynamically grow its vcpu-s array... */
+        if ( d->xenoprof )
+        {
+            rcu_unlock_domain(d);
+            ret = -EAGAIN;
             break;
         }
 
@@ -451,10 +460,27 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
 
         /* We cannot reduce maximum VCPUs. */
         ret = -EINVAL;
-        if ( (max != MAX_VIRT_CPUS) && (d->vcpu[max] != NULL) )
+        if ( (max < d->max_vcpus) && (d->vcpu[max] != NULL) )
             goto maxvcpu_out;
 
         ret = -ENOMEM;
+        if ( max > d->max_vcpus )
+        {
+            struct vcpu **vcpus = xmalloc_array(struct vcpu *, max);
+            void *ptr;
+
+            if ( !vcpus )
+                goto maxvcpu_out;
+            memcpy(vcpus, d->vcpu, d->max_vcpus * sizeof(*vcpus));
+            memset(vcpus + d->max_vcpus, 0,
+                   (max - d->max_vcpus) * sizeof(*vcpus));
+
+            ptr = d->vcpu;
+            d->vcpu = vcpus;
+            wmb();
+            d->max_vcpus = max;
+            xfree(ptr);
+        }
         for ( i = 0; i < max; i++ )
         {
             if ( d->vcpu[i] != NULL )
@@ -505,7 +531,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
             goto vcpuaffinity_out;
 
         ret = -EINVAL;
-        if ( op->u.vcpuaffinity.vcpu >= MAX_VIRT_CPUS )
+        if ( op->u.vcpuaffinity.vcpu >= d->max_vcpus )
             goto vcpuaffinity_out;
 
         ret = -ESRCH;
@@ -599,7 +625,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
             goto getvcpucontext_out;
 
         ret = -EINVAL;
-        if ( op->u.vcpucontext.vcpu >= MAX_VIRT_CPUS )
+        if ( op->u.vcpucontext.vcpu >= d->max_vcpus )
             goto getvcpucontext_out;
 
         ret = -ESRCH;
@@ -661,7 +687,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
             goto getvcpuinfo_out;
 
         ret = -EINVAL;
-        if ( op->u.getvcpuinfo.vcpu >= MAX_VIRT_CPUS )
+        if ( op->u.getvcpuinfo.vcpu >= d->max_vcpus )
             goto getvcpuinfo_out;
 
         ret = -ESRCH;
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/event_channel.c        Thu Jun 18 10:14:16 2009 +0100
@@ -240,9 +240,12 @@ static long evtchn_bind_virq(evtchn_bind
     if ( virq_is_global(virq) && (vcpu != 0) )
         return -EINVAL;
 
-    if ( (vcpu < 0) || (vcpu >= ARRAY_SIZE(d->vcpu)) ||
+    if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
          ((v = d->vcpu[vcpu]) == NULL) )
         return -ENOENT;
+
+    if ( unlikely(!v->vcpu_info) )
+        return -EAGAIN;
 
     spin_lock(&d->event_lock);
 
@@ -273,9 +276,12 @@ static long evtchn_bind_ipi(evtchn_bind_
     int            port, vcpu = bind->vcpu;
     long           rc = 0;
 
-    if ( (vcpu < 0) || (vcpu >= ARRAY_SIZE(d->vcpu)) ||
+    if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
          (d->vcpu[vcpu] == NULL) )
         return -ENOENT;
+
+    if ( unlikely(!d->vcpu[vcpu]->vcpu_info) )
+        return -EAGAIN;
 
     spin_lock(&d->event_lock);
 
@@ -555,13 +561,13 @@ static int evtchn_set_pending(struct vcp
     }
     
     /* Check if some VCPU might be polling for this event. */
-    if ( likely(bitmap_empty(d->poll_mask, MAX_VIRT_CPUS)) )
+    if ( likely(bitmap_empty(d->poll_mask, d->max_vcpus)) )
         return 0;
 
     /* Wake any interested (or potentially interested) pollers. */
-    for ( vcpuid = find_first_bit(d->poll_mask, MAX_VIRT_CPUS);
-          vcpuid < MAX_VIRT_CPUS;
-          vcpuid = find_next_bit(d->poll_mask, MAX_VIRT_CPUS, vcpuid+1) )
+    for ( vcpuid = find_first_bit(d->poll_mask, d->max_vcpus);
+          vcpuid < d->max_vcpus;
+          vcpuid = find_next_bit(d->poll_mask, d->max_vcpus, vcpuid+1) )
     {
         v = d->vcpu[vcpuid];
         if ( ((v->poll_evtchn <= 0) || (v->poll_evtchn == port)) &&
@@ -608,7 +614,7 @@ void send_guest_global_virq(struct domai
 
     ASSERT(virq_is_global(virq));
 
-    if ( unlikely(d == NULL) )
+    if ( unlikely(d == NULL) || unlikely(d->vcpu == NULL) )
         return;
 
     v = d->vcpu[0];
@@ -717,8 +723,11 @@ long evtchn_bind_vcpu(unsigned int port,
     struct evtchn *chn;
     long           rc = 0;
 
-    if ( (vcpu_id >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu_id] == NULL) )
+    if ( (vcpu_id >= d->max_vcpus) || (d->vcpu[vcpu_id] == NULL) )
         return -ENOENT;
+
+    if ( unlikely(!d->vcpu[vcpu_id]->vcpu_info) )
+        return -EAGAIN;
 
     spin_lock(&d->event_lock);
 
@@ -943,6 +952,9 @@ int alloc_unbound_xen_event_channel(
     struct domain *d = local_vcpu->domain;
     int            port;
 
+    if ( unlikely(!local_vcpu->vcpu_info) )
+        return -EAGAIN;
+
     spin_lock(&d->event_lock);
 
     if ( (port = get_free_port(d)) < 0 )
@@ -1016,6 +1028,14 @@ int evtchn_init(struct domain *d)
     if ( get_free_port(d) != 0 )
         return -EINVAL;
     evtchn_from_port(d, 0)->state = ECS_RESERVED;
+
+#if MAX_VIRT_CPUS > BITS_PER_LONG
+    d->poll_mask = xmalloc_array(unsigned long, BITS_TO_LONGS(MAX_VIRT_CPUS));
+    if ( !d->poll_mask )
+        return -ENOMEM;
+    bitmap_zero(d->poll_mask, MAX_VIRT_CPUS);
+#endif
+
     return 0;
 }
 
@@ -1044,6 +1064,11 @@ void evtchn_destroy(struct domain *d)
         d->evtchn[i] = NULL;
     }
     spin_unlock(&d->event_lock);
+
+#if MAX_VIRT_CPUS > BITS_PER_LONG
+    xfree(d->poll_mask);
+    d->poll_mask = NULL;
+#endif
 }
 
 static void domain_dump_evtchn_info(struct domain *d)
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/keyhandler.c
--- a/xen/common/keyhandler.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/keyhandler.c   Thu Jun 18 10:14:16 2009 +0100
@@ -209,8 +209,8 @@ static void dump_domains(unsigned char k
                    v->vcpu_id, v->processor,
                    v->is_running ? 'T':'F',
                    v->pause_flags, v->poll_evtchn,
-                   vcpu_info(v, evtchn_upcall_pending),
-                   vcpu_info(v, evtchn_upcall_mask));
+                   v->vcpu_info ? vcpu_info(v, evtchn_upcall_pending) : 0,
+                   v->vcpu_info ? vcpu_info(v, evtchn_upcall_mask) : 1);
             cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
             printk("dirty_cpus=%s ", tmpstr);
             cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
@@ -218,6 +218,8 @@ static void dump_domains(unsigned char k
             arch_dump_vcpu_info(v);
             periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
             printk("    %s\n", tmpstr);
+            if ( !v->vcpu_info )
+                continue;
             printk("    Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
                    VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/sched_sedf.c   Thu Jun 18 10:14:16 2009 +0100
@@ -1376,6 +1376,9 @@ static int sedf_adjust(struct domain *p,
           p->domain_id, op->u.sedf.period, op->u.sedf.slice,
           op->u.sedf.latency, (op->u.sedf.extratime)?"yes":"no");
 
+    if ( !p->vcpu )
+        return -EINVAL;
+
     if ( op->cmd == XEN_DOMCTL_SCHEDOP_putinfo )
     {
         /* Check for sane parameters. */
diff -r cecc76506afc -r 2f9e1348aa98 xen/common/xenoprof.c
--- a/xen/common/xenoprof.c     Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/common/xenoprof.c     Thu Jun 18 10:14:16 2009 +0100
@@ -120,7 +120,7 @@ static void xenoprof_reset_buf(struct do
         return;
     }
 
-    for ( j = 0; j < MAX_VIRT_CPUS; j++ )
+    for ( j = 0; j < d->max_vcpus; j++ )
     {
         buf = d->xenoprof->vcpu[j].buffer;
         if ( buf != NULL )
@@ -200,6 +200,17 @@ static int alloc_xenoprof_struct(
     }
 
     memset(d->xenoprof, 0, sizeof(*d->xenoprof));
+
+    d->xenoprof->vcpu = xmalloc_array(struct xenoprof_vcpu, d->max_vcpus);
+    if ( d->xenoprof->vcpu == NULL )
+    {
+        xfree(d->xenoprof);
+        d->xenoprof = NULL;
+        printk("alloc_xenoprof_struct(): vcpu array allocation failed\n");
+        return -ENOMEM;
+    }
+
+    memset(d->xenoprof->vcpu, 0, d->max_vcpus * sizeof(*d->xenoprof->vcpu));
 
     nvcpu = 0;
     for_each_vcpu ( d, v )
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/asm-ia64/config.h
--- a/xen/include/asm-ia64/config.h     Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/asm-ia64/config.h     Thu Jun 18 10:14:16 2009 +0100
@@ -31,6 +31,7 @@
 #else
 #define NR_CPUS 64
 #endif
+#define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
 #define CONFIG_NUMA
 #define CONFIG_ACPI_NUMA
 #define NODES_SHIFT 8                          /* linux/asm/numnodes.h */
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/asm-x86/config.h      Thu Jun 18 10:14:16 2009 +0100
@@ -52,8 +52,12 @@
 #define NR_CPUS 32
 #endif
 
-#if defined(__i386__) && (NR_CPUS > 32)
+#ifdef __i386__
+#if NR_CPUS > 32
 #error "Maximum of 32 physical processors supported by Xen on x86_32"
+#endif
+/* Maximum number of virtual CPUs in multi-processor guests. */
+#define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
 #endif
 
 #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
@@ -203,7 +207,7 @@ extern unsigned int video_mode, video_fl
 /* Slot 260: per-domain mappings. */
 #define PERDOMAIN_VIRT_START    (PML4_ADDR(260))
 #define PERDOMAIN_VIRT_END      (PERDOMAIN_VIRT_START + (PERDOMAIN_MBYTES<<20))
-#define PERDOMAIN_MBYTES        ((unsigned long)GDT_LDT_MBYTES)
+#define PERDOMAIN_MBYTES        (PML4_ENTRY_BYTES >> (20 + PAGETABLE_ORDER))
 /* Slot 261: machine-to-phys conversion table (16GB). */
 #define RDWR_MPT_VIRT_START     (PML4_ADDR(261))
 #define RDWR_MPT_VIRT_END       (RDWR_MPT_VIRT_START + (16UL<<30))
@@ -242,6 +246,8 @@ extern unsigned int video_mode, video_fl
 #define COMPAT_L2_PAGETABLE_XEN_SLOTS(d) \
     (COMPAT_L2_PAGETABLE_LAST_XEN_SLOT - COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d) 
+ 1)
 
+#define COMPAT_LEGACY_MAX_VCPUS XEN_LEGACY_MAX_VCPUS
+
 #endif
 
 #define PGT_base_page_table     PGT_l4_page_table
@@ -347,7 +353,12 @@ extern unsigned long xenheap_phys_end;
 /* GDT/LDT shadow mapping area. The first per-domain-mapping sub-area. */
 #define GDT_LDT_VCPU_SHIFT       5
 #define GDT_LDT_VCPU_VA_SHIFT    (GDT_LDT_VCPU_SHIFT + PAGE_SHIFT)
+#ifdef MAX_VIRT_CPUS
 #define GDT_LDT_MBYTES           (MAX_VIRT_CPUS >> (20-GDT_LDT_VCPU_VA_SHIFT))
+#else
+#define GDT_LDT_MBYTES           PERDOMAIN_MBYTES
+#define MAX_VIRT_CPUS            (GDT_LDT_MBYTES << (20-GDT_LDT_VCPU_VA_SHIFT))
+#endif
 #define GDT_LDT_VIRT_START       PERDOMAIN_VIRT_START
 #define GDT_LDT_VIRT_END         (GDT_LDT_VIRT_START + (GDT_LDT_MBYTES << 20))
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/asm-x86/paging.h      Thu Jun 18 10:14:16 2009 +0100
@@ -332,7 +332,7 @@ static inline void paging_write_p2m_entr
 {
     struct vcpu *v = current;
     if ( v->domain != d )
-        v = d->vcpu[0];
+        v = d->vcpu ? d->vcpu[0] : NULL;
     if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
     {
         return v->arch.paging.mode->write_p2m_entry(v, gfn, p, table_mfn,
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/asm-x86/shared.h
--- a/xen/include/asm-x86/shared.h      Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/asm-x86/shared.h      Thu Jun 18 10:14:16 2009 +0100
@@ -26,6 +26,8 @@ static inline void arch_set_##field(stru
 #define GET_SET_VCPU(type, field)                               \
 static inline type arch_get_##field(const struct vcpu *v)       \
 {                                                               \
+    if ( unlikely(!v->vcpu_info) )                              \
+        return 0;                                               \
     return !has_32bit_shinfo(v->domain) ?                       \
            v->vcpu_info->native.arch.field :                    \
            v->vcpu_info->compat.arch.field;                     \
@@ -57,7 +59,7 @@ static inline void arch_set_##field(stru
 #define GET_SET_VCPU(type, field)                               \
 static inline type arch_get_##field(const struct vcpu *v)       \
 {                                                               \
-    return v->vcpu_info->arch.field;                            \
+    return v->vcpu_info ? v->vcpu_info->arch.field : 0;         \
 }                                                               \
 static inline void arch_set_##field(struct vcpu *v,             \
                                     type val)                   \
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/public/arch-ia64.h    Thu Jun 18 10:14:16 2009 +0100
@@ -66,7 +66,7 @@ typedef unsigned long xen_pfn_t;
 
 /* Maximum number of virtual CPUs in multi-processor guests. */
 /* WARNING: before changing this, check that shared_info fits on a page */
-#define MAX_VIRT_CPUS 64
+#define XEN_LEGACY_MAX_VCPUS 64
 
 /* IO ports location for PV.  */
 #define IO_PORTS_PADDR          0x00000ffffc000000UL
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/public/arch-x86/xen.h
--- a/xen/include/public/arch-x86/xen.h Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/public/arch-x86/xen.h Thu Jun 18 10:14:16 2009 +0100
@@ -73,8 +73,8 @@ typedef unsigned long xen_pfn_t;
 #define FIRST_RESERVED_GDT_BYTE  (FIRST_RESERVED_GDT_PAGE * 4096)
 #define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
 
-/* Maximum number of virtual CPUs in multi-processor guests. */
-#define MAX_VIRT_CPUS 32
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+#define XEN_LEGACY_MAX_VCPUS 32
 
 #ifndef __ASSEMBLY__
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/public/xen.h  Thu Jun 18 10:14:16 2009 +0100
@@ -458,7 +458,7 @@ typedef struct vcpu_info vcpu_info_t;
  * of this structure remaining constant.
  */
 struct shared_info {
-    struct vcpu_info vcpu_info[MAX_VIRT_CPUS];
+    struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
 
     /*
      * A domain can create "event channels" on which it can send and receive
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/xen/domain.h  Thu Jun 18 10:14:16 2009 +0100
@@ -14,6 +14,7 @@ int boot_vcpu(
 int boot_vcpu(
     struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
 struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
+struct vcpu *alloc_dom0_vcpu0(void);
 void vcpu_reset(struct vcpu *v);
 
 struct xen_domctl_getdomaininfo;
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/xen/numa.h
--- a/xen/include/xen/numa.h    Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/xen/numa.h    Thu Jun 18 10:14:16 2009 +0100
@@ -15,6 +15,7 @@
 #define vcpu_to_node(v) (cpu_to_node((v)->processor))
 
 #define domain_to_node(d) \
-  (((d)->vcpu[0] != NULL) ? vcpu_to_node((d)->vcpu[0]) : NUMA_NO_NODE)
+  (((d)->vcpu != NULL && (d)->vcpu[0] != NULL) \
+   ? vcpu_to_node((d)->vcpu[0]) : NUMA_NO_NODE)
 
 #endif /* _XEN_NUMA_H */
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/xen/sched.h   Thu Jun 18 10:14:16 2009 +0100
@@ -180,6 +180,8 @@ struct domain
     unsigned int     max_pages;       /* maximum value for tot_pages        */
     unsigned int     xenheap_pages;   /* # pages allocated from Xen heap    */
 
+    unsigned int     max_vcpus;
+
     /* Scheduling. */
     void            *sched_priv;    /* scheduler-specific data */
 
@@ -226,7 +228,11 @@ struct domain
     bool_t           is_pinned;
 
     /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
+#if MAX_VIRT_CPUS <= BITS_PER_LONG
     DECLARE_BITMAP(poll_mask, MAX_VIRT_CPUS);
+#else
+    unsigned long   *poll_mask;
+#endif
 
     /* Guest has shut down (inc. reason code)? */
     spinlock_t       shutdown_lock;
@@ -244,7 +250,7 @@ struct domain
 
     atomic_t         refcnt;
 
-    struct vcpu *vcpu[MAX_VIRT_CPUS];
+    struct vcpu    **vcpu;
 
     /* Bitmask of CPUs which are holding onto this domain's state. */
     cpumask_t        domain_dirty_cpumask;
@@ -497,7 +503,7 @@ extern struct domain *domain_list;
        (_d) = rcu_dereference((_d)->next_in_list )) \
 
 #define for_each_vcpu(_d,_v)                    \
- for ( (_v) = (_d)->vcpu[0];                    \
+ for ( (_v) = (_d)->vcpu ? (_d)->vcpu[0] : NULL; \
        (_v) != NULL;                            \
        (_v) = (_v)->next_in_list )
 
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/xen/shared.h
--- a/xen/include/xen/shared.h  Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/xen/shared.h  Thu Jun 18 10:14:16 2009 +0100
@@ -21,8 +21,6 @@ typedef union {
     (*(!has_32bit_shinfo(d) ?                           \
        (typeof(&(s)->compat.field))&(s)->native.field : \
        (typeof(&(s)->compat.field))&(s)->compat.field))
-#define shared_info(d, field)                   \
-    __shared_info(d, (d)->shared_info, field)
 
 typedef union {
     struct vcpu_info native;
@@ -30,19 +28,22 @@ typedef union {
 } vcpu_info_t;
 
 /* As above, cast to compat field type. */
-#define vcpu_info(v, field)                                                   \
-    (*(!has_32bit_shinfo((v)->domain) ?                                       \
-       (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->native.field : \
-       (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->compat.field))
+#define __vcpu_info(v, i, field)                        \
+    (*(!has_32bit_shinfo((v)->domain) ?                 \
+       (typeof(&(i)->compat.field))&(i)->native.field : \
+       (typeof(&(i)->compat.field))&(i)->compat.field))
 
 #else
 
 typedef struct shared_info shared_info_t;
-#define shared_info(d, field)           ((d)->shared_info->field)
+#define __shared_info(d, s, field) ((s)->field)
 
 typedef struct vcpu_info vcpu_info_t;
-#define vcpu_info(v, field)             ((v)->vcpu_info->field)
+#define __vcpu_info(v, i, field)   ((i)->field)
 
 #endif
 
+#define shared_info(d, field)      __shared_info(d, (d)->shared_info, field)
+#define vcpu_info(v, field)        __vcpu_info(v, (v)->vcpu_info, field)
+
 #endif /* __XEN_SHARED_H__ */
diff -r cecc76506afc -r 2f9e1348aa98 xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h        Thu Jun 18 10:05:23 2009 +0100
+++ b/xen/include/xen/xenoprof.h        Thu Jun 18 10:14:16 2009 +0100
@@ -50,7 +50,7 @@ struct xenoprof {
 #ifdef CONFIG_COMPAT
     int is_compat;
 #endif
-    struct xenoprof_vcpu vcpu [MAX_VIRT_CPUS];
+    struct xenoprof_vcpu *vcpu;
 };
 
 #ifndef CONFIG_COMPAT

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


 


Rackspace

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