@@ -1199,6 +1199,7 @@ int create_grant_host_mapping(unsigned long addr, unsigned long frame,
{
int rc;
p2m_type_t t = p2m_grant_map_rw;
+ struct domain *d = current->domain;
if ( cache_flags || (flags & ~GNTMAP_readonly) != GNTMAP_host_map )
return GNTST_general_error;
@@ -1206,13 +1207,32 @@ int create_grant_host_mapping(unsigned long addr, unsigned long frame,
if ( flags & GNTMAP_readonly )
t = p2m_grant_map_ro;
- rc = guest_physmap_add_entry(current->domain, addr >> PAGE_SHIFT,
- frame, 0, t);
+ rc = guest_physmap_add_entry(d, addr >> PAGE_SHIFT, frame, 0, t);
if ( rc )
- return GNTST_general_error;
- else
- return GNTST_okay;
+ goto gerror;
+
+ /* Grant mapping can be used for DMA request. The dev_bus_addr returned by
+ * the hypercall is the MFN (not the IPA). For device protected by
+ * an IOMMU, Xen needs to add a 1:1 mapping in the domain p2m to
+ * allow DMA request working.
+ * This is only valid when the domain is directed mapped
+ */
+ if ( is_domain_direct_mapped(d) && need_iommu(d) )
+ {
+ rc = guest_physmap_add_entry(d, frame, frame, 0, t);
+ if ( rc )
+ goto unmap;
+ }
+
+ return GNTST_okay;
+
+unmap:
+ guest_physmap_remove_page(d, addr >> PAGE_SHIFT, frame, 0);
+
+gerror:
+ return GNTST_general_error;
+
}
int replace_grant_host_mapping(unsigned long addr, unsigned long mfn,
@@ -1226,6 +1246,9 @@ int replace_grant_host_mapping(unsigned long addr, unsigned long mfn,
guest_physmap_remove_page(d, gfn, mfn, 0);
+ if ( is_domain_direct_mapped(d) && need_iommu(d) )
+ guest_physmap_remove_page(d, mfn, mfn, 0);
+
return GNTST_okay;
}