lkml.org 
[lkml]   [2020]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: [PATCH] iommu/vt-d: Fix a bug in intel_iommu_iova_to_phys() for huge page
From
Date
Hi Yonghyun,

Thanks for the patch.

On 2020/2/19 6:23, Yonghyun Hwang wrote:
> intel_iommu_iova_to_phys() has a bug when it translates an IOVA for a huge
> page onto its corresponding physical address. This commit fixes the bug by
> accomodating the level of page entry for the IOVA and adds IOVA's lower
> address to the physical address. >
> Signed-off-by: Yonghyun Hwang <yonghyun@google.com>
> ---
> drivers/iommu/intel-iommu.c | 11 +++++++++--
> 1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 0c8d81f56a30..ed6e69adb578 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -5555,13 +5555,20 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
> struct dma_pte *pte;
> int level = 0;
> u64 phys = 0;
> + const unsigned long pfn = iova >> VTD_PAGE_SHIFT;

Why do you need a "const unsigned long" here?

>
> if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
> return 0;
>
> - pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
> - if (pte)
> + pte = pfn_to_dma_pte(dmar_domain, pfn, &level);
> + if (pte) {
> phys = dma_pte_addr(pte);
> + if (level > 1)
> + phys += (pfn &
> + ((1UL << level_to_offset_bits(level)) - 1))
> + << VTD_PAGE_SHIFT;
> + phys += iova & (VTD_PAGE_SIZE - 1);

How about

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 9dc37672bf89..bd17c2510bb2 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5693,8 +5693,14 @@ static phys_addr_t
intel_iommu_iova_to_phys(struct iommu_domain *domain,
u64 phys = 0;

pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
- if (pte)
+ if (pte) {
+ unsigned long offset_mask;
+
+ offset_mask = BIT_MASK(level_to_offset_bits(level) +
+ VTD_PAGE_SHIFT) - 1;
phys = dma_pte_addr(pte);
+ phys += iova & (bitmask - 1);
+ }

return phys;
}
Best regards,
baolu

\
 
 \ /
  Last update: 2020-02-19 04:16    [W:0.064 / U:0.144 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site