[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4 18/21] xen/arm: p2m: Clean cache PT when the IOMMU doesn't support coherent walk



Some IOMMU doesn't suppport coherent PT walk. When the p2m is shared with
the CPU, Xen has to make sure the PT changes have reached the memory.

Introduce new IOMMU callback that will retrieve the IOMMU feature for a
specified domain.

On ARM, the platform can contain multiple IOMMUs. Each of them may not
have the same set of feature. The domain parameter will be used to get the
set of features for IOMMUs used by this domain.

Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>

---
    Changes in v4:
        - Patch added
---
 xen/arch/arm/p2m.c              |   24 ++++++++++++++++++------
 xen/drivers/passthrough/iommu.c |   11 +++++++++++
 xen/include/xen/iommu.h         |    5 +++++
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 21219de..996d2bd 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -274,6 +274,18 @@ enum p2m_operation {
     CACHEFLUSH,
 };
 
+static void unmap_coherent_domain_page(struct domain *d, const void *va)
+{
+    /* Some IOMMU doesn't support coherent PT walk. When the p2m is
+     * shared with the CPU, Xen has to make sure that the PT changes have
+     * reached the memory
+     */
+    if ( need_iommu(d) && !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK) )
+        clean_xen_dcache_va_range(va, PAGE_SIZE);
+
+    unmap_domain_page(va);
+}
+
 static int apply_p2m_changes(struct domain *d,
                      enum p2m_operation op,
                      paddr_t start_gpaddr,
@@ -301,7 +313,7 @@ static int apply_p2m_changes(struct domain *d,
     {
         if ( cur_first_page != p2m_first_level_index(addr) )
         {
-            if ( first ) unmap_domain_page(first);
+            if ( first ) unmap_coherent_domain_page(d, first);
             first = p2m_map_first(p2m, addr);
             if ( !first )
             {
@@ -331,7 +343,7 @@ static int apply_p2m_changes(struct domain *d,
 
         if ( cur_first_offset != first_table_offset(addr) )
         {
-            if (second) unmap_domain_page(second);
+            if (second) unmap_coherent_domain_page(d, second);
             second = map_domain_page(first[first_table_offset(addr)].p2m.base);
             cur_first_offset = first_table_offset(addr);
         }
@@ -357,7 +369,7 @@ static int apply_p2m_changes(struct domain *d,
         if ( cur_second_offset != second_table_offset(addr) )
         {
             /* map third level */
-            if (third) unmap_domain_page(third);
+            if (third) unmap_coherent_domain_page(d, third);
             third = 
map_domain_page(second[second_table_offset(addr)].p2m.base);
             cur_second_offset = second_table_offset(addr);
         }
@@ -480,9 +492,9 @@ static int apply_p2m_changes(struct domain *d,
     rc = 0;
 
 out:
-    if (third) unmap_domain_page(third);
-    if (second) unmap_domain_page(second);
-    if (first) unmap_domain_page(first);
+    if (third) unmap_coherent_domain_page(d, third);
+    if (second) unmap_coherent_domain_page(d, second);
+    if (first) unmap_coherent_domain_page(d, first);
 
     spin_unlock(&p2m->lock);
 
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index f93dc79..f24fb46 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -344,6 +344,17 @@ void iommu_crash_shutdown(void)
     iommu_enabled = iommu_intremap = 0;
 }
 
+bool_t iommu_has_feature(struct domain *d, uint32_t feature)
+{
+    const struct iommu_ops *ops = domain_hvm_iommu(d)->platform_ops;
+    uint32_t features = 0;
+
+    if ( iommu_enabled && ops && ops->features )
+        features = ops->features(d);
+
+    return !!(features & feature);
+}
+
 static void iommu_dump_p2m_table(unsigned char key)
 {
     struct domain *d;
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index e119379..9ad909f 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -67,6 +67,10 @@ int iommu_map_page(struct domain *d, unsigned long gfn, 
unsigned long mfn,
                    unsigned int flags);
 int iommu_unmap_page(struct domain *d, unsigned long gfn);
 
+#define IOMMU_FEAT_COHERENT_WALK (1U<<0)
+bool_t iommu_has_feature(struct domain *d, uint32_t feature);
+
+
 #ifdef HAS_PCI
 void pt_pci_init(void);
 
@@ -139,6 +143,7 @@ struct iommu_ops {
     void (*iotlb_flush)(struct domain *d, unsigned long gfn, unsigned int 
page_count);
     void (*iotlb_flush_all)(struct domain *d);
     void (*dump_p2m_table)(struct domain *d);
+    uint32_t (*features)(struct domain *d);
 };
 
 void iommu_suspend(void);
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.