[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |