From patchwork Fri Jun 3 19:31:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Woodhouse X-Patchwork-Id: 848142 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p53JVcwa022491 for ; Fri, 3 Jun 2011 19:31:38 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754076Ab1FCTbf (ORCPT ); Fri, 3 Jun 2011 15:31:35 -0400 Received: from casper.infradead.org ([85.118.1.10]:54153 "EHLO casper.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751553Ab1FCTbf (ORCPT ); Fri, 3 Jun 2011 15:31:35 -0400 Received: from i7.infradead.org ([2001:8b0:10b:1:225:64ff:fee8:e9df]) by casper.infradead.org with esmtpsa (Exim 4.76 #1 (Red Hat Linux)) id 1QSa0B-0006be-KR; Fri, 03 Jun 2011 19:25:47 +0000 Subject: [RFC][PATCH] Fix superpage unmap on Intel IOMMU From: David Woodhouse To: kvm@vger.kernel.org, "Kay, Allen M" Cc: joerg.roedel@amd.com, alex.williamson@redhat.com, iommu@lists.linux-foundation.org Date: Fri, 03 Jun 2011 20:31:30 +0100 X-Mailer: Evolution 3.0.2 (3.0.2-1.fc15) Message-ID: <1307129491.23418.4.camel@i7.infradead.org> Mime-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org See http://www.infradead.org/rpr.html Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Fri, 03 Jun 2011 19:31:38 +0000 (UTC) Tell me it isn't so... diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 59f17ac..6c588ee 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3866,6 +3866,20 @@ static int intel_iommu_unmap(struct iommu_domain *domain, struct dmar_domain *dmar_domain = domain->priv; size_t size = PAGE_SIZE << gfp_order; + /* The KVM code is *fucked* in the head. It maps the range + one page at a time, using 4KiB pages unless it actually + allocated hugepages using hugetlbfs. (So we get to flush + the CPU data cache and then the IOTLB for each page in + its loop). And on unmap, it unmaps 4KiB at a time (always + passing gfp_order==0), regardless of whether it mapped + using superpages or not. So on unmap, if we detect a + superpage in our page tables we are expected to unmap + *more* than we are asked to, and return a value indicating + how much we actually unmapped. WTF? */ + if (dma_pfn_level_pte (dmar_domain, iova >> VTD_PAGE_SHIFT, + 1, &gfp_order)) + size = PAGE_SIZE << gfp_order; + dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, (iova + size - 1) >> VTD_PAGE_SHIFT);