* Re: [PATCH] VT-d: IOTLB flush fixups [not found] <1211950777.17461.0.camel@ip6-localhost> @ 2008-05-28 9:01 ` Yang, Xiaowei [not found] ` <1211965013.16052.16.camel@ip6-localhost> 1 sibling, 0 replies; 4+ messages in thread From: Yang, Xiaowei @ 2008-05-28 9:01 UTC (permalink / raw) To: espen.skoglund; +Cc: xen-devel [-- Attachment #1: Type: text/plain, Size: 783 bytes --] > On map: only flush when old PTE was valid or invalid PTE may be cached. > On unmap: always flush old entry, but skip flush for unaffected IOMMUs. > > Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com> > > -- > iommu.c | 17 +++++++++++------ > 1 file changed, 11 insertions(+), 6 deletions(-) > -- Seems my last mail sent to the xen-devel is lost and I have no local copy so I have to write again... Espen, Thanks for the patch! I also noticed context/iotlb flush need a cleanup. As flush of present/non-present entry are different, your change to iommu_intel_map_page are not that correct. So I made up anther patch. iommu_flush is also removed, as VTd table is not shared with p2m any more. Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com> Thanks, Xiaowei [-- Attachment #2: flush.diff --] [-- Type: text/x-patch, Size: 7951 bytes --] diff -r c93a913c221f xen/arch/x86/mm/hap/p2m-ept.c --- a/xen/arch/x86/mm/hap/p2m-ept.c Tue May 27 13:03:05 2008 +0100 +++ b/xen/arch/x86/mm/hap/p2m-ept.c Wed May 28 06:24:27 2008 +0800 @@ -266,12 +266,6 @@ out: iommu_unmap_page(d, gfn); } } - -#ifdef P2M_SHARE_WITH_VTD_PAGE_TABLE - /* If p2m table is shared with vtd page-table. */ - if ( iommu_enabled && is_hvm_domain(d) && (p2mt == p2m_mmio_direct) ) - iommu_flush(d, gfn, (u64*)ept_entry); -#endif return rv; } diff -r c93a913c221f xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Tue May 27 13:03:05 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed May 28 06:59:25 2008 +0800 @@ -485,9 +485,12 @@ static int flush_iotlb_reg(void *_iommu, /* check IOTLB invalidation granularity */ if ( DMA_TLB_IAIG(val) == 0 ) printk(KERN_ERR VTDPREFIX "IOMMU: flush IOTLB failed\n"); + +#ifdef VTD_DEBUG if ( DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type) ) printk(KERN_ERR VTDPREFIX "IOMMU: tlb flush request %x, actual %x\n", (u32)DMA_TLB_IIRG(type), (u32)DMA_TLB_IAIG(val)); +#endif /* flush context entry will implictly flush write buffer */ return 0; } @@ -581,30 +584,29 @@ static void dma_pte_clear_one(struct dom drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); /* get last level pte */ - pg_maddr = dma_addr_level_page_maddr(domain, addr, 1); + pg_maddr = dma_addr_level_page_maddr(domain, addr, 2); if ( pg_maddr == 0 ) return; page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); pte = page + address_level_offset(addr, 1); - if ( pte ) - { - dma_clear_pte(*pte); - iommu_flush_cache_entry(drhd->iommu, pte); - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - - if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) - continue; - - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), - addr, 1, 0); - else if (cap_rwbf(iommu->cap)) - iommu_flush_write_buffer(iommu); - } - } + + if ( !dma_pte_present(*pte) ) + { + unmap_vtd_domain_page(page); + return; + } + + dma_clear_pte(*pte); + iommu_flush_cache_entry(drhd->iommu, pte); + + for_each_drhd_unit ( drhd ) + { + iommu = drhd->iommu; + + if ( test_bit(iommu->index, &hd->iommu_bitmap) ) + iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), addr, 1, 0); + } + unmap_vtd_domain_page(page); } @@ -1191,12 +1193,13 @@ static int domain_context_mapping_one( unmap_vtd_domain_page(context_entries); + /* it's a non-present to present mapping */ if ( iommu_flush_context_device(iommu, domain_iommu_domid(domain), (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1) ) iommu_flush_write_buffer(iommu); else - iommu_flush_iotlb_dsi(iommu, domain_iommu_domid(domain), 0); + iommu_flush_iotlb_dsi(iommu, 0, 0); set_bit(iommu->index, &hd->iommu_bitmap); spin_unlock_irqrestore(&iommu->lock, flags); @@ -1526,6 +1529,7 @@ int intel_iommu_map_page( struct iommu *iommu; struct dma_pte *page = NULL, *pte = NULL; u64 pg_maddr; + int pte_present; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; @@ -1541,6 +1545,7 @@ int intel_iommu_map_page( return -ENOMEM; page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); pte = page + (gfn & LEVEL_MASK); + pte_present = dma_pte_present(*pte); dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K); dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE); iommu_flush_cache_entry(iommu, pte); @@ -1553,10 +1558,11 @@ int intel_iommu_map_page( if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) continue; - if ( cap_caching_mode(iommu->cap) ) + if ( pte_present ) iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) + else if ( iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), + (paddr_t)gfn << PAGE_SHIFT_4K, 1, 1) ) iommu_flush_write_buffer(iommu); } @@ -1567,8 +1573,6 @@ int intel_iommu_unmap_page(struct domain { struct acpi_drhd_unit *drhd; struct iommu *iommu; - struct dma_pte *page = NULL, *pte = NULL; - u64 pg_maddr; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; @@ -1579,24 +1583,7 @@ int intel_iommu_unmap_page(struct domain return 0; #endif - pg_maddr = addr_to_dma_page_maddr(d, (paddr_t)gfn << PAGE_SHIFT_4K); - if ( pg_maddr == 0 ) - return -ENOMEM; - page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); - pte = page + (gfn & LEVEL_MASK); - dma_clear_pte(*pte); - iommu_flush_cache_entry(drhd->iommu, pte); - unmap_vtd_domain_page(page); - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) - iommu_flush_write_buffer(iommu); - } + dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K); return 0; } @@ -1642,10 +1629,8 @@ int iommu_page_mapping(struct domain *do if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) continue; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), - iova, index, 0); - else if ( cap_rwbf(iommu->cap) ) + if ( iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), + iova, index, 1) ) iommu_flush_write_buffer(iommu); } @@ -1657,30 +1642,6 @@ int iommu_page_unmapping(struct domain * dma_pte_clear_range(domain, addr, addr + size); return 0; -} - -void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry) -{ - struct hvm_iommu *hd = domain_hvm_iommu(d); - struct acpi_drhd_unit *drhd; - struct iommu *iommu = NULL; - struct dma_pte *pte = (struct dma_pte *) p2m_entry; - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - - if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) - continue; - - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) - iommu_flush_write_buffer(iommu); - } - - iommu_flush_cache_entry(iommu, pte); } static int iommu_prepare_rmrr_dev( diff -r c93a913c221f xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Tue May 27 13:03:05 2008 +0100 +++ b/xen/include/xen/iommu.h Wed May 28 06:24:44 2008 +0800 @@ -65,7 +65,6 @@ void reassign_device_ownership(struct do u8 bus, u8 devfn); int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn); int iommu_unmap_page(struct domain *d, unsigned long gfn); -void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry); void iommu_set_pgd(struct domain *d); void iommu_free_pgd(struct domain *d); void iommu_domain_teardown(struct domain *d); [-- Attachment #3: Type: text/plain, Size: 138 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <1211965013.16052.16.camel@ip6-localhost>]
* Re: [PATCH] VT-d: IOTLB flush fixups [not found] ` <1211965013.16052.16.camel@ip6-localhost> @ 2008-05-28 15:00 ` Espen Skoglund 2008-05-29 4:13 ` Yang, Xiaowei 0 siblings, 1 reply; 4+ messages in thread From: Espen Skoglund @ 2008-05-28 15:00 UTC (permalink / raw) To: Yang, Xiaowei; +Cc: xen-devel [-- Attachment #1: message body text --] [-- Type: text/plain, Size: 1451 bytes --] [Xiaowei Yang] >> On map: only flush when old PTE was valid or invalid PTE may be cached. >> On unmap: always flush old entry, but skip flush for unaffected IOMMUs. >> >> Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com> >> >> -- >> iommu.c | 17 +++++++++++------ >> 1 file changed, 11 insertions(+), 6 deletions(-) >> -- > > Seems my last mail sent to the xen-devel is lost and I have no local > copy so I have to write again... > > Espen, > Thanks for the patch! I also noticed context/iotlb flush need a > cleanup. As flush of present/non-present entry are different, your > change to iommu_intel_map_page are not that correct. So I made up > anther patch. iommu_flush is also removed, as VTd table is not > shared with p2m any more. > > Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com> Oh, right. When flushing a non-present cached entry domid 0 must be used. Here's a modification of your patch: - Made the non-present flush testing a bit simpler. - Removed dma_addr_level_page_maddr(). Use a modified addr_to_dma_page_maddr() instead. - Upon mapping new context entry: flush old entry using domid 0 and always flush iotlb. Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com> -- arch/x86/mm/hap/p2m-ept.c | 6 - drivers/passthrough/vtd/iommu.c | 150 ++++++++++------------------------------ include/xen/iommu.h | 1 3 files changed, 38 insertions(+), 119 deletions(-) [-- Attachment #2: xen-vtd-flush.patch --] [-- Type: application/octet-stream, Size: 10230 bytes --] diff -r c93a913c221f xen/arch/x86/mm/hap/p2m-ept.c --- a/xen/arch/x86/mm/hap/p2m-ept.c Tue May 27 13:03:05 2008 +0100 +++ b/xen/arch/x86/mm/hap/p2m-ept.c Wed May 28 15:48:06 2008 +0100 @@ -267,12 +267,6 @@ } } -#ifdef P2M_SHARE_WITH_VTD_PAGE_TABLE - /* If p2m table is shared with vtd page-table. */ - if ( iommu_enabled && is_hvm_domain(d) && (p2mt == p2m_mmio_direct) ) - iommu_flush(d, gfn, (u64*)ept_entry); -#endif - return rv; } diff -r c93a913c221f xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Tue May 27 13:03:05 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Wed May 28 15:48:06 2008 +0100 @@ -191,7 +191,7 @@ return ret; } -static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr) +static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) { struct hvm_iommu *hd = domain_hvm_iommu(domain); struct acpi_drhd_unit *drhd; @@ -201,7 +201,7 @@ int level = agaw_to_level(hd->agaw); int offset; unsigned long flags; - u64 pte_maddr = 0; + u64 pte_maddr = 0, maddr; u64 *vaddr = NULL; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); @@ -211,6 +211,8 @@ spin_lock_irqsave(&hd->mapping_lock, flags); if ( hd->pgd_maddr == 0 ) { + if ( !alloc ) + return 0; hd->pgd_maddr = alloc_pgtable_maddr(); if ( hd->pgd_maddr == 0 ) return 0; @@ -224,7 +226,9 @@ if ( dma_pte_addr(*pte) == 0 ) { - u64 maddr = alloc_pgtable_maddr(); + if ( !alloc ) + break; + maddr = alloc_pgtable_maddr(); dma_set_pte_addr(*pte, maddr); vaddr = map_vtd_domain_page(maddr); if ( !vaddr ) @@ -261,41 +265,6 @@ unmap_vtd_domain_page(parent); spin_unlock_irqrestore(&hd->mapping_lock, flags); return pte_maddr; -} - -/* return address's page at specific level */ -static u64 dma_addr_level_page_maddr( - struct domain *domain, u64 addr, int level) -{ - struct hvm_iommu *hd = domain_hvm_iommu(domain); - struct dma_pte *parent, *pte = NULL; - int total = agaw_to_level(hd->agaw); - int offset; - u64 pg_maddr = hd->pgd_maddr; - - if ( pg_maddr == 0 ) - return 0; - - parent = (struct dma_pte *)map_vtd_domain_page(pg_maddr); - while ( level <= total ) - { - offset = address_level_offset(addr, total); - pte = &parent[offset]; - if ( dma_pte_addr(*pte) == 0 ) - break; - - pg_maddr = pte->val & PAGE_MASK_4K; - unmap_vtd_domain_page(parent); - - if ( level == total ) - return pg_maddr; - - parent = map_vtd_domain_page(pte->val); - total--; - } - - unmap_vtd_domain_page(parent); - return 0; } static void iommu_flush_write_buffer(struct iommu *iommu) @@ -485,9 +454,12 @@ /* check IOTLB invalidation granularity */ if ( DMA_TLB_IAIG(val) == 0 ) printk(KERN_ERR VTDPREFIX "IOMMU: flush IOTLB failed\n"); + +#ifdef VTD_DEBUG if ( DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type) ) printk(KERN_ERR VTDPREFIX "IOMMU: tlb flush request %x, actual %x\n", (u32)DMA_TLB_IIRG(type), (u32)DMA_TLB_IAIG(val)); +#endif /* flush context entry will implictly flush write buffer */ return 0; } @@ -581,30 +553,29 @@ drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); /* get last level pte */ - pg_maddr = dma_addr_level_page_maddr(domain, addr, 1); + pg_maddr = addr_to_dma_page_maddr(domain, addr, 0); if ( pg_maddr == 0 ) return; page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); pte = page + address_level_offset(addr, 1); - if ( pte ) + + if ( !dma_pte_present(*pte) ) { - dma_clear_pte(*pte); - iommu_flush_cache_entry(drhd->iommu, pte); + unmap_vtd_domain_page(page); + return; + } - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; + dma_clear_pte(*pte); + iommu_flush_cache_entry(drhd->iommu, pte); - if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) - continue; + for_each_drhd_unit ( drhd ) + { + iommu = drhd->iommu; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), - addr, 1, 0); - else if (cap_rwbf(iommu->cap)) - iommu_flush_write_buffer(iommu); - } + if ( test_bit(iommu->index, &hd->iommu_bitmap) ) + iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), addr, 1, 0); } + unmap_vtd_domain_page(page); } @@ -1191,12 +1162,11 @@ unmap_vtd_domain_page(context_entries); - if ( iommu_flush_context_device(iommu, domain_iommu_domid(domain), - (((u16)bus) << 8) | devfn, - DMA_CCMD_MASK_NOBIT, 1) ) + /* Context entry was previously non-present (with domid 0). */ + iommu_flush_context_device(iommu, 0, (((u16)bus) << 8) | devfn, + DMA_CCMD_MASK_NOBIT, 1); + if ( iommu_flush_iotlb_dsi(iommu, 0, 1) ) iommu_flush_write_buffer(iommu); - else - iommu_flush_iotlb_dsi(iommu, domain_iommu_domid(domain), 0); set_bit(iommu->index, &hd->iommu_bitmap); spin_unlock_irqrestore(&iommu->lock, flags); @@ -1526,6 +1496,7 @@ struct iommu *iommu; struct dma_pte *page = NULL, *pte = NULL; u64 pg_maddr; + int pte_present; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; @@ -1536,11 +1507,12 @@ return 0; #endif - pg_maddr = addr_to_dma_page_maddr(d, (paddr_t)gfn << PAGE_SHIFT_4K); + pg_maddr = addr_to_dma_page_maddr(d, (paddr_t)gfn << PAGE_SHIFT_4K, 1); if ( pg_maddr == 0 ) return -ENOMEM; page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); pte = page + (gfn & LEVEL_MASK); + pte_present = dma_pte_present(*pte); dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K); dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE); iommu_flush_cache_entry(iommu, pte); @@ -1553,10 +1525,9 @@ if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) continue; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) + if ( iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), + (paddr_t)gfn << PAGE_SHIFT_4K, 1, + !pte_present) ) iommu_flush_write_buffer(iommu); } @@ -1567,8 +1538,6 @@ { struct acpi_drhd_unit *drhd; struct iommu *iommu; - struct dma_pte *page = NULL, *pte = NULL; - u64 pg_maddr; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; @@ -1579,24 +1548,7 @@ return 0; #endif - pg_maddr = addr_to_dma_page_maddr(d, (paddr_t)gfn << PAGE_SHIFT_4K); - if ( pg_maddr == 0 ) - return -ENOMEM; - page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); - pte = page + (gfn & LEVEL_MASK); - dma_clear_pte(*pte); - iommu_flush_cache_entry(drhd->iommu, pte); - unmap_vtd_domain_page(page); - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) - iommu_flush_write_buffer(iommu); - } + dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K); return 0; } @@ -1622,7 +1574,7 @@ index = 0; while ( start_pfn < end_pfn ) { - pg_maddr = addr_to_dma_page_maddr(domain, iova + PAGE_SIZE_4K * index); + pg_maddr = addr_to_dma_page_maddr(domain, iova + PAGE_SIZE_4K*index, 1); if ( pg_maddr == 0 ) return -ENOMEM; page = (struct dma_pte *)map_vtd_domain_page(pg_maddr); @@ -1642,10 +1594,8 @@ if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) continue; - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), - iova, index, 0); - else if ( cap_rwbf(iommu->cap) ) + if ( iommu_flush_iotlb_psi(iommu, domain_iommu_domid(domain), + iova, index, 1) ) iommu_flush_write_buffer(iommu); } @@ -1657,30 +1607,6 @@ dma_pte_clear_range(domain, addr, addr + size); return 0; -} - -void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry) -{ - struct hvm_iommu *hd = domain_hvm_iommu(d); - struct acpi_drhd_unit *drhd; - struct iommu *iommu = NULL; - struct dma_pte *pte = (struct dma_pte *) p2m_entry; - - for_each_drhd_unit ( drhd ) - { - iommu = drhd->iommu; - - if ( !test_bit(iommu->index, &hd->iommu_bitmap) ) - continue; - - if ( cap_caching_mode(iommu->cap) ) - iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); - else if ( cap_rwbf(iommu->cap) ) - iommu_flush_write_buffer(iommu); - } - - iommu_flush_cache_entry(iommu, pte); } static int iommu_prepare_rmrr_dev( diff -r c93a913c221f xen/include/xen/iommu.h --- a/xen/include/xen/iommu.h Tue May 27 13:03:05 2008 +0100 +++ b/xen/include/xen/iommu.h Wed May 28 15:48:06 2008 +0100 @@ -65,7 +65,6 @@ u8 bus, u8 devfn); int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn); int iommu_unmap_page(struct domain *d, unsigned long gfn); -void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry); void iommu_set_pgd(struct domain *d); void iommu_free_pgd(struct domain *d); void iommu_domain_teardown(struct domain *d); [-- Attachment #3: Type: text/plain, Size: 138 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] VT-d: IOTLB flush fixups 2008-05-28 15:00 ` Espen Skoglund @ 2008-05-29 4:13 ` Yang, Xiaowei 0 siblings, 0 replies; 4+ messages in thread From: Yang, Xiaowei @ 2008-05-29 4:13 UTC (permalink / raw) To: Espen Skoglund; +Cc: xen-devel [-- Attachment #1: Type: text/plain, Size: 733 bytes --] On Wed, 2008-05-28 at 23:00 +0800, Espen Skoglund wrote: > Oh, right. When flushing a non-present cached entry domid 0 must be > used. Here's a modification of your patch: > > - Made the non-present flush testing a bit simpler. > - Removed dma_addr_level_page_maddr(). Use a modified > addr_to_dma_page_maddr() instead. Yes, it's simpler. Thanks! However, you forgot spin_unlock before return. so it leads to deadlock. Here's a small fix. > - Upon mapping new context entry: flush old entry using domid 0 and > always flush iotlb. Actually, you may find before/after your modification, the code are the same functionally. We can pass domid=0 or non_present_entry_flush=1 to flush non present tlb. Thanks, Xiaowei > [-- Attachment #2: spin.patch --] [-- Type: text/x-patch, Size: 797 bytes --] diff -r f681c4de91fc xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Wed May 28 16:14:10 2008 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Thu May 29 03:48:33 2008 +0800 @@ -212,10 +212,10 @@ static u64 addr_to_dma_page_maddr(struct if ( hd->pgd_maddr == 0 ) { if ( !alloc ) - return 0; + goto out; hd->pgd_maddr = alloc_pgtable_maddr(); if ( hd->pgd_maddr == 0 ) - return 0; + goto out; } parent = (struct dma_pte *)map_vtd_domain_page(hd->pgd_maddr); @@ -263,6 +263,7 @@ static u64 addr_to_dma_page_maddr(struct } unmap_vtd_domain_page(parent); + out: spin_unlock_irqrestore(&hd->mapping_lock, flags); return pte_maddr; } [-- Attachment #3: Type: text/plain, Size: 138 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] VT-d: IOTLB flush fixups
@ 2008-05-27 16:21 Espen Skoglund
0 siblings, 0 replies; 4+ messages in thread
From: Espen Skoglund @ 2008-05-27 16:21 UTC (permalink / raw)
To: xen-devel
On map: only flush when old PTE was valid or invalid PTE may be cached.
On unmap: always flush old entry, but skip flush for unaffected IOMMUs.
Signed-off-by: Espen Skoglund <espen.skoglund@netronome.com>
--
iommu.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
--
diff -r 8187fd8113f9 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Tue May 27 11:46:52 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Tue May 27 17:16:51 2008 +0100
@@ -1525,6 +1525,7 @@
struct iommu *iommu;
struct dma_pte *page = NULL, *pte = NULL;
u64 pg_maddr;
+ int pte_present;
drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
iommu = drhd->iommu;
@@ -1540,6 +1541,7 @@
return -ENOMEM;
page = (struct dma_pte *)map_vtd_domain_page(pg_maddr);
pte = page + (gfn & LEVEL_MASK);
+ pte_present = dma_pte_present(*pte);
dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K);
dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE);
iommu_flush_cache_entry(iommu, pte);
@@ -1552,7 +1554,7 @@
if ( !test_bit(iommu->index, &hd->iommu_bitmap) )
continue;
- if ( cap_caching_mode(iommu->cap) )
+ if ( pte_present || cap_caching_mode(iommu->cap) )
iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
(paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
else if ( cap_rwbf(iommu->cap) )
@@ -1564,6 +1566,7 @@
int intel_iommu_unmap_page(struct domain *d, unsigned long gfn)
{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
struct dma_pte *page = NULL, *pte = NULL;
@@ -1590,11 +1593,13 @@
for_each_drhd_unit ( drhd )
{
iommu = drhd->iommu;
- if ( cap_caching_mode(iommu->cap) )
- iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
- (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
- else if ( cap_rwbf(iommu->cap) )
- iommu_flush_write_buffer(iommu);
+
+ if ( !test_bit(iommu->index, &hd->iommu_bitmap) )
+ continue;
+
+ if ( iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
+ (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0) )
+ iommu_flush_write_buffer(iommu);
}
return 0;
^ permalink raw reply [flat|nested] 4+ messages in threadend of thread, other threads:[~2008-05-29 4:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1211950777.17461.0.camel@ip6-localhost>
2008-05-28 9:01 ` [PATCH] VT-d: IOTLB flush fixups Yang, Xiaowei
[not found] ` <1211965013.16052.16.camel@ip6-localhost>
2008-05-28 15:00 ` Espen Skoglund
2008-05-29 4:13 ` Yang, Xiaowei
2008-05-27 16:21 Espen Skoglund
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.