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