Skip to content

Commit

Permalink
intel-iommu: ignore page table validation in pass through mode
Browse files Browse the repository at this point in the history
We are seeing a bug when booting w/ iommu=pt with current upstream
(bisect blames 19943b0 "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>
  • Loading branch information
Chris Wright authored and David Woodhouse committed Dec 8, 2009
1 parent 44cd613 commit 1672af1
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions drivers/pci/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1530,12 +1530,15 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,

/* Skip top levels of page tables for
* iommu which has less agaw than default.
* Unnecessary for PT mode.
*/
for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
pgd = phys_to_virt(dma_pte_addr(pgd));
if (!dma_pte_present(pgd)) {
spin_unlock_irqrestore(&iommu->lock, flags);
return -ENOMEM;
if (translation != CONTEXT_TT_PASS_THROUGH) {
for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
pgd = phys_to_virt(dma_pte_addr(pgd));
if (!dma_pte_present(pgd)) {
spin_unlock_irqrestore(&iommu->lock, flags);
return -ENOMEM;
}
}
}
}
Expand Down

0 comments on commit 1672af1

Please sign in to comment.