Re: [PATCH v3] monitor: Refine 'info tlb' command
"Dr. David Alan Gilbert" <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <aoTl_9eaioevcOVM@gallifrey> |
* Marc-André Lureau ([email protected]) wrote: > Hi > > On Tue, Aug 18, 2026 at 5:30 PM <[email protected]> wrote: > > > > When booting an i386 target, the 'info tlb' command > > may walk the entire page table hierarchy and emit > > an enormous amount of output. It will take dozens of > > minutes to print all the info, and > > The same situation also occurred on sparc32 and > > m68k targets. > > > > So this change do the following: > > 1) Add a address range argument to help user control > > the number of output items. > > 2) Add warning note in help message that such address > > range argument only supported on target i386, > > sparc32 and m68k. > > 3) Print ignore warning when user add such address > > range argument on other targets (sh4, sparc64, > > ppc and xtensa). Those targets only print limited > > tlb info. > > > > Signed-off-by: Alano Song <[email protected]> > > lgtm overall > > - m68k print_address_zone() used to be called with page-aligned zones, > but now it is clipped to arbitrary user ranges, which may not be > aligned. 1 byte range will be reported as 0kb. We may want to handle > the case for small ranges. Btw that code could use the macros KiB for > readability > > - A later patch could prune non-overlapping ranges during traversal, > not just during printing Yeh I'd say it's OK, two thoughts: a) I'd have split the patch into a series with more managable chunks b) There's quite a bit of repetition which feels like a common helper might have removed. But: Reviewed-by: Dr. David Alan Gilbert <[email protected]> Dave > > --- > > hmp-commands-info.hx | 17 ++++++-- > > target/i386/monitor.c | 92 ++++++++++++++++++++++++++++----------- > > target/m68k/cpu.h | 2 +- > > target/m68k/helper.c | 55 +++++++++++++++-------- > > target/m68k/monitor.c | 15 ++++++- > > target/ppc/monitor.c | 6 +++ > > target/sh4/monitor.c | 5 +++ > > target/sparc/cpu.h | 3 ++ > > target/sparc/mmu_helper.c | 40 +++++++++++++---- > > target/sparc/monitor.c | 23 ++++++++++ > > target/xtensa/monitor.c | 6 +++ > > 11 files changed, 206 insertions(+), 58 deletions(-) > > > > diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx > > index 82134eb6c2..f907edf273 100644 > > --- a/hmp-commands-info.hx > > +++ b/hmp-commands-info.hx > > @@ -188,17 +188,26 @@ ERST > > > > { > > .name = "tlb", > > - .args_type = "", > > - .params = "", > > - .help = "show virtual to physical memory mappings", > > + .args_type = "start:l?,end:l?", > > + .params = "[start [end]]", > > + .help = "show virtual to physical memory mappings. " > > + "output can be extremely large for i386, sparc32 " > > + "and m68k targets. use 'info tlb [start [end]]' " > > + "to show a range of entries. Note that the range " > > + "argument is only supported on i386, sparc32 and " > > + "m68k targets.", > > .cmd = hmp_info_tlb, > > .arch_bitmask = QEMU_ARCH_I386 | QEMU_ARCH_SH4 | QEMU_ARCH_SPARC \ > > | QEMU_ARCH_PPC | QEMU_ARCH_XTENSA | QEMU_ARCH_M68K, > > }, > > > > SRST > > - ``info tlb`` > > + ``info tlb`` [*start* [*end*]] > > Show virtual to physical memory mappings. > > + The output can be extremely large for i386, sparc32 and m68k targets. > > + Use *start* and *end* to print entries located in virtual address > > + range [start, end] (end is optional). Note that the range argument is > > + only supported on i386, sparc32 and m68k targets. > > ERST > > > > { > > diff --git a/target/i386/monitor.c b/target/i386/monitor.c > > index a536712c75..8db9ab0576 100644 > > --- a/target/i386/monitor.c > > +++ b/target/i386/monitor.c > > @@ -48,11 +48,9 @@ static hwaddr addr_canonical(CPUArchState *env, hwaddr addr) > > return addr; > > } > > > > -static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr, > > - hwaddr pte, hwaddr mask) > > +static void do_print_pte(Monitor *mon, hwaddr addr, > > + hwaddr pte, hwaddr mask) > > { > > - addr = addr_canonical(env, addr); > > - > > monitor_printf(mon, HWADDR_FMT_plx ": " HWADDR_FMT_plx > > " %c%c%c%c%c%c%c%c%c\n", > > addr, > > @@ -68,7 +66,25 @@ static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr, > > pte & PG_RW_MASK ? 'W' : '-'); > > } > > > > -static void tlb_info_32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > +static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr, > > + hwaddr pte, hwaddr mask, hwaddr size, > > + hwaddr start, hwaddr end) > > +{ > > + hwaddr addr_start = addr_canonical(env, addr); > > + hwaddr addr_end = addr_canonical(env, addr + size - 1); > > + /* > > + * Print current page [addr_start, addr_end] only if it overlaps the > > + * requested virtual address range [start, end]. > > + */ > > + if (addr_start > end || addr_end < start) { > > + return; > > + } > > + > > + do_print_pte(mon, addr_start, pte, mask); > > +} > > + > > +static void tlb_info_32(Monitor *mon, CPUArchState *env, AddressSpace *as, > > + hwaddr start, hwaddr end) > > { > > const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; > > unsigned int l1, l2; > > @@ -80,15 +96,16 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > if (pde & PG_PRESENT_MASK) { > > if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { > > /* 4M pages */ > > - print_pte(mon, env, (l1 << 22), pde, ~((1 << 21) - 1)); > > + print_pte(mon, env, (l1 << 22), pde, ~((1 << 21) - 1), > > + 0x400000, start, end); > > } else { > > for(l2 = 0; l2 < 1024; l2++) { > > pte = address_space_ldl_le(as, (pde & ~0xfff) + l2 * 4, > > attrs, NULL); > > if (pte & PG_PRESENT_MASK) { > > print_pte(mon, env, (l1 << 22) + (l2 << 12), > > - pte & ~PG_PSE_MASK, > > - ~0xfff); > > + pte & ~PG_PSE_MASK, ~0xfff, 0x1000, > > + start, end); > > } > > } > > } > > @@ -96,7 +113,8 @@ static void tlb_info_32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > } > > } > > > > -static void tlb_info_pae32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > +static void tlb_info_pae32(Monitor *mon, CPUArchState *env, AddressSpace *as, > > + hwaddr start, hwaddr end) > > { > > const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; > > unsigned int l1, l2, l3; > > @@ -114,17 +132,19 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > if (pde & PG_PSE_MASK) { > > /* 2M pages with PAE, CR4.PSE is ignored */ > > print_pte(mon, env, (l1 << 30) + (l2 << 21), pde, > > - ~((hwaddr)(1 << 20) - 1)); > > + ~((hwaddr)(1 << 20) - 1), 0x200000, > > + start, end); > > } else { > > pt_addr = pde & 0x3fffffffff000ULL; > > for (l3 = 0; l3 < 512; l3++) { > > pte = address_space_ldq_le(as, pt_addr + l3 * 8, > > attrs, NULL); > > if (pte & PG_PRESENT_MASK) { > > - print_pte(mon, env, (l1 << 30) + (l2 << 21) > > - + (l3 << 12), > > + print_pte(mon, env, > > + (l1 << 30) + (l2 << 21) + (l3 << 12), > > pte & ~PG_PSE_MASK, > > - ~(hwaddr)0xfff); > > + ~(hwaddr)0xfff, 0x1000, > > + start, end); > > } > > } > > } > > @@ -136,7 +156,8 @@ static void tlb_info_pae32(Monitor *mon, CPUArchState *env, AddressSpace *as) > > > > #ifdef TARGET_X86_64 > > static void tlb_info_la48(Monitor *mon, CPUArchState *env, AddressSpace *as, > > - uint64_t l0, uint64_t pml4_addr) > > + uint64_t l0, uint64_t pml4_addr, hwaddr start, > > + hwaddr end) > > { > > const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; > > uint64_t l1, l2, l3, l4; > > @@ -159,7 +180,7 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env, AddressSpace *as, > > if (pdpe & PG_PSE_MASK) { > > /* 1G pages, CR4.PSE is ignored */ > > print_pte(mon, env, (l0 << 48) + (l1 << 39) + (l2 << 30), > > - pdpe, 0x3ffffc0000000ULL); > > + pdpe, 0x3ffffc0000000ULL, 0x40000000, start, end); > > continue; > > } > > > > @@ -172,8 +193,9 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env, AddressSpace *as, > > > > if (pde & PG_PSE_MASK) { > > /* 2M pages, CR4.PSE is ignored */ > > - print_pte(mon, env, (l0 << 48) + (l1 << 39) + (l2 << 30) + > > - (l3 << 21), pde, 0x3ffffffe00000ULL); > > + print_pte(mon, env, > > + (l0 << 48) + (l1 << 39) + (l2 << 30) + (l3 << 21), > > + pde, 0x3ffffffe00000ULL, 0x200000, start, end); > > continue; > > } > > > > @@ -182,9 +204,11 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env, AddressSpace *as, > > pte = address_space_ldq_le(as, pt_addr + l4 * 8, > > attrs, NULL); > > if (pte & PG_PRESENT_MASK) { > > - print_pte(mon, env, (l0 << 48) + (l1 << 39) + > > - (l2 << 30) + (l3 << 21) + (l4 << 12), > > - pte & ~PG_PSE_MASK, 0x3fffffffff000ULL); > > + print_pte(mon, env, > > + (l0 << 48) + (l1 << 39) + (l2 << 30) + > > + (l3 << 21) + (l4 << 12), > > + pte & ~PG_PSE_MASK, > > + 0x3fffffffff000ULL, 0x1000, start, end); > > } > > } > > } > > @@ -192,7 +216,8 @@ static void tlb_info_la48(Monitor *mon, CPUArchState *env, AddressSpace *as, > > } > > } > > > > -static void tlb_info_la57(Monitor *mon, CPUArchState *env, AddressSpace *as) > > +static void tlb_info_la57(Monitor *mon, CPUArchState *env, AddressSpace *as, > > + hwaddr start, hwaddr end) > > { > > const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; > > uint64_t l0; > > @@ -203,7 +228,8 @@ static void tlb_info_la57(Monitor *mon, CPUArchState *env, AddressSpace *as) > > for (l0 = 0; l0 < 512; l0++) { > > pml5e = address_space_ldq_le(as, pml5_addr + l0 * 8, attrs, NULL); > > if (pml5e & PG_PRESENT_MASK) { > > - tlb_info_la48(mon, env, as, l0, pml5e & 0x3fffffffff000ULL); > > + tlb_info_la48(mon, env, as, l0, pml5e & 0x3fffffffff000ULL, > > + start, end); > > } > > } > > } > > @@ -213,6 +239,18 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > { > > CPUArchState *env; > > AddressSpace *as; > > + hwaddr start = 0, end = HWADDR_MAX; > > + > > + if (qdict_haskey(qdict, "start")) { > > + start = (hwaddr)qdict_get_int(qdict, "start"); > > + } > > + if (qdict_haskey(qdict, "end")) { > > + end = (hwaddr)qdict_get_int(qdict, "end"); > > + } > > + if (start > end) { > > + monitor_printf(mon, "Invalid address range: start > end.\n"); > > + return; > > + } > > > > env = mon_get_cpu_env(mon); > > if (!env) { > > @@ -229,17 +267,19 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > #ifdef TARGET_X86_64 > > if (env->hflags & HF_LMA_MASK) { > > if (env->cr[4] & CR4_LA57_MASK) { > > - tlb_info_la57(mon, env, as); > > + tlb_info_la57(mon, env, as, start, end); > > } else { > > - tlb_info_la48(mon, env, as, 0, env->cr[3] & 0x3fffffffff000ULL); > > + tlb_info_la48(mon, env, as, 0, > > + env->cr[3] & 0x3fffffffff000ULL, > > + start, end); > > } > > } else > > #endif > > { > > - tlb_info_pae32(mon, env, as); > > + tlb_info_pae32(mon, env, as, start, end); > > } > > } else { > > - tlb_info_32(mon, env, as); > > + tlb_info_32(mon, env, as, start, end); > > } > > } > > > > diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h > > index 7cf3791108..b129cb150f 100644 > > --- a/target/m68k/cpu.h > > +++ b/target/m68k/cpu.h > > @@ -606,6 +606,6 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, > > #define TB_FLAGS_TRACE 16 > > #define TB_FLAGS_TRACE_BIT (1 << TB_FLAGS_TRACE) > > > > -void dump_mmu(CPUM68KState *env); > > +void dump_mmu(CPUM68KState *env, hwaddr start, hwaddr end); > > > > #endif > > diff --git a/target/m68k/helper.c b/target/m68k/helper.c > > index 5f91d206f5..1b854c912b 100644 > > --- a/target/m68k/helper.c > > +++ b/target/m68k/helper.c > > @@ -461,27 +461,46 @@ void m68k_switch_sp(CPUM68KState *env) > > /* MMU: 68040 only */ > > > > static void print_address_zone(uint32_t logical, uint32_t physical, > > - uint32_t size, int attr) > > + uint32_t size, int attr, > > + hwaddr start, hwaddr end) > > { > > + uint64_t zone_start = logical; > > + uint64_t zone_end = zone_start + size - 1; > > + uint64_t zone_len; > > + > > + /* > > + * Print current zone [zone_start, zone_end] only if it overlaps the > > + * requested virtual address range [start, end]. > > + */ > > + if (zone_end < start || zone_start > end) { > > + return; > > + } > > + > > + physical += (uint32_t)(start > zone_start ? start - zone_start : 0); > > + zone_start = zone_start > start ? zone_start : start; > > + zone_end = zone_end < end ? zone_end : end; > > + zone_len = zone_end - zone_start + 1; > > + > > qemu_printf("%08x - %08x -> %08x - %08x %c ", > > - logical, logical + size - 1, > > - physical, physical + size - 1, > > + (uint32_t)zone_start, (uint32_t)zone_end, > > + physical, physical + (uint32_t)(zone_len - 1), > > attr & 4 ? 'W' : '-'); > > - size >>= 10; > > - if (size < 1024) { > > - qemu_printf("(%d KiB)\n", size); > > + zone_len >>= 10; > > + if (zone_len < 1024) { > > + qemu_printf("(%d KiB)\n", (int)zone_len); > > } else { > > - size >>= 10; > > - if (size < 1024) { > > - qemu_printf("(%d MiB)\n", size); > > + zone_len >>= 10; > > + if (zone_len < 1024) { > > + qemu_printf("(%d MiB)\n", (int)zone_len); > > } else { > > - size >>= 10; > > - qemu_printf("(%d GiB)\n", size); > > + zone_len >>= 10; > > + qemu_printf("(%d GiB)\n", (int)zone_len); > > } > > } > > } > > > > -static void dump_address_map(CPUM68KState *env, uint32_t root_pointer) > > +static void dump_address_map(CPUM68KState *env, uint32_t root_pointer, > > + hwaddr start, hwaddr end) > > { > > int tic_size, tic_shift; > > uint32_t tib_mask; > > @@ -550,7 +569,8 @@ static void dump_address_map(CPUM68KState *env, uint32_t root_pointer) > > size = last_logical + (1 << tic_shift) - > > first_logical; > > print_address_zone(first_logical, > > - first_physical, size, last_attr); > > + first_physical, size, last_attr, > > + start, end); > > } > > first_logical = logical; > > first_physical = physical; > > @@ -560,7 +580,8 @@ static void dump_address_map(CPUM68KState *env, uint32_t root_pointer) > > } > > if (first_logical != logical || (attr & 4) != (last_attr & 4)) { > > size = logical + (1 << tic_shift) - first_logical; > > - print_address_zone(first_logical, first_physical, size, last_attr); > > + print_address_zone(first_logical, first_physical, size, last_attr, > > + start, end); > > } > > } > > > > @@ -610,7 +631,7 @@ static void dump_ttr(uint32_t ttr) > > M68K_DESC_USERATTR_SHIFT); > > } > > > > -void dump_mmu(CPUM68KState *env) > > +void dump_mmu(CPUM68KState *env, hwaddr start, hwaddr end) > > { > > if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { > > qemu_printf("Translation disabled\n"); > > @@ -675,10 +696,10 @@ void dump_mmu(CPUM68KState *env) > > dump_ttr(env->mmu.ttr[M68K_DTTR1]); > > > > qemu_printf("SRP: 0x%08x\n", env->mmu.srp); > > - dump_address_map(env, env->mmu.srp); > > + dump_address_map(env, env->mmu.srp, start, end); > > > > qemu_printf("URP: 0x%08x\n", env->mmu.urp); > > - dump_address_map(env, env->mmu.urp); > > + dump_address_map(env, env->mmu.urp, start, end); > > } > > > > static int check_TTR(uint32_t ttr, int *prot, target_ulong addr, > > diff --git a/target/m68k/monitor.c b/target/m68k/monitor.c > > index 3e0df40a6b..bcb528d8e3 100644 > > --- a/target/m68k/monitor.c > > +++ b/target/m68k/monitor.c > > @@ -9,15 +9,28 @@ > > #include "cpu.h" > > #include "monitor/hmp.h" > > #include "monitor/monitor.h" > > +#include "qobject/qdict.h" > > > > void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > { > > CPUArchState *env1 = mon_get_cpu_env(mon); > > + hwaddr start = 0, end = HWADDR_MAX; > > > > if (!env1) { > > monitor_printf(mon, "No CPU available\n"); > > return; > > } > > > > - dump_mmu(env1); > > + if (qdict_haskey(qdict, "start")) { > > + start = (hwaddr)qdict_get_int(qdict, "start"); > > + } > > + if (qdict_haskey(qdict, "end")) { > > + end = (hwaddr)qdict_get_int(qdict, "end"); > > + } > > + if (start > end) { > > + monitor_printf(mon, "Invalid address range: start > end.\n"); > > + return; > > + } > > + > > + dump_mmu(env1, start, end); > > } > > diff --git a/target/ppc/monitor.c b/target/ppc/monitor.c > > index 7c88e0e2bd..753ed6b93d 100644 > > --- a/target/ppc/monitor.c > > +++ b/target/ppc/monitor.c > > @@ -10,6 +10,7 @@ > > #include "monitor/monitor.h" > > #include "monitor/hmp.h" > > #include "cpu.h" > > +#include "qobject/qdict.h" > > > > void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > { > > @@ -19,5 +20,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > monitor_printf(mon, "No CPU available\n"); > > return; > > } > > + > > + if (qdict_haskey(qdict, "start") || qdict_haskey(qdict, "end")) { > > + monitor_printf(mon, "The range arguments will be ignored.\n"); > > + } > > + > > dump_mmu(env1); > > } > > diff --git a/target/sh4/monitor.c b/target/sh4/monitor.c > > index 50324d3600..c804824bab 100644 > > --- a/target/sh4/monitor.c > > +++ b/target/sh4/monitor.c > > @@ -25,6 +25,7 @@ > > #include "cpu.h" > > #include "monitor/monitor.h" > > #include "monitor/hmp.h" > > +#include "qobject/qdict.h" > > > > static void print_tlb(Monitor *mon, int idx, tlb_t *tlb) > > { > > @@ -48,6 +49,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > return; > > } > > > > + if (qdict_haskey(qdict, "start") || qdict_haskey(qdict, "end")) { > > + monitor_printf(mon, "The range arguments will be ignored.\n"); > > + } > > + > > monitor_printf (mon, "ITLB:\n"); > > for (i = 0 ; i < ITLB_SIZE ; i++) > > print_tlb (mon, i, &env->itlb[i]); > > diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h > > index 5f583ed9de..11f94b6bd8 100644 > > --- a/target/sparc/cpu.h > > +++ b/target/sparc/cpu.h > > @@ -601,6 +601,9 @@ bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, > > bool probe, uintptr_t retaddr); > > target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev); > > void dump_mmu(CPUSPARCState *env); > > +#ifndef TARGET_SPARC64 > > +void dump_mmu_range(CPUSPARCState *env, hwaddr start, hwaddr end); > > +#endif > > > > #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) > > int sparc_cpu_memory_rw_debug(CPUState *cpu, vaddr addr, > > diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c > > index 07ba25dfce..65a30b438b 100644 > > --- a/target/sparc/mmu_helper.c > > +++ b/target/sparc/mmu_helper.c > > @@ -354,7 +354,32 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) > > return 0; > > } > > > > +static void print_tlb_entry(target_ulong va, hwaddr pa, uint32_t pde, > > + const char *indent, const char *kind, > > + hwaddr size, hwaddr start, hwaddr end) > > +{ > > + hwaddr va_hw_start = (hwaddr)va; > > + hwaddr va_hw_end = (hwaddr)(va + size - 1); > > + > > + /* > > + * Print current region [va_hw_start, va_hw_end] only if it overlaps the > > + * requested virtual address range [start, end]. > > + */ > > + if (va_hw_start > end || va_hw_end < start) { > > + return; > > + } > > + > > + qemu_printf("%sVA: " TARGET_FMT_lx ", PA: " HWADDR_FMT_plx > > + " %s: " TARGET_FMT_lx "\n", > > + indent, va, pa, kind, pde); > > +} > > + > > void dump_mmu(CPUSPARCState *env) > > +{ > > + dump_mmu_range(env, 0, HWADDR_MAX); > > +} > > + > > +void dump_mmu_range(CPUSPARCState *env, hwaddr start, hwaddr end) > > { > > CPUState *cs = env_cpu(env); > > target_ulong va, va1, va2; > > @@ -373,8 +398,8 @@ void dump_mmu(CPUSPARCState *env) > > } else { > > pa = tres.physaddr; > > } > > - qemu_printf("VA: " TARGET_FMT_lx ", PA: " HWADDR_FMT_plx > > - " PDE: " TARGET_FMT_lx "\n", va, pa, pde); > > + print_tlb_entry(va, pa, pde, "", "PDE", 16 * 1024 * 1024, > > + start, end); > > for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) { > > pde = mmu_probe(env, va1, 1); > > if (pde) { > > @@ -383,9 +408,8 @@ void dump_mmu(CPUSPARCState *env) > > } else { > > pa = tres.physaddr; > > } > > - qemu_printf(" VA: " TARGET_FMT_lx ", PA: " > > - HWADDR_FMT_plx " PDE: " TARGET_FMT_lx "\n", > > - va1, pa, pde); > > + print_tlb_entry(va1, pa, pde, " ", "PDE", 256 * 1024, > > + start, end); > > for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) { > > pde = mmu_probe(env, va2, 0); > > if (pde) { > > @@ -394,10 +418,8 @@ void dump_mmu(CPUSPARCState *env) > > } else { > > pa = tres.physaddr; > > } > > - qemu_printf(" VA: " TARGET_FMT_lx ", PA: " > > - HWADDR_FMT_plx " PTE: " > > - TARGET_FMT_lx "\n", > > - va2, pa, pde); > > + print_tlb_entry(va2, pa, pde, " ", "PTE", > > + 4 * 1024, start, end); > > } > > } > > } > > diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c > > index 36f3d8d58e..993e411a37 100644 > > --- a/target/sparc/monitor.c > > +++ b/target/sparc/monitor.c > > @@ -25,6 +25,7 @@ > > #include "cpu.h" > > #include "monitor/monitor.h" > > #include "monitor/hmp.h" > > +#include "qobject/qdict.h" > > > > > > void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > @@ -35,5 +36,27 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > monitor_printf(mon, "No CPU available\n"); > > return; > > } > > + > > +#ifdef TARGET_SPARC64 > > + if (qdict_haskey(qdict, "start") || qdict_haskey(qdict, "end")) { > > + monitor_printf(mon, "The range arguments will be ignored.\n"); > > + } > > + > > dump_mmu(env1); > > +#else > > + hwaddr start = 0, end = HWADDR_MAX; > > + > > + if (qdict_haskey(qdict, "start")) { > > + start = (hwaddr)qdict_get_int(qdict, "start"); > > + } > > + if (qdict_haskey(qdict, "end")) { > > + end = (hwaddr)qdict_get_int(qdict, "end"); > > + } > > + if (start > end) { > > + monitor_printf(mon, "Invalid address range: start > end.\n"); > > + return; > > + } > > + > > + dump_mmu_range(env1, start, end); > > +#endif > > } > > diff --git a/target/xtensa/monitor.c b/target/xtensa/monitor.c > > index 2af84934f8..df572cba42 100644 > > --- a/target/xtensa/monitor.c > > +++ b/target/xtensa/monitor.c > > @@ -25,6 +25,7 @@ > > #include "cpu.h" > > #include "monitor/monitor.h" > > #include "monitor/hmp.h" > > +#include "qobject/qdict.h" > > > > void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > { > > @@ -34,5 +35,10 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict) > > monitor_printf(mon, "No CPU available\n"); > > return; > > } > > + > > + if (qdict_haskey(qdict, "start") || qdict_haskey(qdict, "end")) { > > + monitor_printf(mon, "The range arguments will be ignored.\n"); > > + } > > + > > dump_mmu(env1); > > } > > -- > > 2.43.0 > > > > > > > -- > Marc-André Lureau -- -----Open up your eyes, open up your mind, open up your code ------- / Dr. David Alan Gilbert | Running GNU/Linux | Happy \ \ dave @ treblig.org | | In Hex / \ _________________________|_____ http://www.treblig.org |_______/