# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1261031869 0
# Node ID c4572f01675ed0a3fe5284e437383d925265a247
# Parent 0d9c11acc93900270caa0a9fdf50cde73157da9c
privcmd: Handle paged-out areas of foreign guest memory in mmap().
Signed-off-by: Grzegorz Milos <Grzegorz.Milos@xxxxxxxxxx>
---
drivers/xen/privcmd/privcmd.c | 33 ++++++++++++++++++++++++++-------
1 files changed, 26 insertions(+), 7 deletions(-)
diff -r 0d9c11acc939 -r c4572f01675e drivers/xen/privcmd/privcmd.c
--- a/drivers/xen/privcmd/privcmd.c Wed Dec 16 16:44:12 2009 +0000
+++ b/drivers/xen/privcmd/privcmd.c Thu Dec 17 06:37:49 2009 +0000
@@ -197,6 +197,7 @@ static long privcmd_ioctl(struct file *f
int i;
LIST_HEAD(pagelist);
struct list_head *l, *l2;
+ int paged_out = 0;
if (!is_initial_xendomain())
return -EPERM;
@@ -236,8 +237,14 @@ static long privcmd_ioctl(struct file *f
(m.addr != vma->vm_start) ||
((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
!privcmd_enforce_singleshot_mapping(vma)) {
- up_write(&mm->mmap_sem);
- goto mmapbatch_out;
+ if (!(vma &&
+ (m.addr >= vma->vm_start) &&
+ ((m.addr + (nr_pages << PAGE_SHIFT)) <=
vma->vm_end) &&
+ (nr_pages == 1) &&
+ !privcmd_enforce_singleshot_mapping(vma))) {
+ up_write(&mm->mmap_sem);
+ goto mmapbatch_out;
+ }
}
p = m.arr;
@@ -246,13 +253,22 @@ static long privcmd_ioctl(struct file *f
ret = 0;
list_for_each(l, &pagelist) {
int nr = i + min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
+ int rc;
+
mfn = (unsigned long *)(l + 1);
while (i<nr) {
- if(direct_remap_pfn_range(vma, addr & PAGE_MASK,
- *mfn, PAGE_SIZE,
- vma->vm_page_prot,
m.dom) < 0) {
- *mfn |= 0xf0000000U;
+ rc = direct_remap_pfn_range(vma, addr &
PAGE_MASK,
+ *mfn, PAGE_SIZE,
+ vma->vm_page_prot,
m.dom);
+ if(rc < 0) {
+ if (rc == -ENOENT)
+ {
+ *mfn |= 0x80000000U;
+ paged_out = 1;
+ }
+ else
+ *mfn |= 0xf0000000U;
ret++;
}
mfn++; i++; addr += PAGE_SIZE;
@@ -263,7 +279,10 @@ static long privcmd_ioctl(struct file *f
if (ret > 0) {
p = m.arr;
i = 0;
- ret = 0;
+ if (paged_out)
+ ret = -ENOENT;
+ else
+ ret = 0;
list_for_each(l, &pagelist) {
int nr = min(nr_pages - i,
MMAPBATCH_NR_PER_PAGE);
mfn = (unsigned long *)(l + 1);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|