aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_linux.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:55 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:55 +0000
commit0645e0177f2a7120d5af731d236d84b9a9a6dbb8 (patch)
treeb475385d086acfa5375673397e647426f16ca670 /tools/libxc/xc_linux.c
parent35b1c10cb4210e14a579e3030d65bb08949ab709 (diff)
downloadxen-0645e0177f2a7120d5af731d236d84b9a9a6dbb8.tar.gz
xen-0645e0177f2a7120d5af731d236d84b9a9a6dbb8.tar.bz2
xen-0645e0177f2a7120d5af731d236d84b9a9a6dbb8.zip
libxc support of memory paging.
libxc accepts the new return code from privcmd mmap, which indicates a page being mapped is actually paged out. Spin until the page is paged in and return as normal to the caller. This allows memory paging to work transparently with existing tools. Since libxc runs in user-space, as does the pager, both processes will be scheduled and run. This enables the page to be paged in without needing to spin in kernel mode (which would cause a dead-lock). Signed-off-by: Patrick Colp <Patrick.Colp@citrix.com>
Diffstat (limited to 'tools/libxc/xc_linux.c')
-rw-r--r--tools/libxc/xc_linux.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/tools/libxc/xc_linux.c b/tools/libxc/xc_linux.c
index 2d4a158af2..de176fbb8b 100644
--- a/tools/libxc/xc_linux.c
+++ b/tools/libxc/xc_linux.c
@@ -64,11 +64,34 @@ 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,
+ xen_pfn_t *mfn, unsigned long addr)
+{
+ privcmd_mmapbatch_t ioctlx;
+ int rc;
+
+ ioctlx.num = 1;
+ ioctlx.dom = dom;
+ ioctlx.addr = addr;
+ ioctlx.arr = mfn;
+
+ do
+ {
+ *mfn ^= XEN_DOMCTL_PFINFO_PAGEDTAB;
+ usleep(100);
+ rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+ }
+ while ( (rc < 0) && (errno == ENOENT) );
+
+ return rc;
+}
+
void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
xen_pfn_t *arr, int num)
{
privcmd_mmapbatch_t ioctlx;
void *addr;
+ int rc;
addr = mmap(NULL, num << PAGE_SHIFT, prot, MAP_SHARED, xc_handle, 0);
if ( addr == MAP_FAILED )
@@ -82,7 +105,27 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
ioctlx.addr = (unsigned long)addr;
ioctlx.arr = arr;
- if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
+ rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx);
+ if ( (rc < 0) && (errno == ENOENT) )
+ {
+ int i;
+
+ for ( i = 0; i < num; i++ )
+ {
+ if ( (arr[i] & XEN_DOMCTL_PFINFO_LTAB_MASK) ==
+ 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],
+ paged_addr);
+ if ( rc < 0 )
+ goto out;
+ }
+ }
+ }
+
+ out:
+ if ( rc < 0 )
{
int saved_errno = errno;
perror("xc_map_foreign_batch: ioctl failed");