Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jul 2020 23:02:18 +0000 (UTC)
From:      Ruslan Bukin <br@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r363747 - in head/sys: dev/iommu x86/iommu
Message-ID:  <202007312302.06VN2ImD065116@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007312302.06VN2ImD065116>