svn commit: r363310 - in head/sys: sys x86/iommu

Ruslan Bukin br at FreeBSD.org
Sat Jul 18 13:10:33 UTC 2020


Author: br
Date: Sat Jul 18 13:10:31 2020
New Revision: 363310
URL: https://svnweb.freebsd.org/changeset/base/363310

Log:
  o Move iommu_test_boundary() to sys/iommu.h
  o Rename DMAR -> IOMMU in comments
  o Add IOMMU_PAGE_SIZE / IOMMU_PAGE_MASK macroses
  o x86 only: dmar_quirks_pre_use() / dmar_instantiate_rmrr_ctxs()
  
  Reviewed by:	kib
  Sponsored by:	DARPA/AFRL
  Differential Revision:	https://reviews.freebsd.org/D25665

Modified:
  head/sys/sys/iommu.h
  head/sys/x86/iommu/busdma_dmar.c
  head/sys/x86/iommu/intel_dmar.h
  head/sys/x86/iommu/intel_drv.c
  head/sys/x86/iommu/intel_gas.c
  head/sys/x86/iommu/intel_reg.h

Modified: head/sys/sys/iommu.h
==============================================================================
--- head/sys/sys/iommu.h	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/sys/iommu.h	Sat Jul 18 13:10:31 2020	(r363310)
@@ -35,6 +35,7 @@
 #define _SYS_IOMMU_H_
 
 #include <sys/queue.h>
+#include <sys/taskqueue.h>
 #include <sys/tree.h>
 #include <sys/types.h>
 
@@ -43,6 +44,7 @@ typedef uint64_t iommu_haddr_t;
 /* Guest or bus address, before translation. */
 typedef uint64_t iommu_gaddr_t;
 
+struct bus_dma_tag_common;
 struct iommu_map_entry;
 TAILQ_HEAD(iommu_map_entries_tailq, iommu_map_entry);
 
@@ -102,6 +104,7 @@ struct iommu_domain {
 	struct iommu_unit *iommu;	/* (c) */
 	struct mtx lock;		/* (c) */
 	struct task unload_task;	/* (c) */
+	u_int entries_cnt;		/* (d) */
 	struct iommu_map_entries_tailq unload_entries; /* (d) Entries to
 							 unload */
 };
@@ -128,6 +131,16 @@ struct iommu_ctx {
 #define	IOMMU_DOMAIN_LOCK(dom)		mtx_lock(&(dom)->lock)
 #define	IOMMU_DOMAIN_UNLOCK(dom)	mtx_unlock(&(dom)->lock)
 #define	IOMMU_DOMAIN_ASSERT_LOCKED(dom)	mtx_assert(&(dom)->lock, MA_OWNED)
+
+static inline bool
+iommu_test_boundary(iommu_gaddr_t start, iommu_gaddr_t size,
+    iommu_gaddr_t boundary)
+{
+
+	if (boundary == 0)
+		return (true);
+	return (start + size <= ((start + boundary) & ~(boundary - 1)));
+}
 
 void iommu_free_ctx(struct iommu_ctx *ctx);
 void iommu_free_ctx_locked(struct iommu_unit *iommu, struct iommu_ctx *ctx);

Modified: head/sys/x86/iommu/busdma_dmar.c
==============================================================================
--- head/sys/x86/iommu/busdma_dmar.c	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/x86/iommu/busdma_dmar.c	Sat Jul 18 13:10:31 2020	(r363310)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/interrupt.h>
+#include <sys/iommu.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
@@ -62,11 +63,13 @@ __FBSDID("$FreeBSD$");
 #include <machine/atomic.h>
 #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/busdma_dmar.h>
 #include <x86/iommu/intel_dmar.h>
+#endif
 
 /*
  * busdma_dmar.c, the implementation of the busdma(9) interface using
@@ -112,11 +115,11 @@ iommu_bus_dma_is_dev_disabled(int domain, int bus, int
 
 /*
  * Given original device, find the requester ID that will be seen by
- * the DMAR unit and used for page table lookup.  PCI bridges may take
+ * the IOMMU unit and used for page table lookup.  PCI bridges may take
  * ownership of transactions from downstream devices, so it may not be
  * the same as the BSF of the target device.  In those cases, all
  * devices downstream of the bridge must share a single mapping
- * domain, and must collectively be assigned to use either DMAR or
+ * domain, and must collectively be assigned to use either IOMMU or
  * bounce mapping.
  */
 device_t
@@ -135,7 +138,7 @@ iommu_get_requester(device_t dev, uint16_t *rid)
 
 	/*
 	 * Walk the bridge hierarchy from the target device to the
-	 * host port to find the translating bridge nearest the DMAR
+	 * host port to find the translating bridge nearest the IOMMU
 	 * unit.
 	 */
 	for (;;) {
@@ -173,7 +176,7 @@ iommu_get_requester(device_t dev, uint16_t *rid)
 		} else {
 			/*
 			 * Device is not PCIe, it cannot be seen as a
-			 * requester by DMAR unit.  Check whether the
+			 * requester by IOMMU unit.  Check whether the
 			 * bridge is PCIe.
 			 */
 			bridge_is_pcie = pci_find_cap(pcib, PCIY_EXPRESS,
@@ -243,8 +246,8 @@ iommu_instantiate_ctx(struct iommu_unit *unit, device_
 
 	/*
 	 * If the user requested the IOMMU disabled for the device, we
-	 * cannot disable the DMAR, due to possibility of other
-	 * devices on the same DMAR still requiring translation.
+	 * cannot disable the IOMMU unit, due to possibility of other
+	 * devices on the same IOMMU unit still requiring translation.
 	 * Instead provide the identity mapping for the device
 	 * context.
 	 */
@@ -279,13 +282,16 @@ acpi_iommu_get_dma_tag(device_t dev, device_t child)
 	bus_dma_tag_t res;
 
 	unit = iommu_find(child, bootverbose);
-	/* Not in scope of any DMAR ? */
+	/* Not in scope of any IOMMU ? */
 	if (unit == NULL)
 		return (NULL);
 	if (!unit->dma_enabled)
 		return (NULL);
+
+#if defined(__amd64__) || defined(__i386__)
 	dmar_quirks_pre_use(unit);
 	dmar_instantiate_rmrr_ctxs(unit);
+#endif
 
 	ctx = iommu_instantiate_ctx(unit, child, false);
 	res = ctx == NULL ? NULL : (bus_dma_tag_t)ctx->tag;
@@ -536,7 +542,7 @@ iommu_bus_dmamap_load_something1(struct bus_dma_tag_io
 	bus_size_t buflen1;
 	int error, idx, gas_flags, seg;
 
-	KASSERT(offset < DMAR_PAGE_SIZE, ("offset %d", offset));
+	KASSERT(offset < IOMMU_PAGE_SIZE, ("offset %d", offset));
 	if (segs == NULL)
 		segs = tag->segments;
 	ctx = tag->ctx;
@@ -621,7 +627,7 @@ iommu_bus_dmamap_load_something1(struct bus_dma_tag_io
 
 		idx += OFF_TO_IDX(trunc_page(offset + buflen1));
 		offset += buflen1;
-		offset &= DMAR_PAGE_MASK;
+		offset &= IOMMU_PAGE_MASK;
 		buflen -= buflen1;
 	}
 	if (error == 0)
@@ -841,7 +847,7 @@ iommu_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmam
 }
 
 /*
- * The limitations of busdma KPI forces the dmar to perform the actual
+ * The limitations of busdma KPI forces the iommu to perform the actual
  * unload, consisting of the unmapping of the map entries page tables,
  * from the delayed context on i386, since page table page mapping
  * might require a sleep to be successfull.  The unfortunate

Modified: head/sys/x86/iommu/intel_dmar.h
==============================================================================
--- head/sys/x86/iommu/intel_dmar.h	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/x86/iommu/intel_dmar.h	Sat Jul 18 13:10:31 2020	(r363310)
@@ -77,7 +77,6 @@ struct dmar_domain {
 	LIST_HEAD(, dmar_ctx) contexts;	/* (u) */
 	vm_object_t pgtbl_obj;		/* (c) Page table pages */
 	u_int flags;			/* (u) */
-	u_int entries_cnt;		/* (d) */
 	struct dmar_gas_entries_tree rb_root; /* (d) */
 	struct iommu_map_entry *first_place, *last_place; /* (d) */
 	u_int batch_no;
@@ -458,16 +457,6 @@ dmar_pte_clear(volatile uint64_t *dst)
 #else
 	*dst = 0;
 #endif
-}
-
-static inline bool
-iommu_test_boundary(iommu_gaddr_t start, iommu_gaddr_t size,
-    iommu_gaddr_t boundary)
-{
-
-	if (boundary == 0)
-		return (true);
-	return (start + size <= ((start + boundary) & ~(boundary - 1)));
 }
 
 extern struct timespec dmar_hw_timeout;

Modified: head/sys/x86/iommu/intel_drv.c
==============================================================================
--- head/sys/x86/iommu/intel_drv.c	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/x86/iommu/intel_drv.c	Sat Jul 18 13:10:31 2020	(r363310)
@@ -1160,7 +1160,7 @@ dmar_print_domain(struct dmar_domain *domain, bool sho
 	    "   ctx_cnt %d flags %x pgobj %p map_ents %u\n",
 	    domain, domain->domain, domain->mgaw, domain->agaw, domain->pglvl,
 	    (uintmax_t)domain->end, domain->refs, domain->ctx_cnt,
-	    domain->flags, domain->pgtbl_obj, domain->entries_cnt);
+	    domain->flags, domain->pgtbl_obj, domain->iodom.entries_cnt);
 	if (!LIST_EMPTY(&domain->contexts)) {
 		db_printf("  Contexts:\n");
 		LIST_FOREACH(ctx, &domain->contexts, link)

Modified: head/sys/x86/iommu/intel_gas.c
==============================================================================
--- head/sys/x86/iommu/intel_gas.c	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/x86/iommu/intel_gas.c	Sat Jul 18 13:10:31 2020	(r363310)
@@ -98,7 +98,7 @@ dmar_gas_alloc_entry(struct dmar_domain *domain, u_int
 	    0 ? M_WAITOK : M_NOWAIT) | M_ZERO);
 	if (res != NULL) {
 		res->domain = (struct iommu_domain *)domain;
-		atomic_add_int(&domain->entries_cnt, 1);
+		atomic_add_int(&domain->iodom.entries_cnt, 1);
 	}
 	return (res);
 }
@@ -110,7 +110,7 @@ dmar_gas_free_entry(struct dmar_domain *domain, struct
 	KASSERT(domain == (struct dmar_domain *)entry->domain,
 	    ("mismatched free domain %p entry %p entry->domain %p", domain,
 	    entry, entry->domain));
-	atomic_subtract_int(&domain->entries_cnt, 1);
+	atomic_subtract_int(&domain->iodom.entries_cnt, 1);
 	uma_zfree(iommu_map_entry_zone, entry);
 }
 
@@ -214,7 +214,7 @@ dmar_gas_init_domain(struct dmar_domain *domain)
 	end = dmar_gas_alloc_entry(domain, DMAR_PGF_WAITOK);
 
 	DMAR_DOMAIN_LOCK(domain);
-	KASSERT(domain->entries_cnt == 2, ("dirty domain %p", domain));
+	KASSERT(domain->iodom.entries_cnt == 2, ("dirty domain %p", domain));
 	KASSERT(RB_EMPTY(&domain->rb_root), ("non-empty entries %p", domain));
 
 	begin->start = 0;
@@ -239,7 +239,8 @@ dmar_gas_fini_domain(struct dmar_domain *domain)
 	struct iommu_map_entry *entry, *entry1;
 
 	DMAR_DOMAIN_ASSERT_LOCKED(domain);
-	KASSERT(domain->entries_cnt == 2, ("domain still in use %p", domain));
+	KASSERT(domain->iodom.entries_cnt == 2,
+	    ("domain still in use %p", domain));
 
 	entry = RB_MIN(dmar_gas_entries_tree, &domain->rb_root);
 	KASSERT(entry->start == 0, ("start entry start %p", domain));

Modified: head/sys/x86/iommu/intel_reg.h
==============================================================================
--- head/sys/x86/iommu/intel_reg.h	Sat Jul 18 13:10:02 2020	(r363309)
+++ head/sys/x86/iommu/intel_reg.h	Sat Jul 18 13:10:31 2020	(r363310)
@@ -41,6 +41,9 @@
 #define	DMAR_NPTEPGSHIFT 9
 #define	DMAR_PTEMASK	(DMAR_NPTEPG - 1)
 
+#define	IOMMU_PAGE_SIZE	DMAR_PAGE_SIZE
+#define	IOMMU_PAGE_MASK	DMAR_PAGE_MASK
+
 typedef struct dmar_root_entry {
 	uint64_t r1;
 	uint64_t r2;


More information about the svn-src-head mailing list