[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-4.0-testing] grant iommu: Correctly handle multiple mappings of same MFN.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1276261283 -3600 # Node ID 351daae7d22555c6b981919774e9762511474187 # Parent 2ad3a78c8cd66b335e7f3a2782826c5780358ee2 grant iommu: Correctly handle multiple mappings of same MFN. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> xen-unstable changeset: 21597:2e38205b0d73 xen-unstable date: Fri Jun 11 09:31:14 2010 +0100 --- xen/common/grant_table.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 files changed, 38 insertions(+), 6 deletions(-) diff -r 2ad3a78c8cd6 -r 351daae7d225 xen/common/grant_table.c --- a/xen/common/grant_table.c Fri Jun 11 14:01:02 2010 +0100 +++ b/xen/common/grant_table.c Fri Jun 11 14:01:23 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |