svn commit: r355086 - in stable/12/sys/x86: include iommu x86

Konstantin Belousov kib at FreeBSD.org
Mon Nov 25 09:43:39 UTC 2019


Author: kib
Date: Mon Nov 25 09:43:36 2019
New Revision: 355086
URL: https://svnweb.freebsd.org/changeset/base/355086

Log:
  MFC r354830:
  bus_dma_dmar_set_buswide(9): KPI to indicate that the whole dmar
  context should share page tables.

Modified:
  stable/12/sys/x86/include/bus_dma.h
  stable/12/sys/x86/iommu/busdma_dmar.c
  stable/12/sys/x86/iommu/intel_ctx.c
  stable/12/sys/x86/iommu/intel_dmar.h
  stable/12/sys/x86/iommu/intel_drv.c
  stable/12/sys/x86/iommu/intel_gas.c
  stable/12/sys/x86/iommu/intel_idpgtbl.c
  stable/12/sys/x86/iommu/intel_intrmap.c
  stable/12/sys/x86/iommu/intel_qi.c
  stable/12/sys/x86/iommu/intel_quirks.c
  stable/12/sys/x86/iommu/intel_utils.c
  stable/12/sys/x86/x86/busdma_machdep.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/x86/include/bus_dma.h
==============================================================================
--- stable/12/sys/x86/include/bus_dma.h	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/include/bus_dma.h	Mon Nov 25 09:43:36 2019	(r355086)
@@ -179,5 +179,7 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t 
 	return (tc->impl->map_complete(dmat, map, segs, nsegs, error));
 }
 
+bool bus_dma_dmar_set_buswide(device_t dev);
+
 #endif /* !_X86_BUS_DMA_H_ */
 

Modified: stable/12/sys/x86/iommu/busdma_dmar.c
==============================================================================
--- stable/12/sys/x86/iommu/busdma_dmar.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/busdma_dmar.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -289,6 +289,34 @@ dmar_get_dma_tag(device_t dev, device_t child)
 	return (res);
 }
 
+bool
+bus_dma_dmar_set_buswide(device_t dev)
+{
+	struct dmar_unit *dmar;
+	device_t parent;
+	u_int busno, slot, func;
+
+	parent = device_get_parent(dev);
+	if (device_get_devclass(parent) != devclass_find("pci"))
+		return (false);
+	dmar = dmar_find(dev, bootverbose);
+	if (dmar == NULL)
+		return (false);
+	busno = pci_get_bus(dev);
+	slot = pci_get_slot(dev);
+	func = pci_get_function(dev);
+	if (slot != 0 || func != 0) {
+		if (bootverbose) {
+			device_printf(dev,
+			    "dmar%d pci%d:%d:%d requested buswide busdma\n",
+			    dmar->unit, busno, slot, func);
+		}
+		return (false);
+	}
+	dmar_set_buswide_ctx(dmar, busno);
+	return (true);
+}
+
 static MALLOC_DEFINE(M_DMAR_DMAMAP, "dmar_dmamap", "Intel DMAR DMA Map");
 
 static void dmar_bus_schedule_dmamap(struct dmar_unit *unit,

Modified: stable/12/sys/x86/iommu/intel_ctx.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_ctx.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_ctx.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -67,8 +67,8 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
-#include <x86/iommu/intel_dmar.h>
 #include <dev/pci/pcireg.h>
+#include <x86/iommu/intel_dmar.h>
 #include <dev/pci/pcivar.h>
 
 static MALLOC_DEFINE(M_DMAR_CTX, "dmar_ctx", "Intel DMAR Context");
@@ -141,20 +141,9 @@ ctx_tag_init(struct dmar_ctx *ctx, device_t dev)
 }
 
 static void
-ctx_id_entry_init(struct dmar_ctx *ctx, dmar_ctx_entry_t *ctxp, bool move)
+ctx_id_entry_init_one(dmar_ctx_entry_t *ctxp, struct dmar_domain *domain,
+    vm_page_t ctx_root)
 {
-	struct dmar_unit *unit;
-	struct dmar_domain *domain;
-	vm_page_t ctx_root;
-
-	domain = ctx->domain;
-	unit = domain->dmar;
-	KASSERT(move || (ctxp->ctx1 == 0 && ctxp->ctx2 == 0),
-	    ("dmar%d: initialized ctx entry %d:%d:%d 0x%jx 0x%jx",
-	    unit->unit, pci_get_bus(ctx->ctx_tag.owner),
-	    pci_get_slot(ctx->ctx_tag.owner),
-	    pci_get_function(ctx->ctx_tag.owner),
-	    ctxp->ctx1, ctxp->ctx2));
 	/*
 	 * For update due to move, the store is not atomic.  It is
 	 * possible that DMAR read upper doubleword, while low
@@ -166,17 +155,49 @@ ctx_id_entry_init(struct dmar_ctx *ctx, dmar_ctx_entry
 	 */
 	dmar_pte_store1(&ctxp->ctx2, DMAR_CTX2_DID(domain->domain) |
 	    domain->awlvl);
+	if (ctx_root == NULL) {
+		dmar_pte_store1(&ctxp->ctx1, DMAR_CTX1_T_PASS | DMAR_CTX1_P);
+	} else {
+		dmar_pte_store1(&ctxp->ctx1, DMAR_CTX1_T_UNTR |
+		    (DMAR_CTX1_ASR_MASK & VM_PAGE_TO_PHYS(ctx_root)) |
+		    DMAR_CTX1_P);
+	}
+}
+
+static void
+ctx_id_entry_init(struct dmar_ctx *ctx, dmar_ctx_entry_t *ctxp, bool move,
+    int busno)
+{
+	struct dmar_unit *unit;
+	struct dmar_domain *domain;
+	vm_page_t ctx_root;
+	int i;
+
+	domain = ctx->domain;
+	unit = domain->dmar;
+	KASSERT(move || (ctxp->ctx1 == 0 && ctxp->ctx2 == 0),
+	    ("dmar%d: initialized ctx entry %d:%d:%d 0x%jx 0x%jx",
+	    unit->unit, busno, pci_get_slot(ctx->ctx_tag.owner),
+	    pci_get_function(ctx->ctx_tag.owner),
+	    ctxp->ctx1, ctxp->ctx2));
+
 	if ((domain->flags & DMAR_DOMAIN_IDMAP) != 0 &&
 	    (unit->hw_ecap & DMAR_ECAP_PT) != 0) {
 		KASSERT(domain->pgtbl_obj == NULL,
 		    ("ctx %p non-null pgtbl_obj", ctx));
-		dmar_pte_store1(&ctxp->ctx1, DMAR_CTX1_T_PASS | DMAR_CTX1_P);
+		ctx_root = NULL;
 	} else {
 		ctx_root = dmar_pgalloc(domain->pgtbl_obj, 0, DMAR_PGF_NOALLOC);
-		dmar_pte_store1(&ctxp->ctx1, DMAR_CTX1_T_UNTR |
-		    (DMAR_CTX1_ASR_MASK & VM_PAGE_TO_PHYS(ctx_root)) |
-		    DMAR_CTX1_P);
 	}
+
+	if (dmar_is_buswide_ctx(unit, busno)) {
+		MPASS(!move);
+		for (i = 0; i <= PCI_BUSMAX; i++) {
+			ctx_id_entry_init_one(&ctxp[i], domain, ctx_root);
+		}
+	} else {
+		ctx_id_entry_init_one(ctxp, domain, ctx_root);
+	}
 	dmar_flush_ctx_to_ram(unit, ctxp);
 }
 
@@ -444,6 +465,9 @@ dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t
 	enable = false;
 	TD_PREP_PINNED_ASSERT;
 	DMAR_LOCK(dmar);
+	KASSERT(!dmar_is_buswide_ctx(dmar, bus) || (slot == 0 && func == 0),
+	    ("dmar%d pci%d:%d:%d get_ctx for buswide", dmar->unit, bus,
+	    slot, func));
 	ctx = dmar_find_ctx_locked(dmar, rid);
 	error = 0;
 	if (ctx == NULL) {
@@ -492,7 +516,7 @@ dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t
 			if (LIST_EMPTY(&dmar->domains))
 				enable = true;
 			LIST_INSERT_HEAD(&dmar->domains, domain, link);
-			ctx_id_entry_init(ctx, ctxp, false);
+			ctx_id_entry_init(ctx, ctxp, false, bus);
 			if (dev != NULL) {
 				device_printf(dev,
 			    "dmar%d pci%d:%d:%d:%d rid %x domain %d mgaw %d "
@@ -597,7 +621,7 @@ dmar_move_ctx_to_domain(struct dmar_domain *domain, st
 	dmar_ctx_unlink(ctx);
 	ctx->domain = domain;
 	dmar_ctx_link(ctx);
-	ctx_id_entry_init(ctx, ctxp, true);
+	ctx_id_entry_init(ctx, ctxp, true, PCI_BUSMAX + 100);
 	dmar_unmap_pgtbl(sf);
 	error = dmar_flush_for_ctx_entry(dmar, true);
 	/* If flush failed, rolling back would not work as well. */

Modified: stable/12/sys/x86/iommu/intel_dmar.h
==============================================================================
--- stable/12/sys/x86/iommu/intel_dmar.h	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_dmar.h	Mon Nov 25 09:43:36 2019	(r355086)
@@ -239,6 +239,15 @@ struct dmar_unit {
 	struct taskqueue *delayed_taskqueue;
 
 	int dma_enabled;
+
+	/*
+	 * Bitmap of buses for which context must ignore slot:func,
+	 * duplicating the page table pointer into all context table
+	 * entries.  This is a client-controlled quirk to support some
+	 * NTBs.
+	 */
+	uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)];
+
 };
 
 #define	DMAR_LOCK(dmar)		mtx_lock(&(dmar)->lock)
@@ -376,6 +385,9 @@ void dmar_quirks_pre_use(struct dmar_unit *dmar);
 
 int dmar_init_irt(struct dmar_unit *unit);
 void dmar_fini_irt(struct dmar_unit *unit);
+
+void dmar_set_buswide_ctx(struct dmar_unit *unit, u_int busno);
+bool dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno);
 
 #define	DMAR_GM_CANWAIT	0x0001
 #define	DMAR_GM_CANSPLIT 0x0002

Modified: stable/12/sys/x86/iommu/intel_drv.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_drv.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_drv.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -68,9 +68,9 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
-#include <x86/iommu/intel_dmar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
+#include <x86/iommu/intel_dmar.h>
 
 #ifdef DEV_APIC
 #include "pcib_if.h"
@@ -593,6 +593,26 @@ static driver_t	dmar_driver = {
 
 DRIVER_MODULE(dmar, acpi, dmar_driver, dmar_devclass, 0, 0);
 MODULE_DEPEND(dmar, acpi, 1, 1, 1);
+
+void
+dmar_set_buswide_ctx(struct dmar_unit *unit, u_int busno)
+{
+
+	MPASS(busno <= PCI_BUSMAX);
+	DMAR_LOCK(unit);
+	unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] |=
+	    1 << (busno % (NBBY * sizeof(uint32_t)));
+	DMAR_UNLOCK(unit);
+}
+
+bool
+dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno)
+{
+
+	MPASS(busno <= PCI_BUSMAX);
+	return ((unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] &
+	    (1U << (busno % (NBBY * sizeof(uint32_t))))) != 0);
+}
 
 static void
 dmar_print_path(int busno, int depth, const ACPI_DMAR_PCI_PATH *path)

Modified: stable/12/sys/x86/iommu/intel_gas.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_gas.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_gas.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 
 /*

Modified: stable/12/sys/x86/iommu/intel_idpgtbl.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_idpgtbl.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_idpgtbl.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 
 static int domain_unmap_buf_locked(struct dmar_domain *domain,

Modified: stable/12/sys/x86/iommu/intel_intrmap.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_intrmap.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_intrmap.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 #include <dev/pci/pcivar.h>
 #include <x86/iommu/iommu_intrmap.h>

Modified: stable/12/sys/x86/iommu/intel_qi.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_qi.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_qi.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 
 static bool

Modified: stable/12/sys/x86/iommu/intel_quirks.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_quirks.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_quirks.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 #include <dev/pci/pcivar.h>
 

Modified: stable/12/sys/x86/iommu/intel_utils.c
==============================================================================
--- stable/12/sys/x86/iommu/intel_utils.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/iommu/intel_utils.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <x86/include/busdma_impl.h>
 #include <x86/iommu/intel_reg.h>
 #include <x86/iommu/busdma_dmar.h>
+#include <dev/pci/pcireg.h>
 #include <x86/iommu/intel_dmar.h>
 
 u_int

Modified: stable/12/sys/x86/x86/busdma_machdep.c
==============================================================================
--- stable/12/sys/x86/x86/busdma_machdep.c	Mon Nov 25 07:48:16 2019	(r355085)
+++ stable/12/sys/x86/x86/busdma_machdep.c	Mon Nov 25 09:43:36 2019	(r355086)
@@ -33,6 +33,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_acpi.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
@@ -245,3 +247,10 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 	return (tc->impl->tag_destroy(dmat));
 }
 
+#ifndef ACPI_DMAR
+bool
+bus_dma_dmar_set_buswide(device_t dev)
+{
+	return (false);
+}
+#endif


More information about the svn-src-all mailing list