git: e9d948cfe0d2 - main - iommu: move context link and ref count into device-independent parts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 13 Oct 2024 22:30:52 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=e9d948cfe0d21780d2e94137e322ecfe89f75d6a commit e9d948cfe0d21780d2e94137e322ecfe89f75d6a Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2024-10-12 19:56:14 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2024-10-13 22:30:26 +0000 iommu: move context link and ref count into device-independent parts This also allows to move some bits of ddb print routines into iommu_utils.c common for x86 iommu drivers. Sponsored by: Advanced Micro Devices (AMD) Sponsored by: The FreeBSD Foundation MFC after: 1 week --- 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 5af5ac7335b8..c2371d4d9c4f 100644 --- a/sys/x86/iommu/intel_ctx.c +++ b/sys/x86/iommu/intel_ctx.c @@ -375,7 +375,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; @@ -430,7 +430,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); } @@ -446,7 +446,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 @@ -463,7 +463,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 @@ -476,7 +476,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)); @@ -593,13 +593,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); @@ -737,15 +737,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; } @@ -762,15 +762,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; @@ -820,14 +820,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