The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e9d948cfe0d21780d2e94137e322ecfe89f75d6a

commit e9d948cfe0d21780d2e94137e322ecfe89f75d6a
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2024-10-12 19:56:14 +0000
Commit:     Konstantin Belousov <[email protected]>
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

Reply via email to