From: "Dr. David Alan Gilbert" <dave@treblig.org>
To: "Marc-André Lureau" <marcandre.lureau@gmail.com>
Cc: AlanoSong@163.com, qemu-devel@nongnu.org, laurent@vivier.eu,
zhao1.liu@intel.com, atar4qemu@gmail.com
Subject: Re: [PATCH v3] monitor: Refine 'info tlb' command
Date: Tue, 18 Aug 2026 23:08:47 +0000 [thread overview]
Message-ID: <aoTl_9eaioevcOVM@gallifrey> (raw)
In-Reply-To: <CAJ+F1CJ7swW-JWMoRT8=v4hsdGk-O5eFsD=n8XBCirjBHJWAgA@mail.gmail.com>
* Marc-André Lureau (marcandre.lureau@gmail.com) wrote:
> Hi
>
> On Tue, Aug 18, 2026 at 5:30 PM <AlanoSong@163.com> 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 <AlanoSong@163.com>
>
> 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 <dave@treblig.org>
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 |_______/
prev parent reply other threads:[~2026-08-18 23:09 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 13:25 [PATCH v3] monitor: Refine 'info tlb' command AlanoSong
2026-08-18 13:36 ` Philippe Mathieu-Daudé
2026-08-18 15:12 ` Marc-André Lureau
2026-08-18 23:08 ` Dr. David Alan Gilbert [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aoTl_9eaioevcOVM@gallifrey \
--to=dave@treblig.org \
--cc=AlanoSong@163.com \
--cc=atar4qemu@gmail.com \
--cc=laurent@vivier.eu \
--cc=marcandre.lureau@gmail.com \
--cc=qemu-devel@nongnu.org \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox