The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f2e36d47e3be31ce819e28d8178b6695556a9e53
commit f2e36d47e3be31ce819e28d8178b6695556a9e53
Author:     Andrew Turner <and...@freebsd.org>
AuthorDate: 2022-03-14 12:40:25 +0000
Commit:     Andrew Turner <and...@freebsd.org>
CommitDate: 2022-03-15 09:52:15 +0000

    Make page size dynamic in libkvm for arm64
    
    To allow for a future 16k or 64k page size we need to tell libkvm which
    is being used. Add a flag field in unused space in minidumphdr and use
    it to signal between the different options.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D34548
---
 lib/libkvm/kvm_aarch64.h           | 15 ++++----
 lib/libkvm/kvm_minidump_aarch64.c  | 79 ++++++++++++++++++++++++++------------
 sys/arm64/arm64/minidump_machdep.c |  1 +
 sys/arm64/include/minidump.h       |  7 +++-
 4 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/lib/libkvm/kvm_aarch64.h b/lib/libkvm/kvm_aarch64.h
index fbbd869ab425..fdbdafde025b 100644
--- a/lib/libkvm/kvm_aarch64.h
+++ b/lib/libkvm/kvm_aarch64.h
@@ -35,9 +35,11 @@
 typedef uint64_t       aarch64_physaddr_t;
 typedef uint64_t       aarch64_pte_t;
 
-#define        AARCH64_PAGE_SHIFT      12
-#define        AARCH64_PAGE_SIZE       (1 << AARCH64_PAGE_SHIFT)
-#define        AARCH64_PAGE_MASK       (AARCH64_PAGE_SIZE - 1)
+#define        AARCH64_PAGE_SHIFT_4K   12
+#define        AARCH64_PAGE_SIZE_4K    (1 << AARCH64_PAGE_SHIFT_4K)
+
+#define        AARCH64_PAGE_SHIFT_16K  14
+#define        AARCH64_PAGE_SIZE_16K   (1 << AARCH64_PAGE_SHIFT_16K)
 
 /* Source: arm64/include/pte.h */
 #define        AARCH64_ATTR_MASK       0xfffc000000000fff
@@ -49,17 +51,14 @@ typedef uint64_t    aarch64_pte_t;
 
 #define        AARCH64_ATTR_DESCR_MASK 3
 
-#define        AARCH64_L3_SHIFT        12
+#define        AARCH64_L3_SHIFT_4K     12
+#define        AARCH64_L3_SHIFT_16K    14
 #define        AARCH64_L3_PAGE         0x3
 
 #ifdef __aarch64__
-_Static_assert(PAGE_SHIFT == AARCH64_PAGE_SHIFT, "PAGE_SHIFT mismatch");
-_Static_assert(PAGE_SIZE == AARCH64_PAGE_SIZE, "PAGE_SIZE mismatch");
-_Static_assert(PAGE_MASK == AARCH64_PAGE_MASK, "PAGE_MASK mismatch");
 _Static_assert(ATTR_MASK == AARCH64_ATTR_MASK, "ATTR_MASK mismatch");
 _Static_assert(ATTR_DESCR_MASK == AARCH64_ATTR_DESCR_MASK,
     "ATTR_DESCR_MASK mismatch");
-_Static_assert(L3_SHIFT == AARCH64_L3_SHIFT, "L3_SHIFT mismatch");
 _Static_assert(L3_PAGE == AARCH64_L3_PAGE, "L3_PAGE mismatch");
 #endif
 
diff --git a/lib/libkvm/kvm_minidump_aarch64.c 
b/lib/libkvm/kvm_minidump_aarch64.c
index 7fd4219fbf21..5e9ac739406f 100644
--- a/lib/libkvm/kvm_minidump_aarch64.c
+++ b/lib/libkvm/kvm_minidump_aarch64.c
@@ -47,10 +47,13 @@ __FBSDID("$FreeBSD$");
 #include "kvm_private.h"
 #include "kvm_aarch64.h"
 
-#define        aarch64_round_page(x)   roundup2((kvaddr_t)(x), 
AARCH64_PAGE_SIZE)
+#define        aarch64_round_page(x, size)     roundup2((kvaddr_t)(x), size)
+#define        aarch64_trunc_page(x, size)     rounddown2((kvaddr_t)(x), size)
 
 struct vmstate {
        struct minidumphdr hdr;
+       size_t page_size;
+       u_int l3_shift;
 };
 
 static aarch64_pte_t
@@ -102,7 +105,7 @@ _aarch64_minidump_initvtop(kvm_t *kd)
        }
 
        vmst->hdr.version = le32toh(vmst->hdr.version);
-       if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) {
+       if (vmst->hdr.version > MINIDUMP_VERSION || vmst->hdr.version < 1) {
                _kvm_err(kd, kd->program, "wrong minidump version. "
                    "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version);
                return (-1);
@@ -114,28 +117,56 @@ _aarch64_minidump_initvtop(kvm_t *kd)
        vmst->hdr.dmapphys = le64toh(vmst->hdr.dmapphys);
        vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase);
        vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend);
-       vmst->hdr.dumpavailsize = vmst->hdr.version == MINIDUMP_VERSION ?
-           le32toh(vmst->hdr.dumpavailsize) : 0;
+       /* dumpavailsize added in version 2 */
+       if (vmst->hdr.version >= 2) {
+               vmst->hdr.dumpavailsize = le32toh(vmst->hdr.dumpavailsize);
+       } else {
+               vmst->hdr.dumpavailsize = 0;
+       }
+       /* flags added in version 3 */
+       if (vmst->hdr.version >= 3) {
+               vmst->hdr.flags = le32toh(vmst->hdr.flags);
+       } else {
+               vmst->hdr.flags = MINIDUMP_FLAG_PS_4K;
+       }
+
+       switch (vmst->hdr.flags & MINIDUMP_FLAG_PS_MASK) {
+       case MINIDUMP_FLAG_PS_4K:
+               vmst->page_size = AARCH64_PAGE_SIZE_4K;
+               vmst->l3_shift = AARCH64_L3_SHIFT_4K;
+               break;
+       case MINIDUMP_FLAG_PS_16K:
+               vmst->page_size = AARCH64_PAGE_SIZE_16K;
+               vmst->l3_shift = AARCH64_L3_SHIFT_16K;
+               break;
+       default:
+               _kvm_err(kd, kd->program, "unknown page size flag %x",
+                   vmst->hdr.flags & MINIDUMP_FLAG_PS_MASK);
+               return (-1);
+       }
 
        /* Skip header and msgbuf */
-       dump_avail_off = AARCH64_PAGE_SIZE + 
aarch64_round_page(vmst->hdr.msgbufsize);
+       dump_avail_off = vmst->page_size +
+           aarch64_round_page(vmst->hdr.msgbufsize, vmst->page_size);
 
        /* Skip dump_avail */
-       off = dump_avail_off + aarch64_round_page(vmst->hdr.dumpavailsize);
+       off = dump_avail_off +
+           aarch64_round_page(vmst->hdr.dumpavailsize, vmst->page_size);
 
        /* build physical address lookup table for sparse pages */
-       sparse_off = off + aarch64_round_page(vmst->hdr.bitmapsize) +
-           aarch64_round_page(vmst->hdr.pmapsize);
+       sparse_off = off +
+           aarch64_round_page(vmst->hdr.bitmapsize, vmst->page_size) +
+           aarch64_round_page(vmst->hdr.pmapsize, vmst->page_size);
        if (_kvm_pt_init(kd, vmst->hdr.dumpavailsize, dump_avail_off,
-           vmst->hdr.bitmapsize, off, sparse_off, AARCH64_PAGE_SIZE) == -1) {
+           vmst->hdr.bitmapsize, off, sparse_off, vmst->page_size) == -1) {
                return (-1);
        }
-       off += aarch64_round_page(vmst->hdr.bitmapsize);
+       off += aarch64_round_page(vmst->hdr.bitmapsize, vmst->page_size);
 
        if (_kvm_pmap_init(kd, vmst->hdr.pmapsize, off) == -1) {
                return (-1);
        }
-       off += aarch64_round_page(vmst->hdr.pmapsize);
+       off += aarch64_round_page(vmst->hdr.pmapsize, vmst->page_size);
 
        return (0);
 }
@@ -151,12 +182,12 @@ _aarch64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
        off_t ofs;
 
        vm = kd->vmst;
-       offset = va & AARCH64_PAGE_MASK;
+       offset = va & (kd->vmst->page_size - 1);
 
        if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) {
-               a = (va - vm->hdr.dmapbase + vm->hdr.dmapphys) &
-                   ~AARCH64_PAGE_MASK;
-               ofs = _kvm_pt_find(kd, a, AARCH64_PAGE_SIZE);
+               a = aarch64_trunc_page(va - vm->hdr.dmapbase + vm->hdr.dmapphys,
+                   kd->vmst->page_size);
+               ofs = _kvm_pt_find(kd, a, kd->vmst->page_size);
                if (ofs == -1) {
                        _kvm_err(kd, kd->program, "_aarch64_minidump_vatop: "
                            "direct map address 0x%jx not in minidump",
@@ -164,9 +195,9 @@ _aarch64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
                        goto invalid;
                }
                *pa = ofs + offset;
-               return (AARCH64_PAGE_SIZE - offset);
+               return (kd->vmst->page_size - offset);
        } else if (va >= vm->hdr.kernbase) {
-               l3_index = (va - vm->hdr.kernbase) >> AARCH64_L3_SHIFT;
+               l3_index = (va - vm->hdr.kernbase) >> kd->vmst->l3_shift;
                if (l3_index >= vm->hdr.pmapsize / sizeof(l3))
                        goto invalid;
                l3 = _aarch64_pte_get(kd, l3_index);
@@ -176,7 +207,7 @@ _aarch64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
                        goto invalid;
                }
                a = l3 & ~AARCH64_ATTR_MASK;
-               ofs = _kvm_pt_find(kd, a, AARCH64_PAGE_SIZE);
+               ofs = _kvm_pt_find(kd, a, kd->vmst->page_size);
                if (ofs == -1) {
                        _kvm_err(kd, kd->program, "_aarch64_minidump_vatop: "
                            "physical address 0x%jx not in minidump",
@@ -184,7 +215,7 @@ _aarch64_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
                        goto invalid;
                }
                *pa = ofs + offset;
-               return (AARCH64_PAGE_SIZE - offset);
+               return (kd->vmst->page_size - offset);
        } else {
                _kvm_err(kd, kd->program,
            "_aarch64_minidump_vatop: virtual address 0x%jx not minidumped",
@@ -252,26 +283,26 @@ _aarch64_minidump_walk_pages(kvm_t *kd, 
kvm_walk_pages_cb_t *cb, void *arg)
                if ((pte & AARCH64_ATTR_DESCR_MASK) != AARCH64_L3_PAGE)
                        continue;
 
-               va = vm->hdr.kernbase + (pteindex << AARCH64_L3_SHIFT);
+               va = vm->hdr.kernbase + (pteindex << kd->vmst->l3_shift);
                pa = pte & ~AARCH64_ATTR_MASK;
                dva = vm->hdr.dmapbase + pa;
                if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva,
-                   _aarch64_entry_to_prot(pte), AARCH64_PAGE_SIZE, 0)) {
+                   _aarch64_entry_to_prot(pte), kd->vmst->page_size, 0)) {
                        goto out;
                }
        }
 
        while (_kvm_bitmap_next(&bm, &bmindex)) {
-               pa = _kvm_bit_id_pa(kd, bmindex, AARCH64_PAGE_SIZE);
+               pa = _kvm_bit_id_pa(kd, bmindex, kd->vmst->page_size);
                if (pa == _KVM_PA_INVALID)
                        break;
                dva = vm->hdr.dmapbase + pa;
-               if (vm->hdr.dmapend < (dva + AARCH64_PAGE_SIZE))
+               if (vm->hdr.dmapend < (dva + kd->vmst->page_size))
                        break;
                va = 0;
                prot = VM_PROT_READ | VM_PROT_WRITE;
                if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva,
-                   prot, AARCH64_PAGE_SIZE, 0)) {
+                   prot, kd->vmst->page_size, 0)) {
                        goto out;
                }
        }
diff --git a/sys/arm64/arm64/minidump_machdep.c 
b/sys/arm64/arm64/minidump_machdep.c
index ac5a7b271b85..e05a19fc1c41 100644
--- a/sys/arm64/arm64/minidump_machdep.c
+++ b/sys/arm64/arm64/minidump_machdep.c
@@ -239,6 +239,7 @@ cpu_minidumpsys(struct dumperinfo *di, const struct 
minidumpstate *state)
        mdhdr.dmapbase = DMAP_MIN_ADDRESS;
        mdhdr.dmapend = DMAP_MAX_ADDRESS;
        mdhdr.dumpavailsize = round_page(sizeof(dump_avail));
+       mdhdr.flags = MINIDUMP_FLAG_PS_4K;
 
        dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_AARCH64_VERSION,
            dumpsize);
diff --git a/sys/arm64/include/minidump.h b/sys/arm64/include/minidump.h
index 87aaffc5ec87..c27d2c71bc12 100644
--- a/sys/arm64/include/minidump.h
+++ b/sys/arm64/include/minidump.h
@@ -31,7 +31,7 @@
 #define        _MACHINE_MINIDUMP_H_ 1
 
 #define        MINIDUMP_MAGIC          "minidump FreeBSD/arm64"
-#define        MINIDUMP_VERSION        2
+#define        MINIDUMP_VERSION        3
 
 struct minidumphdr {
        char magic[24];
@@ -44,6 +44,11 @@ struct minidumphdr {
        uint64_t dmapbase;
        uint64_t dmapend;
        uint32_t dumpavailsize;
+#define        MINIDUMP_FLAG_PS_MASK   (3 << 0)
+#define        MINIDUMP_FLAG_PS_4K     (0 << 0)
+#define        MINIDUMP_FLAG_PS_16K    (1 << 0)
+/* MINIDUMP_FLAG_PS_64K                (2 << 0) */
+       uint32_t flags;
 };
 
 #endif /* _MACHINE_MINIDUMP_H_ */

Reply via email to