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

[Xen-devel] [PATCH 6 of 8] Implement sub-page grant support



# HG changeset patch
# User Steven Smith <steven.smith@xxxxxxxxxxxxx>
# Date 1222085347 -3600
# Node ID e9b623fd710f2130bcb925161abe26c6980b91c3
# Parent  842baf721920b032f358ad326145817b42d053a1
Implement sub-page grant support.

Signed-off-by: Steven Smith <steven.smith@xxxxxxxxxx>

diff -r 842baf721920 -r e9b623fd710f xen/common/grant_table.c
--- a/xen/common/grant_table.c  Mon Sep 22 12:23:28 2008 +0100
+++ b/xen/common/grant_table.c  Mon Sep 22 13:09:07 2008 +0100
@@ -210,6 +210,7 @@
 
 static int _set_status_v1(domid_t  domid,
                           int readonly,
+                          int mapflag,
                           grant_entry_header_t *shah, 
                           struct active_grant_entry *act)
 {
@@ -226,6 +227,11 @@
      * so we allow a few retries before failing.
      */
     int retries = 0;
+
+    /* if this is a grant mapping operation we should ensure GTF_sub_page
+       is not set */
+    if (mapflag)
+        mask |= GTF_sub_page;
 
     scombo.word = *(u32 *)shah;
 
@@ -276,6 +282,7 @@
 
 static int _set_status_v2(domid_t  domid,
                           int readonly,
+                          int mapflag,
                           grant_entry_header_t *shah, 
                           struct active_grant_entry *act,
                           grant_status_t *status)
@@ -294,6 +301,11 @@
                   it back into two reads */
     flags = scombo.shorts.flags;
     id = scombo.shorts.domid;
+
+    /* if this is a grant mapping operation we should ensure GTF_sub_page
+       is not set */
+    if (mapflag)
+        mask |= GTF_sub_page;
 
     /* If not already pinned, check the grant domid and type. */
     if ( !act->pin &&
@@ -355,15 +367,16 @@
 static int _set_status(unsigned gt_version,
                        domid_t  domid,
                        int readonly,
+                       int mapflag,
                        grant_entry_header_t *shah,
                        struct active_grant_entry *act,
                        grant_status_t *status)
 {
 
     if (gt_version == 1)
-        return _set_status_v1(domid, readonly, shah, act);
+        return _set_status_v1(domid, readonly, mapflag, shah, act);
     else
-        return _set_status_v2(domid, readonly, shah, act, status);
+        return _set_status_v2(domid, readonly, mapflag, shah, act, status);
 }
 
 /*
@@ -460,10 +473,11 @@
     /* If already pinned, check the active domid and avoid refcnt overflow. */
     if ( act->pin &&
          ((act->domid != ld->domain_id) ||
-          (act->pin & 0x80808080U) != 0) )
+          (act->pin & 0x80808080U) != 0 ||
+          (act->is_sub_page)) )
         PIN_FAIL(unlock_out, GNTST_general_error,
-                 "Bad domain (%d != %d), or risk of counter overflow %08x\n",
-                 act->domid, ld->domain_id, act->pin);
+                 "Bad domain (%d != %d), or risk of counter overflow %08x, or 
subpage %d\n",
+                 act->domid, ld->domain_id, act->pin, act->is_sub_page);
 
     if ( !act->pin ||
          (!(op->flags & GNTMAP_readonly) &&
@@ -471,7 +485,7 @@
     {
         if ( (rc = _set_status(rd->grant_table->gt_version,
                                ld->domain_id, op->flags & GNTMAP_readonly,
-                               shah, act, status) ) != GNTST_okay )
+                               1, shah, act, status) ) != GNTST_okay )
              goto unlock_out;
 
         if ( !act->pin )
@@ -482,6 +496,9 @@
             else
                 act->gfn = sha2->full_page.frame;
             act->frame = gmfn_to_mfn(rd, act->gfn);
+            act->start = 0;
+            act->length = PAGE_SIZE;
+            act->is_sub_page = 0;
         }
     }
 
@@ -1554,7 +1571,7 @@
 static int
 __acquire_grant_for_copy(
     struct domain *rd, unsigned long gref, int readonly,
-    unsigned long *frame)
+    unsigned long *frame, unsigned *page_off, unsigned *length)
 {
     grant_entry_v1_t *sha1;
     grant_entry_v2_t *sha2;
@@ -1601,21 +1618,40 @@
     {
         if ( (rc = _set_status(rd->grant_table->gt_version,
                                current->domain->domain_id, 
-                               readonly, shah, act, status) ) != GNTST_okay )
+                               readonly, 0, shah, act, status) ) != GNTST_okay 
)
              goto unlock_out;
+
         if ( !act->pin )
         {
             act->domid = current->domain->domain_id;
+            act->is_sub_page = 0;
+            act->start = 0;
+            act->length = PAGE_SIZE;
+
             if ( sha1 )
+            {
                 act->gfn = sha1->frame;
+            }
+            else if ( shah->flags & GTF_sub_page )
+            {
+                act->start = sha2->sub_page.page_off;
+                act->length = sha2->sub_page.length;
+                act->is_sub_page = 1;
+                act->gfn = sha2->sub_page.frame;
+            }
             else
+            {
                 act->gfn = sha2->full_page.frame;
+            }
+
             act->frame = gmfn_to_mfn(rd, act->gfn);
         }
     }
 
     act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
 
+    *page_off = act->start;
+    *length = act->length;
     *frame = act->frame;
 
  unlock_out:
@@ -1667,10 +1703,18 @@
 
     if ( src_is_gref )
     {
-        rc = __acquire_grant_for_copy(sd, op->source.u.ref, 1, &s_frame);
+        unsigned source_off, source_len;
+        rc = __acquire_grant_for_copy(sd, op->source.u.ref, 1, &s_frame,
+                                      &source_off, &source_len);
         if ( rc != GNTST_okay )
             goto error_out;
         have_s_grant = 1;
+        if ( op->source.offset < source_off ||
+             op->len > source_len )
+            PIN_FAIL(error_out, GNTST_general_error,
+                     "copy source out of bounds: %d < %d || %d > %d\n",
+                     op->source.offset, source_off,
+                     op->len, source_len);
     }
     else
     {
@@ -1690,10 +1734,18 @@
 
     if ( dest_is_gref )
     {
-        rc = __acquire_grant_for_copy(dd, op->dest.u.ref, 0, &d_frame);
+        unsigned dest_off, dest_len;
+        rc = __acquire_grant_for_copy(dd, op->dest.u.ref, 0, &d_frame,
+                                      &dest_off, &dest_len);
         if ( rc != GNTST_okay )
             goto error_out;
         have_d_grant = 1;
+        if ( op->dest.offset < dest_off ||
+             op->len > dest_len )
+            PIN_FAIL(error_out, GNTST_general_error,
+                     "copy dest out of bounds: %d < %d || %d > %d\n",
+                     op->dest.offset, dest_off,
+                     op->len, dest_len);
     }
     else
     {
diff -r 842baf721920 -r e9b623fd710f xen/include/public/grant_table.h
--- a/xen/include/public/grant_table.h  Mon Sep 22 12:23:28 2008 +0100
+++ b/xen/include/public/grant_table.h  Mon Sep 22 13:09:07 2008 +0100
@@ -130,6 +130,9 @@
  *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
  *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
  *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
+ *  GTF_sub_page: Grant access to only a subrange of the page.  @domid
+ *                will only be allowed to copy from the grant, and not
+ *                map it. [GST]
  */
 #define _GTF_readonly       (2)
 #define GTF_readonly        (1U<<_GTF_readonly)
@@ -143,6 +146,8 @@
 #define GTF_PCD             (1U<<_GTF_PCD)
 #define _GTF_PAT            (7)
 #define GTF_PAT             (1U<<_GTF_PAT)
+#define _GTF_sub_page       (8)
+#define GTF_sub_page        (1U<<_GTF_sub_page)
 
 /*
  * Subflags for GTF_accept_transfer:
@@ -200,6 +205,18 @@
         uint32_t pad0;
         uint64_t frame;
     } full_page;
+
+    /*
+     * If the grant type is GTF_grant_access and GTF_sub_page is set,
+     * @domid is allowed to access bytes [@page_off,@page_off+@length)
+     * in frame @frame.
+     */
+    struct {
+        grant_entry_header_t hdr;
+        uint16_t page_off;
+        uint16_t length;
+        uint64_t frame;
+    } sub_page;
 
     uint32_t __spacer[4]; /* Pad to a power of two */
 };
diff -r 842baf721920 -r e9b623fd710f xen/include/xen/grant_table.h
--- a/xen/include/xen/grant_table.h     Mon Sep 22 12:23:28 2008 +0100
+++ b/xen/include/xen/grant_table.h     Mon Sep 22 13:09:07 2008 +0100
@@ -30,10 +30,15 @@
 
 /* Active grant entry - used for shadowing GTF_permit_access grants. */
 struct active_grant_entry {
-    u32           pin;    /* Reference count information.  */
-    domid_t       domid;  /* Domain being granted access.  */
+    u32           pin;    /* Reference count information.             */
+    domid_t       domid;  /* Domain being granted access.             */
+    unsigned long frame;  /* Frame being granted.                     */
     unsigned long gfn;    /* Guest's idea of the frame being granted. */
-    unsigned long frame;  /* Frame being granted.          */
+    unsigned      is_sub_page:1; /* True if this is a sub-page grant. */
+    unsigned      start:15; /* For sub-page grants, the start offset
+                               in the page.                           */
+    unsigned      length:16; /* For sub-page grants, the length of the
+                                grant.                                */
 };
 
  /* Count of writable host-CPU mappings. */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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