Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
xen.481
54ad06e6-VT-d-don-t-crash-when-PTE-bits-52-and-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 54ad06e6-VT-d-don-t-crash-when-PTE-bits-52-and-up-are-non-zero.patch of Package xen.481
References: bsc#910254 # Commit 46e0baf59105200d43612cf0c59de216958b008d # Date 2015-01-07 11:13:58 +0100 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> 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@suse.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> --- 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 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 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 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(pad 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); --- 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) --- a/xen/drivers/passthrough/vtd/utils.c +++ b/xen/drivers/passthrough/vtd/utils.c @@ -170,16 +170,16 @@ void print_vtd_entries(struct iommu *iom 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 ); }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor