diff options
author | Andrei Dulea <adulea@amazon.de> | 2019-09-13 16:42:29 +0200 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2019-09-24 11:15:37 +0200 |
commit | 6ccb72f8374e17d60b58a7bfd5570496332c54e2 (patch) | |
tree | 58153196ad6c1423e86fa4388cd402bb13fe384f | |
parent | iommu/amd: Fix pages leak in free_pagetable() (diff) | |
download | linux-6ccb72f8374e17d60b58a7bfd5570496332c54e2.tar.xz linux-6ccb72f8374e17d60b58a7bfd5570496332c54e2.zip |
iommu/amd: Fix downgrading default page-sizes in alloc_pte()
Downgrading an existing large mapping to a mapping using smaller
page-sizes works only for the mappings created with page-mode 7 (i.e.
non-default page size).
Treat large mappings created with page-mode 0 (i.e. default page size)
like a non-present mapping and allow to overwrite it in alloc_pte().
While around, make sure that we flush the TLB only if we change an
existing mapping, otherwise we might end up acting on garbage PTEs.
Fixes: 6d568ef9a622 ("iommu/amd: Allow downgrading page-sizes in alloc_pte()")
Signed-off-by: Andrei Dulea <adulea@amazon.de>
-rw-r--r-- | drivers/iommu/amd_iommu.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 138547446345..c7e28a8d25d1 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1490,6 +1490,7 @@ static u64 *alloc_pte(struct protection_domain *domain, pte_level = PM_PTE_LEVEL(__pte); if (!IOMMU_PTE_PRESENT(__pte) || + pte_level == PAGE_MODE_NONE || pte_level == PAGE_MODE_7_LEVEL) { page = (u64 *)get_zeroed_page(gfp); if (!page) @@ -1500,7 +1501,7 @@ static u64 *alloc_pte(struct protection_domain *domain, /* pte could have been changed somewhere. */ if (cmpxchg64(pte, __pte, __npte) != __pte) free_page((unsigned long)page); - else if (pte_level == PAGE_MODE_7_LEVEL) + else if (IOMMU_PTE_PRESENT(__pte)) domain->updated = true; continue; |