All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 thread

* 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

* 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

end 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.