* Alano Song ([email protected]) wrote:
See below: > At 2026-07-02 05:05:58, "Dr. David Alan Gilbert" <[email protected]> wrote: > >(Added Phil's new address in) > > > >* [email protected] ([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, > >> because each monitor print function will holds 'mon_lock'. > >> This effectively hangs the qemu monitor. > >> > >> It may be better to add warning note in help message, > >> and add a address range by argument to help user control > >> the number of output items. > >> > >> Signed-off-by: Alano Song <[email protected]> > >> --- > >> hmp-commands-info.hx | 12 ++++--- > >> target/i386/monitor.c | 82 +++++++++++++++++++++++++++++-------------- > >> 2 files changed, 64 insertions(+), 30 deletions(-) > >> > >> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx > >> index 82134eb6c2..3189e20de3 100644 > >> --- a/hmp-commands-info.hx > >> +++ b/hmp-commands-info.hx > >> @@ -188,17 +188,21 @@ 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 target. " > >> + "use 'info tlb [start] [end]' to show a range of > >> entries.", > > > >That can be; > >> + "The address range can be limited with the optional > >> parameters." > > > >Now, is that the *virtual* address - because it feels like that needs > >specifying. > > > >> .cmd = hmp_info_tlb, > >> .arch_bitmask = QEMU_ARCH_I386 | QEMU_ARCH_SH4 | QEMU_ARCH_SPARC \ > >> | QEMU_ARCH_PPC | QEMU_ARCH_XTENSA | > >> QEMU_ARCH_M68K, > > > >You have added the start/end params to the help, but only implemented it on > >x86. > >That seems odd. > > > >Dave > > > > > > Hi Dr. Gilbert, > > On this patch, I’m currently enabling the `start`/`end` parameters only for > x86, since other targets typically maintain a relatively small TLB. > > For example, xtensa only has a handful of entries, as shown below, so it’s > reasonable to simply ignore start/end parameters and dump all items: We shouldn't blindly ignore parameters; we should always tell the user, this is mainly because a user would be very confused if they were using these parameters and still getting pages of output from say sparc32. Perhaps if you create a little helper function that the unsupported hmp_info_tlb's can call to check it. Something like if (hmp_check_unsupported_info_tlb_params(qdict,something)) { return; } so then it's easy to add that to the ones that's not supported. > // target/xtensa/cpu.h > ... > #define MAX_TLB_WAY_SIZE 8 > ... > struct CPUArchState { > ... > #ifndef CONFIG_USER_ONLY > xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE]; > xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE]; > ... > > The same applies to sparc64, ppc, and sh4. > > > Thanks for the reminder. > I went through all architectures supporting the > > `info tlb` command. I noticed that sparc32 and m68k may also produce a > large number of TLB entries, so I plan to extend start/end filtering > to those as well. > What do you think? > Yeh that would be great, I think the more important bit is not to confuse users about ones which aren't supported. > >> SRST > >> - ``info tlb`` > >> + ``info tlb`` [*start* [*end*]] > >> Show virtual to physical memory mappings. > >> + The output can be extremely large for i386 target. > >> + Use *start* and *end* to print entries located in address range > >> [start, end]. > >> ERST I think I'd change it to something like *start* and *end can restrict the address range printed to [start, end] (This restriction is only supported on i386) Dave > Alano. > > > >> }, > >> > >> SRST > >> - ``info tlb`` > >> + ``info tlb`` [*start* [*end*]] > >> Show virtual to physical memory mappings. > >> + The output can be extremely large for i386 target. > >> + Use *start* and *end* to print entries located in address range > >> [start, end]. > >> ERST > >> > >> { > >> diff --git a/target/i386/monitor.c b/target/i386/monitor.c > >> index a536712c75..c0e0c3e405 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, CPUArchState *env, 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,20 @@ 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 start, hwaddr end) > >> +{ > >> + addr = addr_canonical(env, addr); > >> + if (addr < start || addr > end) { > >> + return; > >> + } > >> + > >> + do_print_pte(mon, env, addr, 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 +91,15 @@ 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), > >> + 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, start, end); > >> } > >> } > >> } > >> @@ -96,7 +107,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 +126,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), > >> + 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, > >> + start, end); > >> } > >> } > >> } > >> @@ -136,7 +150,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 +174,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, start, end); > >> continue; > >> } > >> > >> @@ -172,8 +187,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, start, end); > >> continue; > >> } > >> > >> @@ -182,9 +198,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, start, end); > >> } > >> } > >> } > >> @@ -192,7 +210,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 +222,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 +233,14 @@ 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"); > >> + } > >> > >> env = mon_get_cpu_env(mon); > >> if (!env) { > >> @@ -229,17 +257,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); > >> } > >> } > >> > >> -- > >> 2.43.0 > >> > >-- > > -----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 |_______/ -- -----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 |_______/
