aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c29
-rw-r--r--tools/libxc/xc_domain.c9
-rw-r--r--tools/libxc/xc_domain_restore.c50
-rw-r--r--tools/libxc/xc_domain_save.c40
-rw-r--r--tools/libxc/xenctrl.h2
-rw-r--r--tools/libxc/xg_private.h1
6 files changed, 59 insertions, 72 deletions
diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c
index 4de4a7fe1a..2ecb492b9a 100644
--- a/tools/libxc/ia64/xc_ia64_linux_save.c
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c
@@ -432,9 +432,9 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
int last_iter = 0;
/* Bitmap of pages to be sent. */
- unsigned long *to_send = NULL;
+ DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
/* Bitmap of pages not to be sent (because dirtied). */
- unsigned long *to_skip = NULL;
+ DECLARE_HYPERCALL_BUFFER(unsigned long, to_skip);
char *mem;
@@ -542,8 +542,8 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
last_iter = 0;
bitmap_size = ((p2m_size + BITS_PER_LONG-1) & ~(BITS_PER_LONG-1)) / 8;
- to_send = malloc(bitmap_size);
- to_skip = malloc(bitmap_size);
+ 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");
@@ -553,15 +553,6 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
/* Initially all the pages must be sent. */
memset(to_send, 0xff, bitmap_size);
- if (lock_pages(to_send, bitmap_size)) {
- ERROR("Unable to lock_pages to_send");
- goto out;
- }
- if (lock_pages(to_skip, bitmap_size)) {
- ERROR("Unable to lock_pages to_skip");
- goto out;
- }
-
/* 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");
@@ -621,7 +612,7 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
if (!last_iter) {
if (xc_shadow_control(xch, dom,
XEN_DOMCTL_SHADOW_OP_PEEK,
- to_skip, p2m_size,
+ HYPERCALL_BUFFER(to_skip), p2m_size,
NULL, 0, NULL) != p2m_size) {
ERROR("Error peeking shadow bitmap");
goto out;
@@ -713,7 +704,7 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
/* Pages to be sent are pages which were dirty. */
if (xc_shadow_control(xch, dom,
XEN_DOMCTL_SHADOW_OP_CLEAN,
- to_send, p2m_size,
+ HYPERCALL_BUFFER(to_send), p2m_size,
NULL, 0, NULL ) != p2m_size) {
ERROR("Error flushing shadow PT");
goto out;
@@ -779,7 +770,7 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
//print_stats(xch, dom, 0, &stats, 1);
if ( xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_CLEAN, to_send,
+ XEN_DOMCTL_SHADOW_OP_CLEAN, HYPERCALL_BUFFER(to_send),
p2m_size, NULL, 0, NULL) != p2m_size )
{
ERROR("Error flushing shadow PT");
@@ -799,10 +790,8 @@ xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
}
}
- unlock_pages(to_send, bitmap_size);
- free(to_send);
- unlock_pages(to_skip, bitmap_size);
- free(to_skip);
+ 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)
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index f097b57ccf..54ed939bbc 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -400,7 +400,7 @@ int xc_watchdog(xc_interface *xch,
int xc_shadow_control(xc_interface *xch,
uint32_t domid,
unsigned int sop,
- unsigned long *dirty_bitmap,
+ xc_hypercall_buffer_t *dirty_bitmap,
unsigned long pages,
unsigned long *mb,
uint32_t mode,
@@ -408,14 +408,17 @@ int xc_shadow_control(xc_interface *xch,
{
int rc;
DECLARE_DOMCTL;
+ DECLARE_HYPERCALL_BUFFER_ARGUMENT(dirty_bitmap);
+
domctl.cmd = XEN_DOMCTL_shadow_op;
domctl.domain = (domid_t)domid;
domctl.u.shadow_op.op = sop;
domctl.u.shadow_op.pages = pages;
domctl.u.shadow_op.mb = mb ? *mb : 0;
domctl.u.shadow_op.mode = mode;
- set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
- (uint8_t *)dirty_bitmap);
+ if (dirty_bitmap != NULL)
+ xc_set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
+ dirty_bitmap);
rc = do_domctl(xch, &domctl);
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 316f32dac5..047cd774a7 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -1063,7 +1063,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
shared_info_any_t *new_shared_info;
/* A copy of the CPU context of the guest. */
- vcpu_guest_context_any_t ctxt;
+ DECLARE_HYPERCALL_BUFFER(vcpu_guest_context_any_t, ctxt);
/* A table containing the type of each PFN (/not/ MFN!). */
unsigned long *pfn_type = NULL;
@@ -1113,6 +1113,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
if ( superpages )
return 1;
+ ctxt = xc_hypercall_buffer_alloc(xch, ctxt, sizeof(*ctxt));
+
+ if ( ctxt == NULL )
+ {
+ PERROR("Unable to allocate VCPU ctxt buffer");
+ return 1;
+ }
+
+
if ( (orig_io_fd_flags = fcntl(io_fd, F_GETFL, 0)) < 0 ) {
PERROR("unable to read IO FD flags");
goto out;
@@ -1539,26 +1548,20 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
}
}
- if ( lock_pages(xch, &ctxt, sizeof(ctxt)) )
- {
- PERROR("Unable to lock ctxt");
- return 1;
- }
-
vcpup = tailbuf.u.pv.vcpubuf;
for ( i = 0; i <= max_vcpu_id; i++ )
{
if ( !(vcpumap & (1ULL << i)) )
continue;
- memcpy(&ctxt, vcpup, ((dinfo->guest_width == 8) ? sizeof(ctxt.x64)
- : sizeof(ctxt.x32)));
- vcpup += (dinfo->guest_width == 8) ? sizeof(ctxt.x64) : sizeof(ctxt.x32);
+ memcpy(ctxt, vcpup, ((dinfo->guest_width == 8) ? sizeof(ctxt->x64)
+ : sizeof(ctxt->x32)));
+ vcpup += (dinfo->guest_width == 8) ? sizeof(ctxt->x64) : sizeof(ctxt->x32);
DPRINTF("read VCPU %d\n", i);
if ( !new_ctxt_format )
- SET_FIELD(&ctxt, flags, GET_FIELD(&ctxt, flags) | VGCF_online);
+ SET_FIELD(ctxt, flags, GET_FIELD(ctxt, flags) | VGCF_online);
if ( i == 0 )
{
@@ -1566,7 +1569,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
* Uncanonicalise the suspend-record frame number and poke
* resume record.
*/
- pfn = GET_FIELD(&ctxt, user_regs.edx);
+ pfn = GET_FIELD(ctxt, user_regs.edx);
if ( (pfn >= dinfo->p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
@@ -1574,7 +1577,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
goto out;
}
mfn = ctx->p2m[pfn];
- SET_FIELD(&ctxt, user_regs.edx, mfn);
+ SET_FIELD(ctxt, user_regs.edx, mfn);
start_info = xc_map_foreign_range(
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
@@ -1589,15 +1592,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
munmap(start_info, PAGE_SIZE);
}
/* Uncanonicalise each GDT frame number. */
- if ( GET_FIELD(&ctxt, gdt_ents) > 8192 )
+ if ( GET_FIELD(ctxt, gdt_ents) > 8192 )
{
ERROR("GDT entry count out of range");
goto out;
}
- for ( j = 0; (512*j) < GET_FIELD(&ctxt, gdt_ents); j++ )
+ for ( j = 0; (512*j) < GET_FIELD(ctxt, gdt_ents); j++ )
{
- pfn = GET_FIELD(&ctxt, gdt_frames[j]);
+ pfn = GET_FIELD(ctxt, gdt_frames[j]);
if ( (pfn >= dinfo->p2m_size) ||
(pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
{
@@ -1605,10 +1608,10 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
j, (unsigned long)pfn);
goto out;
}
- SET_FIELD(&ctxt, gdt_frames[j], ctx->p2m[pfn]);
+ SET_FIELD(ctxt, gdt_frames[j], ctx->p2m[pfn]);
}
/* Uncanonicalise the page table base pointer. */
- pfn = UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3]));
+ pfn = UNFOLD_CR3(GET_FIELD(ctxt, ctrlreg[3]));
if ( pfn >= dinfo->p2m_size )
{
@@ -1625,12 +1628,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
(unsigned long)ctx->pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
- SET_FIELD(&ctxt, ctrlreg[3], FOLD_CR3(ctx->p2m[pfn]));
+ SET_FIELD(ctxt, ctrlreg[3], FOLD_CR3(ctx->p2m[pfn]));
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
- if ( (ctx->pt_levels == 4) && (ctxt.x64.ctrlreg[1] & 1) )
+ if ( (ctx->pt_levels == 4) && (ctxt->x64.ctrlreg[1] & 1) )
{
- pfn = UNFOLD_CR3(ctxt.x64.ctrlreg[1] & ~1);
+ pfn = UNFOLD_CR3(ctxt->x64.ctrlreg[1] & ~1);
if ( pfn >= dinfo->p2m_size )
{
ERROR("User PT base is bad: pfn=%lu p2m_size=%lu",
@@ -1645,12 +1648,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
(unsigned long)ctx->pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
- ctxt.x64.ctrlreg[1] = FOLD_CR3(ctx->p2m[pfn]);
+ ctxt->x64.ctrlreg[1] = FOLD_CR3(ctx->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.c);
+ xc_set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
frc = xc_domctl(xch, &domctl);
if ( frc != 0 )
{
@@ -1791,6 +1794,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
out:
if ( (rc != 0) && (dom != 0) )
xc_domain_destroy(xch, dom);
+ xc_hypercall_buffer_free(xch, ctxt);
free(mmu);
free(ctx->p2m);
free(pfn_type);
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index eee8fb47d2..8dc08e0003 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -411,7 +411,7 @@ static int print_stats(xc_interface *xch, uint32_t domid, int pages_sent,
static int analysis_phase(xc_interface *xch, uint32_t domid, struct save_ctx *ctx,
- unsigned long *arr, int runs)
+ xc_hypercall_buffer_t *arr, int runs)
{
long long start, now;
xc_shadow_op_stats_t stats;
@@ -909,7 +909,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
- that should be sent this iteration (unless later marked as skip);
- to skip this iteration because already dirty;
- to fixup by sending at the end if not already resent; */
- unsigned long *to_send = NULL, *to_skip = NULL, *to_fix = NULL;
+ DECLARE_HYPERCALL_BUFFER(unsigned long, to_skip);
+ DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
+ unsigned long *to_fix = NULL;
xc_shadow_op_stats_t stats;
@@ -1038,9 +1040,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
sent_last_iter = dinfo->p2m_size;
/* Setup to_send / to_fix and to_skip bitmaps */
- to_send = xc_memalign(PAGE_SIZE, ROUNDUP(BITMAP_SIZE, PAGE_SHIFT));
+ to_send = xc_hypercall_buffer_alloc_pages(xch, to_send, NRPAGES(BITMAP_SIZE));
+ to_skip = xc_hypercall_buffer_alloc_pages(xch, to_skip, NRPAGES(BITMAP_SIZE));
to_fix = calloc(1, BITMAP_SIZE);
- to_skip = xc_memalign(PAGE_SIZE, ROUNDUP(BITMAP_SIZE, PAGE_SHIFT));
if ( !to_send || !to_fix || !to_skip )
{
@@ -1050,20 +1052,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
memset(to_send, 0xff, BITMAP_SIZE);
- if ( lock_pages(xch, to_send, BITMAP_SIZE) )
- {
- PERROR("Unable to lock to_send");
- return 1;
- }
-
- /* (to fix is local only) */
- if ( lock_pages(xch, to_skip, BITMAP_SIZE) )
- {
- PERROR("Unable to lock to_skip");
- return 1;
- }
-
- if ( hvm )
+ if ( hvm )
{
/* Need another buffer for HVM context */
hvm_buf_size = xc_domain_hvm_getcontext(xch, dom, 0, 0);
@@ -1080,7 +1069,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
}
}
- analysis_phase(xch, dom, ctx, to_skip, 0);
+ analysis_phase(xch, dom, ctx, HYPERCALL_BUFFER(to_skip), 0);
pfn_type = xc_memalign(PAGE_SIZE, ROUNDUP(
MAX_BATCH_SIZE * sizeof(*pfn_type), PAGE_SHIFT));
@@ -1192,7 +1181,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
/* Slightly wasteful to peek the whole array evey time,
but this is fast enough for the moment. */
frc = xc_shadow_control(
- xch, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip,
+ xch, dom, XEN_DOMCTL_SHADOW_OP_PEEK, HYPERCALL_BUFFER(to_skip),
dinfo->p2m_size, NULL, 0, NULL);
if ( frc != dinfo->p2m_size )
{
@@ -1532,8 +1521,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
}
- if ( xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_CLEAN, to_send,
+ if ( xc_shadow_control(xch, dom,
+ XEN_DOMCTL_SHADOW_OP_CLEAN, HYPERCALL_BUFFER(to_send),
dinfo->p2m_size, NULL, 0, &stats) != dinfo->p2m_size )
{
PERROR("Error flushing shadow PT");
@@ -1861,7 +1850,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
print_stats(xch, dom, 0, &stats, 1);
if ( xc_shadow_control(xch, dom,
- XEN_DOMCTL_SHADOW_OP_CLEAN, to_send,
+ XEN_DOMCTL_SHADOW_OP_CLEAN, HYPERCALL_BUFFER(to_send),
dinfo->p2m_size, NULL, 0, &stats) != dinfo->p2m_size )
{
PERROR("Error flushing shadow PT");
@@ -1892,12 +1881,13 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
if ( ctx->live_m2p )
munmap(ctx->live_m2p, M2P_SIZE(ctx->max_mfn));
+ xc_hypercall_buffer_free_pages(xch, to_send, NRPAGES(BITMAP_SIZE));
+ xc_hypercall_buffer_free_pages(xch, to_skip, NRPAGES(BITMAP_SIZE));
+
free(pfn_type);
free(pfn_batch);
free(pfn_err);
- free(to_send);
free(to_fix);
- free(to_skip);
DPRINTF("Save exit rc=%d\n",rc);
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index f69826302b..35e1ac1303 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -601,7 +601,7 @@ typedef xen_domctl_shadow_op_stats_t xc_shadow_op_stats_t;
int xc_shadow_control(xc_interface *xch,
uint32_t domid,
unsigned int sop,
- unsigned long *dirty_bitmap,
+ xc_hypercall_buffer_t *dirty_bitmap,
unsigned long pages,
unsigned long *mb,
uint32_t mode,
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index 6f3e93ad03..a29fa26665 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -157,6 +157,7 @@ typedef l4_pgentry_64_t l4_pgentry_t;
#define PAGE_MASK_IA64 (~(PAGE_SIZE_IA64-1))
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+#define NRPAGES(x) (ROUNDUP(x, PAGE_SHIFT) >> PAGE_SHIFT)
/* XXX SMH: following skanky macros rely on variable p2m_size being set */