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

Re: [Xen-devel] [PATCH] Allow programatic iomem permissions



On Fri, 2007-07-13 at 15:12 +0100, Keir Fraser wrote:
> On 13/7/07 14:03, "Kieran Mansley" <kmansley@xxxxxxxxxxxxxx> wrote:
> 
> >> The issue is that the granter is informed that the grant is released before
> >> stale grantee TLB entries are flushed. If the grantee is multi-vcpu then he
> >> could theoretically still access a granted page via a stale TLB entry after
> >> the granter has recycled the page. The window is extremely tiny though! The
> >> correct fix is to reorder the unmap operation to be unmap-list-of-grants
> >> then TLB-flush then update-grant-entries-to-indicate-release. Then the 
> >> whole
> >> problem disappears.
> > 
> > OK, that makes sense, and doesn't at first impression look too hard to
> > rectify.
> > 
> > Am I right in thinking that it's the shared grant table entry that is
> > the critical one in this sense (as opposed to the "active" entry).
> 
> That's correct.

OK, patch attached.  It compiles and seems to work, but hasn't been
heavily tested yet.  I'm sure it could be more efficient, but wanted to
check I was heading in the right direction.

Kieran

Fix TLB flush on grant unmap

diff -r 87cc3035108f xen/common/grant_table.c
--- a/xen/common/grant_table.c  Fri Jul 13 14:32:11 2007 +0100
+++ b/xen/common/grant_table.c  Fri Jul 13 16:35:27 2007 +0100
@@ -505,16 +505,49 @@ __gnttab_unmap_common(
         }
     }
 
-    if ( (map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
-    {
-        map->flags = 0;
-        put_maptrack_handle(ld->grant_table, op->handle);
-    }
-
     /* If just unmapped a writable mapping, mark as dirtied */
     if ( !(flags & GNTMAP_readonly) )
          gnttab_mark_dirty(rd, frame);
 
+ unmap_out:
+    op->status = rc;
+    spin_unlock(&rd->grant_table->lock);
+    rcu_unlock_domain(rd);
+}
+
+static void
+__gnttab_unmap_common_complete(struct gnttab_unmap_common *op)
+{
+    struct domain   *ld, *rd;
+    domid_t          dom;
+    struct active_grant_entry *act;
+    grant_entry_t   *sha;
+    struct grant_mapping *map;
+    u16 flags;
+
+    ld = current->domain;
+    map = &maptrack_entry(ld->grant_table, op->handle);
+    dom = map->domid;
+    flags = map->flags;
+
+    if ( unlikely((rd = rcu_lock_domain_by_id(dom)) == NULL) ) {
+        /* This shouldn't happen - __gnttab_unmap_common should have
+           already crashed the domain */
+        gdprintk(XENLOG_INFO, "Could not find domain %d\n", dom);
+        return;
+    }
+       
+    spin_lock(&rd->grant_table->lock);
+
+    act = &active_entry(rd->grant_table, map->ref);
+    sha = &shared_entry(rd->grant_table, map->ref);
+
+    if ( (map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
+    {
+        map->flags = 0;
+        put_maptrack_handle(ld->grant_table, op->handle);
+    }
+
     if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
          !(flags & GNTMAP_readonly) )
         gnttab_clear_flag(_GTF_writing, &sha->flags);
@@ -522,8 +555,6 @@ __gnttab_unmap_common(
     if ( act->pin == 0 )
         gnttab_clear_flag(_GTF_reading, &sha->flags);
 
- unmap_out:
-    op->status = rc;
     spin_unlock(&rd->grant_table->lock);
     rcu_unlock_domain(rd);
 }
@@ -542,28 +573,51 @@ __gnttab_unmap_grant_ref(
     op->status = common.status;
 }
 
+static void
+__gnttab_unmap_grant_ref_complete(struct gnttab_unmap_grant_ref *op)
+{
+    struct gnttab_unmap_common common = {
+       .host_addr = op->host_addr,
+       .dev_bus_addr = op->dev_bus_addr,
+       .handle = op->handle,
+    };
+
+    __gnttab_unmap_common_complete(&common);
+}
+
 static long
 gnttab_unmap_grant_ref(
     XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t) uop, unsigned int count)
 {
-    int i;
+    int i, done = 0;
+    long rc = -EFAULT;
     struct gnttab_unmap_grant_ref op;
 
     for ( i = 0; i < count; i++ )
     {
         if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
-            goto fault;
+            goto out;
         __gnttab_unmap_grant_ref(&op);
+        ++done;
         if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
-            goto fault;
-    }
-
+            goto out;
+    }
+
+    rc = 0;
+
+out:
     flush_tlb_mask(current->domain->domain_dirty_cpumask);
-    return 0;
-
-fault:
-    flush_tlb_mask(current->domain->domain_dirty_cpumask);
-    return -EFAULT;    
+
+    for ( i = 0; i < done; i++ )
+    {
+        if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
+            /* This really shouldn't happen as it worked earlier in
+               the function */
+            continue;
+        __gnttab_unmap_grant_ref_complete(&op);
+
+    }
+    return rc;
 }
 
 static void
@@ -580,28 +634,51 @@ __gnttab_unmap_and_replace(
     op->status = common.status;
 }
 
+static void
+__gnttab_unmap_and_replace(
+    struct gnttab_unmap_and_replace *op)
+{
+    struct gnttab_unmap_common common = {
+       .host_addr = op->host_addr,
+       .new_addr = op->new_addr,
+       .handle = op->handle,
+    };
+
+    __gnttab_unmap_common_complete(&common);
+}
+
 static long
 gnttab_unmap_and_replace(
     XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t) uop, unsigned int
count)
 {
-    int i;
+    int i, done = 0;
+    long rc = -EFAULT;
     struct gnttab_unmap_and_replace op;
 
     for ( i = 0; i < count; i++ )
     {
         if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
-            goto fault;
+            goto out;
         __gnttab_unmap_and_replace(&op);
+        ++done;
         if ( unlikely(__copy_to_guest_offset(uop, i, &op, 1)) )
-            goto fault;
-    }
-
+            goto out;
+    }
+
+    rc = 0;
+
+out:
     flush_tlb_mask(current->domain->domain_dirty_cpumask);
-    return 0;
-
-fault:
-    flush_tlb_mask(current->domain->domain_dirty_cpumask);
-    return -EFAULT;    
+
+    for ( i = 0; i < done; i++ )
+    {
+        if ( unlikely(__copy_from_guest_offset(&op, uop, i, 1)) )
+            /* This really shouldn't happen as it worked earlier in
+               the function */
+            continue;
+        __gnttab_unmap_and_replace_complete(&op);
+    }
+    return rc;    
 }
 
 int

Attachment: unmap_tlb_fix
Description: Text document

_______________________________________________
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®.