The branch main has been updated by kib:

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

commit 29e227047065c6b1d08fdb72a21f33560637332b
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2024-07-19 23:47:48 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2024-09-04 21:50:19 +0000

    x86 iommu: move page level related functions to common utils
    
    Also improve pglvl_page_size() to handle level 6.
    
    Sponsored by:   Advanced Micro Devices (AMD)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
---
 sys/x86/iommu/intel_dmar.h    |  2 --
 sys/x86/iommu/intel_idpgtbl.c | 38 ++---------------------
 sys/x86/iommu/intel_utils.c   | 37 ----------------------
 sys/x86/iommu/iommu_utils.c   | 71 +++++++++++++++++++++++++++++++++++++++++++
 sys/x86/iommu/x86_iommu.h     |  5 +++
 5 files changed, 78 insertions(+), 75 deletions(-)

diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h
index edb152f42fe7..c1e6c8f06f64 100644
--- a/sys/x86/iommu/intel_dmar.h
+++ b/sys/x86/iommu/intel_dmar.h
@@ -175,9 +175,7 @@ bool dmar_pglvl_supported(struct dmar_unit *unit, int 
pglvl);
 int domain_set_agaw(struct dmar_domain *domain, int mgaw);
 int dmar_maxaddr2mgaw(struct dmar_unit *unit, iommu_gaddr_t maxaddr,
     bool allow_less);
-vm_pindex_t pglvl_max_pages(int pglvl);
 int domain_is_sp_lvl(struct dmar_domain *domain, int lvl);
-iommu_gaddr_t pglvl_page_size(int total_pglvl, int lvl);
 iommu_gaddr_t domain_page_size(struct dmar_domain *domain, int lvl);
 int calc_am(struct dmar_unit *unit, iommu_gaddr_t base, iommu_gaddr_t size,
     iommu_gaddr_t *isizep);
diff --git a/sys/x86/iommu/intel_idpgtbl.c b/sys/x86/iommu/intel_idpgtbl.c
index eb6a51216dfd..53851622340b 100644
--- a/sys/x86/iommu/intel_idpgtbl.c
+++ b/sys/x86/iommu/intel_idpgtbl.c
@@ -316,40 +316,6 @@ put_idmap_pgtbl(vm_object_t obj)
  * address.  Support superpages.
  */
 
-/*
- * Index of the pte for the guest address base in the page table at
- * the level lvl.
- */
-static int
-domain_pgtbl_pte_off(struct dmar_domain *domain, iommu_gaddr_t base, int lvl)
-{
-
-       base >>= IOMMU_PAGE_SHIFT + (domain->pglvl - lvl - 1) *
-           IOMMU_NPTEPGSHIFT;
-       return (base & IOMMU_PTEMASK);
-}
-
-/*
- * Returns the page index of the page table page in the page table
- * object, which maps the given address base at the page table level
- * lvl.
- */
-static vm_pindex_t
-domain_pgtbl_get_pindex(struct dmar_domain *domain, iommu_gaddr_t base, int 
lvl)
-{
-       vm_pindex_t idx, pidx;
-       int i;
-
-       KASSERT(lvl >= 0 && lvl < domain->pglvl,
-           ("wrong lvl %p %d", domain, lvl));
-
-       for (pidx = idx = 0, i = 0; i < lvl; i++, pidx = idx) {
-               idx = domain_pgtbl_pte_off(domain, base, i) +
-                   pidx * IOMMU_NPTEPG + 1;
-       }
-       return (idx);
-}
-
 static iommu_pte_t *
 domain_pgtbl_map_pte(struct dmar_domain *domain, iommu_gaddr_t base, int lvl,
     int flags, vm_pindex_t *idxp, struct sf_buf **sf)
@@ -362,7 +328,7 @@ domain_pgtbl_map_pte(struct dmar_domain *domain, 
iommu_gaddr_t base, int lvl,
        DMAR_DOMAIN_ASSERT_PGLOCKED(domain);
        KASSERT((flags & IOMMU_PGF_OBJL) != 0, ("lost PGF_OBJL"));
 
-       idx = domain_pgtbl_get_pindex(domain, base, lvl);
+       idx = pglvl_pgtbl_get_pindex(domain->pglvl, base, lvl);
        if (*sf != NULL && idx == *idxp) {
                pte = (iommu_pte_t *)sf_buf_kva(*sf);
        } else {
@@ -414,7 +380,7 @@ retry:
                        goto retry;
                }
        }
-       pte += domain_pgtbl_pte_off(domain, base, lvl);
+       pte += pglvl_pgtbl_pte_off(domain->pglvl, base, lvl);
        return (pte);
 }
 
diff --git a/sys/x86/iommu/intel_utils.c b/sys/x86/iommu/intel_utils.c
index a96f65fddfc5..141452b3393d 100644
--- a/sys/x86/iommu/intel_utils.c
+++ b/sys/x86/iommu/intel_utils.c
@@ -172,23 +172,6 @@ dmar_maxaddr2mgaw(struct dmar_unit *unit, iommu_gaddr_t 
maxaddr, bool allow_less
        return (-1);
 }
 
-/*
- * Calculate the total amount of page table pages needed to map the
- * whole bus address space on the context with the selected agaw.
- */
-vm_pindex_t
-pglvl_max_pages(int pglvl)
-{
-       vm_pindex_t res;
-       int i;
-
-       for (res = 0, i = pglvl; i > 0; i--) {
-               res *= IOMMU_NPTEPG;
-               res++;
-       }
-       return (res);
-}
-
 /*
  * Return true if the page table level lvl supports the superpage for
  * the context ctx.
@@ -209,26 +192,6 @@ domain_is_sp_lvl(struct dmar_domain *domain, int lvl)
        return (alvl < nitems(sagaw_sp) && (sagaw_sp[alvl] & cap_sps) != 0);
 }
 
-iommu_gaddr_t
-pglvl_page_size(int total_pglvl, int lvl)
-{
-       int rlvl;
-       static const iommu_gaddr_t pg_sz[] = {
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE,
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE << IOMMU_NPTEPGSHIFT,
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (2 * IOMMU_NPTEPGSHIFT),
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (3 * IOMMU_NPTEPGSHIFT),
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (4 * IOMMU_NPTEPGSHIFT),
-               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (5 * IOMMU_NPTEPGSHIFT),
-       };
-
-       KASSERT(lvl >= 0 && lvl < total_pglvl,
-           ("total %d lvl %d", total_pglvl, lvl));
-       rlvl = total_pglvl - lvl - 1;
-       KASSERT(rlvl < nitems(pg_sz), ("sizeof pg_sz lvl %d", lvl));
-       return (pg_sz[rlvl]);
-}
-
 iommu_gaddr_t
 domain_page_size(struct dmar_domain *domain, int lvl)
 {
diff --git a/sys/x86/iommu/iommu_utils.c b/sys/x86/iommu/iommu_utils.c
index 9c6cae5ff51f..645c7e15740a 100644
--- a/sys/x86/iommu/iommu_utils.c
+++ b/sys/x86/iommu/iommu_utils.c
@@ -619,3 +619,74 @@ iommu_domain_free_entry(struct iommu_map_entry *entry, 
bool free)
                entry->flags = 0;
 }
 
+/*
+ * Index of the pte for the guest address base in the page table at
+ * the level lvl.
+ */
+int
+pglvl_pgtbl_pte_off(int pglvl, iommu_gaddr_t base, int lvl)
+{
+
+       base >>= IOMMU_PAGE_SHIFT + (pglvl - lvl - 1) *
+           IOMMU_NPTEPGSHIFT;
+       return (base & IOMMU_PTEMASK);
+}
+
+/*
+ * Returns the page index of the page table page in the page table
+ * object, which maps the given address base at the page table level
+ * lvl.
+ */
+vm_pindex_t
+pglvl_pgtbl_get_pindex(int pglvl, iommu_gaddr_t base, int lvl)
+{
+       vm_pindex_t idx, pidx;
+       int i;
+
+       KASSERT(lvl >= 0 && lvl < pglvl,
+           ("wrong lvl %d %d", pglvl, lvl));
+
+       for (pidx = idx = 0, i = 0; i < lvl; i++, pidx = idx) {
+               idx = pglvl_pgtbl_pte_off(pglvl, base, i) +
+                   pidx * IOMMU_NPTEPG + 1;
+       }
+       return (idx);
+}
+
+/*
+ * Calculate the total amount of page table pages needed to map the
+ * whole bus address space on the context with the selected agaw.
+ */
+vm_pindex_t
+pglvl_max_pages(int pglvl)
+{
+       vm_pindex_t res;
+       int i;
+
+       for (res = 0, i = pglvl; i > 0; i--) {
+               res *= IOMMU_NPTEPG;
+               res++;
+       }
+       return (res);
+}
+
+iommu_gaddr_t
+pglvl_page_size(int total_pglvl, int lvl)
+{
+       int rlvl;
+       static const iommu_gaddr_t pg_sz[] = {
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE,
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << IOMMU_NPTEPGSHIFT,
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (2 * IOMMU_NPTEPGSHIFT),
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (3 * IOMMU_NPTEPGSHIFT),
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (4 * IOMMU_NPTEPGSHIFT),
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (5 * IOMMU_NPTEPGSHIFT),
+               (iommu_gaddr_t)IOMMU_PAGE_SIZE << (6 * IOMMU_NPTEPGSHIFT),
+       };
+
+       KASSERT(lvl >= 0 && lvl < total_pglvl,
+           ("total %d lvl %d", total_pglvl, lvl));
+       rlvl = total_pglvl - lvl - 1;
+       KASSERT(rlvl < nitems(pg_sz), ("sizeof pg_sz lvl %d", lvl));
+       return (pg_sz[rlvl]);
+}
diff --git a/sys/x86/iommu/x86_iommu.h b/sys/x86/iommu/x86_iommu.h
index 9e3a82283729..b2caed550e35 100644
--- a/sys/x86/iommu/x86_iommu.h
+++ b/sys/x86/iommu/x86_iommu.h
@@ -187,4 +187,9 @@ void iommu_release_intr(struct iommu_unit *unit, int idx);
 
 void iommu_device_tag_init(struct iommu_ctx *ctx, device_t dev);
 
+int pglvl_pgtbl_pte_off(int pglvl, iommu_gaddr_t base, int lvl);
+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);
+
 #endif

Reply via email to