intel-iommu: iova_to_phys: fill in bits from iova when large pte
intel_iommu_iova_to_phys returns incorrect physical address when iova is translated by large pte.
Fill in bits from iova when creating the physical address.
drivers/iommu/intel-iommu.c +22 -7
@@ -774,7 +774,8 @@ out: }static struct dma_pte *pfn_to_dma_pte (struct dmar_domain *domain, -unsigned long pfn,int target_level) +unsigned long pfn,int target_level, +int *large_page) {int addr_width =agaw_to_width (domain->agaw) -VTD_PAGE_SHIFT ;struct dma_pte *parent, *pte =NULL ;
@@ -790,8 +791,15 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, offset =pfn_level_offset (pfn, level); pte = &parent[offset]; -if (!target_level && (dma_pte_superpage (pte) || !dma_pte_present (pte))) -break ; +if (!target_level) { +if (!dma_pte_present (pte)) +break ; +if (dma_pte_superpage (pte)) { +if (large_page) + *large_page = level; +break ; + } + }if (level == target_level)break ;
@@ -1824,7 +1832,8 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,if (!pte) { largepage_lvl =hardware_largepage_caps (domain, iov_pfn, phys_pfn, sg_res); - first_pte = pte =pfn_to_dma_pte (domain, iov_pfn, largepage_lvl); + first_pte = pte =pfn_to_dma_pte (domain, iov_pfn, + largepage_lvl,NULL );if (!pte)return -ENOMEM ;/* It is large page*/
@@ -4129,11 +4138,17 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, {struct dmar_domain *dmar_domain = domain->priv;struct dma_pte *pte; -u64 phys =0 ; +u64 phys =0 , iova_mask; +int large_page =1 ; - pte =pfn_to_dma_pte (dmar_domain, iova >>VTD_PAGE_SHIFT ,0 ); -if (pte) + pte =pfn_to_dma_pte (dmar_domain, iova >>VTD_PAGE_SHIFT ,0 , + &large_page); +if (pte) { phys =dma_pte_addr (pte); + large_page--; + iova_mask = (1ULL << (VTD_PAGE_SHIFT +(large_page*9 )))-1 ; + phys |= iova & iova_mask; + }return phys; }
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 5 lines · Marcelo Tosatti
intel_iommu_iova_to_physreturns incorrect physical address when iova is translated by large pte.Fill in bits from iova when creating the physical address.
Marcelo, for what it's worth, this patch alone didn't fix the BUG when using KVM PCI assignment with huge pages. I still needed the hva alignment patch as well.
Greg
Quoted 5 lines · Greg Edwards
Quoted 4 lines · Marcelo Tosatti
intel_iommu_iova_to_physreturns incorrect physical address when iova is translated by large pte.
Quoted 7 lines
Quoted 1 line
Fill in bits from iova when creating the physical address.
Marcelo, for what it's worth, this patch alone didn't fix the BUG when using KVM PCI assignment with huge pages. I still needed the hva alignment patch as well.
Greg
Yep, still a bugfix though.
Good catch, Greg.