# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1287756891 -3600
# Node ID 5795b64811bada7ad161982b4f47cc4c88a41a05
# Parent 60a3dfbe7e59b6af8776f3c75f1997dc1655ecb2
libxc: convert shadow domctl interfaces and save/restore over to hypercall
buffers
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Signed-off-by: Ian Jackson <ian.jackson.citrix.com>
---
tools/libxc/ia64/xc_ia64_linux_save.c | 29 +++++-------------
tools/libxc/xc_domain.c | 9 +++--
tools/libxc/xc_domain_restore.c | 54 ++++++++++++++++++----------------
tools/libxc/xc_domain_save.c | 40 +++++++++----------------
tools/libxc/xenctrl.h | 2 -
tools/libxc/xg_private.h | 1
6 files changed, 61 insertions(+), 74 deletions(-)
diff -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/ia64/xc_ia64_linux_save.c
--- a/tools/libxc/ia64/xc_ia64_linux_save.c Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c Fri Oct 22 15:14:51 2010 +0100
@@ -432,9 +432,9 @@ xc_domain_save(xc_interface *xch, int io
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
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");
@@ -552,15 +552,6 @@ xc_domain_save(xc_interface *xch, int io
/* 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)) {
@@ -621,7 +612,7 @@ xc_domain_save(xc_interface *xch, int io
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
/* 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
//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
}
}
- 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 -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/xc_domain.c Fri Oct 22 15:14:51 2010 +0100
@@ -400,7 +400,7 @@ int xc_shadow_control(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 -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/xc_domain_restore.c Fri Oct 22 15:14:51 2010 +0100
@@ -1063,7 +1063,7 @@ int xc_domain_restore(xc_interface *xch,
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;
@@ -1112,6 +1112,15 @@ int xc_domain_restore(xc_interface *xch,
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");
@@ -1539,26 +1548,20 @@ int xc_domain_restore(xc_interface *xch,
}
}
- 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,
* 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,
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,
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++ )
- {
- pfn = GET_FIELD(&ctxt, gdt_frames[j]);
+ for ( j = 0; (512*j) < GET_FIELD(ctxt, gdt_ents); 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,
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,
(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) )
- {
- pfn = UNFOLD_CR3(ctxt.x64.ctrlreg[1] & ~1);
+ if ( (ctx->pt_levels == 4) && (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,
(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,
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 -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/xc_domain_save.c Fri Oct 22 15:14:51 2010 +0100
@@ -411,7 +411,7 @@ static int print_stats(xc_interface *xch
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, in
- 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, in
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, in
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, in
}
}
- 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, in
/* 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, in
}
- 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, in
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, in
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 -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/xenctrl.h Fri Oct 22 15:14:51 2010 +0100
@@ -601,7 +601,7 @@ int xc_shadow_control(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,
diff -r 60a3dfbe7e59 -r 5795b64811ba tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h Fri Oct 22 15:14:51 2010 +0100
+++ b/tools/libxc/xg_private.h Fri Oct 22 15:14:51 2010 +0100
@@ -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 */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|