git: b38cff22720b - stable/14 - iommu: move context link and ref count into device-independent parts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 20 Oct 2024 00:34:47 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=b38cff22720b66d6c22b157487772091e3f3e8ee
commit b38cff22720b66d6c22b157487772091e3f3e8ee
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-10-12 19:56:14 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-10-20 00:33:04 +0000
iommu: move context link and ref count into device-independent parts
(cherry picked from commit e9d948cfe0d21780d2e94137e322ecfe89f75d6a)
---
sys/dev/iommu/iommu.h | 3 +++
sys/x86/iommu/intel_ctx.c | 38 ++++++++++++++--------------
sys/x86/iommu/intel_dmar.h | 3 ---
sys/x86/iommu/intel_drv.c | 61 +++++++++------------------------------------
sys/x86/iommu/iommu_utils.c | 41 ++++++++++++++++++++++++++++++
sys/x86/iommu/x86_iommu.h | 3 +++
6 files changed, 78 insertions(+), 71 deletions(-)
diff --git a/sys/dev/iommu/iommu.h b/sys/dev/iommu/iommu.h
index f425024117d3..b1858f0df9f7 100644
--- a/sys/dev/iommu/iommu.h
+++ b/sys/dev/iommu/iommu.h
@@ -121,11 +121,14 @@ struct iommu_domain {
iommu_gaddr_t msi_base; /* (d) Arch-specific */
vm_paddr_t msi_phys; /* (d) Arch-specific */
u_int flags; /* (u) */
+ LIST_HEAD(, iommu_ctx) contexts;/* (u) */
};
struct iommu_ctx {
struct iommu_domain *domain; /* (c) */
struct bus_dma_tag_iommu *tag; /* (c) Root tag */
+ LIST_ENTRY(iommu_ctx) link; /* (u) Member in the domain list */
+ u_int refs; /* (u) References from tags */
u_long loads; /* atomic updates, for stat only */
u_long unloads; /* same */
u_int flags; /* (u) */
diff --git a/sys/x86/iommu/intel_ctx.c b/sys/x86/iommu/intel_ctx.c
index bdb5f8740bf2..c7c7012e94ea 100644
--- a/sys/x86/iommu/intel_ctx.c
+++ b/sys/x86/iommu/intel_ctx.c
@@ -376,7 +376,7 @@ dmar_domain_alloc(struct dmar_unit *dmar, bool id_mapped)
iodom = DOM2IODOM(domain);
unit = DMAR2IOMMU(dmar);
domain->domain = id;
- LIST_INIT(&domain->contexts);
+ LIST_INIT(&iodom->contexts);
iommu_domain_init(unit, iodom, &dmar_domain_map_ops);
domain->dmar = dmar;
@@ -431,7 +431,7 @@ dmar_ctx_alloc(struct dmar_domain *domain, uint16_t rid)
ctx->context.tag = malloc(sizeof(struct bus_dma_tag_iommu),
M_DMAR_CTX, M_WAITOK | M_ZERO);
ctx->context.rid = rid;
- ctx->refs = 1;
+ ctx->context.refs = 1;
return (ctx);
}
@@ -447,7 +447,7 @@ dmar_ctx_link(struct dmar_ctx *ctx)
domain->ctx_cnt));
domain->refs++;
domain->ctx_cnt++;
- LIST_INSERT_HEAD(&domain->contexts, ctx, link);
+ LIST_INSERT_HEAD(&domain->iodom.contexts, &ctx->context, link);
}
static void
@@ -464,7 +464,7 @@ dmar_ctx_unlink(struct dmar_ctx *ctx)
domain->refs, domain->ctx_cnt));
domain->refs--;
domain->ctx_cnt--;
- LIST_REMOVE(ctx, link);
+ LIST_REMOVE(&ctx->context, link);
}
static void
@@ -477,7 +477,7 @@ dmar_domain_destroy(struct dmar_domain *domain)
KASSERT(TAILQ_EMPTY(&domain->iodom.unload_entries),
("unfinished unloads %p", domain));
- KASSERT(LIST_EMPTY(&domain->contexts),
+ KASSERT(LIST_EMPTY(&iodom->contexts),
("destroying dom %p with contexts", domain));
KASSERT(domain->ctx_cnt == 0,
("destroying dom %p with ctx_cnt %d", domain, domain->ctx_cnt));
@@ -594,13 +594,13 @@ dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t dev, uint16_t rid,
/* Nothing needs to be done to destroy ctx1. */
free(ctx1, M_DMAR_CTX);
domain = CTX2DOM(ctx);
- ctx->refs++; /* tag referenced us */
+ ctx->context.refs++; /* tag referenced us */
}
} else {
domain = CTX2DOM(ctx);
if (ctx->context.tag->owner == NULL)
ctx->context.tag->owner = dev;
- ctx->refs++; /* tag referenced us */
+ ctx->context.refs++; /* tag referenced us */
}
error = dmar_flush_for_ctx_entry(dmar, enable);
@@ -738,15 +738,15 @@ dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ctx)
struct dmar_domain *domain;
DMAR_ASSERT_LOCKED(dmar);
- KASSERT(ctx->refs >= 1,
- ("dmar %p ctx %p refs %u", dmar, ctx, ctx->refs));
+ KASSERT(ctx->context.refs >= 1,
+ ("dmar %p ctx %p refs %u", dmar, ctx, ctx->context.refs));
/*
* If our reference is not last, only the dereference should
* be performed.
*/
- if (ctx->refs > 1) {
- ctx->refs--;
+ if (ctx->context.refs > 1) {
+ ctx->context.refs--;
DMAR_UNLOCK(dmar);
return;
}
@@ -763,15 +763,15 @@ dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ctx)
TD_PREP_PINNED_ASSERT;
ctxp = dmar_map_ctx_entry(ctx, &sf);
DMAR_LOCK(dmar);
- KASSERT(ctx->refs >= 1,
- ("dmar %p ctx %p refs %u", dmar, ctx, ctx->refs));
+ KASSERT(ctx->context.refs >= 1,
+ ("dmar %p ctx %p refs %u", dmar, ctx, ctx->context.refs));
/*
* Other thread might have referenced the context, in which
* case again only the dereference should be performed.
*/
- if (ctx->refs > 1) {
- ctx->refs--;
+ if (ctx->context.refs > 1) {
+ ctx->context.refs--;
DMAR_UNLOCK(dmar);
iommu_unmap_pgtbl(sf);
TD_PINNED_ASSERT;
@@ -821,14 +821,14 @@ struct dmar_ctx *
dmar_find_ctx_locked(struct dmar_unit *dmar, uint16_t rid)
{
struct dmar_domain *domain;
- struct dmar_ctx *ctx;
+ struct iommu_ctx *ctx;
DMAR_ASSERT_LOCKED(dmar);
LIST_FOREACH(domain, &dmar->domains, link) {
- LIST_FOREACH(ctx, &domain->contexts, link) {
- if (ctx->context.rid == rid)
- return (ctx);
+ LIST_FOREACH(ctx, &domain->iodom.contexts, link) {
+ if (ctx->rid == rid)
+ return (IOCTX2CTX(ctx));
}
}
return (NULL);
diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h
index fcdc915abcfd..c3163abf6f92 100644
--- a/sys/x86/iommu/intel_dmar.h
+++ b/sys/x86/iommu/intel_dmar.h
@@ -65,7 +65,6 @@ struct dmar_domain {
u_int refs; /* (u) Refs, including ctx */
struct dmar_unit *dmar; /* (c) */
LIST_ENTRY(dmar_domain) link; /* (u) Member in the dmar list */
- LIST_HEAD(, dmar_ctx) contexts; /* (u) */
vm_object_t pgtbl_obj; /* (c) Page table pages */
u_int batch_no;
};
@@ -73,8 +72,6 @@ struct dmar_domain {
struct dmar_ctx {
struct iommu_ctx context;
uint64_t last_fault_rec[2]; /* Last fault reported */
- LIST_ENTRY(dmar_ctx) link; /* (u) Member in the domain list */
- u_int refs; /* (u) References from tags */
};
#define DMAR_DOMAIN_PGLOCK(dom) VM_OBJECT_WLOCK((dom)->pgtbl_obj)
diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c
index cc16759ebe34..e973115df21b 100644
--- a/sys/x86/iommu/intel_drv.c
+++ b/sys/x86/iommu/intel_drv.c
@@ -1053,48 +1053,12 @@ dmar_instantiate_rmrr_ctxs(struct iommu_unit *unit)
#include <ddb/ddb.h>
#include <ddb/db_lex.h>
-static void
-dmar_print_domain_entry(const struct iommu_map_entry *entry)
-{
- struct iommu_map_entry *l, *r;
-
- db_printf(
- " start %jx end %jx first %jx last %jx free_down %jx flags %x ",
- entry->start, entry->end, entry->first, entry->last,
- entry->free_down, entry->flags);
- db_printf("left ");
- l = RB_LEFT(entry, rb_entry);
- if (l == NULL)
- db_printf("NULL ");
- else
- db_printf("%jx ", l->start);
- db_printf("right ");
- r = RB_RIGHT(entry, rb_entry);
- if (r == NULL)
- db_printf("NULL");
- else
- db_printf("%jx", r->start);
- db_printf("\n");
-}
-
-static void
-dmar_print_ctx(struct dmar_ctx *ctx)
-{
-
- db_printf(
- " @%p pci%d:%d:%d refs %d flags %x loads %lu unloads %lu\n",
- ctx, pci_get_bus(ctx->context.tag->owner),
- pci_get_slot(ctx->context.tag->owner),
- pci_get_function(ctx->context.tag->owner), ctx->refs,
- ctx->context.flags, ctx->context.loads, ctx->context.unloads);
-}
-
static void
dmar_print_domain(struct dmar_domain *domain, bool show_mappings)
{
struct iommu_domain *iodom;
struct iommu_map_entry *entry;
- struct dmar_ctx *ctx;
+ struct iommu_ctx *ctx;
iodom = DOM2IODOM(domain);
@@ -1104,16 +1068,16 @@ dmar_print_domain(struct dmar_domain *domain, bool show_mappings)
domain, domain->domain, domain->mgaw, domain->agaw, domain->pglvl,
(uintmax_t)domain->iodom.end, domain->refs, domain->ctx_cnt,
domain->iodom.flags, domain->pgtbl_obj, domain->iodom.entries_cnt);
- if (!LIST_EMPTY(&domain->contexts)) {
+ if (!LIST_EMPTY(&iodom->contexts)) {
db_printf(" Contexts:\n");
- LIST_FOREACH(ctx, &domain->contexts, link)
- dmar_print_ctx(ctx);
+ LIST_FOREACH(ctx, &iodom->contexts, link)
+ iommu_db_print_ctx(ctx);
}
if (!show_mappings)
return;
db_printf(" mapped:\n");
RB_FOREACH(entry, iommu_gas_entries_tree, &iodom->rb_root) {
- dmar_print_domain_entry(entry);
+ iommu_db_print_domain_entry(entry);
if (db_pager_quit)
break;
}
@@ -1121,7 +1085,7 @@ dmar_print_domain(struct dmar_domain *domain, bool show_mappings)
return;
db_printf(" unloading:\n");
TAILQ_FOREACH(entry, &domain->iodom.unload_entries, dmamap_link) {
- dmar_print_domain_entry(entry);
+ iommu_db_print_domain_entry(entry);
if (db_pager_quit)
break;
}
@@ -1131,7 +1095,7 @@ DB_SHOW_COMMAND_FLAGS(dmar_domain, db_dmar_print_domain, CS_OWN)
{
struct dmar_unit *unit;
struct dmar_domain *domain;
- struct dmar_ctx *ctx;
+ struct iommu_ctx *ctx;
bool show_mappings, valid;
int pci_domain, bus, device, function, i, t;
db_expr_t radix;
@@ -1179,13 +1143,12 @@ DB_SHOW_COMMAND_FLAGS(dmar_domain, db_dmar_print_domain, CS_OWN)
for (i = 0; i < dmar_devcnt; i++) {
unit = device_get_softc(dmar_devs[i]);
LIST_FOREACH(domain, &unit->domains, link) {
- LIST_FOREACH(ctx, &domain->contexts, link) {
+ LIST_FOREACH(ctx, &domain->iodom.contexts, link) {
if (pci_domain == unit->segment &&
- bus == pci_get_bus(ctx->context.tag->owner) &&
- device ==
- pci_get_slot(ctx->context.tag->owner) &&
- function ==
- pci_get_function(ctx->context.tag->owner)) {
+ bus == pci_get_bus(ctx->tag->owner) &&
+ device == pci_get_slot(ctx->tag->owner) &&
+ function == pci_get_function(ctx->tag->
+ owner)) {
dmar_print_domain(domain,
show_mappings);
goto out;
diff --git a/sys/x86/iommu/iommu_utils.c b/sys/x86/iommu/iommu_utils.c
index db8f94eb584f..fde3f150947b 100644
--- a/sys/x86/iommu/iommu_utils.c
+++ b/sys/x86/iommu/iommu_utils.c
@@ -34,6 +34,7 @@
#else
#include "opt_apic.h"
#endif
+#include "opt_ddb.h"
#include <sys/systm.h>
#include <sys/bus.h>
@@ -756,3 +757,43 @@ pglvl_page_size(int total_pglvl, int lvl)
KASSERT(rlvl < nitems(pg_sz), ("sizeof pg_sz lvl %d", lvl));
return (pg_sz[rlvl]);
}
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#include <ddb/db_lex.h>
+
+void
+iommu_db_print_domain_entry(const struct iommu_map_entry *entry)
+{
+ struct iommu_map_entry *l, *r;
+
+ db_printf(
+ " start %jx end %jx first %jx last %jx free_down %jx flags %x ",
+ entry->start, entry->end, entry->first, entry->last,
+ entry->free_down, entry->flags);
+ db_printf("left ");
+ l = RB_LEFT(entry, rb_entry);
+ if (l == NULL)
+ db_printf("NULL ");
+ else
+ db_printf("%jx ", l->start);
+ db_printf("right ");
+ r = RB_RIGHT(entry, rb_entry);
+ if (r == NULL)
+ db_printf("NULL");
+ else
+ db_printf("%jx", r->start);
+ db_printf("\n");
+}
+
+void
+iommu_db_print_ctx(struct iommu_ctx *ctx)
+{
+ db_printf(
+ " @%p pci%d:%d:%d refs %d flags %#x loads %lu unloads %lu\n",
+ ctx, pci_get_bus(ctx->tag->owner),
+ pci_get_slot(ctx->tag->owner),
+ pci_get_function(ctx->tag->owner), ctx->refs,
+ ctx->flags, ctx->loads, ctx->unloads);
+}
+#endif
diff --git a/sys/x86/iommu/x86_iommu.h b/sys/x86/iommu/x86_iommu.h
index 4d0ac8351e2e..043935a3e0de 100644
--- a/sys/x86/iommu/x86_iommu.h
+++ b/sys/x86/iommu/x86_iommu.h
@@ -194,4 +194,7 @@ vm_pindex_t pglvl_pgtbl_get_pindex(int pglvl, iommu_gaddr_t base, int lvl);
vm_pindex_t pglvl_max_pages(int pglvl);
iommu_gaddr_t pglvl_page_size(int total_pglvl, int lvl);
+void iommu_db_print_domain_entry(const struct iommu_map_entry *entry);
+void iommu_db_print_ctx(struct iommu_ctx *ctx);
+
#endif