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

[Xen-changelog] [xen-unstable] grant iommu: Correctly handle multiple mappings of same MFN.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1276245074 -3600
# Node ID 2e38205b0d736bea92c3909cff6b363809f89d91
# Parent  04e81a65d27ef09654cd731735fc6a4ebc6314d4
grant iommu: Correctly handle multiple mappings of same MFN.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/common/grant_table.c |   44 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 38 insertions(+), 6 deletions(-)

diff -r 04e81a65d27e -r 2e38205b0d73 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Thu Jun 10 22:39:52 2010 +0100
+++ b/xen/common/grant_table.c  Fri Jun 11 09:31:14 2010 +0100
@@ -393,6 +393,29 @@ static int _set_status(unsigned gt_versi
         return _set_status_v2(domid, readonly, mapflag, shah, act, status);
 }
 
+static void mapcount(
+    struct domain *ld, unsigned long mfn,
+    unsigned int *wrc, unsigned int *rdc)
+{
+    struct grant_table *gt = ld->grant_table;
+    struct grant_mapping *map;
+    grant_handle_t handle;
+    struct domain *rd;
+
+    *wrc = *rdc = 0;
+
+    for ( handle = 0; handle < gt->maptrack_limit; handle++ )
+    {
+        map = &maptrack_entry(gt, handle);
+        if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
+            continue;
+        rd = rcu_lock_domain_by_id(map->domid);
+        if ( active_entry(rd->grant_table, map->ref).frame == mfn )
+            (map->flags & GNTMAP_readonly) ? (*rdc)++ : (*wrc)++;
+        rcu_unlock_domain(rd);
+    }
+}
+
 /*
  * Returns 0 if TLB flush / invalidate required by caller.
  * va will indicate the address to be invalidated.
@@ -598,17 +621,25 @@ __gnttab_map_grant_ref(
 
     if ( !is_hvm_domain(ld) && need_iommu(ld) )
     {
+        unsigned int wrc, rdc;
         int err = 0;
         /* Shouldn't happen, because you can't use iommu in a HVM domain. */
         BUG_ON(paging_mode_translate(ld));
         /* We're not translated, so we know that gmfns and mfns are
            the same things, so the IOMMU entry is always 1-to-1. */
+        mapcount(ld, frame, &wrc, &rdc);
         if ( (act_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) &&
              !(old_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
-            err = iommu_map_page(ld, frame, frame,
-                                 IOMMUF_readable|IOMMUF_writable);
+        {
+            if ( wrc == 0 )
+                err = iommu_map_page(ld, frame, frame,
+                                     IOMMUF_readable|IOMMUF_writable);
+        }
         else if ( act_pin && !old_pin )
-            err = iommu_map_page(ld, frame, frame, IOMMUF_readable);
+        {
+            if ( (wrc + rdc) == 0 )
+                err = iommu_map_page(ld, frame, frame, IOMMUF_readable);
+        }
         if ( err )
         {
             rc = GNTST_general_error;
@@ -785,12 +816,13 @@ __gnttab_unmap_common(
 
     if ( !is_hvm_domain(ld) && need_iommu(ld) )
     {
+        unsigned int wrc, rdc;
         int err = 0;
         BUG_ON(paging_mode_translate(ld));
-        if ( old_pin && !act->pin )
+        mapcount(ld, op->frame, &wrc, &rdc);
+        if ( (wrc + rdc) == 0 )
             err = iommu_unmap_page(ld, op->frame);
-        else if ( (old_pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) &&
-                  !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
+        else if ( wrc == 0 )
             err = iommu_map_page(ld, op->frame, op->frame, IOMMUF_readable);
         if ( err )
         {

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