(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
> },
>
> 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 |_______/