aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2011-11-10 04:32:26 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2011-11-10 05:40:37 -0500
commit7d3002cc8c160dbda0e6ab9cd66dc6eb401b8b70 (patch)
tree453bad0319d12fc0a3fe6594b8e212615e7e2a70 /virt/kvm
parent5009065d38c95455bd2d27c2838313e3dd0c5bc7 (diff)
iommu/core: split mapping to page sizes as supported by the hardware
When mapping a memory region, split it to page sizes as supported by the iommu hardware. Always prefer bigger pages, when possible, in order to reduce the TLB pressure. The logic to do that is now added to the IOMMU core, so neither the iommu drivers themselves nor users of the IOMMU API have to duplicate it. This allows a more lenient granularity of mappings; traditionally the IOMMU API took 'order' (of a page) as a mapping size, and directly let the low level iommu drivers handle the mapping, but now that the IOMMU core can split arbitrary memory regions into pages, we can remove this limitation, so users don't have to split those regions by themselves. Currently the supported page sizes are advertised once and they then remain static. That works well for OMAP and MSM but it would probably not fly well with intel's hardware, where the page size capabilities seem to have the potential to be different between several DMA remapping devices. register_iommu() currently sets a default pgsize behavior, so we can convert the IOMMU drivers in subsequent patches. After all the drivers are converted, the temporary default settings will be removed. Mainline users of the IOMMU API (kvm and omap-iovmm) are adopted to deal with bytes instead of page order. Many thanks to Joerg Roedel <Joerg.Roedel@amd.com> for significant review! Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Cc: David Brown <davidb@codeaurora.org> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Joerg Roedel <Joerg.Roedel@amd.com> Cc: Stepan Moskovchenko <stepanm@codeaurora.org> Cc: KyongHo Cho <pullip.cho@samsung.com> Cc: Hiroshi DOYU <hdoyu@nvidia.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: kvm@vger.kernel.org Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/iommu.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index a195c07fa829..304d7e5717e9 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -113,7 +113,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
113 113
114 /* Map into IO address space */ 114 /* Map into IO address space */
115 r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn), 115 r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn),
116 get_order(page_size), flags); 116 page_size, flags);
117 if (r) { 117 if (r) {
118 printk(KERN_ERR "kvm_iommu_map_address:" 118 printk(KERN_ERR "kvm_iommu_map_address:"
119 "iommu failed to map pfn=%llx\n", pfn); 119 "iommu failed to map pfn=%llx\n", pfn);
@@ -292,15 +292,15 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
292 292
293 while (gfn < end_gfn) { 293 while (gfn < end_gfn) {
294 unsigned long unmap_pages; 294 unsigned long unmap_pages;
295 int order; 295 size_t size;
296 296
297 /* Get physical address */ 297 /* Get physical address */
298 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn)); 298 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
299 pfn = phys >> PAGE_SHIFT; 299 pfn = phys >> PAGE_SHIFT;
300 300
301 /* Unmap address from IO address space */ 301 /* Unmap address from IO address space */
302 order = iommu_unmap(domain, gfn_to_gpa(gfn), 0); 302 size = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
303 unmap_pages = 1ULL << order; 303 unmap_pages = 1ULL << get_order(size);
304 304
305 /* Unpin all pages we just unmapped to not leak any memory */ 305 /* Unpin all pages we just unmapped to not leak any memory */
306 kvm_unpin_pages(kvm, pfn, unmap_pages); 306 kvm_unpin_pages(kvm, pfn, unmap_pages);