[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.12] AMD/IOMMU: fix off-by-one in amd_iommu_get_paging_mode() callers
commit 813757cf12eab38f3f86fc76a59d9e11749b4b27 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Thu Apr 9 09:29:00 2020 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Apr 9 09:29:00 2020 +0200 AMD/IOMMU: fix off-by-one in amd_iommu_get_paging_mode() callers amd_iommu_get_paging_mode() expects a count, not a "maximum possible" value. Prior to b4f042236ae0 dropping the reference, the use of our mis- named "max_page" in amd_iommu_domain_init() may have lead to such a misunderstanding. In an attempt to avoid such confusion in the future, rename the function's parameter and - while at it - convert it to an inline function. Also replace a literal 4 by an expression tying it to a wider use constant, just like amd_iommu_quarantine_init() does. Fixes: ea38867831da ("x86 / iommu: set up a scratch page in the quarantine domain") Fixes: b4f042236ae0 ("AMD/IOMMU: Cease using a dynamic height for the IOMMU pagetables") Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> master commit: b75b3c62fe4afe381c6f74a07f614c0b39fe2f5d master date: 2020-03-16 11:24:29 +0100 --- xen/drivers/passthrough/amd/iommu_map.c | 6 +++--- xen/drivers/passthrough/amd/pci_amd_iommu.c | 22 ++++------------------ xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index c05ed9c317..8f0ec3dc8e 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -653,9 +653,9 @@ void amd_iommu_share_p2m(struct domain *d) int __init amd_iommu_quarantine_init(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); - unsigned long max_gfn = - PFN_DOWN((1ul << DEFAULT_DOMAIN_ADDRESS_WIDTH) - 1); - unsigned int level = amd_iommu_get_paging_mode(max_gfn); + unsigned long end_gfn = + 1ul << (DEFAULT_DOMAIN_ADDRESS_WIDTH - PAGE_SHIFT); + unsigned int level = amd_iommu_get_paging_mode(end_gfn); uint64_t *table; if ( hd->arch.root_table ) diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index 00b34bf930..a0555e30a4 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -222,22 +222,6 @@ static int __must_check allocate_domain_resources(struct domain_iommu *hd) return rc; } -int amd_iommu_get_paging_mode(unsigned long entries) -{ - int level = 1; - - BUG_ON( !entries ); - - while ( entries > PTE_PER_TABLE_SIZE ) - { - entries = PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT; - if ( ++level > 6 ) - return -ENOMEM; - } - - return level; -} - static int amd_iommu_domain_init(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); @@ -250,8 +234,10 @@ static int amd_iommu_domain_init(struct domain *d) * physical address space we give it, but this isn't known yet so use 4 * unilaterally. */ - hd->arch.paging_mode = is_hvm_domain(d) - ? 4 : amd_iommu_get_paging_mode(get_upper_mfn_bound()); + hd->arch.paging_mode = amd_iommu_get_paging_mode( + is_hvm_domain(d) + ? 1ul << (DEFAULT_DOMAIN_ADDRESS_WIDTH - PAGE_SHIFT) + : get_upper_mfn_bound() + 1); return 0; } diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index 5a160b89ca..53189806bb 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -51,7 +51,6 @@ void get_iommu_features(struct amd_iommu *iommu); int amd_iommu_init(void); int amd_iommu_update_ivrs_mapping_acpi(void); -int amd_iommu_get_paging_mode(unsigned long entries); int amd_iommu_quarantine_init(struct domain *d); /* mapping functions */ @@ -169,6 +168,22 @@ static inline unsigned long region_to_pages(unsigned long addr, unsigned long si return (PAGE_ALIGN(addr + size) - (addr & PAGE_MASK)) >> PAGE_SHIFT; } +static inline int amd_iommu_get_paging_mode(unsigned long max_frames) +{ + int level = 1; + + BUG_ON(!max_frames); + + while ( max_frames > PTE_PER_TABLE_SIZE ) + { + max_frames = PTE_PER_TABLE_ALIGN(max_frames) >> PTE_PER_TABLE_SHIFT; + if ( ++level > 6 ) + return -ENOMEM; + } + + return level; +} + static inline struct page_info* alloc_amd_iommu_pgtable(void) { struct page_info *pg; -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.12
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |