WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] privcmd: add new (replacement) mmap-b

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] privcmd: add new (replacement) mmap-batch ioctl
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 13 Jan 2010 00:40:36 -0800
Delivery-date: Wed, 13 Jan 2010 00:40:58 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1263370311 0
# Node ID 6d6c3dd995c07527b94d5278b0df4f5252888ccd
# Parent  6061d56155223f92362420ec9a5a4dbe933efa60
privcmd: add new (replacement) mmap-batch ioctl

While the error indicator of IOCTL_PRIVCMD_MMAPBATCH should be in the
top nibble (it is documented that way in include/xen/public/privcmd.h
and include/xen/compat_ioctl.h), it really wasn't for 64-bit
implementations. With MFNs now possibly being 32 or more bits wide on
x86-64, using bits 28-31 as failure indicator (and bit 31 as paged-out
indicator) is not longer acceptable. Instead, a new ioctl with a
separate error indication array is being introduced.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 drivers/xen/privcmd/compat_privcmd.c |   50 +++++++++++++++++
 drivers/xen/privcmd/privcmd.c        |  102 +++++++++++++++++++++++++++++++++++
 fs/compat_ioctl.c                    |    1 
 include/xen/compat_ioctl.h           |   20 ++++++
 include/xen/public/privcmd.h         |   10 +++
 5 files changed, 182 insertions(+), 1 deletion(-)

diff -r 6061d5615522 -r 6d6c3dd995c0 drivers/xen/privcmd/compat_privcmd.c
--- a/drivers/xen/privcmd/compat_privcmd.c      Fri Jan 08 13:07:17 2010 +0000
+++ b/drivers/xen/privcmd/compat_privcmd.c      Wed Jan 13 08:11:51 2010 +0000
@@ -97,6 +97,56 @@ int privcmd_ioctl_32(int fd, unsigned in
 #endif
        }
                break;
+       case IOCTL_PRIVCMD_MMAPBATCH_V2_32: {
+               struct privcmd_mmapbatch_v2 *p;
+               struct privcmd_mmapbatch_v2_32 *p32;
+               struct privcmd_mmapbatch_v2_32 n32;
+#ifdef xen_pfn32_t
+               xen_pfn_t *__user arr;
+               xen_pfn32_t *__user arr32;
+               unsigned int i;
+#endif
+
+               p32 = compat_ptr(arg);
+               p = compat_alloc_user_space(sizeof(*p));
+               if (copy_from_user(&n32, p32, sizeof(n32)) ||
+                   put_user(n32.num, &p->num) ||
+                   put_user(n32.dom, &p->dom) ||
+                   put_user(n32.addr, &p->addr) ||
+                   put_user(compat_ptr(n32.err), &p->err))
+                       return -EFAULT;
+#ifdef xen_pfn32_t
+               arr = compat_alloc_user_space(n32.num * sizeof(*arr)
+                                             + sizeof(*p));
+               arr32 = compat_ptr(n32.arr);
+               for (i = 0; i < n32.num; ++i) {
+                       xen_pfn32_t mfn;
+
+                       if (get_user(mfn, arr32 + i) || put_user(mfn, arr + i))
+                               return -EFAULT;
+               }
+
+               if (put_user(arr, &p->arr))
+                       return -EFAULT;
+#else
+               if (put_user(compat_ptr(n32.arr), &p->arr))
+                       return -EFAULT;
+#endif
+
+               ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, (unsigned 
long)p);
+
+#ifdef xen_pfn32_t
+               for (i = 0; !ret && i < n32.num; ++i) {
+                       xen_pfn_t mfn;
+
+                       if (get_user(mfn, arr + i) || put_user(mfn, arr32 + i))
+                               ret = -EFAULT;
+                       else if (mfn != (xen_pfn32_t)mfn)
+                               ret = -ERANGE;
+               }
+#endif
+       }
+               break;
        default:
                ret = -EINVAL;
                break;
diff -r 6061d5615522 -r 6d6c3dd995c0 drivers/xen/privcmd/privcmd.c
--- a/drivers/xen/privcmd/privcmd.c     Fri Jan 08 13:07:17 2010 +0000
+++ b/drivers/xen/privcmd/privcmd.c     Wed Jan 13 08:11:51 2010 +0000
@@ -321,6 +321,108 @@ static long privcmd_ioctl(struct file *f
        mmapbatch_out:
                list_for_each_safe(l,l2,&pagelist)
                        free_page((unsigned long)l);
+       }
+       break;
+
+       case IOCTL_PRIVCMD_MMAPBATCH_V2: {
+               privcmd_mmapbatch_v2_t m;
+               struct mm_struct *mm = current->mm;
+               struct vm_area_struct *vma;
+               const xen_pfn_t __user *p;
+               xen_pfn_t *mfn;
+               unsigned long addr, nr_pages;
+               unsigned int i, nr;
+               LIST_HEAD(pagelist);
+               struct list_head *l, *l2;
+               int *err, paged_out;
+
+               if (!is_initial_xendomain())
+                       return -EPERM;
+
+               if (copy_from_user(&m, udata, sizeof(m)))
+                       return -EFAULT;
+
+               nr_pages = m.num;
+               addr = m.addr;
+               if (m.num <= 0 || nr_pages > (ULONG_MAX >> PAGE_SHIFT) ||
+                   addr != m.addr || nr_pages > (-addr >> PAGE_SHIFT))
+                       return -EINVAL;
+
+               p = m.arr;
+               for (i = 0; i < nr_pages; i += nr, p += nr) {
+                       nr = min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
+
+                       ret = -ENOMEM;
+                       l = (struct list_head *)__get_free_page(GFP_KERNEL);
+                       if (l == NULL)
+                               goto mmapbatch_v2_out;
+
+                       INIT_LIST_HEAD(l);
+                       list_add_tail(l, &pagelist);
+
+                       mfn = (void *)(l + 1);
+                       ret = -EFAULT;
+                       if (copy_from_user(mfn, p, nr * sizeof(*mfn)))
+                               goto mmapbatch_v2_out;
+               }
+
+               down_write(&mm->mmap_sem);
+
+               vma = find_vma(mm, addr);
+               ret = -EINVAL;
+               if (!vma ||
+                   addr < vma->vm_start ||
+                   addr + (nr_pages << PAGE_SHIFT) > vma->vm_end ||
+                   !enforce_singleshot_mapping(vma, addr, nr_pages)) {
+                       up_write(&mm->mmap_sem);
+                       goto mmapbatch_v2_out;
+               }
+
+               i = 0;
+               ret = 0;
+               paged_out = 0;
+               list_for_each(l, &pagelist) {
+                       int rc;
+
+                       nr = i + min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
+                       mfn = (void *)(l + 1);
+                       err = (void *)(l + 1);
+                       BUILD_BUG_ON(sizeof(*err) > sizeof(*mfn));
+
+                       while (i < nr) {
+                               rc = direct_remap_pfn_range(vma, addr & 
PAGE_MASK,
+                                                           *mfn, PAGE_SIZE,
+                                                           vma->vm_page_prot, 
m.dom);
+                               if (rc < 0) {
+                                       if (rc == -ENOENT)
+                                               paged_out = 1;
+                                       ret++;
+                               } else
+                                       BUG_ON(rc > 0);
+                               *err++ = rc;
+                               mfn++; i++; addr += PAGE_SIZE;
+                       }
+               }
+
+               up_write(&mm->mmap_sem);
+
+               if (ret > 0) {
+                       int __user *p = m.err;
+
+                       ret = paged_out ? -ENOENT : 0;
+                       i = 0;
+                       list_for_each(l, &pagelist) {
+                               nr = min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
+                               err = (void *)(l + 1);
+                               if (copy_to_user(p, err, nr * sizeof(*err)))
+                                       ret = -EFAULT;
+                               i += nr; p += nr;
+                       }
+               }
+
+       mmapbatch_v2_out:
+               list_for_each_safe(l, l2, &pagelist)
+                       free_page((unsigned long)l);
 #undef MMAPBATCH_NR_PER_PAGE
        }
        break;
diff -r 6061d5615522 -r 6d6c3dd995c0 fs/compat_ioctl.c
--- a/fs/compat_ioctl.c Fri Jan 08 13:07:17 2010 +0000
+++ b/fs/compat_ioctl.c Wed Jan 13 08:11:51 2010 +0000
@@ -2959,6 +2959,7 @@ HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_tr
 #ifdef CONFIG_XEN
 HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32)
 HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32)
+HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_V2_32, privcmd_ioctl_32)
 COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL)
 COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ)
 COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN)
diff -r 6061d5615522 -r 6d6c3dd995c0 include/xen/compat_ioctl.h
--- a/include/xen/compat_ioctl.h        Fri Jan 08 13:07:17 2010 +0000
+++ b/include/xen/compat_ioctl.h        Wed Jan 13 08:11:51 2010 +0000
@@ -49,9 +49,27 @@ struct privcmd_mmapbatch_32 {
 #endif
        compat_uptr_t arr; /* array of mfns - top nibble set on err */
 };
+
+struct privcmd_mmapbatch_v2_32 {
+       unsigned int num; /* number of pages to populate */
+       domid_t dom;      /* target domain */
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+       union {      /* virtual address */
+               __u64 addr __attribute__((packed));
+               __u32 va; /* ensures union is 4-byte aligned */
+       };
+#else
+       __u64 addr;  /* virtual address */
+#endif
+       compat_uptr_t arr; /* array of mfns */
+       compat_uptr_t err; /* array of error codes */
+};
+
 #define IOCTL_PRIVCMD_MMAP_32                   \
        _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap_32))
-#define IOCTL_PRIVCMD_MMAPBATCH_32                  \
+#define IOCTL_PRIVCMD_MMAPBATCH_32              \
        _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch_32))
+#define IOCTL_PRIVCMD_MMAPBATCH_V2_32           \
+       _IOC(_IOC_NONE, 'P', 4, sizeof(struct privcmd_mmapbatch_v2_32))
 
 #endif /* __LINUX_XEN_COMPAT_H__ */
diff -r 6061d5615522 -r 6d6c3dd995c0 include/xen/public/privcmd.h
--- a/include/xen/public/privcmd.h      Fri Jan 08 13:07:17 2010 +0000
+++ b/include/xen/public/privcmd.h      Wed Jan 13 08:11:51 2010 +0000
@@ -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__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] privcmd: add new (replacement) mmap-batch ioctl, Xen patchbot-linux-2.6.18-xen <=