[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.4] VT-d: don't crash when PTE bits 52 and up are non-zero
commit b4bde3fd8970ae44b88b5dc3f26ed9c1ea9a22da Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Feb 3 12:28:00 2015 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Feb 3 12:28:00 2015 +0100 VT-d: don't crash when PTE bits 52 and up are non-zero This can (and will) be legitimately the case when sharing page tables with EPT (more of a problem before p2m_access_rwx became zero, but still possible even now when other than that is the default for a guest), leading to an unconditional crash (in print_vtd_entries()) when a DMA remapping fault occurs. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx> master commit: 46e0baf59105200d43612cf0c59de216958b008d master date: 2015-01-07 11:13:58 +0100 --- xen/drivers/passthrough/vtd/iommu.c | 26 ++++++++------------------ xen/drivers/passthrough/vtd/iommu.h | 2 +- xen/drivers/passthrough/vtd/utils.c | 6 +++--- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index be346b2..81ea72f 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -259,8 +259,7 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) struct dma_pte *parent, *pte = NULL; int level = agaw_to_level(hd->agaw); int offset; - u64 pte_maddr = 0, maddr; - u64 *vaddr = NULL; + u64 pte_maddr = 0; addr &= (((u64)1) << addr_width) - 1; ASSERT(spin_is_locked(&hd->mapping_lock)); @@ -282,19 +281,19 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) offset = address_level_offset(addr, level); pte = &parent[offset]; - if ( dma_pte_addr(*pte) == 0 ) + pte_maddr = dma_pte_addr(*pte); + if ( !pte_maddr ) { if ( !alloc ) break; pdev = pci_get_pdev_by_domain(domain, -1, -1, -1); drhd = acpi_find_matched_drhd_unit(pdev); - maddr = alloc_pgtable_maddr(drhd, 1); - if ( !maddr ) + pte_maddr = alloc_pgtable_maddr(drhd, 1); + if ( !pte_maddr ) break; - dma_set_pte_addr(*pte, maddr); - vaddr = map_vtd_domain_page(maddr); + dma_set_pte_addr(*pte, pte_maddr); /* * high level table always sets r/w, last level @@ -304,21 +303,12 @@ static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) dma_set_pte_writable(*pte); iommu_flush_cache_entry(pte, sizeof(struct dma_pte)); } - else - { - vaddr = map_vtd_domain_page(pte->val); - } if ( level == 2 ) - { - pte_maddr = pte->val & PAGE_MASK_4K; - unmap_vtd_domain_page(vaddr); break; - } unmap_vtd_domain_page(parent); - parent = (struct dma_pte *)vaddr; - vaddr = NULL; + parent = map_vtd_domain_page(pte_maddr); level--; } @@ -2447,7 +2437,7 @@ static void vtd_dump_p2m_table_level(paddr_t pt_maddr, int level, paddr_t gpa, printk("%*sgfn: %08lx mfn: %08lx\n", indent, "", (unsigned long)(address >> PAGE_SHIFT_4K), - (unsigned long)(pte->val >> PAGE_SHIFT_4K)); + (unsigned long)(dma_pte_addr(*pte) >> PAGE_SHIFT_4K)); } unmap_vtd_domain_page(pt_vaddr); diff --git a/xen/drivers/passthrough/vtd/iommu.h b/xen/drivers/passthrough/vtd/iommu.h index 1a1f20a..a90f81a 100644 --- a/xen/drivers/passthrough/vtd/iommu.h +++ b/xen/drivers/passthrough/vtd/iommu.h @@ -276,7 +276,7 @@ struct dma_pte { #define dma_set_pte_snp(p) do {(p).val |= DMA_PTE_SNP;} while(0) #define dma_set_pte_prot(p, prot) \ do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0) -#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K) +#define dma_pte_addr(p) ((p).val & PADDR_MASK & PAGE_MASK_4K) #define dma_set_pte_addr(p, addr) do {\ (p).val |= ((addr) & PAGE_MASK_4K); } while (0) #define dma_pte_present(p) (((p).val & 3) != 0) diff --git a/xen/drivers/passthrough/vtd/utils.c b/xen/drivers/passthrough/vtd/utils.c index a33564b..db4c326 100644 --- a/xen/drivers/passthrough/vtd/utils.c +++ b/xen/drivers/passthrough/vtd/utils.c @@ -170,16 +170,16 @@ void print_vtd_entries(struct iommu *iommu, int bus, int devfn, u64 gmfn) l_index = get_level_index(gmfn, level); printk(" l%d_index = %x\n", level, l_index); - pte.val = val = l[l_index]; + pte.val = l[l_index]; unmap_vtd_domain_page(l); - printk(" l%d[%x] = %"PRIx64"\n", level, l_index, val); + printk(" l%d[%x] = %"PRIx64"\n", level, l_index, pte.val); - pte.val = val; if ( !dma_pte_present(pte) ) { printk(" l%d[%x] not present\n", level, l_index); break; } + val = dma_pte_addr(pte); } while ( --level ); } -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.4 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |