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

[Xen-changelog] [xen-unstable] Save/restore context of all online VCPUs in PV save/restore/migrate.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1172771957 0
# Node ID 139794d55898642e3f0bef2f771a83979333ee1e
# Parent  33d733c3649df6e6713de5852892d7ffd74f3170
Save/restore context of all online VCPUs in PV save/restore/migrate.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/libxc/xc_linux_restore.c |  167 +++++++++++++++++++++++------------------
 tools/libxc/xc_linux_save.c    |   85 +++++++++++++-------
 2 files changed, 153 insertions(+), 99 deletions(-)

diff -r 33d733c3649d -r 139794d55898 tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c    Thu Mar 01 17:28:31 2007 +0000
+++ b/tools/libxc/xc_linux_restore.c    Thu Mar 01 17:59:17 2007 +0000
@@ -144,7 +144,7 @@ int xc_linux_restore(int xc_handle, int 
                      unsigned int console_evtchn, unsigned long *console_mfn)
 {
     DECLARE_DOMCTL;
-    int rc = 1, i, n, m, pae_extended_cr3 = 0;
+    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
     unsigned long mfn, pfn;
     unsigned int prev_pc, this_pc;
     int verify = 0;
@@ -187,6 +187,8 @@ int xc_linux_restore(int xc_handle, int 
     struct mmuext_op pin[MAX_PIN_BATCH];
     unsigned int nr_pins;
 
+    uint64_t vcpumap = 1ULL;
+    unsigned int max_vcpu_id = 0;
 
     max_pfn = nr_pfns;
 
@@ -366,6 +368,16 @@ int xc_linux_restore(int xc_handle, int 
         if (j == -1) {
             verify = 1;
             DPRINTF("Entering page verify mode\n");
+            continue;
+        }
+
+        if (j == -2) {
+            if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) ||
+                (max_vcpu_id >= 64) ||
+                !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) {
+                ERROR("Error when reading max_vcpu_id");
+                goto out;
+            }
             continue;
         }
 
@@ -776,64 +788,90 @@ int xc_linux_restore(int xc_handle, int 
         }
     }
 
-    if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) ||
-        !read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
-        ERROR("Error when reading ctxt or shared info page");
-        goto out;
-    }
-
-    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
-    pfn = ctxt.user_regs.edx;
-    if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
-        ERROR("Suspend record frame number is bad");
-        goto out;
-    }
-    ctxt.user_regs.edx = mfn = p2m[pfn];
-    start_info = xc_map_foreign_range(
-        xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
-    start_info->nr_pages    = max_pfn;
-    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
-    start_info->flags       = 0;
-    *store_mfn = start_info->store_mfn       = p2m[start_info->store_mfn];
-    start_info->store_evtchn                 = store_evtchn;
-    start_info->console.domU.mfn    = p2m[start_info->console.domU.mfn];
-    start_info->console.domU.evtchn = console_evtchn;
-    *console_mfn                    = start_info->console.domU.mfn;
-    munmap(start_info, PAGE_SIZE);
-
-    /* Uncanonicalise each GDT frame number. */
-    if (ctxt.gdt_ents > 8192) {
-        ERROR("GDT entry count out of range");
-        goto out;
-    }
-
-    for (i = 0; (512*i) < ctxt.gdt_ents; i++) {
-        pfn = ctxt.gdt_frames[i];
-        if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
-            ERROR("GDT frame number is bad");
-            goto out;
-        }
-        ctxt.gdt_frames[i] = p2m[pfn];
-    }
-
-    /* Uncanonicalise the page table base pointer. */
-    pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
-
-    if (pfn >= max_pfn) {
-        ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
-            pfn, max_pfn, pfn_type[pfn]);
-        goto out;
-    }
-
-    if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
-         ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
-        ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
-            pfn, max_pfn, pfn_type[pfn],
-            (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
-        goto out;
-    }
-
-    ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
+    for (i = 0; i <= max_vcpu_id; i++) {
+        if (!(vcpumap & (1ULL << i)))
+            continue;
+
+        if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
+            ERROR("Error when reading ctxt %d", i);
+            goto out;
+        }
+
+        if (i == 0) {
+            /*
+             * Uncanonicalise the suspend-record frame number and poke
+             * resume record.
+             */
+            pfn = ctxt.user_regs.edx;
+            if ((pfn >= max_pfn) ||
+                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
+                ERROR("Suspend record frame number is bad");
+                goto out;
+            }
+            ctxt.user_regs.edx = mfn = p2m[pfn];
+            start_info = xc_map_foreign_range(
+                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
+            start_info->nr_pages = max_pfn;
+            start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+            start_info->flags = 0;
+            *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
+            start_info->store_evtchn = store_evtchn;
+            start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
+            start_info->console.domU.evtchn = console_evtchn;
+            *console_mfn = start_info->console.domU.mfn;
+            munmap(start_info, PAGE_SIZE);
+        }
+
+        /* Uncanonicalise each GDT frame number. */
+        if (ctxt.gdt_ents > 8192) {
+            ERROR("GDT entry count out of range");
+            goto out;
+        }
+
+        for (j = 0; (512*j) < ctxt.gdt_ents; j++) {
+            pfn = ctxt.gdt_frames[j];
+            if ((pfn >= max_pfn) ||
+                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
+                ERROR("GDT frame number is bad");
+                goto out;
+            }
+            ctxt.gdt_frames[j] = p2m[pfn];
+        }
+
+        /* Uncanonicalise the page table base pointer. */
+        pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
+
+        if (pfn >= max_pfn) {
+            ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
+                  pfn, max_pfn, pfn_type[pfn]);
+            goto out;
+        }
+
+        if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
+             ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
+            ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
+                  pfn, max_pfn, pfn_type[pfn],
+                  (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
+            goto out;
+        }
+
+        ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
+
+        domctl.cmd = XEN_DOMCTL_setvcpucontext;
+        domctl.domain = (domid_t)dom;
+        domctl.u.vcpucontext.vcpu = i;
+        set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
+        rc = xc_domctl(xc_handle, &domctl);
+        if (rc != 0) {
+            ERROR("Couldn't build vcpu%d", i);
+            goto out;
+        }
+    }
+
+    if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
+        ERROR("Error when reading shared info page");
+        goto out;
+    }
 
     /* clear any pending events and the selector */
     memset(&(shared_info->evtchn_pending[0]), 0,
@@ -869,17 +907,6 @@ int xc_linux_restore(int xc_handle, int 
     munmap(live_p2m, P2M_SIZE);
 
     DPRINTF("Domain ready to be built.\n");
-
-    domctl.cmd = XEN_DOMCTL_setvcpucontext;
-    domctl.domain = (domid_t)dom;
-    domctl.u.vcpucontext.vcpu   = 0;
-    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
-    rc = xc_domctl(xc_handle, &domctl);
-
-    if (rc != 0) {
-        ERROR("Couldn't build the domain");
-        goto out;
-    }
 
  out:
     if ( (rc != 0) && (dom != 0) )
diff -r 33d733c3649d -r 139794d55898 tools/libxc/xc_linux_save.c
--- a/tools/libxc/xc_linux_save.c       Thu Mar 01 17:28:31 2007 +0000
+++ b/tools/libxc/xc_linux_save.c       Thu Mar 01 17:59:17 2007 +0000
@@ -696,6 +696,7 @@ int xc_linux_save(int xc_handle, int io_
     unsigned long needed_to_fix = 0;
     unsigned long total_sent    = 0;
 
+    uint64_t vcpumap = 1ULL;
 
     /* If no explicit control parameters given, use defaults */
     if(!max_iters)
@@ -716,24 +717,11 @@ int xc_linux_save(int xc_handle, int io_
         return 1;
     }
 
-    if (lock_pages(&ctxt, sizeof(ctxt))) {
-        ERROR("Unable to lock ctxt");
-        return 1;
-    }
-
-    /* Only have to worry about vcpu 0 even for SMP */
     if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
         ERROR("Could not get vcpu context");
         goto out;
     }
     shared_info_frame = info.shared_info_frame;
-
-    /* A cheesy test to see whether the domain contains valid state. */
-    if (ctxt.ctrlreg[3] == 0)
-    {
-        ERROR("Domain is not in a valid Linux guest OS state");
-        goto out;
-    }
 
     /* Map the shared info frame */
     if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
@@ -1194,6 +1182,32 @@ int xc_linux_save(int xc_handle, int io_
 
     DPRINTF("All memory is saved\n");
 
+    {
+        struct {
+            int minustwo;
+            int max_vcpu_id;
+            uint64_t vcpumap;
+        } chunk = { -2, info.max_vcpu_id };
+
+        if (info.max_vcpu_id >= 64) {
+            ERROR("Too many VCPUS in guest!");
+            goto out;
+        }
+
+        for (i = 1; i <= info.max_vcpu_id; i++) {
+            xc_vcpuinfo_t vinfo;
+            if ((xc_vcpu_getinfo(xc_handle, dom, i, &vinfo) == 0) &&
+                vinfo.online)
+                vcpumap |= 1ULL << i;
+        }
+
+        chunk.vcpumap = vcpumap;
+        if(!write_exact(io_fd, &chunk, sizeof(chunk))) {
+            ERROR("Error when writing to state file (errno %d)", errno);
+            goto out;
+        }
+    }
+
     /* Zero terminate */
     i = 0;
     if (!write_exact(io_fd, &i, sizeof(int))) {
@@ -1240,30 +1254,43 @@ int xc_linux_save(int xc_handle, int io_
         goto out;
     }
 
-    /* Canonicalise each GDT frame number. */
-    for ( i = 0; (512*i) < ctxt.gdt_ents; i++ ) {
-        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
-            ERROR("GDT frame is not in range of pseudophys map");
+    for (i = 0; i <= info.max_vcpu_id; i++) {
+        if (!(vcpumap & (1ULL << i)))
+            continue;
+
+        if ((i != 0) && xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) {
+            ERROR("No context for VCPU%d", i);
             goto out;
         }
-    }
-
-    /* Canonicalise the page table base pointer. */
-    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) {
-        ERROR("PT base is not in range of pseudophys map");
-        goto out;
-    }
-    ctxt.ctrlreg[3] = 
-        xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3])));
+
+        /* Canonicalise each GDT frame number. */
+        for ( j = 0; (512*j) < ctxt.gdt_ents; j++ ) {
+            if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[j]) ) {
+                ERROR("GDT frame is not in range of pseudophys map");
+                goto out;
+            }
+        }
+
+        /* Canonicalise the page table base pointer. */
+        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) {
+            ERROR("PT base is not in range of pseudophys map");
+            goto out;
+        }
+        ctxt.ctrlreg[3] = 
+            xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3])));
+
+        if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) {
+            ERROR("Error when writing to state file (1) (errno %d)", errno);
+            goto out;
+        }
+    }
 
     /*
      * Reset the MFN to be a known-invalid value. See map_frame_list_list().
      */
     memcpy(page, live_shinfo, PAGE_SIZE);
     ((shared_info_t *)page)->arch.pfn_to_mfn_frame_list_list = 0;
-
-    if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) ||
-        !write_exact(io_fd, page, PAGE_SIZE)) {
+    if (!write_exact(io_fd, page, PAGE_SIZE)) {
         ERROR("Error when writing to state file (1) (errno %d)", errno);
         goto out;
     }

_______________________________________________
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®.