Index: sys/arm64/arm64/pmap.c =================================================================== --- sys/arm64/arm64/pmap.c +++ sys/arm64/arm64/pmap.c @@ -105,6 +105,7 @@ * and to when physical maps must be made correct. */ +#include "opt_ddb.h" #include "opt_vm.h" #include @@ -149,6 +150,7 @@ #include #include #include +#include #define PMAP_ASSERT_STAGE1(pmap) MPASS((pmap)->pm_stage == PM_STAGE1) #define PMAP_ASSERT_STAGE2(pmap) MPASS((pmap)->pm_stage == PM_STAGE2) @@ -7021,9 +7023,11 @@ int l1blocks; }; +typedef void (*kmaps_printf)(void *, const char *, ...); + static void -sysctl_kmaps_dump(struct sbuf *sb, struct pmap_kernel_map_range *range, - vm_offset_t eva) +kmaps_dump(kmaps_printf kmaps_printf, void *arg, + struct pmap_kernel_map_range *range, vm_offset_t eva) { const char *mode; int index; @@ -7053,7 +7057,7 @@ break; } - sbuf_printf(sb, "0x%016lx-0x%016lx r%c%c%c%c %3s %d %d %d %d\n", + kmaps_printf(arg, "0x%016lx-0x%016lx r%c%c%c%c %3s %d %d %d %d\n", range->sva, eva, (range->attrs & ATTR_S1_AP_RW_BIT) == ATTR_S1_AP_RW ? 'w' : '-', (range->attrs & ATTR_S1_PXN) != 0 ? '-' : 'x', @@ -7071,14 +7075,14 @@ * being tracked by the current range. */ static bool -sysctl_kmaps_match(struct pmap_kernel_map_range *range, pt_entry_t attrs) +kmaps_match(struct pmap_kernel_map_range *range, pt_entry_t attrs) { return (range->attrs == attrs); } static void -sysctl_kmaps_reinit(struct pmap_kernel_map_range *range, vm_offset_t va, +kmaps_reinit(struct pmap_kernel_map_range *range, vm_offset_t va, pt_entry_t attrs) { @@ -7089,7 +7093,7 @@ /* Get the block/page attributes that correspond to the table attributes */ static pt_entry_t -sysctl_kmaps_table_attrs(pd_entry_t table) +kmaps_table_attrs(pd_entry_t table) { pt_entry_t attrs; @@ -7106,7 +7110,7 @@ /* Read the block/page attributes we care about */ static pt_entry_t -sysctl_kmaps_block_attrs(pt_entry_t block) +kmaps_block_attrs(pt_entry_t block) { return (block & (ATTR_S1_AP_MASK | ATTR_S1_XN | ATTR_S1_IDX_MASK)); } @@ -7117,50 +7121,43 @@ * begin a new run. */ static void -sysctl_kmaps_check(struct sbuf *sb, struct pmap_kernel_map_range *range, - vm_offset_t va, pd_entry_t l0e, pd_entry_t l1e, pd_entry_t l2e, - pt_entry_t l3e) +kmaps_check(kmaps_printf kmaps_printf, void *arg, + struct pmap_kernel_map_range *range, vm_offset_t va, pd_entry_t l0e, + pd_entry_t l1e, pd_entry_t l2e, pt_entry_t l3e) { pt_entry_t attrs; - attrs = sysctl_kmaps_table_attrs(l0e); + attrs = kmaps_table_attrs(l0e); if ((l1e & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) { - attrs |= sysctl_kmaps_block_attrs(l1e); + attrs |= kmaps_block_attrs(l1e); goto done; } - attrs |= sysctl_kmaps_table_attrs(l1e); + attrs |= kmaps_table_attrs(l1e); if ((l2e & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) { - attrs |= sysctl_kmaps_block_attrs(l2e); + attrs |= kmaps_block_attrs(l2e); goto done; } - attrs |= sysctl_kmaps_table_attrs(l2e); - attrs |= sysctl_kmaps_block_attrs(l3e); + attrs |= kmaps_table_attrs(l2e); + attrs |= kmaps_block_attrs(l3e); done: - if (range->sva > va || !sysctl_kmaps_match(range, attrs)) { - sysctl_kmaps_dump(sb, range, va); - sysctl_kmaps_reinit(range, va, attrs); + if (range->sva > va || !kmaps_match(range, attrs)) { + kmaps_dump(kmaps_printf, arg, range, va); + kmaps_reinit(range, va, attrs); } } -static int -sysctl_kmaps(SYSCTL_HANDLER_ARGS) +static void +kmaps_dump_all(kmaps_printf kmaps_printf, void *arg) { struct pmap_kernel_map_range range; - struct sbuf sbuf, *sb; pd_entry_t l0e, *l1, l1e, *l2, l2e; pt_entry_t *l3, l3e; vm_offset_t sva; vm_paddr_t pa; - int error, i, j, k, l; - - error = sysctl_wire_old_buffer(req, 0); - if (error != 0) - return (error); - sb = &sbuf; - sbuf_new_for_sysctl(sb, NULL, PAGE_SIZE, req); + int i, j, k, l; /* Sentinel value. */ range.sva = 0xfffffffffffffffful; @@ -7173,13 +7170,13 @@ for (sva = 0xffff000000000000ul, i = pmap_l0_index(sva); i < Ln_ENTRIES; i++) { if (i == pmap_l0_index(DMAP_MIN_ADDRESS)) - sbuf_printf(sb, "\nDirect map:\n"); + kmaps_printf(arg, "\nDirect map:\n"); else if (i == pmap_l0_index(VM_MIN_KERNEL_ADDRESS)) - sbuf_printf(sb, "\nKernel map:\n"); + kmaps_printf(arg, "\nKernel map:\n"); l0e = kernel_pmap->pm_l0[i]; if ((l0e & ATTR_DESCR_VALID) == 0) { - sysctl_kmaps_dump(sb, &range, sva); + kmaps_dump(kmaps_printf, arg, &range, sva); sva += L0_SIZE; continue; } @@ -7189,13 +7186,13 @@ for (j = pmap_l1_index(sva); j < Ln_ENTRIES; j++) { l1e = l1[j]; if ((l1e & ATTR_DESCR_VALID) == 0) { - sysctl_kmaps_dump(sb, &range, sva); + kmaps_dump(kmaps_printf, arg, &range, sva); sva += L1_SIZE; continue; } if ((l1e & ATTR_DESCR_MASK) == L1_BLOCK) { - sysctl_kmaps_check(sb, &range, sva, l0e, l1e, - 0, 0); + kmaps_check(kmaps_printf, arg, &range, sva, + l0e, l1e, 0, 0); range.l1blocks++; sva += L1_SIZE; continue; @@ -7206,13 +7203,14 @@ for (k = pmap_l2_index(sva); k < Ln_ENTRIES; k++) { l2e = l2[k]; if ((l2e & ATTR_DESCR_VALID) == 0) { - sysctl_kmaps_dump(sb, &range, sva); + kmaps_dump(kmaps_printf, arg, &range, + sva); sva += L2_SIZE; continue; } if ((l2e & ATTR_DESCR_MASK) == L2_BLOCK) { - sysctl_kmaps_check(sb, &range, sva, - l0e, l1e, l2e, 0); + kmaps_check(kmaps_printf, arg, &range, + sva, l0e, l1e, l2e, 0); range.l2blocks++; sva += L2_SIZE; continue; @@ -7224,12 +7222,12 @@ l++, sva += L3_SIZE) { l3e = l3[l]; if ((l3e & ATTR_DESCR_VALID) == 0) { - sysctl_kmaps_dump(sb, &range, - sva); + kmaps_dump(kmaps_printf, arg, + &range, sva); continue; } - sysctl_kmaps_check(sb, &range, sva, - l0e, l1e, l2e, l3e); + kmaps_check(kmaps_printf, arg, &range, + sva, l0e, l1e, l2e, l3e); if ((l3e & ATTR_CONTIGUOUS) != 0) range.l3contig += l % 16 == 0 ? 1 : 0; @@ -7239,6 +7237,33 @@ } } } +} + +static void +sysctl_kmaps_printf(void *arg, const char *fmt, ...) +{ + struct sbuf *sb; + va_list va; + + sb = arg; + va_start(va, fmt); + sbuf_vprintf(sb, fmt, va); + va_end(va); +} + +static int +sysctl_kmaps(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sbuf, *sb; + int error; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sb = &sbuf; + sbuf_new_for_sysctl(sb, NULL, PAGE_SIZE, req); + + kmaps_dump_all(sysctl_kmaps_printf, sb); error = sbuf_finish(sb); sbuf_delete(sb); @@ -7248,3 +7273,22 @@ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_SKIP, NULL, 0, sysctl_kmaps, "A", "Dump kernel address layout"); + +#ifdef DDB +#include + +static void +db_kmaps_printf(void *arg __unused, const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + db_vprintf(fmt, va); + va_end(va); +} + +DB_SHOW_COMMAND(kernel_maps, db_show_kmaps) +{ + kmaps_dump_all(db_kmaps_printf, NULL); +} +#endif