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

[Xen-changelog] [xen-unstable] Add a GNTTABOP to swap the content of two grant references under lock



# HG changeset patch
# User Wei Liu <wei.liu2@xxxxxxxxxx>
# Date 1327414564 0
# Node ID d115844ebfbb02bd785a4bd1b50fa31072f36bff
# Parent  370924e204dc29e12cd807dd730974d6b2bc53d3
Add a GNTTABOP to swap the content of two grant references under lock
provided that they are not currently active.

Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
Committed-by: Keir Fraser <keir@xxxxxxx>
---


diff -r 370924e204dc -r d115844ebfbb xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Jan 23 15:10:43 2012 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Tue Jan 24 14:16:04 2012 +0000
@@ -2959,6 +2959,7 @@
     case GNTTABOP_copy:
     case GNTTABOP_map_grant_ref:
     case GNTTABOP_unmap_grant_ref:
+    case GNTTABOP_swap_grant_ref:
         return 1;
     default:
         /* all other commands need auditing */
diff -r 370924e204dc -r d115844ebfbb xen/common/compat/grant_table.c
--- a/xen/common/compat/grant_table.c   Mon Jan 23 15:10:43 2012 +0000
+++ b/xen/common/compat/grant_table.c   Tue Jan 24 14:16:04 2012 +0000
@@ -47,6 +47,10 @@
 CHECK_gnttab_get_version;
 #undef xen_gnttab_get_version
 
+#define xen_gnttab_swap_grant_ref gnttab_swap_grant_ref
+CHECK_gnttab_swap_grant_ref;
+#undef xen_gnttab_swap_grant_ref
+
 int compat_grant_table_op(unsigned int cmd,
                           XEN_GUEST_HANDLE(void) cmp_uop,
                           unsigned int count)
@@ -98,6 +102,10 @@
     CASE(get_status_frames);
 #endif
 
+#ifndef CHECK_gnttab_swap_grant_ref
+    CASE(swap_grant_ref);
+#endif
+
 #undef CASE
     default:
         return do_grant_table_op(cmd, cmp_uop, count);
diff -r 370924e204dc -r d115844ebfbb xen/common/grant_table.c
--- a/xen/common/grant_table.c  Mon Jan 23 15:10:43 2012 +0000
+++ b/xen/common/grant_table.c  Tue Jan 24 14:16:04 2012 +0000
@@ -2283,6 +2283,81 @@
     return 0;
 }
 
+static s16
+__gnttab_swap_grant_ref(grant_ref_t ref_a, grant_ref_t ref_b)
+{
+    struct domain *d;
+    struct active_grant_entry *act;
+    s16 rc = GNTST_okay;
+
+    d = rcu_lock_current_domain();
+
+    spin_lock(&d->grant_table->lock);
+
+    act = &active_entry(d->grant_table, ref_a);
+    if ( act->pin )
+        PIN_FAIL(out, GNTST_eagain, "ref a %ld busy\n", (long)ref_a);
+
+    act = &active_entry(d->grant_table, ref_b);
+    if ( act->pin )
+        PIN_FAIL(out, GNTST_eagain, "ref b %ld busy\n", (long)ref_b);
+
+    if ( d->grant_table->gt_version == 1 )
+    {
+        grant_entry_v1_t shared;
+
+        shared = shared_entry_v1(d->grant_table, ref_a);
+
+        shared_entry_v1(d->grant_table, ref_a) =
+            shared_entry_v1(d->grant_table, ref_b);
+
+        shared_entry_v1(d->grant_table, ref_b) = shared;
+    }
+    else
+    {
+        grant_entry_v2_t shared;
+        grant_status_t status;
+
+        shared = shared_entry_v2(d->grant_table, ref_a);
+        status = status_entry(d->grant_table, ref_a);
+
+        shared_entry_v2(d->grant_table, ref_a) =
+            shared_entry_v2(d->grant_table, ref_b);
+        status_entry(d->grant_table, ref_a) =
+            status_entry(d->grant_table, ref_b);
+
+        shared_entry_v2(d->grant_table, ref_b) = shared;
+        status_entry(d->grant_table, ref_b) = status;
+    }
+
+out:
+    spin_unlock(&d->grant_table->lock);
+
+    rcu_unlock_domain(d);
+
+    return rc;
+}
+
+static long
+gnttab_swap_grant_ref(XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t uop),
+                      unsigned int count)
+{
+    int i;
+    gnttab_swap_grant_ref_t op;
+
+    for ( i = 0; i < count; i++ )
+    {
+        if ( i && hypercall_preempt_check() )
+            return i;
+        if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
+            return -EFAULT;
+        op.status = __gnttab_swap_grant_ref(op.ref_a, op.ref_b);
+        if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
+            return -EFAULT;
+    }
+    return 0;
+}
+
 long
 do_grant_table_op(
     unsigned int cmd, XEN_GUEST_HANDLE(void) uop, unsigned int count)
@@ -2401,6 +2476,20 @@
         rc = gnttab_get_version(guest_handle_cast(uop, gnttab_get_version_t));
         break;
     }
+    case GNTTABOP_swap_grant_ref:
+    {
+        XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t) swap =
+            guest_handle_cast(uop, gnttab_swap_grant_ref_t);
+        if ( unlikely(!guest_handle_okay(swap, count)) )
+            goto out;
+        rc = gnttab_swap_grant_ref(swap, count);
+        if ( rc > 0 )
+        {
+            guest_handle_add_offset(swap, rc);
+            uop = guest_handle_cast(swap, void);
+        }
+        break;
+    }
     default:
         rc = -ENOSYS;
         break;
diff -r 370924e204dc -r d115844ebfbb xen/include/public/grant_table.h
--- a/xen/include/public/grant_table.h  Mon Jan 23 15:10:43 2012 +0000
+++ b/xen/include/public/grant_table.h  Tue Jan 24 14:16:04 2012 +0000
@@ -511,6 +511,20 @@
 typedef struct gnttab_get_version gnttab_get_version_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
 
+/* 
+ * GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
+ */
+#define GNTTABOP_swap_grant_ref              11
+struct gnttab_swap_grant_ref {
+    /* IN parameters */
+    grant_ref_t ref_a;
+    grant_ref_t ref_b;
+    /* OUT parameters */
+    int16_t status;             /* GNTST_* */
+};
+typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
@@ -566,7 +580,7 @@
 #define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
 #define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary.   */
 #define GNTST_address_too_big (-11) /* transfer page address too large.      */
-#define GNTST_eagain          (-12) /* Could not map at the moment. Retry.   */
+#define GNTST_eagain          (-12) /* Operation not done; try again.        */
 
 #define GNTTABOP_error_msgs {                   \
     "okay",                                     \
@@ -581,7 +595,7 @@
     "bad page",                                 \
     "copy arguments cross page boundary",       \
     "page address size too large",              \
-    "could not map at the moment, retry"        \
+    "operation not done; try again"             \
 }
 
 #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
diff -r 370924e204dc -r d115844ebfbb xen/include/xlat.lst
--- a/xen/include/xlat.lst      Mon Jan 23 15:10:43 2012 +0000
+++ b/xen/include/xlat.lst      Tue Jan 24 14:16:04 2012 +0000
@@ -50,6 +50,7 @@
 ?      grant_entry_v1                  grant_table.h
 ?       grant_entry_header              grant_table.h
 ?      grant_entry_v2                  grant_table.h
+?      gnttab_swap_grant_ref           grant_table.h
 ?      kexec_exec                      kexec.h
 !      kexec_image                     kexec.h
 !      kexec_range                     kexec.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®.