Hi,

On 9/25/19 1:00 PM, Tian, Kevin wrote:
From: Lu Baolu [mailto:[email protected]]
Sent: Monday, September 23, 2019 8:25 PM

If a dmar domain has DOMAIN_FLAG_FIRST_LEVEL_TRANS bit set
in its flags, IOMMU will use the first level page table for
translation. Hence, we need to map or unmap addresses in the
first level page table.

Cc: Ashok Raj <[email protected]>
Cc: Jacob Pan <[email protected]>
Cc: Kevin Tian <[email protected]>
Cc: Liu Yi L <[email protected]>
Cc: Yi Sun <[email protected]>
Signed-off-by: Lu Baolu <[email protected]>
---
  drivers/iommu/intel-iommu.c | 94 ++++++++++++++++++++++++++++++++-
----
  1 file changed, 82 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 9cfe8098d993..103480016010 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -168,6 +168,11 @@ static inline unsigned long virt_to_dma_pfn(void
*p)
        return page_to_dma_pfn(virt_to_page(p));
  }

+static inline unsigned long dma_pfn_to_addr(unsigned long pfn)
+{
+       return pfn << VTD_PAGE_SHIFT;
+}
+
  /* global iommu list, set NULL for ignored DMAR units */
  static struct intel_iommu **g_iommus;

@@ -307,6 +312,9 @@ static int hw_pass_through = 1;
   */
  #define DOMAIN_FLAG_LOSE_CHILDREN             BIT(1)

+/* Domain uses first level translation for DMA remapping. */
+#define DOMAIN_FLAG_FIRST_LEVEL_TRANS          BIT(2)
+
  #define for_each_domain_iommu(idx, domain)                    \
        for (idx = 0; idx < g_num_of_iommus; idx++)          \
                if (domain->iommu_refcnt[idx])
@@ -552,6 +560,11 @@ static inline int domain_type_is_si(struct
dmar_domain *domain)
        return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
  }

+static inline int domain_type_is_flt(struct dmar_domain *domain)
+{
+       return domain->flags & DOMAIN_FLAG_FIRST_LEVEL_TRANS;
+}
+
  static inline int domain_pfn_supported(struct dmar_domain *domain,
                                       unsigned long pfn)
  {
@@ -1147,8 +1160,15 @@ static struct page *domain_unmap(struct
dmar_domain *domain,
        BUG_ON(start_pfn > last_pfn);

        /* we don't need lock here; nobody else touches the iova range */
-       freelist = dma_pte_clear_level(domain, agaw_to_level(domain-
agaw),
-                                      domain->pgd, 0, start_pfn, last_pfn,
NULL);
+       if (domain_type_is_flt(domain))
+               freelist = intel_mmunmap_range(domain,
+                                              dma_pfn_to_addr(start_pfn),
+                                              dma_pfn_to_addr(last_pfn + 1));
+       else
+               freelist = dma_pte_clear_level(domain,
+                                              agaw_to_level(domain->agaw),
+                                              domain->pgd, 0, start_pfn,
+                                              last_pfn, NULL);

what about providing an unified interface at the caller side, then having
the level differentiated within the interface?

Good point! I ever thought about adding some ops in struct dmar_domain,
something like:

diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index ed11ef594378..1dd184f76bfb 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -489,7 +489,14 @@ struct dmar_domain {
struct list_head auxd; /* link to device's auxiliary list */ struct iova_domain iovad; /* iova's that belong to this domain */

+       /* per domain page table and manipulation ops */
        struct dma_pte  *pgd;           /* virtual address */
+       int (*map)(struct dmar_domain *domain,
+                  unsigned long addr, unsigned long end,
+                  phys_addr_t phys_addr, int dma_prot);
+       struct page *(*unmap)(struct dmar_domain *domain,
+                             unsigned long addr, unsigned long end);
+
        int             gaw;            /* max guest address width */

        /* adjusted guest address width, 0 is level 2 30-bit */

So that this code could be simply like this:

        freelist = domain->unmap(...);

Best regards,
Baolu
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to