Index: lib/libkvm/kvm_minidump_aarch64.c =================================================================== --- lib/libkvm/kvm_minidump_aarch64.c +++ lib/libkvm/kvm_minidump_aarch64.c @@ -121,8 +121,8 @@ /* build physical address lookup table for sparse pages */ sparse_off = off + aarch64_round_page(vmst->hdr.bitmapsize) + aarch64_round_page(vmst->hdr.pmapsize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - AARCH64_PAGE_SIZE, sizeof(uint64_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, AARCH64_PAGE_SIZE, sizeof(uint64_t)) == -1) { return (-1); } off += aarch64_round_page(vmst->hdr.bitmapsize); @@ -257,7 +257,7 @@ } while (_kvm_bitmap_next(&bm, &bmindex)) { - pa = bmindex * AARCH64_PAGE_SIZE; + pa = _kvm_bit_id_pa(kd, bmindex, AARCH64_PAGE_SIZE); dva = vm->hdr.dmapbase + pa; if (vm->hdr.dmapend < (dva + AARCH64_PAGE_SIZE)) break; Index: lib/libkvm/kvm_minidump_amd64.c =================================================================== --- lib/libkvm/kvm_minidump_amd64.c +++ lib/libkvm/kvm_minidump_amd64.c @@ -163,8 +163,8 @@ sparse_off = off + amd64_round_page(vmst->hdr.bitmapsize) + amd64_round_page(vmst->hdr.pmapsize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - AMD64_PAGE_SIZE, sizeof(uint64_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, AMD64_PAGE_SIZE, sizeof(uint64_t)) == -1) { return (-1); } off += amd64_round_page(vmst->hdr.bitmapsize); @@ -372,7 +372,7 @@ pa = (pde & AMD64_PG_PS_FRAME) + ((va & AMD64_PDRMASK) ^ VA_OFF(vm, va)); dva = vm->hdr.dmapbase + pa; - _kvm_bitmap_set(&bm, pa, AMD64_PAGE_SIZE); + _kvm_bitmap_set(&bm, _kvm_pa_bit_id(kd, pa, AMD64_PAGE_SIZE)); if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, _amd64_entry_to_prot(pde), AMD64_NBPDR, pgsz)) { goto out; @@ -392,7 +392,8 @@ pa = pte & AMD64_PG_FRAME; dva = vm->hdr.dmapbase + pa; if ((pte & AMD64_PG_V) != 0) { - _kvm_bitmap_set(&bm, pa, AMD64_PAGE_SIZE); + _kvm_bitmap_set(&bm, + _kvm_pa_bit_id(kd, pa, AMD64_PAGE_SIZE)); if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, _amd64_entry_to_prot(pte), pgsz, 0)) { goto out; @@ -403,7 +404,7 @@ } while (_kvm_bitmap_next(&bm, &bmindex)) { - pa = bmindex * AMD64_PAGE_SIZE; + pa = _kvm_bit_id_pa(kd, bmindex, AMD64_PAGE_SIZE); dva = vm->hdr.dmapbase + pa; if (vm->hdr.dmapend < (dva + pgsz)) break; Index: lib/libkvm/kvm_minidump_arm.c =================================================================== --- lib/libkvm/kvm_minidump_arm.c +++ lib/libkvm/kvm_minidump_arm.c @@ -129,8 +129,8 @@ sparse_off = off + arm_round_page(vmst->hdr.bitmapsize) + arm_round_page(vmst->hdr.ptesize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - ARM_PAGE_SIZE, sizeof(uint32_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, ARM_PAGE_SIZE, sizeof(uint32_t)) == -1) { return (-1); } off += arm_round_page(vmst->hdr.bitmapsize); Index: lib/libkvm/kvm_minidump_i386.c =================================================================== --- lib/libkvm/kvm_minidump_i386.c +++ lib/libkvm/kvm_minidump_i386.c @@ -125,8 +125,8 @@ sparse_off = off + i386_round_page(vmst->hdr.bitmapsize) + i386_round_page(vmst->hdr.ptesize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - I386_PAGE_SIZE, sizeof(uint32_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, I386_PAGE_SIZE, sizeof(uint32_t)) == -1) { return (-1); } off += i386_round_page(vmst->hdr.bitmapsize); Index: lib/libkvm/kvm_minidump_mips.c =================================================================== --- lib/libkvm/kvm_minidump_mips.c +++ lib/libkvm/kvm_minidump_mips.c @@ -130,8 +130,8 @@ sparse_off = off + mips_round_page(vmst->hdr.bitmapsize) + mips_round_page(vmst->hdr.ptesize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - MIPS_PAGE_SIZE, sizeof(uint32_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, MIPS_PAGE_SIZE, sizeof(uint32_t)) == -1) { return (-1); } off += mips_round_page(vmst->hdr.bitmapsize); Index: lib/libkvm/kvm_minidump_powerpc64.c =================================================================== --- lib/libkvm/kvm_minidump_powerpc64.c +++ lib/libkvm/kvm_minidump_powerpc64.c @@ -151,8 +151,8 @@ (uintmax_t)pmap_off, (uintmax_t)sparse_off); /* build physical address lookup table for sparse pages */ - if (_kvm_pt_init(kd, hdr->bitmapsize, bitmap_off, sparse_off, - PPC64_PAGE_SIZE, sizeof(uint64_t)) == -1) + if (_kvm_pt_init(kd, sizeof(*hdr), hdr->bitmapsize, bitmap_off, + sparse_off, PPC64_PAGE_SIZE, sizeof(uint64_t)) == -1) goto failed; if (_kvm_pmap_init(kd, hdr->pmapsize, pmap_off) == -1) Index: lib/libkvm/kvm_minidump_riscv.c =================================================================== --- lib/libkvm/kvm_minidump_riscv.c +++ lib/libkvm/kvm_minidump_riscv.c @@ -122,8 +122,8 @@ /* build physical address lookup table for sparse pages */ sparse_off = off + riscv_round_page(vmst->hdr.bitmapsize) + riscv_round_page(vmst->hdr.pmapsize); - if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, - RISCV_PAGE_SIZE, sizeof(uint64_t)) == -1) { + if (_kvm_pt_init(kd, sizeof(vmst->hdr), vmst->hdr.bitmapsize, off, + sparse_off, RISCV_PAGE_SIZE, sizeof(uint64_t)) == -1) { return (-1); } off += riscv_round_page(vmst->hdr.bitmapsize); @@ -258,7 +258,7 @@ } while (_kvm_bitmap_next(&bm, &bmindex)) { - pa = bmindex * RISCV_PAGE_SIZE; + pa = _kvm_bit_id_pa(kd, bmindex, RISCV_PAGE_SIZE); dva = vm->hdr.dmapbase + pa; if (vm->hdr.dmapend < (dva + RISCV_PAGE_SIZE)) break; Index: lib/libkvm/kvm_private.h =================================================================== --- lib/libkvm/kvm_private.h +++ lib/libkvm/kvm_private.h @@ -106,6 +106,8 @@ /* Page table lookup structures. */ uint64_t *pt_map; size_t pt_map_size; + kpaddr_t *dump_avail; + size_t dump_avail_size; off_t pt_sparse_off; uint64_t pt_sparse_size; uint32_t *pt_popcounts; @@ -152,8 +154,11 @@ return (be64toh(val)); } +uint64_t _kvm_pa_bit_id(kvm_t *kd, uint64_t pa, unsigned int page_size); +uint64_t _kvm_bit_id_pa(kvm_t *kd, uint64_t bit_id, unsigned int page_size); + int _kvm_bitmap_init(struct kvm_bitmap *, u_long, u_long *); -void _kvm_bitmap_set(struct kvm_bitmap *, u_long, unsigned int); +void _kvm_bitmap_set(struct kvm_bitmap *, u_long); int _kvm_bitmap_next(struct kvm_bitmap *, u_long *); void _kvm_bitmap_deinit(struct kvm_bitmap *); @@ -173,7 +178,7 @@ int _kvm_probe_elf_kernel(kvm_t *, int, int); int _kvm_is_minidump(kvm_t *); int _kvm_read_core_phdrs(kvm_t *, size_t *, GElf_Phdr **); -int _kvm_pt_init(kvm_t *, size_t, off_t, off_t, int, int); +int _kvm_pt_init(kvm_t *, off_t, size_t, off_t, off_t, int, int); off_t _kvm_pt_find(kvm_t *, uint64_t, unsigned int); int _kvm_visit_cb(kvm_t *, kvm_walk_pages_cb_t *, void *, u_long, u_long, u_long, vm_prot_t, size_t, unsigned int); Index: lib/libkvm/kvm_private.c =================================================================== --- lib/libkvm/kvm_private.c +++ lib/libkvm/kvm_private.c @@ -290,15 +290,42 @@ } int -_kvm_pt_init(kvm_t *kd, size_t map_len, off_t map_off, off_t sparse_off, - int page_size, int word_size) +_kvm_pt_init(kvm_t *kd, off_t dump_avail_off, size_t map_len, off_t map_off, + off_t sparse_off, int page_size, int word_size) { uint64_t *addr; uint32_t *popcount_bin; - int bin_popcounts = 0; + int bin_popcounts = 0, i; uint64_t pc_bins, res; ssize_t rd; + i = 0; + do { + if (i * sizeof(kpaddr_t) >= kd->dump_avail_size) { + kd->dump_avail_size = MAX(8 * sizeof(kpaddr_t), + 2 * kd->dump_avail_size); + kd->dump_avail = realloc(kd->dump_avail, + kd->dump_avail_size); + if (kd->dump_avail == NULL) { + _kvm_err(kd, kd->program, "cannot allocate %zu " + "bytes for dump_avail", kd->dump_avail_size); + return (-1); + } + } + rd = pread(kd->pmfd, &kd->dump_avail[i], 2 * sizeof(kpaddr_t), + dump_avail_off); + if (rd < 0 || rd != 2 * sizeof(kpaddr_t)) { + _kvm_err(kd, kd->program, "cannot read %zu bytes for " + "dump_avail", 2 * sizeof(kpaddr_t)); + return (-1); + } + i += 2; + dump_avail_off += 2 * sizeof(kpaddr_t); + } while (kd->dump_avail[i - 1] != 0 && i < 128); + + if (i >= 128) + kd->dump_avail[0] = kd->dump_avail[1] = 0; + /* * Map the bitmap specified by the arguments. */ @@ -394,6 +421,45 @@ return (0); } +uint64_t +_kvm_pa_bit_id(kvm_t *kd, uint64_t pa, unsigned int page_size) +{ + uint64_t adj; + int i; + + adj = 0; + for (i = 0; kd->dump_avail[i + 1] != 0; i += 2) { + if (pa >= kd->dump_avail[i + 1]) { + adj += howmany(kd->dump_avail[i + 1], page_size) - + kd->dump_avail[i] / page_size; + } else { + return (pa / page_size - + kd->dump_avail[i] / page_size + adj); + } + } + return (adj + pa / page_size - + howmany(kd->dump_avail[i - 1], page_size)); +} + +uint64_t +_kvm_bit_id_pa(kvm_t *kd, uint64_t bit_id, unsigned int page_size) +{ + uint64_t sz; + int i; + + for (i = 0; kd->dump_avail[i + 1] != 0; i += 2) { + sz = howmany(kd->dump_avail[i + 1], page_size) - + kd->dump_avail[i] / page_size; + if (bit_id < sz) { + return (rounddown2(kd->dump_avail[i], page_size) + + bit_id * page_size); + } + bit_id -= sz; + } + return (bit_id * page_size + + roundup2(kd->dump_avail[i - 1], page_size)); +} + /* * Find the offset for the given physical page address; returns -1 otherwise. * @@ -412,7 +478,7 @@ _kvm_pt_find(kvm_t *kd, uint64_t pa, unsigned int page_size) { uint64_t *bitmap = kd->pt_map; - uint64_t pte_bit_id = pa / page_size; + uint64_t pte_bit_id = _kvm_pa_bit_id(kd, pa, page_size); uint64_t pte_u64 = pte_bit_id / BITS_IN(*bitmap); uint64_t popcount_id = pte_bit_id / POPCOUNT_BITS; uint64_t pte_mask = 1ULL << (pte_bit_id % BITS_IN(*bitmap)); @@ -714,9 +780,8 @@ } void -_kvm_bitmap_set(struct kvm_bitmap *bm, u_long pa, unsigned int page_size) +_kvm_bitmap_set(struct kvm_bitmap *bm, u_long bm_index) { - u_long bm_index = pa / page_size; uint8_t *byte = &bm->map[bm_index / 8]; *byte |= (1UL << (bm_index % 8)); Index: sys/amd64/amd64/minidump_machdep.c =================================================================== --- sys/amd64/amd64/minidump_machdep.c +++ sys/amd64/amd64/minidump_machdep.c @@ -216,6 +216,7 @@ int minidumpsys(struct dumperinfo *di) { + kpaddr_t *dump_avail_out; uint32_t pmapsize; vm_offset_t va; int error; @@ -317,7 +318,7 @@ strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.pmapsize = pmapsize; mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; mdhdr.dmapbase = DMAP_MIN_ADDRESS; @@ -336,6 +337,12 @@ /* Dump my header */ bzero(&fakepd, sizeof(fakepd)); bcopy(&mdhdr, &fakepd, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)((char *)fakepd + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, (char *)&fakepd, 0, PAGE_SIZE); if (error) goto fail; Index: sys/amd64/include/minidump.h =================================================================== --- sys/amd64/include/minidump.h +++ sys/amd64/include/minidump.h @@ -32,7 +32,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/amd64" -#define MINIDUMP_VERSION 2 +#define MINIDUMP_VERSION 3 struct minidumphdr { char magic[24]; Index: sys/arm/arm/minidump_machdep.c =================================================================== --- sys/arm/arm/minidump_machdep.c +++ sys/arm/arm/minidump_machdep.c @@ -176,6 +176,7 @@ { struct minidumphdr mdhdr; uint64_t dumpsize; + kpaddr_t *dump_avail_out; uint32_t ptesize; uint32_t pa, prev_pa = 0, count = 0; vm_offset_t va; @@ -223,7 +224,7 @@ strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.ptesize = ptesize; mdhdr.kernbase = KERNBASE; mdhdr.arch = __ARM_ARCH; @@ -245,6 +246,12 @@ /* Dump my header */ bzero(dumpbuf, sizeof(dumpbuf)); bcopy(&mdhdr, dumpbuf, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)(dumpbuf + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, dumpbuf, 0, PAGE_SIZE); if (error) goto fail; Index: sys/arm/include/minidump.h =================================================================== --- sys/arm/include/minidump.h +++ sys/arm/include/minidump.h @@ -33,7 +33,7 @@ #define _MACHINE_MINIDUMP_H_ #define MINIDUMP_MAGIC "minidump FreeBSD/arm" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 /* * The first page of vmcore is dedicated to the following header. Index: sys/arm64/arm64/minidump_machdep.c =================================================================== --- sys/arm64/arm64/minidump_machdep.c +++ sys/arm64/arm64/minidump_machdep.c @@ -208,6 +208,7 @@ pt_entry_t *l3; vm_offset_t va; vm_paddr_t pa; + kpaddr_t *dump_avail_out; uint32_t pmapsize; int bit, error, i, j, retry_count; @@ -265,7 +266,7 @@ strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.pmapsize = pmapsize; mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; mdhdr.dmapphys = DMAP_MIN_PHYSADDR; @@ -285,6 +286,12 @@ /* Dump my header */ bzero(&tmpbuffer, sizeof(tmpbuffer)); bcopy(&mdhdr, &tmpbuffer, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)((char *)tmpbuffer + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); if (error) goto fail; Index: sys/arm64/include/minidump.h =================================================================== --- sys/arm64/include/minidump.h +++ sys/arm64/include/minidump.h @@ -31,7 +31,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/arm64" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 struct minidumphdr { char magic[24]; Index: sys/i386/i386/minidump_machdep_base.c =================================================================== --- sys/i386/i386/minidump_machdep_base.c +++ sys/i386/i386/minidump_machdep_base.c @@ -176,6 +176,7 @@ minidumpsys(struct dumperinfo *di) { uint64_t dumpsize; + kpaddr_t *dump_avail_out; uint32_t ptesize; vm_offset_t va; int error; @@ -260,6 +261,12 @@ /* Dump my header */ bzero(&fakept, sizeof(fakept)); bcopy(&mdhdr, &fakept, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)((char *)fakept + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i++) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); if (error) goto fail; Index: sys/i386/include/minidump.h =================================================================== --- sys/i386/include/minidump.h +++ sys/i386/include/minidump.h @@ -32,7 +32,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/i386" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 struct minidumphdr { char magic[24]; Index: sys/mips/include/minidump.h =================================================================== --- sys/mips/include/minidump.h +++ sys/mips/include/minidump.h @@ -32,7 +32,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/mips" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 struct minidumphdr { char magic[24]; Index: sys/mips/mips/minidump_machdep.c =================================================================== --- sys/mips/mips/minidump_machdep.c +++ sys/mips/mips/minidump_machdep.c @@ -164,6 +164,7 @@ minidumpsys(struct dumperinfo *di) { struct minidumphdr mdhdr; + kpaddr_t *dump_avail_out; uint32_t ptesize; vm_paddr_t pa; vm_offset_t prev_pte = 0; @@ -222,7 +223,7 @@ strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.ptesize = ptesize; mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; @@ -239,6 +240,12 @@ /* Dump my header */ bzero(tmpbuffer, sizeof(tmpbuffer)); bcopy(&mdhdr, tmpbuffer, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)(tmpbuffer + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = write_buffer(di, tmpbuffer, PAGE_SIZE); if (error) goto fail; Index: sys/powerpc/include/minidump.h =================================================================== --- sys/powerpc/include/minidump.h +++ sys/powerpc/include/minidump.h @@ -31,7 +31,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/powerpc64" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 struct minidumphdr { char magic[32]; Index: sys/powerpc/powerpc/minidump_machdep.c =================================================================== --- sys/powerpc/powerpc/minidump_machdep.c +++ sys/powerpc/powerpc/minidump_machdep.c @@ -249,6 +249,7 @@ int bit, error, i, retry_count; uint32_t pmapsize; struct minidumphdr mdhdr; + kpaddr_t *dump_avail_out; retry_count = 0; retry: @@ -288,7 +289,7 @@ strncpy(mdhdr.mmu_name, pmap_mmu_name(), sizeof(mdhdr.mmu_name) - 1); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.pmapsize = pmapsize; mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; mdhdr.kernend = VM_MAX_SAFE_KERNEL_ADDRESS; @@ -311,6 +312,12 @@ /* Dump minidump header */ bzero(pgbuf, sizeof(pgbuf)); memcpy(pgbuf, &mdhdr, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)(pgbuf + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, pgbuf, 0, PAGE_SIZE); if (error) goto fail; Index: sys/riscv/include/minidump.h =================================================================== --- sys/riscv/include/minidump.h +++ sys/riscv/include/minidump.h @@ -31,7 +31,7 @@ #define _MACHINE_MINIDUMP_H_ 1 #define MINIDUMP_MAGIC "minidump FreeBSD/riscv" -#define MINIDUMP_VERSION 1 +#define MINIDUMP_VERSION 2 struct minidumphdr { char magic[24]; Index: sys/riscv/riscv/minidump_machdep.c =================================================================== --- sys/riscv/riscv/minidump_machdep.c +++ sys/riscv/riscv/minidump_machdep.c @@ -213,6 +213,7 @@ pd_entry_t *l1, *l2; pt_entry_t *l3; struct minidumphdr mdhdr; + kpaddr_t *dump_avail_out; uint32_t pmapsize; vm_offset_t va; vm_paddr_t pa; @@ -274,7 +275,7 @@ strcpy(mdhdr.magic, MINIDUMP_MAGIC); mdhdr.version = MINIDUMP_VERSION; mdhdr.msgbufsize = msgbufp->msg_size; - mdhdr.bitmapsize = BITSET_SIZE(vm_page_dump_pages); + mdhdr.bitmapsize = round_page(BITSET_SIZE(vm_page_dump_pages)); mdhdr.pmapsize = pmapsize; mdhdr.kernbase = KERNBASE; mdhdr.dmapphys = DMAP_MIN_PHYSADDR; @@ -294,6 +295,12 @@ /* Dump minidump header */ bzero(&tmpbuffer, sizeof(tmpbuffer)); bcopy(&mdhdr, &tmpbuffer, sizeof(mdhdr)); + dump_avail_out = (kpaddr_t *)((char *)tmpbuffer + sizeof(mdhdr)); + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + dump_avail_out[i] = dump_avail[i]; + dump_avail_out[i + 1] = dump_avail[i + 1]; + } + dump_avail_out[i] = dump_avail_out[i + 1] = 0; error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); if (error) goto fail; Index: sys/vm/vm_page.h =================================================================== --- sys/vm/vm_page.h +++ sys/vm/vm_page.h @@ -589,22 +589,65 @@ extern struct bitset *vm_page_dump; extern long vm_page_dump_pages; +extern vm_paddr_t dump_avail[]; static inline void dump_add_page(vm_paddr_t pa) { - BIT_SET_ATOMIC(vm_page_dump_pages, pa >> PAGE_SHIFT, vm_page_dump); + vm_pindex_t adj; + int i; + + adj = 0; + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) { + BIT_SET_ATOMIC(vm_page_dump_pages, + (pa >> PAGE_SHIFT) - (dump_avail[i] >> PAGE_SHIFT) + adj, + vm_page_dump); + return; + } + adj += howmany(dump_avail[i + 1], PAGE_SIZE) - + dump_avail[i] / PAGE_SIZE; + } } static inline void dump_drop_page(vm_paddr_t pa) { - BIT_CLR_ATOMIC(vm_page_dump_pages, pa >> PAGE_SHIFT, vm_page_dump); + vm_pindex_t adj; + int i; + + adj = 0; + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) { + BIT_CLR_ATOMIC(vm_page_dump_pages, + (pa >> PAGE_SHIFT) - (dump_avail[i] >> PAGE_SHIFT) + adj, + vm_page_dump); + return; + } + adj += howmany(dump_avail[i + 1], PAGE_SIZE) - + dump_avail[i] / PAGE_SIZE; + } +} + +static inline vm_paddr_t +vm_page_dump_index_to_pa(int bit) +{ + int i, tot; + + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + tot = howmany(dump_avail[i + 1], PAGE_SIZE) - + dump_avail[i] / PAGE_SIZE; + if (bit < tot) + return ((vm_paddr_t)bit * PAGE_SIZE + + dump_avail[i] & ~PAGE_MASK); + bit -= tot; + } + return ((vm_paddr_t)NULL); } #define VM_PAGE_DUMP_FOREACH(bit, pa) \ for ((bit) = BIT_FFS(vm_page_dump_pages, vm_page_dump); \ - pa = ((bit) - 1) * PAGE_SIZE, (bit) != 0; \ + pa = vm_page_dump_index_to_pa(bit - 1), (bit) != 0; \ (bit) = BIT_FFS_AT(vm_page_dump_pages, vm_page_dump, bit)) \ bool vm_page_busy_acquire(vm_page_t m, int allocflags); Index: sys/vm/vm_page.c =================================================================== --- sys/vm/vm_page.c +++ sys/vm/vm_page.c @@ -603,10 +603,13 @@ * included should the sf_buf code decide to use them. */ last_pa = 0; - for (i = 0; dump_avail[i + 1] != 0; i += 2) + vm_page_dump_pages = 0; + for (i = 0; dump_avail[i + 1] != 0; i += 2) { + vm_page_dump_pages += howmany(dump_avail[i + 1], PAGE_SIZE) - + dump_avail[i] / PAGE_SIZE; if (dump_avail[i + 1] > last_pa) last_pa = dump_avail[i + 1]; - vm_page_dump_pages = last_pa / PAGE_SIZE; + } vm_page_dump_size = round_page(BITSET_SIZE(vm_page_dump_pages)); new_end -= vm_page_dump_size; vm_page_dump = (void *)(uintptr_t)pmap_map(&vaddr, new_end,