aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-01-13 08:12:56 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-01-13 08:12:56 +0000
commit9fececad98aa1259a9896edf7e7931822e3eef87 (patch)
tree5f7b5081edfee2647be16264a12e48c10465fc82 /tools
parentd092fb82a229773dad917f5a6eaa3cced9054d19 (diff)
downloadxen-9fececad98aa1259a9896edf7e7931822e3eef87.tar.gz
xen-9fececad98aa1259a9896edf7e7931822e3eef87.tar.bz2
xen-9fececad98aa1259a9896edf7e7931822e3eef87.zip
libxc: use new (replacement) mmap-batch ioctl
Replace all calls to xc_map_foreign_batch() where the caller doesn't look at the passed in array to check for errors by calls to xc_map_foreign_pages(). Replace all remaining calls by such to the newly introduced xc_map_foreign_bulk(). As a sideband modification (needed while writing the patch to ensure they're unused) eliminate unused parameters to uncanonicalize_pagetable() and xc_map_foreign_batch_single(). Also unmap live_p2m_frame_list earlier in map_and_save_p2m_table(), reducing the peak amount of virtual address space required. All supported OSes other than Linux continue to use the old ioctl for the time being. Also change libxc's MAJOR to 4.0 to reflect the API change. Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/include/xen-sys/Linux/privcmd.h10
-rw-r--r--tools/libxc/Makefile2
-rw-r--r--tools/libxc/xc_domain_restore.c16
-rw-r--r--tools/libxc/xc_domain_save.c49
-rw-r--r--tools/libxc/xc_linux.c133
-rw-r--r--tools/libxc/xc_misc.c69
-rw-r--r--tools/libxc/xc_resume.c4
-rw-r--r--tools/libxc/xenctrl.h10
-rw-r--r--tools/xenpaging/xenpaging.c13
9 files changed, 249 insertions, 57 deletions
diff --git a/tools/include/xen-sys/Linux/privcmd.h b/tools/include/xen-sys/Linux/privcmd.h
index d1162eebb0..d35aac9baa 100644
--- a/tools/include/xen-sys/Linux/privcmd.h
+++ b/tools/include/xen-sys/Linux/privcmd.h
@@ -64,6 +64,14 @@ typedef struct privcmd_mmapbatch {
xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */
} privcmd_mmapbatch_t;
+typedef struct privcmd_mmapbatch_v2 {
+ unsigned int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ __u64 addr; /* virtual address */
+ const xen_pfn_t __user *arr; /* array of mfns */
+ int __user *err; /* array of error codes */
+} privcmd_mmapbatch_v2_t;
+
/*
* @cmd: IOCTL_PRIVCMD_HYPERCALL
* @arg: &privcmd_hypercall_t
@@ -75,5 +83,7 @@ typedef struct privcmd_mmapbatch {
_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
#define IOCTL_PRIVCMD_MMAPBATCH \
_IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+#define IOCTL_PRIVCMD_MMAPBATCH_V2 \
+ _IOC(_IOC_NONE, 'P', 4, sizeof(privcmd_mmapbatch_v2_t))
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 8a5bdb5ced..8a565e1370 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -1,7 +1,7 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
-MAJOR = 3.4
+MAJOR = 4.0
MINOR = 0
CTRL_SRCS-y :=
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 827ba6bfd0..3999569582 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -118,7 +118,7 @@ static int break_super_page(int xc_handle,
page_array[i] = start_pfn + i;
}
- ram_base = xc_map_foreign_batch(xc_handle, dom, PROT_READ,
+ ram_base = xc_map_foreign_pages(xc_handle, dom, PROT_READ,
page_array, tot_pfns);
if ( ram_base == NULL )
@@ -166,7 +166,7 @@ static int break_super_page(int xc_handle,
page_array[i] = start_pfn + i;
}
- ram_base = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
+ ram_base = xc_map_foreign_pages(xc_handle, dom, PROT_WRITE,
page_array, tot_pfns);
if ( ram_base == NULL )
{
@@ -494,7 +494,7 @@ static ssize_t read_exact_timed(int fd, void* buf, size_t size)
** the (now known) appropriate mfn values.
*/
static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, struct restore_ctx *ctx,
- unsigned long type, void *page, int superpages)
+ void *page, int superpages)
{
int i, pte_last;
unsigned long pfn;
@@ -1186,7 +1186,7 @@ static int apply_batch(int xc_handle, uint32_t dom, struct restore_ctx *ctx,
}
/* Map relevant mfns */
- region_base = xc_map_foreign_batch(
+ region_base = xc_map_foreign_pages(
xc_handle, dom, PROT_WRITE, region_mfn, j);
if ( region_base == NULL )
@@ -1240,7 +1240,7 @@ static int apply_batch(int xc_handle, uint32_t dom, struct restore_ctx *ctx,
(pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
if (!uncanonicalize_pagetable(xc_handle, dom, ctx,
- pagetype, page, superpages)) {
+ page, superpages)) {
/*
** Failing to uncanonicalize a page table can be ok
** under live migration since the pages type may have
@@ -1655,7 +1655,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
if ( (i == (dinfo->p2m_size-1)) || (j == MAX_BATCH_SIZE) )
{
- region_base = xc_map_foreign_batch(
+ region_base = xc_map_foreign_pages(
xc_handle, dom, PROT_READ | PROT_WRITE, region_mfn, j);
if ( region_base == NULL )
{
@@ -1666,7 +1666,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
for ( k = 0; k < j; k++ )
{
if ( !uncanonicalize_pagetable(
- xc_handle, dom, ctx, XEN_DOMCTL_PFINFO_L1TAB,
+ xc_handle, dom, ctx,
region_base + k*PAGE_SIZE, superpages) )
{
ERROR("failed uncanonicalize pt!");
@@ -1949,7 +1949,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
}
/* Copy the P2M we've constructed to the 'live' P2M */
- if ( !(ctx->live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
+ if ( !(ctx->live_p2m = xc_map_foreign_pages(xc_handle, dom, PROT_WRITE,
p2m_frame_list, P2M_FL_ENTRIES)) )
{
ERROR("Couldn't map p2m table");
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 3f351ad071..87ec7dbbd6 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -709,7 +709,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i];
live_p2m_frame_list =
- xc_map_foreign_batch(xc_handle, dom, PROT_READ,
+ xc_map_foreign_pages(xc_handle, dom, PROT_READ,
p2m_frame_list_list,
P2M_FLL_ENTRIES);
if ( !live_p2m_frame_list )
@@ -727,6 +727,9 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
memset(p2m_frame_list, 0, P2M_TOOLS_FL_SIZE);
memcpy(p2m_frame_list, live_p2m_frame_list, P2M_GUEST_FL_SIZE);
+ munmap(live_p2m_frame_list, P2M_FLL_ENTRIES * PAGE_SIZE);
+ live_p2m_frame_list = NULL;
+
/* Canonicalize guest's unsigned long vs ours */
if ( dinfo->guest_width > sizeof(unsigned long) )
for ( i = 0; i < P2M_FL_ENTRIES; i++ )
@@ -741,7 +744,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
(its not clear why it would want to change them, and we'll be OK
from a safety POV anyhow. */
- p2m = xc_map_foreign_batch(xc_handle, dom, PROT_READ,
+ p2m = xc_map_foreign_pages(xc_handle, dom, PROT_READ,
p2m_frame_list,
P2M_FL_ENTRIES);
if ( !p2m )
@@ -873,8 +876,9 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
vcpu_guest_context_any_t ctxt;
/* A table containing the type of each PFN (/not/ MFN!). */
- unsigned long *pfn_type = NULL;
+ xen_pfn_t *pfn_type = NULL;
unsigned long *pfn_batch = NULL;
+ int *pfn_err = NULL;
/* A copy of one frame of guest memory. */
char page[PAGE_SIZE];
@@ -1263,8 +1267,8 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if ( batch == 0 )
goto skip; /* vanishingly unlikely... */
- region_base = xc_map_foreign_batch(
- xc_handle, dom, PROT_READ, pfn_type, batch);
+ region_base = xc_map_foreign_bulk(
+ xc_handle, dom, PROT_READ, pfn_type, pfn_err, batch);
if ( region_base == NULL )
{
ERROR("map batch failed");
@@ -1275,14 +1279,19 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
{
/* Look for and skip completely empty batches. */
for ( j = 0; j < batch; j++ )
- if ( (pfn_type[j] & XEN_DOMCTL_PFINFO_LTAB_MASK) !=
- XEN_DOMCTL_PFINFO_XTAB )
+ {
+ if ( !pfn_err[j] )
break;
+ pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB;
+ }
if ( j == batch )
{
munmap(region_base, batch*PAGE_SIZE);
continue; /* bail on this batch: no valid pages */
}
+ for ( ; j < batch; j++ )
+ if ( pfn_err[j] )
+ pfn_type[j] |= XEN_DOMCTL_PFINFO_XTAB;
}
else
{
@@ -1296,16 +1305,17 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
for ( j = batch-1; j >= 0; j-- )
- pfn_type[j] = ((uint32_t *)pfn_type)[j];
+ pfn_type[j] = ((uint32_t *)pfn_type)[j] &
+ XEN_DOMCTL_PFINFO_LTAB_MASK;
for ( j = 0; j < batch; j++ )
{
+ unsigned long mfn = pfn_to_mfn(pfn_batch[j]);
- if ( (pfn_type[j] & XEN_DOMCTL_PFINFO_LTAB_MASK) ==
- XEN_DOMCTL_PFINFO_XTAB )
+ if ( pfn_type[j] == XEN_DOMCTL_PFINFO_XTAB )
{
DPRINTF("type fail: page %i mfn %08lx\n",
- j, pfn_type[j]);
+ j, mfn);
continue;
}
@@ -1313,16 +1323,13 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
DPRINTF("%d pfn= %08lx mfn= %08lx [mfn]= %08lx"
" sum= %08lx\n",
iter,
- (pfn_type[j] & XEN_DOMCTL_PFINFO_LTAB_MASK) |
- pfn_batch[j],
- pfn_type[j],
- mfn_to_pfn(pfn_type[j] &
- ~XEN_DOMCTL_PFINFO_LTAB_MASK),
+ pfn_type[j] | pfn_batch[j],
+ mfn,
+ mfn_to_pfn(mfn),
csum_page(region_base + (PAGE_SIZE*j)));
/* canonicalise mfn->pfn */
- pfn_type[j] = (pfn_type[j] & XEN_DOMCTL_PFINFO_LTAB_MASK) |
- pfn_batch[j];
+ pfn_type[j] |= pfn_batch[j];
}
}
@@ -1332,11 +1339,17 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
+ if ( sizeof(unsigned long) < sizeof(*pfn_type) )
+ for ( j = 0; j < batch; j++ )
+ ((unsigned long *)pfn_type)[j] = pfn_type[j];
if ( write_exact(io_fd, pfn_type, sizeof(unsigned long)*batch) )
{
PERROR("Error when writing to state file (3)");
goto out;
}
+ if ( sizeof(unsigned long) < sizeof(*pfn_type) )
+ while ( --j >= 0 )
+ pfn_type[j] = ((unsigned long *)pfn_type)[j];
/* entering this loop, pfn_type is now in pfns (Not mfns) */
run = 0;
diff --git a/tools/libxc/xc_linux.c b/tools/libxc/xc_linux.c
index 0f1b78aa57..e0e807f2cc 100644
--- a/tools/libxc/xc_linux.c
+++ b/tools/libxc/xc_linux.c
@@ -64,7 +64,7 @@ int xc_interface_close(int xc_handle)
return close(xc_handle);
}
-static int xc_map_foreign_batch_single(int xc_handle, uint32_t dom, int prot,
+static int xc_map_foreign_batch_single(int xc_handle, uint32_t dom,
xen_pfn_t *mfn, unsigned long addr)
{
privcmd_mmapbatch_t ioctlx;
@@ -116,7 +116,7 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
XEN_DOMCTL_PFINFO_PAGEDTAB )
{
unsigned long paged_addr = (unsigned long)addr + (i << PAGE_SHIFT);
- rc = xc_map_foreign_batch_single(xc_handle, dom, prot, &arr[i],
+ rc = xc_map_foreign_batch_single(xc_handle, dom, &arr[i],
paged_addr);
if ( rc < 0 )
goto out;
@@ -137,6 +137,131 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
return addr;
}
+void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num)
+{
+ privcmd_mmapbatch_v2_t ioctlx;
+ void *addr;
+ unsigned int i;
+ int rc;
+
+ addr = mmap(NULL, (unsigned long)num << PAGE_SHIFT, prot, MAP_SHARED,
+ xc_handle, 0);
+ if ( addr == MAP_FAILED )
+ {
+ perror("xc_map_foreign_batch: mmap failed");
+ return NULL;
+ }
+
+ ioctlx.num = num;
+ ioctlx.dom = dom;
+ ioctlx.addr = (unsigned long)addr;
+ ioctlx.arr = arr;
+ ioctlx.err = err;
+
+ rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
+
+ if ( rc < 0 && errno == ENOENT )
+ {
+ for ( i = rc = 0; rc == 0 && i < num; i++ )
+ {
+ if ( err[i] != -ENOENT )
+ continue;
+
+ ioctlx.num = 1;
+ ioctlx.dom = dom;
+ ioctlx.addr = (unsigned long)addr + ((unsigned long)i<<PAGE_SHIFT);
+ ioctlx.arr = arr + i;
+ ioctlx.err = err + i;
+ do {
+ usleep(100);
+ rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx);
+ } while ( rc < 0 && err[i] == -ENOENT );
+ }
+ }
+
+ if ( rc < 0 && errno == ENOTTY && (int)num > 0 )
+ {
+ /*
+ * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to
+ * IOCTL_PRIVCMD_MMAPBATCH.
+ */
+ xen_pfn_t *pfn = calloc(num, sizeof(*pfn));
+
+ if ( pfn )
+ {
+ privcmd_mmapbatch_t ioctlx;
+
+ memcpy(pfn, arr, num * sizeof(*arr));
+
+ ioctlx.num = num;
+ ioctlx.dom = dom;
+ ioctlx.addr = (unsigned long)addr;
+ ioctlx.arr = pfn;
+
+ rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+
+ rc = rc < 0 ? -errno : 0;
+
+ for ( i = 0; i < num; ++i )
+ {
+ switch ( pfn[i] ^ arr[i] )
+ {
+ case 0:
+ err[i] = rc != -ENOENT ? rc : 0;
+ continue;
+ default:
+ err[i] = -EINVAL;
+ continue;
+ case XEN_DOMCTL_PFINFO_PAGEDTAB:
+ if ( rc != -ENOENT )
+ {
+ err[i] = rc ?: -EINVAL;
+ continue;
+ }
+ rc = xc_map_foreign_batch_single(xc_handle, dom, pfn + i,
+ (unsigned long)addr + ((unsigned long)i<<PAGE_SHIFT));
+ if ( rc < 0 )
+ {
+ rc = -errno;
+ break;
+ }
+ rc = -ENOENT;
+ continue;
+ }
+ break;
+ }
+
+ free(pfn);
+
+ if ( rc == -ENOENT && i == num )
+ rc = 0;
+ else if ( rc )
+ {
+ errno = -rc;
+ rc = -1;
+ }
+ }
+ else
+ {
+ errno = -ENOMEM;
+ rc = -1;
+ }
+ }
+
+ if ( rc < 0 )
+ {
+ int saved_errno = errno;
+
+ perror("xc_map_foreign_bulk: ioctl failed");
+ (void)munmap(addr, (unsigned long)num << PAGE_SHIFT);
+ errno = saved_errno;
+ return NULL;
+ }
+
+ return addr;
+}
+
void *xc_map_foreign_range(int xc_handle, uint32_t dom, int size, int prot,
unsigned long mfn)
{
@@ -151,7 +276,7 @@ void *xc_map_foreign_range(int xc_handle, uint32_t dom, int size, int prot,
for ( i = 0; i < num; i++ )
arr[i] = mfn + i;
- ret = xc_map_foreign_batch(xc_handle, dom, prot, arr, num);
+ ret = xc_map_foreign_pages(xc_handle, dom, prot, arr, num);
free(arr);
return ret;
}
@@ -175,7 +300,7 @@ void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, size_t size, int prot,
for ( j = 0; j < num_per_entry; j++ )
arr[i * num_per_entry + j] = entries[i].mfn + j;
- ret = xc_map_foreign_batch(xc_handle, dom, prot, arr, num);
+ ret = xc_map_foreign_pages(xc_handle, dom, prot, arr, num);
free(arr);
return ret;
}
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index ffc04fb50f..e237b7862d 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -352,25 +352,23 @@ int xc_hvm_set_mem_type(
void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
const xen_pfn_t *arr, int num)
{
- xen_pfn_t *pfn;
void *res;
- int i;
+ int i, *err;
+
+ if (num < 0) {
+ errno = -EINVAL;
+ return NULL;
+ }
- pfn = malloc(num * sizeof(*pfn));
- if (!pfn)
+ err = calloc(num, sizeof(*err));
+ if (!err)
return NULL;
- memcpy(pfn, arr, num * sizeof(*pfn));
- res = xc_map_foreign_batch(xc_handle, dom, prot, pfn, num);
+ res = xc_map_foreign_bulk(xc_handle, dom, prot, arr, err, num);
if (res) {
for (i = 0; i < num; i++) {
- if ((pfn[i] & 0xF0000000UL) == 0xF0000000UL) {
- /*
- * xc_map_foreign_batch() doesn't give us an error
- * code, so we have to make one up. May not be the
- * appropriate one.
- */
- errno = EINVAL;
+ if (err[i]) {
+ errno = -err[i];
munmap(res, num * PAGE_SIZE);
res = NULL;
break;
@@ -378,10 +376,53 @@ void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
}
}
- free(pfn);
+ free(err);
return res;
}
+/* stub for all not yet converted OSes */
+void *
+#ifdef __GNUC__
+__attribute__((__weak__))
+#endif
+xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num)
+{
+ xen_pfn_t *pfn;
+ unsigned int i;
+ void *ret;
+
+ if ((int)num <= 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ pfn = calloc(num, sizeof(*pfn));
+ if (!pfn) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ memcpy(pfn, arr, num * sizeof(*arr));
+ ret = xc_map_foreign_batch(xc_handle, dom, prot, pfn, num);
+
+ if (ret) {
+ for (i = 0; i < num; ++i)
+ switch (pfn[i] ^ arr[i]) {
+ case 0:
+ err[i] = 0;
+ break;
+ default:
+ err[i] = -EINVAL;
+ break;
+ }
+ }
+
+ free(pfn);
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index 2816609b0d..c17ae262d3 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -158,7 +158,7 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid)
goto out;
}
- p2m_frame_list = xc_map_foreign_batch(xc_handle, domid, PROT_READ,
+ p2m_frame_list = xc_map_foreign_pages(xc_handle, domid, PROT_READ,
p2m_frame_list_list,
P2M_FLL_ENTRIES);
if ( p2m_frame_list == NULL )
@@ -171,7 +171,7 @@ static int xc_domain_resume_any(int xc_handle, uint32_t domid)
the guest must not change which frames are used for this purpose.
(its not clear why it would want to change them, and we'll be OK
from a safety POV anyhow. */
- p2m = xc_map_foreign_batch(xc_handle, domid, PROT_READ,
+ p2m = xc_map_foreign_pages(xc_handle, domid, PROT_READ,
p2m_frame_list,
P2M_FL_ENTRIES);
if ( p2m == NULL )
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 4be69a814f..7a35a1439c 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -749,6 +749,8 @@ void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
const xen_pfn_t *arr, int num );
/**
+ * DEPRECATED - use xc_map_foreign_bulk() instead.
+ *
* Like xc_map_foreign_pages(), except it can succeeed partially.
* When a page cannot be mapped, its PFN in @arr is or'ed with
* 0xF0000000 to indicate the error.
@@ -757,6 +759,14 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
xen_pfn_t *arr, int num );
/**
+ * Like xc_map_foreign_pages(), except it can succeed partially.
+ * When a page cannot be mapped, its respective field in @err is
+ * set to the corresponding errno value.
+ */
+void *xc_map_foreign_bulk(int xc_handle, uint32_t dom, int prot,
+ const xen_pfn_t *arr, int *err, unsigned int num);
+
+/**
* Translates a virtual address in the context of a given domain and
* vcpu returning the GFN containing the address (that is, an MFN for
* PV guests, a PFN for HVM guests). Returns 0 for failure.
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 2817cb7312..a207ca8ac9 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -310,9 +310,9 @@ int xenpaging_evict_page(xenpaging_t *paging, xenpaging_victim_t *victim, int fd
/* Map page */
gfn = victim->gfn;
ret = -EFAULT;
- page = xc_map_foreign_batch(paging->xc_handle, victim->domain_id,
+ page = xc_map_foreign_pages(paging->xc_handle, victim->domain_id,
PROT_READ | PROT_WRITE, &gfn, 1);
- if ( (gfn & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB )
+ if ( page == NULL )
{
ERROR("Error mapping page");
goto out;
@@ -386,7 +386,7 @@ int xenpaging_populate_page(xenpaging_t *paging, unsigned long *gfn, int fd, int
/* Map page */
ret = -EFAULT;
- page = xc_map_foreign_batch(paging->xc_handle, paging->mem_event.domain_id,
+ page = xc_map_foreign_pages(paging->xc_handle, paging->mem_event.domain_id,
PROT_READ | PROT_WRITE, gfn, 1);
if ( page == NULL )
{
@@ -394,13 +394,6 @@ int xenpaging_populate_page(xenpaging_t *paging, unsigned long *gfn, int fd, int
goto out_map;
}
- /* Check that the page exists */
- if ( (*gfn & XEN_DOMCTL_PFINFO_LTAB_MASK) == XEN_DOMCTL_PFINFO_XTAB )
- {
- ERROR("Error mapping page: gfn is invalid");
- goto out;
- }
-
/* Read page */
ret = read_page(fd, page, i);
if ( ret != 0 )