From: "Dr. David Alan Gilbert" <dave@treblig.org>
To: AlanoSong@163.com, philmd@mailo.com
Cc: qemu-devel@nongnu.org, pbonzini@redhat.com, zhao1.liu@intel.com
Subject: Re: [PATCH v2] target/i386/monitor: Refine `info tlb` command
Date: Wed, 1 Jul 2026 21:05:58 +0000 [thread overview]
Message-ID: <akWBNn45ADv1V7ns@gallifrey> (raw)
In-Reply-To: <20260619125602.17077-1-AlanoSong@163.com>
(Added Phil's new address in)
* AlanoSong@163.com (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,
> 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 <AlanoSong@163.com>
> ---
> 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
> },
>
> 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 |_______/
prev parent reply other threads:[~2026-07-01 21:06 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-19 12:56 [PATCH v2] target/i386/monitor: Refine `info tlb` command AlanoSong
2026-07-01 14:02 ` Alano Song
2026-07-01 21:05 ` 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=akWBNn45ADv1V7ns@gallifrey \
--to=dave@treblig.org \
--cc=AlanoSong@163.com \
--cc=pbonzini@redhat.com \
--cc=philmd@mailo.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.