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

[Xen-devel] [RFC v3 6/6] xen/arm: Implement toolstack for xl restore/save/migration



This patch implements xl save/restore operation in xc_arm_migrate.c
and make it compilable with existing design. The operation is also
used by migration.

The overall process of save/restore is the following: 1) save guest
parameters; 2) save memory; 3) save HVM states.

Signed-off-by: Alexey Sokolov <sokolov.a@xxxxxxxxxxx>
Signed-off-by: Wei Huang <w1.huang@xxxxxxxxxxx>
---
 config/arm32.mk              |    1 +
 config/arm64.mk              |    1 +
 tools/libxc/Makefile         |    5 +
 tools/libxc/xc_arm_migrate.c |  653 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxc/xc_dom_arm.c     |    4 +-
 tools/libxc/xc_resume.c      |   20 +-
 tools/libxl/libxl.h          |    3 -
 tools/misc/Makefile          |    4 +-
 8 files changed, 677 insertions(+), 14 deletions(-)
 create mode 100644 tools/libxc/xc_arm_migrate.c

diff --git a/config/arm32.mk b/config/arm32.mk
index aa79d22..01374c9 100644
--- a/config/arm32.mk
+++ b/config/arm32.mk
@@ -1,6 +1,7 @@
 CONFIG_ARM := y
 CONFIG_ARM_32 := y
 CONFIG_ARM_$(XEN_OS) := y
+CONFIG_MIGRATE := y
 
 CONFIG_XEN_INSTALL_SUFFIX :=
 
diff --git a/config/arm64.mk b/config/arm64.mk
index 15b57a4..7ac3b65 100644
--- a/config/arm64.mk
+++ b/config/arm64.mk
@@ -1,6 +1,7 @@
 CONFIG_ARM := y
 CONFIG_ARM_64 := y
 CONFIG_ARM_$(XEN_OS) := y
+CONFIG_MIGRATE := y
 
 CONFIG_XEN_INSTALL_SUFFIX :=
 
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index a74b19e..9aaa6ff 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -43,8 +43,13 @@ CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
 GUEST_SRCS-y :=
 GUEST_SRCS-y += xg_private.c xc_suspend.c
 ifeq ($(CONFIG_MIGRATE),y)
+ifeq ($(CONFIG_X86),y)
 GUEST_SRCS-y += xc_domain_restore.c xc_domain_save.c
 GUEST_SRCS-y += xc_offline_page.c xc_compression.c
+endif
+ifeq ($(CONFIG_ARM),y)
+GUEST_SRCS-y += xc_arm_migrate.c
+endif
 else
 GUEST_SRCS-y += xc_nomigrate.c
 endif
diff --git a/tools/libxc/xc_arm_migrate.c b/tools/libxc/xc_arm_migrate.c
new file mode 100644
index 0000000..776e373
--- /dev/null
+++ b/tools/libxc/xc_arm_migrate.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <inttypes.h>
+#include <errno.h>
+#include <xenctrl.h>
+#include <xenguest.h>
+
+#include <unistd.h>
+#include <xc_private.h>
+#include <xc_dom.h>
+#include "xc_bitops.h"
+#include "xg_private.h"
+
+#define DEF_MAX_ITERS          29 /* limit us to 30 times round loop   */
+#define DEF_MAX_FACTOR         3  /* never send more than 3x p2m_size  */
+#define DEF_MIN_DIRTY_PER_ITER 50 /* dirty page count to define last iter */
+#define DEF_PROGRESS_RATE      50 /* progress bar update rate */
+
+/* Guest params to save */
+typedef struct guest_params
+{
+    unsigned long console_pfn;
+    unsigned long store_pfn;
+    uint32_t flags;
+    xen_pfn_t start_gpfn;
+    xen_pfn_t max_gpfn;
+    uint32_t max_vcpu_id;
+} guest_params_t;
+
+/***********************************/
+/*           Misc Support          */
+/***********************************/
+static int suspend_and_state(int (*suspend)(void*), void *data,
+                             xc_interface *xch, int dom)
+{
+    xc_dominfo_t info;
+
+    if ( !(*suspend)(data) )
+    {
+        PERROR("Suspend request failed");
+        return -1;
+    }
+
+    if ( (xc_domain_getinfo(xch, dom, 1, &info) != 1) || info.domid != dom ||
+         !info.shutdown || (info.shutdown_reason != SHUTDOWN_suspend) )
+    {
+        PERROR("Domain is not in suspended state after suspend attempt");
+        return -1;
+    }
+
+    return 0;
+}
+
+/***********************************/
+/*           Guest Memory          */
+/***********************************/
+static int save_guest_memory(xc_interface *xch, int io_fd, uint32_t dom,
+                             struct save_callbacks *callbacks,
+                             uint32_t max_iters, uint32_t max_factor,
+                             guest_params_t *params)
+{
+    int live =  !!(params->flags & XCFLAGS_LIVE);
+    int debug =  !!(params->flags & XCFLAGS_DEBUG);
+    xen_pfn_t i;
+    char reportbuf[80];
+    int iter = 0;
+    int last_iter = !live;
+    int total_dirty = 0;    /* total number of dirty pages */
+    int prev_iter_dirty = 0;
+    int count = 0;
+    char *page = NULL;
+    xen_pfn_t *busy_pages = 0;
+    int busy_pages_count = 0;
+    int busy_pages_max = 256;
+    DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
+    xen_pfn_t start = params->start_gpfn;
+    const xen_pfn_t end = params->max_gpfn;
+    const xen_pfn_t mem_size = end - start;    
+    int rc = -1, frc;
+
+    if ( debug )
+    {
+        IPRINTF("Saving memory: start=0x%llx end=0x%llx!\n",
+                (unsigned long long)start, (unsigned long long)end);
+    }
+
+    /* Note: to_send will be deallocated at the end of this function. */
+    to_send = xc_hypercall_buffer_alloc_pages(xch, to_send,
+                                              NRPAGES(bitmap_size(mem_size)));
+    if ( !to_send )
+    {
+        PERROR("Can't allocate to_send array!\n");
+        goto out;
+    }
+    /* send all pages on first iter */
+    memset(to_send, 0xff, bitmap_size(mem_size));
+
+    if ( live )
+    {
+        if ( xc_shadow_control(xch, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
+                               NULL, 0, NULL, 0, NULL) < 0 )
+        {
+            PERROR("Can't enable log-dirty mode!\n");
+            goto out;
+        }
+
+        max_iters  = max_iters  ? : DEF_MAX_ITERS;
+        max_factor = max_factor ? : DEF_MAX_FACTOR;
+    }
+
+    for ( ; ; )
+    {
+        int current_iter_dirty = 0; /* num of dirty pages in current iter */
+
+        iter++;
+        snprintf(reportbuf, sizeof(reportbuf),
+                 "Saving memory: iter %d, last sent %u", iter, 
+                 prev_iter_dirty);
+
+        xc_report_progress_start(xch, reportbuf, mem_size);
+
+        if ( (iter > 1 && prev_iter_dirty < DEF_MIN_DIRTY_PER_ITER) ||
+             (iter == max_iters) ||
+             (total_dirty >= mem_size*max_factor) )
+        {
+            last_iter = 1;
+        }
+
+        if ( last_iter )
+        {
+            if ( suspend_and_state(callbacks->suspend, callbacks->data, xch, 
+                                   dom) )
+            {
+                PERROR("Domain appears not to have suspended");
+                goto out;
+            }
+        }
+
+        if ( live && iter > 1 )
+        {
+            frc = xc_shadow_control(xch, dom, XEN_DOMCTL_SHADOW_OP_CLEAN,
+                                    HYPERCALL_BUFFER(to_send), mem_size,
+                                    NULL, 0, NULL);
+            if ( frc != mem_size )
+            {
+                PERROR("Can't peek bitmap of guest VM's dirty pages");
+                goto out;
+            }
+        }
+
+        /* busy_pages allocation */
+        busy_pages = malloc(sizeof(xen_pfn_t) * busy_pages_max);
+
+        for ( i = start; i < end; ++i )
+        {
+            if ( test_bit(i - start, to_send) )
+            {
+                page = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ, i);
+                if ( !page )
+                {
+                    /* This page is mapped elsewhere, should be resent later */
+                    busy_pages[busy_pages_count] = i;
+                    busy_pages_count++;
+                    if ( busy_pages_count >= busy_pages_max )
+                    {
+                        busy_pages_max += 256;
+                        busy_pages = realloc(busy_pages, sizeof(xen_pfn_t) *
+                                             busy_pages_max);
+                    }
+                    continue;
+                }
+
+                if ( write_exact(io_fd, &i, sizeof(i)) ||
+                     write_exact(io_fd, page, PAGE_SIZE) )
+                {
+                    PERROR("Write Error: guest memory gpfn and content");
+                    free(busy_pages); /* must do here */
+                    goto out;
+                }
+
+                if ( (i % DEF_PROGRESS_RATE) == 0 )
+                    xc_report_progress_step(xch, i - start, mem_size);
+
+                count++;
+                munmap(page, PAGE_SIZE);
+                current_iter_dirty++;
+            }
+        }
+
+        while ( busy_pages_count )
+        {
+            /* Send busy pages */
+            busy_pages_count--;
+            i = busy_pages[busy_pages_count];
+            if ( test_bit(i - start, to_send) )
+            {
+                page = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ, i);
+                if ( !page )
+                {
+                    IPRINTF("WARNING: 2nd attempt to save page failed at "
+                            "pfn=0x%llx", (unsigned long long)i);
+                    continue;
+                }
+
+                if ( write_exact(io_fd, &i, sizeof(i)) ||
+                     write_exact(io_fd, page, PAGE_SIZE) )
+                {
+                    PERROR("Write Error: guest memory gpfn and content");
+                    free(busy_pages); /* must do here */
+                    goto out;
+                }
+
+                count++;
+                munmap(page, PAGE_SIZE);
+                current_iter_dirty++;
+            }
+        }
+        free(busy_pages);
+
+        xc_report_progress_step(xch, mem_size, mem_size);
+
+        prev_iter_dirty = current_iter_dirty;
+        total_dirty += current_iter_dirty;
+
+        if ( last_iter )
+        {
+            if ( live )
+            {
+                if ( xc_shadow_control(xch, dom, XEN_DOMCTL_SHADOW_OP_OFF,
+                                       NULL, 0, NULL, 0, NULL) < 0 )
+                    PERROR("Can't disable log-dirty mode");
+            }
+            break;
+        }
+    }
+
+    i = (xen_pfn_t) -1; /* end page marker */
+    if ( write_exact(io_fd, &i, sizeof(i)) )
+    {
+        PERROR("Write Error: end page mark");
+        goto out;
+    }
+    /* flush last write and check for errno (must do, see fsync()). */
+    if ( fsync(io_fd) && errno != EINVAL )
+    {
+        PERROR("Write Error: flushing stream");
+        goto out;
+    }
+
+    rc = 0;
+ out:
+    /* clean up */
+    if ( page )
+        munmap(page, PAGE_SIZE);
+    if ( to_send )
+        xc_hypercall_buffer_free_pages(xch, to_send, 
+                                       NRPAGES(bitmap_size(mem_size)));
+    return rc;
+}
+
+static int restore_guest_memory(xc_interface *xch, int io_fd, uint32_t dom,
+                                guest_params_t *params)
+{
+    xen_pfn_t gpfn;
+    xen_pfn_t start = params->start_gpfn;
+    xen_pfn_t end = params->max_gpfn;
+    int count = 0;
+    char *page = NULL;
+    int rc = -1;
+
+    /* TODO: batch operation */
+    for ( gpfn = start; gpfn < end; ++gpfn )
+    {
+        if ( xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &gpfn) )
+        {
+            PERROR("Can't populate guest physical memory");
+            goto out;
+        }
+    }
+
+    while ( 1 )
+    {
+        if ( read_exact(io_fd, &gpfn, sizeof(gpfn)) )
+        {
+            PERROR("Read Error: guest memory gpfn (count=%d)", count);
+            goto out;
+        }
+
+        /* end of guest pages */
+        if ( gpfn == (xen_pfn_t) -1 ) 
+            break;
+
+        if ( gpfn < start || gpfn >= end )
+        {
+            PERROR("gpfn 0x%llx doesn't belong to guest RAM addr space "
+                   "[0x%llx, 0x%llx]", gpfn, start, end);
+            goto out;
+        }
+
+        if ( !(page = xc_map_foreign_range(xch, dom, PAGE_SIZE, 
+                                           PROT_READ | PROT_WRITE, gpfn)) )
+        {
+            PERROR("Can't map guest page to dom0 (gpfn=0x%llx)", gpfn);
+            goto out;
+        }
+
+        if ( read_exact(io_fd, page, PAGE_SIZE) )
+        {
+            PERROR("Read Error: guest memory content (gpfn=0x%llx)", gpfn);
+            goto out;
+        }
+
+        munmap(page, PAGE_SIZE);
+        count++;
+    }
+
+    rc = 0;
+ out:
+    if ( page )
+        munmap(page, PAGE_SIZE);
+
+    return rc;
+}
+
+/***********************************/
+/*            HVM Context          */
+/***********************************/
+static int save_guest_hvm_ctxt(xc_interface *xch, int io_fd, uint32_t dom)
+{
+    uint32_t ctxt_size = 0;
+    uint8_t *hvm_ctxt = NULL;
+    uint32_t rec_size;
+    int rc = -1;
+
+    /* Figure out HVM context size and allocate a local buffer */
+    if ( (ctxt_size = xc_domain_hvm_getcontext(xch, dom, 0, 0)) == -1 )
+    {
+        PERROR("Can't get HVM context size");
+        goto out;
+    }
+
+    if ( (hvm_ctxt = malloc(ctxt_size)) == NULL )
+    {
+        PERROR("Can't allocate memory for HVM context");
+        goto out;
+    }
+
+    /* Retrieve HVM context from Xen and save it */
+    if ( (rec_size = xc_domain_hvm_getcontext(xch, dom, hvm_ctxt, 
+                                              ctxt_size)) == -1 )
+    {
+        PERROR("Can't receive HVM context");
+        goto out;
+    }
+
+    if ( write_exact(io_fd, &rec_size, sizeof(uint32_t)) || 
+         write_exact(io_fd, hvm_ctxt, rec_size) )
+    {
+        PERROR("Write Error: HVM context");
+        goto out;
+    }
+
+    rc = 0;
+out:
+    free (hvm_ctxt);
+    return rc;
+}
+
+static int restore_guest_hvm_ctxt(xc_interface *xch, int io_fd, uint32_t dom)
+{
+    uint32_t rec_size;
+    uint32_t ctxt_size = 0;
+    uint8_t *hvm_ctxt = NULL;
+    int frc = 0;
+    int rc = -1;
+
+    if ( read_exact(io_fd, &rec_size, sizeof(uint32_t)) )
+    {
+        PERROR("Read Error: HVM context size");
+        goto out;
+    }
+
+    if ( !rec_size )
+    {
+        PERROR("No HVM context");
+        goto out;
+    }
+
+    if ( (ctxt_size = xc_domain_hvm_getcontext(xch, dom, 0, 0)) != rec_size )
+    {
+        PERROR("Stored HVM context size isn't matched with current system");
+        goto out;
+    }
+
+    if ( !(hvm_ctxt = malloc(ctxt_size)) )
+    {
+        PERROR("Can't allocate memory");
+        goto out;
+    }
+
+    if ( read_exact(io_fd, hvm_ctxt, ctxt_size) )
+    {
+        PERROR("Read Error: HVM context");
+        goto out;
+    }
+
+    if ( (frc = xc_domain_hvm_setcontext(xch, dom, hvm_ctxt, ctxt_size)) )
+    {
+        PERROR("Can't set HVM context");
+        goto out;
+    }
+
+    rc = 0;
+out:
+    free (hvm_ctxt);
+    return rc;
+}
+
+/***********************************/
+/*         Guest Parameters        */
+/***********************************/
+static int save_guest_params(xc_interface *xch, int io_fd, uint32_t dom, 
+                             uint32_t flags, guest_params_t *params)
+{
+    xc_dominfo_t dom_info;
+
+    /* retrieve domain info */
+    if ( (xc_domain_getinfo(xch, dom, 1, &dom_info ) != 1) || 
+         dom_info.domid != dom)
+    {
+        PERROR("Can't get domain info for dom %d", dom);
+        return -1;
+    }
+
+    /* start and max of gpfn */
+    params->start_gpfn = (GUEST_RAM_BASE >> PAGE_SHIFT);
+    params->max_gpfn = (GUEST_RAM_BASE >> PAGE_SHIFT) + dom_info.nr_pages;
+
+    /* console pfn */
+    if ( xc_get_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
+                          &params->console_pfn) )
+    {
+        PERROR("Can't get console gpfn");
+        return -1;
+    }
+
+    if ( xc_get_hvm_param(xch, dom, HVM_PARAM_STORE_PFN, &params->store_pfn) )
+    {
+        PERROR("Can't get store gpfn");
+        return -1;
+    }
+
+    params->max_vcpu_id = dom_info.max_vcpu_id;
+    params->flags = flags;
+
+    if ( write_exact(io_fd, params, sizeof(*params)) )
+    {
+        PERROR("Write Error: guest params");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int restore_guest_params(xc_interface *xch, int io_fd, uint32_t dom,
+                                guest_params_t *params)
+{
+    xen_pfn_t nr_pfns;
+    unsigned int maxmemkb;
+
+    if ( read_exact(io_fd, params, sizeof(*params)) )
+    {
+        PERROR("Read Error: guest params");
+        return -1;
+    }
+
+    nr_pfns = params->max_gpfn - params->start_gpfn;
+    maxmemkb = (unsigned int) nr_pfns << (PAGE_SHIFT - 10);
+
+    if ( xc_domain_setmaxmem(xch, dom, maxmemkb) )
+    {
+        PERROR("Can't set memory map");
+        return -1;
+    }
+
+    if ( xc_domain_max_vcpus(xch, dom, params->max_vcpu_id + 1) )
+    {
+        PERROR("Can't set max vcpu number for domain");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* Configure guest parameters after restore */
+static int set_guest_params(xc_interface *xch, int io_fd, uint32_t dom,
+                            guest_params_t *params, 
+                            unsigned int console_evtchn, domid_t console_domid,
+                            unsigned int store_evtchn, domid_t store_domid)
+{
+    int rc = 0;
+
+    if ( (rc = xc_clear_domain_page(xch, dom, params->console_pfn)) )
+    {
+        PERROR("Can't clear console page");
+        return rc;
+    }
+
+    if ( (rc = xc_clear_domain_page(xch, dom, params->store_pfn)) )
+    {
+        PERROR("Can't clear xenstore page");
+        return rc;
+    }
+
+    if ( (rc = xc_dom_gnttab_hvm_seed(xch, dom, params->console_pfn,
+                                      params->store_pfn, console_domid,
+                                      store_domid)) )
+    {
+        PERROR("Can't grant console and xenstore pages");
+        return rc;
+    }
+
+    if ( (rc = xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
+                                params->console_pfn)) )
+    {
+        PERROR("Can't set console gpfn");
+        return rc;
+    }
+
+    if ( (rc = xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
+                                params->store_pfn)) )
+    {
+        PERROR("Can't set xenstore gpfn");
+        return rc;
+    }
+
+    if ( (rc = xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_EVTCHN,
+                                console_evtchn)) )
+    {
+        PERROR("Can't set console event channel");
+        return rc;
+    }
+
+    if ( (rc = xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_EVTCHN,
+                                store_evtchn)) )
+    {
+        PERROR("Can't set xenstore event channel");
+        return rc;
+    }
+
+    return 0;
+}
+
+/***********************************/
+/*          Main Entries           */
+/***********************************/
+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)
+{
+    guest_params_t params;
+
+    if ( save_guest_params(xch, io_fd, dom, flags, &params) )
+    {
+        PERROR("Can't save guest params");
+        return -1;
+    }
+
+    if ( save_guest_memory(xch, io_fd, dom, callbacks, max_iters, max_factor, 
+                           &params) )
+    {
+        PERROR("Can't save guest memory");
+        return -1;
+    }
+
+    if ( save_guest_hvm_ctxt(xch, io_fd, dom) )
+    {
+        PERROR("Cant' save guest HVM context");
+        return -1;
+    }
+
+    return 0;
+}
+
+int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
+                      unsigned int store_evtchn, unsigned long *store_gpfn,
+                      domid_t store_domid, unsigned int console_evtchn,
+                      unsigned long *console_gpfn, domid_t console_domid,
+                      unsigned int hvm, unsigned int pae, int superpages,
+                      int no_incr_generationid, int checkpointed_stream,
+                      unsigned long *vm_generationid_addr,
+                      struct restore_callbacks *callbacks)
+{
+    guest_params_t params;
+
+    if ( restore_guest_params(xch, io_fd, dom, &params) )
+    {
+        PERROR("Can't restore guest params");
+        return -1;
+    }
+
+    if ( restore_guest_memory(xch, io_fd, dom, &params) )
+    {
+        PERROR("Can't restore memory");
+        return -1;
+    }
+
+    if ( set_guest_params(xch, io_fd, dom, &params, console_evtchn, 
+                          console_domid, store_evtchn, store_domid) )
+    {
+        PERROR("Can't setup guest params");
+        return -1;
+    }
+
+    /* setup console and store PFNs to caller */
+    *console_gpfn = params.console_pfn;
+    *store_gpfn = params.store_pfn;
+
+    /* restore HVM context of guest VM */
+    if ( restore_guest_hvm_ctxt(xch, io_fd, dom) )
+    {
+        PERROR("Can't restore HVM context");
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
index 60ac51a..d9e50d2 100644
--- a/tools/libxc/xc_dom_arm.c
+++ b/tools/libxc/xc_dom_arm.c
@@ -348,7 +348,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
         modbase += dtb_size;
     }
 
-    return 0;
+    return xc_domain_setmaxmem(dom->xch, dom->guest_domid,
+                               (dom->total_pages + NR_MAGIC_PAGES)
+                                << (PAGE_SHIFT - 10));
 }
 
 int arch_setup_bootearly(struct xc_dom_image *dom)
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index 18b4818..6d05d4e 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -18,11 +18,15 @@
 #include "xg_private.h"
 #include "xg_save_restore.h"
 
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \
+    defined(__aarch64__)
 
+/* Only required for x86 */
+#if defined(__i386__) || defined(__x86_64__)
 #include <xen/foreign/x86_32.h>
 #include <xen/foreign/x86_64.h>
 #include <xen/hvm/params.h>
+#endif
 
 static int modify_returncode(xc_interface *xch, uint32_t domid)
 {
@@ -33,7 +37,7 @@ static int modify_returncode(xc_interface *xch, uint32_t 
domid)
     struct domain_info_context *dinfo = &_dinfo;
     int rc;
 
-    if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
+    if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 || info.domid != domid )
     {
         PERROR("Could not get domain info");
         return -1;
@@ -65,23 +69,23 @@ static int modify_returncode(xc_interface *xch, uint32_t 
domid)
     if ( (rc = xc_vcpu_getcontext(xch, domid, 0, &ctxt)) != 0 )
         return rc;
 
+#if defined(__i386__) || defined(__x86_64__)
     SET_FIELD(&ctxt, user_regs.eax, 1);
+#elif defined(__arm__) || defined(__aarch64__)
+    ctxt.c.user_regs.r0_usr = 1;
+#endif
 
     if ( (rc = xc_vcpu_setcontext(xch, domid, 0, &ctxt)) != 0 )
         return rc;
 
     return 0;
 }
-
-#else
-
+#else /* any architecture other than x86 or ARM */
 static int modify_returncode(xc_interface *xch, uint32_t domid)
 {
     return 0;
-
 }
-
-#endif
+#endif 
 
 static int xc_domain_resume_cooperative(xc_interface *xch, uint32_t domid)
 {
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 84f9c0e..ce22aa0 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -448,9 +448,6 @@
  *  - libxl_domain_resume
  *  - libxl_domain_remus_start
  */
-#if defined(__arm__) || defined(__aarch64__)
-#define LIBXL_HAVE_NO_SUSPEND_RESUME 1
-#endif
 
 /*
  * LIBXL_HAVE_DEVICE_PCI_SEIZE
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index 69b1817..f4ea7ab 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -11,7 +11,7 @@ HDRS     = $(wildcard *.h)
 
 TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat 
xenlockprof xenwatchdogd xencov
 TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd 
xen-mfndump
-TARGETS-$(CONFIG_MIGRATE) += xen-hptool
+TARGETS-$(CONFIG_X86) += xen-hptool
 TARGETS := $(TARGETS-y)
 
 SUBDIRS := $(SUBDIRS-y)
@@ -23,7 +23,7 @@ INSTALL_BIN := $(INSTALL_BIN-y)
 INSTALL_SBIN-y := xen-bugtool xen-python-path xenperf xenpm 
xen-tmem-list-parse gtraceview \
        gtracestat xenlockprof xenwatchdogd xen-ringwatch xencov
 INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash xen-lowmemd xen-mfndump
-INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
+INSTALL_SBIN-$(CONFIG_X86) += xen-hptool
 INSTALL_SBIN := $(INSTALL_SBIN-y)
 
 INSTALL_PRIVBIN-y := xenpvnetboot
-- 
1.7.9.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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