[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] New memory_op subcall XENMEM_translate_gpfn_list.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 0d10fac284274733fe67cf5384fe032508c13766
# Parent  2b0078f771cc1152a003721e20c3972fe7cf6ea8
New memory_op subcall XENMEM_translate_gpfn_list.

Allows translation from GPFNs to MFNs for an auto-translated
guest.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xc_domain.c   Thu Feb 16 17:52:06 2006
@@ -326,6 +326,53 @@
     return err;
 }
 
+int xc_domain_memory_populate_physmap(int xc_handle,
+                                          uint32_t domid,
+                                          unsigned long nr_extents,
+                                          unsigned int extent_order,
+                                          unsigned int address_bits,
+                                          unsigned long *extent_start)
+{
+    int err;
+    struct xen_memory_reservation reservation = {
+        .extent_start = extent_start,
+        .nr_extents   = nr_extents,
+        .extent_order = extent_order,
+        .address_bits = address_bits,
+        .domid        = domid
+    };
+
+    err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
+    if ( err == nr_extents )
+        return 0;
+
+    if ( err > 0 )
+    {
+        fprintf(stderr,"Failed deallocation for dom %d: %ld pages order %d\n",
+                domid, nr_extents, extent_order);
+        errno = EBUSY;
+        err = -1;
+    }
+
+    return err;
+}
+
+int xc_domain_translate_gpfn_list(int xc_handle,
+                                  uint32_t domid,
+                                  unsigned long nr_gpfns,
+                                  unsigned long *gpfn_list,
+                                  unsigned long *mfn_list)
+{
+    struct xen_translate_gpfn_list op = {
+        .domid        = domid,
+        .nr_gpfns     = nr_gpfns,
+        .gpfn_list    = gpfn_list,
+        .mfn_list     = mfn_list
+    };
+
+    return xc_memory_op(xc_handle, XENMEM_translate_gpfn_list, &op);
+}
+
 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
 {
     DECLARE_DOM0_OP;
diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c  Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xc_private.c  Thu Feb 16 17:52:06 2006
@@ -191,6 +191,7 @@
     DECLARE_HYPERCALL;
     struct xen_memory_reservation *reservation = arg;
     struct xen_machphys_mfn_list *xmml = arg;
+    struct xen_translate_gpfn_list *trans = arg;
     long ret = -EINVAL;
 
     hypercall.op     = __HYPERVISOR_memory_op;
@@ -234,6 +235,26 @@
         if ( mlock(arg, sizeof(struct xen_reserved_phys_area)) )
         {
             PERROR("Could not mlock");
+            goto out1;
+        }
+        break;
+    case XENMEM_translate_gpfn_list:
+        if ( mlock(trans, sizeof(*trans)) != 0 )
+        {
+            PERROR("Could not mlock");
+            goto out1;
+        }
+        if ( mlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
+        {
+            PERROR("Could not mlock");
+            safe_munlock(trans, sizeof(*trans));
+            goto out1;
+        }
+        if ( mlock(trans->mfn_list, trans->nr_gpfns * sizeof(long)) != 0 )
+        {
+            PERROR("Could not mlock");
+            safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
+            safe_munlock(trans, sizeof(*trans));
             goto out1;
         }
         break;
@@ -258,6 +279,11 @@
         break;
     case XENMEM_reserved_phys_area:
         safe_munlock(arg, sizeof(struct xen_reserved_phys_area));
+        break;
+    case XENMEM_translate_gpfn_list:
+            safe_munlock(trans->mfn_list, trans->nr_gpfns * sizeof(long));
+            safe_munlock(trans->gpfn_list, trans->nr_gpfns * sizeof(long));
+            safe_munlock(trans, sizeof(*trans));
         break;
     }
 
diff -r 2b0078f771cc -r 0d10fac28427 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Thu Feb 16 16:37:21 2006
+++ b/tools/libxc/xenctrl.h     Thu Feb 16 17:52:06 2006
@@ -373,6 +373,19 @@
                                           unsigned int extent_order,
                                          unsigned long *extent_start);
 
+int xc_domain_memory_populate_physmap(int xc_handle,
+                                      uint32_t domid,
+                                      unsigned long nr_extents,
+                                      unsigned int extent_order,
+                                      unsigned int address_bits,
+                                      unsigned long *extent_start);
+
+int xc_domain_translate_gpfn_list(int xc_handle,
+                                  uint32_t domid,
+                                  unsigned long nr_gpfns,
+                                  unsigned long *gpfn_list,
+                                  unsigned long *mfn_list);
+
 int xc_domain_ioport_permission(int xc_handle,
                                 uint32_t domid,
                                 uint32_t first_port,
diff -r 2b0078f771cc -r 0d10fac28427 xen/common/memory.c
--- a/xen/common/memory.c       Thu Feb 16 16:37:21 2006
+++ b/xen/common/memory.c       Thu Feb 16 17:52:06 2006
@@ -19,6 +19,13 @@
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <public/memory.h>
+
+/*
+ * To allow safe resume of do_memory_op() after preemption, we need to know 
+ * at what point in the page list to resume. For this purpose I steal the 
+ * high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ */
+#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
 
 static long
 increase_reservation(
@@ -188,17 +195,74 @@
     return nr_extents;
 }
 
-/*
- * To allow safe resume of do_memory_op() after preemption, we need to know 
- * at what point in the page list to resume. For this purpose I steal the 
- * high-order bits of the @cmd parameter, which are otherwise unused and zero.
- */
-#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
-
-long do_memory_op(int cmd, void *arg)
-{
+static long
+translate_gpfn_list(
+    struct xen_translate_gpfn_list *uop, unsigned long *progress)
+{
+    struct xen_translate_gpfn_list op;
+    unsigned long i, gpfn, mfn;
     struct domain *d;
-    int rc, start_extent, op, flags = 0, preempted = 0;
+
+    if ( copy_from_user(&op, uop, sizeof(op)) )
+        return -EFAULT;
+
+    /* Is size too large for us to encode a continuation? */
+    if ( op.nr_gpfns > (ULONG_MAX >> START_EXTENT_SHIFT) )
+        return -EINVAL;
+
+    if ( !array_access_ok(op.gpfn_list, op.nr_gpfns, sizeof(*op.gpfn_list)) ||
+         !array_access_ok(op.mfn_list, op.nr_gpfns, sizeof(*op.mfn_list)) )
+        return -EFAULT;
+
+    if ( op.domid == DOMID_SELF )
+        op.domid = current->domain->domain_id;
+    else if ( !IS_PRIV(current->domain) )
+        return -EPERM;
+
+    if ( (d = find_domain_by_id(op.domid)) == NULL )
+        return -ESRCH;
+
+    if ( !shadow_mode_translate(d) )
+    {
+        put_domain(d);
+        return -EINVAL;
+    }
+
+    for ( i = *progress; i < op.nr_gpfns; i++ )
+    {
+        if ( hypercall_preempt_check() )
+        {
+            put_domain(d);
+            *progress = i;
+            return -EAGAIN;
+        }
+
+        if ( unlikely(__copy_from_user(&gpfn, &op.gpfn_list[i],
+                                       sizeof(gpfn))) )
+        {
+            put_domain(d);
+            return -EFAULT;
+        }
+
+        mfn = gmfn_to_mfn(d, gpfn);
+
+        if ( unlikely(__copy_to_user(&op.mfn_list[i], &mfn,
+                                     sizeof(mfn))) )
+        {
+            put_domain(d);
+            return -EFAULT;
+        }
+    }
+
+    put_domain(d);
+    return 0;
+}
+
+long do_memory_op(unsigned long cmd, void *arg)
+{
+    struct domain *d;
+    int rc, op, flags = 0, preempted = 0;
+    unsigned long start_extent, progress;
     struct xen_memory_reservation reservation;
     domid_t domid;
 
@@ -211,6 +275,10 @@
     case XENMEM_populate_physmap:
         if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
             return -EFAULT;
+
+        /* Is size too large for us to encode a continuation? */
+        if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) )
+            return -EINVAL;
 
         start_extent = cmd >> START_EXTENT_SHIFT;
         if ( unlikely(start_extent > reservation.nr_extents) )
@@ -302,6 +370,16 @@
 
         break;
 
+    case XENMEM_translate_gpfn_list:
+        progress = cmd >> START_EXTENT_SHIFT;
+        rc = translate_gpfn_list(arg, &progress);
+        if ( rc == -EAGAIN )
+            return hypercall2_create_continuation(
+                __HYPERVISOR_memory_op,
+                op | (progress << START_EXTENT_SHIFT),
+                arg);
+        break;
+
     default:
         rc = arch_memory_op(op, arg);
         break;
diff -r 2b0078f771cc -r 0d10fac28427 xen/include/public/memory.h
--- a/xen/include/public/memory.h       Thu Feb 16 16:37:21 2006
+++ b/xen/include/public/memory.h       Thu Feb 16 17:52:06 2006
@@ -101,7 +101,7 @@
  */
 #define XENMEM_reserved_phys_area   7
 typedef struct xen_reserved_phys_area {
-    /* Which request to report about? */
+    /* Which domain to report about? */
     domid_t domid;
 
     /*
@@ -114,6 +114,28 @@
     unsigned long first_gpfn, nr_gpfns;
 } xen_reserved_phys_area_t;
 
+/*
+ * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+ * code on failure. This call only works for auto-translated guests.
+ */
+#define XENMEM_translate_gpfn_list  8
+typedef struct xen_translate_gpfn_list {
+    /* Which domain to translate for? */
+    domid_t domid;
+
+    /* Length of list. */
+    unsigned long nr_gpfns;
+
+    /* List of GPFNs to translate. */
+    unsigned long *gpfn_list;
+
+    /*
+     * Output list to contain MFN translations. May be the same as the input
+     * list (in which case each input GPFN is overwritten with the output MFN).
+     */
+    unsigned long *mfn_list;
+} xen_translate_gpfn_list_t;
+
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
 
 /*

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.