aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intel-iommu.c
diff options
context:
space:
mode:
authorChris Wright <chrisw@sous-sol.org>2009-12-02 15:06:34 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-12-08 05:03:25 -0500
commit1672af1164d3d50ba8908014fd34cc0b58afdc1e (patch)
treeb485a7cfb4b305906bb19c145cd3e4ff9e1fe349 /drivers/pci/intel-iommu.c
parent44cd613c0e4cd93079ea2a93aa06649d8ca0830a (diff)
intel-iommu: ignore page table validation in pass through mode
We are seeing a bug when booting w/ iommu=pt with current upstream (bisect blames 19943b0e30b05d42e494ae6fef78156ebc8c637e "intel-iommu: Unify hardware and software passthrough support). The issue is specific to this loop during identity map initialization of each device: domain_context_mapping_one(si_domain, ..., CONTEXT_TT_PASS_THROUGH) ... /* Skip top levels of page tables for * iommu which has less agaw than default. */ for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) { pgd = phys_to_virt(dma_pte_addr(pgd)); if (!dma_pte_present(pgd)) { <------ failing here spin_unlock_irqrestore(&iommu->lock, flags); return -ENOMEM; } This box has 2 iommu's in it. The catchall iommu has MGAW == 48, and SAGAW == 4. The other iommu has MGAW == 39, SAGAW == 2. The device that's failing the above pgd test is the only device connected to the non-catchall iommu, which has a smaller address width than the domain default. This test is not necessary since the context is in PT mode and the ASR is ignored. Thanks to Don Dutile for discovering and debugging this one. Cc: stable@kernel.org Signed-off-by: Chris Wright <chrisw@sous-sol.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r--drivers/pci/intel-iommu.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index e3e84cac0e98..466079535330 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1530,12 +1530,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
1530 1530
1531 /* Skip top levels of page tables for 1531 /* Skip top levels of page tables for
1532 * iommu which has less agaw than default. 1532 * iommu which has less agaw than default.
1533 * Unnecessary for PT mode.
1533 */ 1534 */
1534 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) { 1535 if (translation != CONTEXT_TT_PASS_THROUGH) {
1535 pgd = phys_to_virt(dma_pte_addr(pgd)); 1536 for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
1536 if (!dma_pte_present(pgd)) { 1537 pgd = phys_to_virt(dma_pte_addr(pgd));
1537 spin_unlock_irqrestore(&iommu->lock, flags); 1538 if (!dma_pte_present(pgd)) {
1538 return -ENOMEM; 1539 spin_unlock_irqrestore(&iommu->lock, flags);
1540 return -ENOMEM;
1541 }
1539 } 1542 }
1540 } 1543 }
1541 } 1544 }