Author: br
Date: Fri Jul 31 23:02:17 2020
New Revision: 363747
URL: https://svnweb.freebsd.org/changeset/base/363747

Log:
  Add iommu_domain_map_ops virtual table with map/unmap methods
  so x86 can support Intel DMAR and AMD IOMMU simultaneously.
  
  Reviewed by:  kib
  Sponsored by: DARPA/AFRL
  Differential Revision:        https://reviews.freebsd.org/D25894

Modified:
  head/sys/dev/iommu/iommu.h
  head/sys/dev/iommu/iommu_gas.c
  head/sys/x86/iommu/intel_ctx.c
  head/sys/x86/iommu/intel_dmar.h
  head/sys/x86/iommu/intel_idpgtbl.c

Modified: head/sys/dev/iommu/iommu.h
==============================================================================
--- head/sys/dev/iommu/iommu.h  Fri Jul 31 22:23:32 2020        (r363746)
+++ head/sys/dev/iommu/iommu.h  Fri Jul 31 23:02:17 2020        (r363747)
@@ -100,6 +100,13 @@ struct iommu_unit {
        uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)];
 };
 
+struct iommu_domain_map_ops {
+       int (*map)(struct iommu_domain *domain, iommu_gaddr_t base,
+           iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags);
+       int (*unmap)(struct iommu_domain *domain, iommu_gaddr_t base,
+           iommu_gaddr_t size, int flags);
+};
+
 /*
  * Locking annotations:
  * (u) - Protected by iommu unit lock
@@ -109,6 +116,7 @@ struct iommu_unit {
 
 struct iommu_domain {
        struct iommu_unit *iommu;       /* (c) */
+       const struct iommu_domain_map_ops *ops;
        struct mtx lock;                /* (c) */
        struct task unload_task;        /* (c) */
        u_int entries_cnt;              /* (d) */

Modified: head/sys/dev/iommu/iommu_gas.c
==============================================================================
--- head/sys/dev/iommu/iommu_gas.c      Fri Jul 31 22:23:32 2020        
(r363746)
+++ head/sys/dev/iommu/iommu_gas.c      Fri Jul 31 23:02:17 2020        
(r363747)
@@ -66,10 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/md_var.h>
 #if defined(__amd64__) || defined(__i386__)
-#include <machine/specialreg.h>
-#include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
-#include <x86/iommu/intel_dmar.h>
 #endif
 #include <dev/iommu/busdma_iommu.h>
 
@@ -620,9 +617,9 @@ iommu_gas_map(struct iommu_domain *domain,
        entry->flags |= eflags;
        IOMMU_DOMAIN_UNLOCK(domain);
 
-       error = domain_map_buf(domain, entry->start, entry->end - entry->start,
-           ma, eflags,
-           ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
+       error = domain->ops->map(domain, entry->start,
+           entry->end - entry->start, ma, eflags,
+           ((flags & IOMMU_MF_CANWAIT) != 0 ?  IOMMU_PGF_WAITOK : 0));
        if (error == ENOMEM) {
                iommu_domain_unload_entry(entry, true);
                return (error);
@@ -658,9 +655,9 @@ iommu_gas_map_region(struct iommu_domain *domain, stru
        if (entry->end == entry->start)
                return (0);
 
-       error = domain_map_buf(domain, entry->start, entry->end - entry->start,
-           ma + OFF_TO_IDX(start - entry->start), eflags,
-           ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
+       error = domain->ops->map(domain, entry->start,
+           entry->end - entry->start, ma + OFF_TO_IDX(start - entry->start),
+           eflags, ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
        if (error == ENOMEM) {
                iommu_domain_unload_entry(entry, false);
                return (error);

Modified: head/sys/x86/iommu/intel_ctx.c
==============================================================================
--- head/sys/x86/iommu/intel_ctx.c      Fri Jul 31 22:23:32 2020        
(r363746)
+++ head/sys/x86/iommu/intel_ctx.c      Fri Jul 31 23:02:17 2020        
(r363747)
@@ -341,6 +341,7 @@ dmar_domain_alloc(struct dmar_unit *dmar, bool id_mapp
        mtx_init(&domain->iodom.lock, "dmardom", NULL, MTX_DEF);
        domain->dmar = dmar;
        domain->iodom.iommu = &dmar->iommu;
+       domain_pgtbl_init(domain);
 
        /*
         * For now, use the maximal usable physical address of the
@@ -842,15 +843,17 @@ dmar_domain_unload(struct dmar_domain *domain,
     struct iommu_map_entries_tailq *entries, bool cansleep)
 {
        struct dmar_unit *unit;
+       struct iommu_domain *iodom;
        struct iommu_map_entry *entry, *entry1;
        int error;
 
+       iodom = (struct iommu_domain *)domain;
        unit = (struct dmar_unit *)domain->iodom.iommu;
 
        TAILQ_FOREACH_SAFE(entry, entries, dmamap_link, entry1) {
                KASSERT((entry->flags & IOMMU_MAP_ENTRY_MAP) != 0,
                    ("not mapped entry %p %p", domain, entry));
-               error = domain_unmap_buf(domain, entry->start, entry->end -
+               error = iodom->ops->unmap(iodom, entry->start, entry->end -
                    entry->start, cansleep ? IOMMU_PGF_WAITOK : 0);
                KASSERT(error == 0, ("unmap %p error %d", domain, error));
                if (!unit->qi_enabled) {

Modified: head/sys/x86/iommu/intel_dmar.h
==============================================================================
--- head/sys/x86/iommu/intel_dmar.h     Fri Jul 31 22:23:32 2020        
(r363746)
+++ head/sys/x86/iommu/intel_dmar.h     Fri Jul 31 23:02:17 2020        
(r363747)
@@ -244,14 +244,11 @@ void dmar_qi_invalidate_iec(struct dmar_unit *unit, u_
 vm_object_t domain_get_idmap_pgtbl(struct dmar_domain *domain,
     iommu_gaddr_t maxaddr);
 void put_idmap_pgtbl(vm_object_t obj);
-int domain_map_buf(struct iommu_domain *domain, iommu_gaddr_t base,
-    iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags);
-int domain_unmap_buf(struct dmar_domain *domain, iommu_gaddr_t base,
-    iommu_gaddr_t size, int flags);
 void domain_flush_iotlb_sync(struct dmar_domain *domain, iommu_gaddr_t base,
     iommu_gaddr_t size);
 int domain_alloc_pgtbl(struct dmar_domain *domain);
 void domain_free_pgtbl(struct dmar_domain *domain);
+void domain_pgtbl_init(struct dmar_domain *domain);
 
 int dmar_dev_depth(device_t child);
 void dmar_dev_path(device_t child, int *busno, void *path1, int depth);

Modified: head/sys/x86/iommu/intel_idpgtbl.c
==============================================================================
--- head/sys/x86/iommu/intel_idpgtbl.c  Fri Jul 31 22:23:32 2020        
(r363746)
+++ head/sys/x86/iommu/intel_idpgtbl.c  Fri Jul 31 23:02:17 2020        
(r363747)
@@ -498,7 +498,7 @@ domain_map_buf_locked(struct dmar_domain *domain, iomm
        return (0);
 }
 
-int
+static int
 domain_map_buf(struct iommu_domain *iodom, iommu_gaddr_t base,
     iommu_gaddr_t size, vm_page_t *ma, uint64_t eflags, int flags)
 {
@@ -684,12 +684,15 @@ domain_unmap_buf_locked(struct dmar_domain *domain, io
        return (0);
 }
 
-int
-domain_unmap_buf(struct dmar_domain *domain, iommu_gaddr_t base,
+static int
+domain_unmap_buf(struct iommu_domain *iodom, iommu_gaddr_t base,
     iommu_gaddr_t size, int flags)
 {
+       struct dmar_domain *domain;
        int error;
 
+       domain = (struct dmar_domain *)iodom;
+
        DMAR_DOMAIN_PGLOCK(domain);
        error = domain_unmap_buf_locked(domain, base, size, flags);
        DMAR_DOMAIN_PGUNLOCK(domain);
@@ -808,4 +811,18 @@ domain_flush_iotlb_sync(struct dmar_domain *domain, io
                }
        }
        DMAR_UNLOCK(unit);
+}
+
+static const struct iommu_domain_map_ops dmar_domain_map_ops = {
+       .map = domain_map_buf,
+       .unmap = domain_unmap_buf,
+};
+
+void
+domain_pgtbl_init(struct dmar_domain *domain)
+{
+       struct iommu_domain *iodom;
+
+       iodom = (struct iommu_domain *)domain;
+       iodom->ops = &dmar_domain_map_ops;
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to