aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/ia64/xc_ia64_linux_save.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxc/ia64/xc_ia64_linux_save.c')
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c801
1 files changed, 0 insertions, 801 deletions
diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c
deleted file mode 100644
index 3440da343a..0000000000
--- a/tools/libxc/ia64/xc_ia64_linux_save.c
+++ /dev/null
@@ -1,801 +0,0 @@
-/******************************************************************************
- * xc_ia64_linux_save.c
- *
- * Save the state of a running Linux session.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Copyright (c) 2003, K A Fraser.
- * Rewritten for ia64 by Tristan Gingold <tristan.gingold@bull.net>
- *
- * Copyright (c) 2007 Isaku Yamahata <yamahata@valinux.co.jp>
- * Use foreign p2m exposure.
- * VTi domain support.
- */
-
-#include <inttypes.h>
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-#include "xg_private.h"
-#include "xc_bitops.h"
-#include "xc_ia64.h"
-#include "xc_ia64_save_restore.h"
-#include "xc_efi.h"
-#include "xen/hvm/params.h"
-
-/*
-** Default values for important tuning parameters. Can override by passing
-** non-zero replacement values to xc_linux_save().
-**
-** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.
-**
-*/
-#define DEF_MAX_ITERS (4 - 1) /* limit us to 4 times round loop */
-#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns */
-
-/*
-** During (live) save/migrate, we maintain a number of bitmaps to track
-** which pages we have to send, and to skip.
-*/
-
-static int
-suspend_and_state(int (*suspend)(void*), void* data,
- xc_interface *xch, int io_fd,
- int dom, xc_dominfo_t *info)
-{
- if ( !(*suspend)(data) ) {
- ERROR("Suspend request failed");
- return -1;
- }
-
- if ( (xc_domain_getinfo(xch, dom, 1, info) != 1) ||
- !info->shutdown || (info->shutdown_reason != SHUTDOWN_suspend) ) {
- ERROR("Could not get domain info");
- return -1;
- }
-
- return 0;
-}
-
-static inline int
-md_is_not_ram(const efi_memory_desc_t *md)
-{
- return ((md->type != EFI_CONVENTIONAL_MEMORY) ||
- (md->attribute != EFI_MEMORY_WB) ||
- (md->num_pages == 0));
-}
-
-/*
- * Send through a list of all the PFNs that were not in map at the close.
- * We send pages which was allocated. However balloon driver may
- * decreased after sending page. So we have to check the freed
- * page after pausing the domain.
- */
-static int
-xc_ia64_send_unallocated_list(xc_interface *xch, int io_fd,
- struct xen_ia64_p2m_table *p2m_table,
- xen_ia64_memmap_info_t *memmap_info,
- void *memmap_desc_start, void *memmap_desc_end)
-{
- void *p;
- efi_memory_desc_t *md;
-
- unsigned long N;
- unsigned long pfntab[1024];
- unsigned int j;
-
- j = 0;
- for (p = memmap_desc_start;
- p < memmap_desc_end;
- p += memmap_info->efi_memdesc_size) {
- md = p;
-
- if (md_is_not_ram(md))
- continue;
-
- for (N = md->phys_addr >> PAGE_SHIFT;
- N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
- PAGE_SHIFT;
- N++) {
- if (!xc_ia64_p2m_allocated(p2m_table, N))
- j++;
- }
- }
- if (write_exact(io_fd, &j, sizeof(unsigned int))) {
- ERROR("Error when writing to state file (6a)");
- return -1;
- }
-
- j = 0;
- for (p = memmap_desc_start;
- p < memmap_desc_end;
- p += memmap_info->efi_memdesc_size) {
- md = p;
-
- if (md_is_not_ram(md))
- continue;
-
- for (N = md->phys_addr >> PAGE_SHIFT;
- N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
- PAGE_SHIFT;
- N++) {
- if (!xc_ia64_p2m_allocated(p2m_table, N))
- pfntab[j++] = N;
- if (j == sizeof(pfntab)/sizeof(pfntab[0])) {
- if (write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) {
- ERROR("Error when writing to state file (6b)");
- return -1;
- }
- j = 0;
- }
- }
- }
- if (j > 0) {
- if (write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) {
- ERROR("Error when writing to state file (6c)");
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-xc_ia64_send_vcpu_context(xc_interface *xch, int io_fd, uint32_t dom,
- uint32_t vcpu, vcpu_guest_context_any_t *ctxt_any)
-{
- vcpu_guest_context_t *ctxt = &ctxt_any->c;
- if (xc_vcpu_getcontext(xch, dom, vcpu, ctxt_any)) {
- ERROR("Could not get vcpu context");
- return -1;
- }
-
- if (write_exact(io_fd, ctxt, sizeof(*ctxt))) {
- ERROR("Error when writing to state file (1)");
- return -1;
- }
-
- fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt->regs.ip, ctxt->regs.b[0]);
- return 0;
-}
-
-static int
-xc_ia64_send_shared_info(xc_interface *xch, int io_fd, shared_info_t *live_shinfo)
-{
- if (write_exact(io_fd, live_shinfo, PAGE_SIZE)) {
- ERROR("Error when writing to state file (1)");
- return -1;
- }
- return 0;
-}
-
-static int
-xc_ia64_send_vcpumap(xc_interface *xch, int io_fd, uint32_t dom,
- const xc_dominfo_t *info, uint64_t max_virt_cpus,
- uint64_t **vcpumapp)
-{
- int rc = -1;
- unsigned int i;
- unsigned long vcpumap_size;
- uint64_t *vcpumap = NULL;
-
- vcpumap_size = bitmap_size(max_virt_cpus);
- vcpumap = bitmap_alloc(max_virt_cpus);
- if (!vcpumap) {
- ERROR("memory alloc for vcpumap");
- goto out;
- }
-
- for (i = 0; i <= info->max_vcpu_id; i++) {
- xc_vcpuinfo_t vinfo;
- if ((xc_vcpu_getinfo(xch, dom, i, &vinfo) == 0) && vinfo.online)
- set_bit(i, vcpumap);
- }
-
- if (write_exact(io_fd, &max_virt_cpus, sizeof(max_virt_cpus))) {
- ERROR("write max_virt_cpus");
- goto out;
- }
-
- if (write_exact(io_fd, vcpumap, vcpumap_size)) {
- ERROR("write vcpumap");
- goto out;
- }
-
- rc = 0;
-
- out:
- if (rc != 0 && vcpumap != NULL) {
- free(vcpumap);
- vcpumap = NULL;
- }
- *vcpumapp = vcpumap;
- return rc;
-}
-
-
-static int
-xc_ia64_pv_send_context(xc_interface *xch, int io_fd, uint32_t dom,
- const xc_dominfo_t *info, shared_info_t *live_shinfo)
-{
- int rc = -1;
- unsigned int i;
-
- /* vcpu map */
- uint64_t *vcpumap = NULL;
- if (xc_ia64_send_vcpumap(xch, io_fd, dom, info, XEN_LEGACY_MAX_VCPUS,
- &vcpumap))
- goto out;
-
- /* vcpu context */
- for (i = 0; i <= info->max_vcpu_id; i++) {
- /* A copy of the CPU context of the guest. */
- vcpu_guest_context_any_t ctxt_any;
- vcpu_guest_context_t *ctxt = &ctxt_any.c;
-
- char *mem;
-
- if (!test_bit(i, vcpumap))
- continue;
-
- if (xc_ia64_send_vcpu_context(xch, io_fd, dom, i, &ctxt_any))
- goto out;
-
- mem = xc_map_foreign_range(xch, dom, PAGE_SIZE,
- PROT_READ|PROT_WRITE, ctxt->privregs_pfn);
- if (mem == NULL) {
- ERROR("cannot map privreg page");
- goto out;
- }
- if (write_exact(io_fd, mem, PAGE_SIZE)) {
- ERROR("Error when writing privreg to state file (5)");
- munmap(mem, PAGE_SIZE);
- goto out;
- }
- munmap(mem, PAGE_SIZE);
- }
-
- rc = xc_ia64_send_shared_info(xch, io_fd, live_shinfo);
-
- out:
- if (vcpumap != NULL)
- free(vcpumap);
- return rc;
-}
-
-static int
-xc_ia64_hvm_send_context(xc_interface *xch, int io_fd, uint32_t dom,
- const xc_dominfo_t *info, shared_info_t *live_shinfo)
-{
- int rc = -1;
- unsigned int i;
-
- /* vcpu map */
- uint64_t *vcpumap = NULL;
-
- /* HVM: magic frames for ioreqs and xenstore comms */
- const int hvm_params[] = {
- HVM_PARAM_STORE_PFN,
- HVM_PARAM_IOREQ_PFN,
- HVM_PARAM_BUFIOREQ_PFN,
- HVM_PARAM_BUFPIOREQ_PFN,
- };
- const int NR_PARAMS = sizeof(hvm_params) / sizeof(hvm_params[0]);
- /* ioreq_pfn, bufioreq_pfn, store_pfn */
- uint64_t magic_pfns[NR_PARAMS];
-
- /* HVM: a buffer for holding HVM contxt */
- uint64_t rec_size;
- uint64_t hvm_buf_size = 0;
- uint8_t *hvm_buf = NULL;
-
- if (xc_ia64_send_shared_info(xch, io_fd, live_shinfo))
- return -1;
-
- /* vcpu map */
- if (xc_ia64_send_vcpumap(xch, io_fd, dom, info, XEN_LEGACY_MAX_VCPUS,
- &vcpumap))
- goto out;
-
- /* vcpu context */
- for (i = 0; i <= info->max_vcpu_id; i++) {
- /* A copy of the CPU context of the guest. */
- vcpu_guest_context_any_t ctxt_any;
-
- if (!test_bit(i, vcpumap))
- continue;
-
- if (xc_ia64_send_vcpu_context(xch, io_fd, dom, i, &ctxt_any))
- goto out;
-
- /* system context of vcpu is sent as hvm context. */
- }
-
- /* Save magic-page locations. */
- memset(magic_pfns, 0, sizeof(magic_pfns));
- for (i = 0; i < NR_PARAMS; i++) {
- if (xc_get_hvm_param(xch, dom, hvm_params[i], &magic_pfns[i])) {
- PERROR("Error when xc_get_hvm_param");
- goto out;
- }
- }
-
- if (write_exact(io_fd, magic_pfns, sizeof(magic_pfns))) {
- ERROR("Error when writing to state file (7)");
- goto out;
- }
-
- /* Need another buffer for HVM context */
- hvm_buf_size = xc_domain_hvm_getcontext(xch, dom, 0, 0);
- if (hvm_buf_size == -1) {
- ERROR("Couldn't get HVM context size from Xen");
- goto out;
- }
-
- hvm_buf = malloc(hvm_buf_size);
- if (!hvm_buf) {
- ERROR("Couldn't allocate memory");
- goto out;
- }
-
- /* Get HVM context from Xen and save it too */
- rec_size = xc_domain_hvm_getcontext(xch, dom, hvm_buf, hvm_buf_size);
- if (rec_size == -1) {
- ERROR("HVM:Could not get hvm buffer");
- goto out;
- }
-
- if (write_exact(io_fd, &rec_size, sizeof(rec_size))) {
- ERROR("error write hvm buffer size");
- goto out;
- }
-
- if (write_exact(io_fd, hvm_buf, rec_size)) {
- ERROR("write HVM info failed!\n");
- goto out;
- }
-
- rc = 0;
-out:
- if (hvm_buf != NULL)
- free(hvm_buf);
- if (vcpumap != NULL)
- free(vcpumap);
- return rc;
-}
-
-int
-xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
- uint32_t max_factor, uint32_t flags,
- struct save_callbacks* callbacks, int hvm,
- unsigned long vm_generationid_addr)
-{
- DECLARE_DOMCTL;
- xc_dominfo_t info;
-
- int rc = 1;
-
- int debug = (flags & XCFLAGS_DEBUG);
- int live = (flags & XCFLAGS_LIVE);
-
- /* The new domain's shared-info frame number. */
- unsigned long shared_info_frame;
-
- /* Live mapping of shared info structure */
- shared_info_t *live_shinfo = NULL;
-
- /* Iteration number. */
- int iter;
-
- /* Number of pages sent in the last iteration (live only). */
- unsigned int sent_last_iter;
-
- /* Number of pages sent (live only). */
- unsigned int total_sent = 0;
-
- /* total number of pages used by the current guest */
- unsigned long p2m_size;
-
- /* Size of the shadow bitmap (live only). */
- unsigned int bitmap_size = 0;
-
- /* True if last iteration. */
- int last_iter = 0;
-
- /* Bitmap of pages to be sent. */
- DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
- /* Bitmap of pages not to be sent (because dirtied). */
- DECLARE_HYPERCALL_BUFFER(unsigned long, to_skip);
-
- char *mem;
-
- /* for foreign p2m exposure */
- unsigned long memmap_info_num_pages;
- /* Unsigned int was used before. To keep file format compatibility. */
- unsigned int memmap_info_num_pages_to_send;
- unsigned long memmap_size = 0;
- xen_ia64_memmap_info_t *memmap_info = NULL;
- void *memmap_desc_start;
- void *memmap_desc_end;
- void *p;
- efi_memory_desc_t *md;
- struct xen_ia64_p2m_table p2m_table;
-
- if ( hvm && !callbacks->switch_qemu_logdirty )
- {
- ERROR("No switch_qemu_logdirty callback given.");
- errno = EINVAL;
- return 1;
- }
-
- xc_ia64_p2m_init(&p2m_table);
-
- if (debug)
- fprintf(stderr, "xc_linux_save (ia64): started dom=%d\n", dom);
-
- /* If no explicit control parameters given, use defaults */
- if (!max_iters)
- max_iters = DEF_MAX_ITERS;
- if (!max_factor)
- max_factor = DEF_MAX_FACTOR;
-
- //initialize_mbit_rate();
-
- if (xc_domain_getinfo(xch, dom, 1, &info) != 1) {
- ERROR("Could not get domain info");
- return 1;
- }
-
- shared_info_frame = info.shared_info_frame;
-
-#if 0
- /* cheesy sanity check */
- if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
- ERROR("Invalid state record -- pfn count out of range: %lu",
- (info.max_memkb >> (PAGE_SHIFT - 10)));
- goto out;
- }
-#endif
-
- /* Map the shared info frame */
- live_shinfo = xc_map_foreign_range(xch, dom, PAGE_SIZE,
- PROT_READ, shared_info_frame);
- if (!live_shinfo) {
- ERROR("Couldn't map live_shinfo");
- goto out;
- }
-
- p2m_size = xc_domain_maximum_gpfn(xch, dom) + 1;
-
- /* This is expected by xm restore. */
- if (write_exact(io_fd, &p2m_size, sizeof(unsigned long))) {
- ERROR("write: p2m_size");
- goto out;
- }
-
- /* xc_linux_restore starts to read here. */
- /* Write a version number. This can avoid searching for a stupid bug
- if the format change.
- The version is hard-coded, don't forget to change the restore code
- too! */
- {
- unsigned long version = XC_IA64_SR_FORMAT_VER_CURRENT;
-
- if (write_exact(io_fd, &version, sizeof(unsigned long))) {
- ERROR("write: version");
- goto out;
- }
- }
-
- domctl.cmd = XEN_DOMCTL_arch_setup;
- domctl.domain = (domid_t)dom;
- domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query;
- if (xc_domctl(xch, &domctl) < 0) {
- ERROR("Could not get domain setup");
- goto out;
- }
- if (write_exact(io_fd, &domctl.u.arch_setup,
- sizeof(domctl.u.arch_setup))) {
- ERROR("write: domain setup");
- goto out;
- }
-
- /* Domain is still running at this point */
- if (live) {
-
- if (xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
- NULL, 0, NULL, 0, NULL ) < 0) {
- ERROR("Couldn't enable shadow mode");
- goto out;
- }
-
- last_iter = 0;
-
- bitmap_size = ((p2m_size + BITS_PER_LONG-1) & ~(BITS_PER_LONG-1)) / 8;
- to_send = xc_hypercall_buffer_alloc(xch, to_send, bitmap_size);
- to_skip = xc_hypercall_buffer_alloc(xch, to_skip, bitmap_size);
-
- if (!to_send || !to_skip) {
- ERROR("Couldn't allocate bitmap array");
- goto out;
- }
-
- /* Initially all the pages must be sent. */
- memset(to_send, 0xff, bitmap_size);
-
- /* Enable qemu-dm logging dirty pages to xen */
- if (hvm && callbacks->switch_qemu_logdirty(dom, 1, callbacks->data)) {
- ERROR("Unable to enable qemu log-dirty mode");
- goto out;
- }
- } else {
-
- /* This is a non-live suspend. Issue the call back to get the
- domain suspended */
-
- last_iter = 1;
-
- if (suspend_and_state(callbacks->suspend, callbacks->data, xch,
- io_fd, dom, &info)) {
- ERROR("Domain appears not to have suspended");
- goto out;
- }
-
- }
-
- /* copy before use in case someone updating them */
- if (xc_ia64_copy_memmap(xch, info.domid, live_shinfo,
- &memmap_info, &memmap_info_num_pages) != 0) {
- PERROR("Could not copy memmap");
- goto out;
- }
- memmap_size = memmap_info_num_pages << PAGE_SHIFT;
-
- if (xc_ia64_p2m_map(&p2m_table, xch, dom, memmap_info, 0) < 0) {
- PERROR("xc_ia64_p2m_map");
- goto out;
- }
- memmap_info_num_pages_to_send = memmap_info_num_pages;
- if (write_exact(io_fd, &memmap_info_num_pages_to_send,
- sizeof(memmap_info_num_pages_to_send))) {
- PERROR("write: arch.memmap_info_num_pages");
- goto out;
- }
- if (write_exact(io_fd, memmap_info, memmap_size)) {
- PERROR("write: memmap_info");
- goto out;
- }
-
- sent_last_iter = p2m_size;
-
- copypages:
- for (iter = 1; ; iter++) {
- unsigned int sent_this_iter, skip_this_iter;
- unsigned long N;
-
- sent_this_iter = 0;
- skip_this_iter = 0;
-
- /* Dirtied pages won't be saved.
- slightly wasteful to peek the whole array evey time,
- but this is fast enough for the moment. */
- if (!last_iter) {
- if (xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_PEEK,
- HYPERCALL_BUFFER(to_skip), p2m_size,
- NULL, 0, NULL) != p2m_size) {
- ERROR("Error peeking shadow bitmap");
- goto out;
- }
- }
-
- /* Start writing out the saved-domain record. */
- memmap_desc_start = &memmap_info->memdesc;
- memmap_desc_end = memmap_desc_start + memmap_info->efi_memmap_size;
- for (p = memmap_desc_start;
- p < memmap_desc_end;
- p += memmap_info->efi_memdesc_size) {
- md = p;
- if (md_is_not_ram(md))
- continue;
-
- for (N = md->phys_addr >> PAGE_SHIFT;
- N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
- PAGE_SHIFT;
- N++) {
-
- if (!xc_ia64_p2m_allocated(&p2m_table, N))
- continue;
-
- if (!last_iter) {
- if (test_bit(N, to_skip) && test_bit(N, to_send))
- skip_this_iter++;
- if (test_bit(N, to_skip) || !test_bit(N, to_send))
- continue;
- } else if (live) {
- if (!test_bit(N, to_send))
- continue;
- }
-
- if (debug)
- fprintf(stderr, "xc_linux_save: page %lx (%lu/%lu)\n",
- xc_ia64_p2m_mfn(&p2m_table, N),
- N, p2m_size);
-
- mem = xc_map_foreign_range(xch, dom, PAGE_SIZE,
- PROT_READ|PROT_WRITE, N);
- if (mem == NULL) {
- /* The page may have move.
- It will be remarked dirty.
- FIXME: to be tracked. */
- fprintf(stderr, "cannot map mfn page %lx gpfn %lx: %s\n",
- xc_ia64_p2m_mfn(&p2m_table, N),
- N, xc_strerror(xch, errno));
- goto out;
- }
-
- if (write_exact(io_fd, &N, sizeof(N))) {
- ERROR("write: p2m_size");
- munmap(mem, PAGE_SIZE);
- goto out;
- }
-
- if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
- ERROR("Error when writing to state file (5)");
- munmap(mem, PAGE_SIZE);
- goto out;
- }
- munmap(mem, PAGE_SIZE);
- sent_this_iter++;
- total_sent++;
- }
- }
-
- if (last_iter)
- break;
-
- DPRINTF(" %d: sent %d, skipped %d\n",
- iter, sent_this_iter, skip_this_iter );
-
- if (live) {
- if ( /* ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) || */
- (iter >= max_iters) || (sent_this_iter+skip_this_iter < 50) ||
- (total_sent > p2m_size*max_factor)) {
- DPRINTF("Start last iteration\n");
- last_iter = 1;
-
- if (suspend_and_state(callbacks->suspend, callbacks->data,
- xch, io_fd, dom, &info)) {
- ERROR("Domain appears not to have suspended");
- goto out;
- }
- }
-
- /* Pages to be sent are pages which were dirty. */
- if (xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_CLEAN,
- HYPERCALL_BUFFER(to_send), p2m_size,
- NULL, 0, NULL ) != p2m_size) {
- ERROR("Error flushing shadow PT");
- goto out;
- }
-
- sent_last_iter = sent_this_iter;
-
- //print_stats(xch, dom, sent_this_iter, &stats, 1);
- }
- }
-
- fprintf(stderr, "All memory is saved\n");
-
- /* terminate */
- {
- unsigned long pfn = INVALID_MFN;
- if (write_exact(io_fd, &pfn, sizeof(pfn))) {
- ERROR("Error when writing to state file (6)");
- goto out;
- }
- }
-
- if (xc_ia64_send_unallocated_list(xch, io_fd, &p2m_table,
- memmap_info,
- memmap_desc_start, memmap_desc_end))
- goto out;
-
- if (!hvm)
- rc = xc_ia64_pv_send_context(xch, io_fd,
- dom, &info, live_shinfo);
- else
- rc = xc_ia64_hvm_send_context(xch, io_fd,
- dom, &info, live_shinfo);
- if (rc)
- goto out;
-
- /* Success! */
- rc = 0;
-
- out:
- if ( !rc && callbacks->postcopy )
- callbacks->postcopy(callbacks->data);
-
- /* Flush last write and discard cache for file. */
- discard_file_cache(xch, io_fd, 1 /* flush */);
-
- /* checkpoint_cb can spend arbitrarily long in between rounds */
- if (!rc && callbacks->checkpoint &&
- callbacks->checkpoint(callbacks->data) > 0)
- {
- /* reset stats timer */
- //print_stats(xch, dom, 0, &stats, 0);
-
- rc = 1;
- /* last_iter = 1; */
- if ( suspend_and_state(callbacks->suspend, callbacks->data, xch,
- io_fd, dom, &info) )
- {
- ERROR("Domain appears not to have suspended");
- goto out;
- }
- DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame);
- //print_stats(xch, dom, 0, &stats, 1);
-
- if ( xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_CLEAN, HYPERCALL_BUFFER(to_send),
- p2m_size, NULL, 0, NULL) != p2m_size )
- {
- ERROR("Error flushing shadow PT");
- }
-
- goto copypages;
- }
-
- if (live) {
- if (xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_OFF,
- NULL, 0, NULL, 0, NULL ) < 0) {
- DPRINTF("Warning - couldn't disable shadow mode");
- }
- if ( hvm &&
- callbacks->switch_qemu_logdirty(dom, 0, callbacks->data) ) {
- DPRINTF("Warning - couldn't disable qemu log-dirty mode");
- }
- }
-
- xc_hypercall_buffer_free(xch, to_send);
- xc_hypercall_buffer_free(xch, to_skip);
- if (live_shinfo)
- munmap(live_shinfo, PAGE_SIZE);
- if (memmap_info)
- free(memmap_info);
- xc_ia64_p2m_unmap(&p2m_table);
-
- fprintf(stderr,"Save exit rc=%d\n",rc);
-
- return !!rc;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */