From: Don Porter <porter@cs.unc.edu>
To: qemu-devel@nongnu.org
Cc: dave@treblig.org, peter.maydell@linaro.org, nadav.amit@gmail.com,
richard.henderson@linaro.org, philmd@linaro.org,
berrange@redhat.com, Don Porter <porter@cs.unc.edu>
Subject: [PATCH v4 4/7] Convert 'info tlb' to use generic iterator.
Date: Mon, 22 Jul 2024 21:05:42 -0400 [thread overview]
Message-ID: <20240723010545.3648706-5-porter@cs.unc.edu> (raw)
In-Reply-To: <20240723010545.3648706-1-porter@cs.unc.edu>
If the the guest is using nested page tables, change the output format
slightly, to first show guest virtual to guest physical, then guest
physical to host physical, as below:
(qemu) info tlb
Info guest TLB (guest virtual to guest physical):
0000008000800000: 000000000076a000 -------U-P
0000008000801000: 000000000076b000 -------U-P
0000008000802000: 000000000076c000 -------U-P
0000008000803000: 000000000076d000 -------U-P
[...]
0000008004ffd000: 0000000000ffd000 --------WP
0000008004ffe000: 0000000000ffe000 --------WP
0000008004fff000: 0000000000fff000 --------WP
Info host TLB, (guest physical to host physical):
0000000000001000: 0000000001b20000 ----XWR
0000000000002000: 0000000001b21000 ----XWR
0000000000003000: 0000000001b22000 ----XWR
0000000000004000: 0000000001b23000 ----XWR
0000000000005000: 0000000001b24000 ----XWR
[...]
Signed-off-by: Don Porter <porter@cs.unc.edu>
---
include/hw/core/sysemu-cpu-ops.h | 7 +
target/i386/cpu.c | 1 +
target/i386/cpu.h | 2 +
target/i386/monitor.c | 233 +++++++++----------------------
4 files changed, 75 insertions(+), 168 deletions(-)
diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
index d0e939def8..083df4717c 100644
--- a/include/hw/core/sysemu-cpu-ops.h
+++ b/include/hw/core/sysemu-cpu-ops.h
@@ -225,6 +225,13 @@ typedef struct SysemuCPUOps {
bool (*mon_flush_page_print_state)(CPUState *cs,
struct mem_print_state *state);
+ /**
+ * @mon_print_pte: Hook called by the monitor to print a page
+ * table entry at address addr, with contents pte.
+ */
+ void (*mon_print_pte) (CPUState *cs, GString *buf, hwaddr addr,
+ hwaddr pte, uint64_t prot, int mmu_idx);
+
} SysemuCPUOps;
int compressing_iterator(CPUState *cs, void *data, DecodedPTE *pte,
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ec419e0ef0..030198497a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -8388,6 +8388,7 @@ static const struct SysemuCPUOps i386_sysemu_ops = {
.mon_init_page_table_iterator = &x86_mon_init_page_table_iterator,
.mon_info_pg_print_header = &x86_mon_info_pg_print_header,
.mon_flush_page_print_state = &x86_mon_flush_print_pg_state,
+ .mon_print_pte = &x86_mon_print_pte,
};
#endif
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 4e5877f41d..413c743c1a 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2264,6 +2264,8 @@ bool x86_mon_init_page_table_iterator(CPUState *cpu, GString *buf, int mmu_idx,
struct mem_print_state *state);
void x86_mon_info_pg_print_header(struct mem_print_state *state);
bool x86_mon_flush_print_pg_state(CPUState *cs, struct mem_print_state *state);
+void x86_mon_print_pte(CPUState *cs, GString *out_buf, hwaddr addr,
+ hwaddr child, uint64_t prot, int mmu_idx);
bool x86_ptw_translate(CPUState *cs, vaddr vaddress, hwaddr *hpa,
bool debug, int mmu_idx, bool user_access,
const MMUAccessType access_type, uint64_t *page_size,
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 8ef92e7c42..d88347684b 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -224,201 +224,98 @@ static hwaddr addr_canonical(CPUArchState *env, hwaddr addr)
return addr;
}
-static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr,
- hwaddr pte, hwaddr mask)
+void x86_mon_print_pte(CPUState *cs, GString *out_buf, hwaddr addr,
+ hwaddr child, uint64_t prot, int mmu_idx)
{
+ CPUX86State *env = cpu_env(cs);
+ g_autoptr(GString) buf = g_string_new("");
+
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,
- pte & mask,
- pte & PG_NX_MASK ? 'X' : '-',
- pte & PG_GLOBAL_MASK ? 'G' : '-',
- pte & PG_PSE_MASK ? 'P' : '-',
- pte & PG_DIRTY_MASK ? 'D' : '-',
- pte & PG_ACCESSED_MASK ? 'A' : '-',
- pte & PG_PCD_MASK ? 'C' : '-',
- pte & PG_PWT_MASK ? 'T' : '-',
- pte & PG_USER_MASK ? 'U' : '-',
- pte & PG_RW_MASK ? 'W' : '-');
-}
+ g_string_append_printf(buf, HWADDR_FMT_plx ": " HWADDR_FMT_plx " ",
+ addr, child);
-static void tlb_info_32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2;
- uint32_t pgd, pde, pte;
+ g_string_append_printf(buf, " %s", pg_bits(cs, prot, mmu_idx));
- pgd = env->cr[3] & ~0xfff;
- for(l1 = 0; l1 < 1024; l1++) {
- cpu_physical_memory_read(pgd + l1 * 4, &pde, 4);
- pde = le32_to_cpu(pde);
- 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));
- } else {
- for(l2 = 0; l2 < 1024; l2++) {
- cpu_physical_memory_read((pde & ~0xfff) + l2 * 4, &pte, 4);
- pte = le32_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, env, (l1 << 22) + (l2 << 12),
- pte & ~PG_PSE_MASK,
- ~0xfff);
- }
- }
- }
- }
- }
-}
-
-static void tlb_info_pae32(Monitor *mon, CPUArchState *env)
-{
- unsigned int l1, l2, l3;
- uint64_t pdpe, pde, pte;
- uint64_t pdp_addr, pd_addr, pt_addr;
+ /* Trim line to fit screen */
+ g_string_truncate(buf, 79);
- pdp_addr = env->cr[3] & ~0x1f;
- for (l1 = 0; l1 < 4; l1++) {
- cpu_physical_memory_read(pdp_addr + l1 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- if (pdpe & PG_PRESENT_MASK) {
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pd_addr + l2 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- if (pde & PG_PRESENT_MASK) {
- 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));
- } else {
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pt_addr + l3 * 8, &pte, 8);
- pte = le64_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, env, (l1 << 30) + (l2 << 21)
- + (l3 << 12),
- pte & ~PG_PSE_MASK,
- ~(hwaddr)0xfff);
- }
- }
- }
- }
- }
- }
- }
+ g_string_append_printf(out_buf, "%s\n", buf->str);
}
-#ifdef TARGET_X86_64
-static void tlb_info_la48(Monitor *mon, CPUArchState *env,
- uint64_t l0, uint64_t pml4_addr)
+static
+int mem_print_tlb(CPUState *cs, void *data, DecodedPTE *pte, int height,
+ int offset, int mmu_idx, const PageTableLayout *layout)
{
- uint64_t l1, l2, l3, l4;
- uint64_t pml4e, pdpe, pde, pte;
- uint64_t pdp_addr, pd_addr, pt_addr;
-
- for (l1 = 0; l1 < 512; l1++) {
- cpu_physical_memory_read(pml4_addr + l1 * 8, &pml4e, 8);
- pml4e = le64_to_cpu(pml4e);
- if (!(pml4e & PG_PRESENT_MASK)) {
- continue;
- }
-
- pdp_addr = pml4e & 0x3fffffffff000ULL;
- for (l2 = 0; l2 < 512; l2++) {
- cpu_physical_memory_read(pdp_addr + l2 * 8, &pdpe, 8);
- pdpe = le64_to_cpu(pdpe);
- if (!(pdpe & PG_PRESENT_MASK)) {
- continue;
- }
+ struct mem_print_state *state = (struct mem_print_state *) data;
+ CPUClass *cc = CPU_GET_CLASS(cs);
- if (pdpe & PG_PSE_MASK) {
- /* 1G pages, CR4.PSE is ignored */
- print_pte(mon, env, (l0 << 48) + (l1 << 39) + (l2 << 30),
- pdpe, 0x3ffffc0000000ULL);
- continue;
- }
-
- pd_addr = pdpe & 0x3fffffffff000ULL;
- for (l3 = 0; l3 < 512; l3++) {
- cpu_physical_memory_read(pd_addr + l3 * 8, &pde, 8);
- pde = le64_to_cpu(pde);
- if (!(pde & PG_PRESENT_MASK)) {
- continue;
- }
+ cc->sysemu_ops->mon_print_pte(cs, state->buf, pte->bits_translated,
+ pte->child, pte->prot, mmu_idx);
- 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);
- continue;
- }
-
- pt_addr = pde & 0x3fffffffff000ULL;
- for (l4 = 0; l4 < 512; l4++) {
- cpu_physical_memory_read(pt_addr
- + l4 * 8,
- &pte, 8);
- pte = le64_to_cpu(pte);
- if (pte & PG_PRESENT_MASK) {
- print_pte(mon, env, (l0 << 48) + (l1 << 39) +
- (l2 << 30) + (l3 << 21) + (l4 << 12),
- pte & ~PG_PSE_MASK, 0x3fffffffff000ULL);
- }
- }
- }
- }
- }
+ return 0;
}
-static void tlb_info_la57(Monitor *mon, CPUArchState *env)
+static
+void helper_hmp_info_tlb(CPUState *cs, Monitor *mon, int mmu_idx)
{
- uint64_t l0;
- uint64_t pml5e;
- uint64_t pml5_addr;
+ struct mem_print_state state;
+ g_autoptr(GString) buf = g_string_new("");
+ CPUClass *cc = CPU_GET_CLASS(cs);
- pml5_addr = env->cr[3] & 0x3fffffffff000ULL;
- for (l0 = 0; l0 < 512; l0++) {
- cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
- pml5e = le64_to_cpu(pml5e);
- if (pml5e & PG_PRESENT_MASK) {
- tlb_info_la48(mon, env, l0, pml5e & 0x3fffffffff000ULL);
- }
+ if (!cc->sysemu_ops->mon_init_page_table_iterator(cs, buf, mmu_idx,
+ &state)) {
+ monitor_printf(mon, "Unable to initialize page table iterator\n");
+ return;
}
+
+ /**
+ * 'info tlb' visits only leaf PTEs marked present.
+ * It does not check other protection bits.
+ */
+ for_each_pte(cs, &mem_print_tlb, &state, false, false, false, mmu_idx);
+
+ monitor_printf(mon, "%s", buf->str);
}
-#endif /* TARGET_X86_64 */
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
- CPUArchState *env;
+ CPUState *cs = mon_get_cpu(mon);
+ bool nested;
- env = mon_get_cpu_env(mon);
- if (!env) {
- monitor_printf(mon, "No CPU available\n");
+ if (!cs) {
+ monitor_printf(mon, "Unable to get CPUState. Internal error\n");
return;
}
- if (!(env->cr[0] & CR0_PG_MASK)) {
+ if (!cpu_paging_enabled(cs, 0)) {
monitor_printf(mon, "PG disabled\n");
return;
}
- if (env->cr[4] & CR4_PAE_MASK) {
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- if (env->cr[4] & CR4_LA57_MASK) {
- tlb_info_la57(mon, env);
- } else {
- tlb_info_la48(mon, env, 0, env->cr[3] & 0x3fffffffff000ULL);
- }
- } else
-#endif
- {
- tlb_info_pae32(mon, env);
- }
- } else {
- tlb_info_32(mon, env);
+
+ CPUClass *cc = CPU_GET_CLASS(cs);
+
+ if (!cc->sysemu_ops->mon_print_pte
+ || !cc->sysemu_ops->mon_init_page_table_iterator) {
+ monitor_printf(mon, "Info tlb unsupported on this ISA\n");
+ return;
+ }
+
+ nested = cpu_paging_enabled(cs, 1);
+
+ if (nested) {
+ monitor_printf(mon,
+ "Info guest TLB (guest virtual to guest physical):\n");
+ }
+
+ helper_hmp_info_tlb(cs, mon, 0);
+
+ if (nested) {
+ monitor_printf(mon,
+ "Info host TLB, (guest physical to host physical):\n");
+
+ helper_hmp_info_tlb(cs, mon, 1);
+
}
}
--
2.34.1
next prev parent reply other threads:[~2024-07-23 1:07 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-23 1:05 [PATCH v4 0/7] Rework x86 page table walks Don Porter
2024-07-23 1:05 ` [PATCH v4 1/7] Code motion: expose some TCG definitions for page table walk consolidation Don Porter
2024-07-24 3:14 ` Richard Henderson
2024-07-23 1:05 ` [PATCH v4 2/7] Import vmcs12 definition from Linux/KVM Don Porter
2024-07-24 1:34 ` Dr. David Alan Gilbert
2024-07-24 3:18 ` Richard Henderson
2024-07-23 1:05 ` [PATCH v4 3/7] Add an "info pg" command that prints the current page tables Don Porter
2024-07-24 3:33 ` Richard Henderson
2024-07-26 20:07 ` Don Porter
2024-07-23 1:05 ` Don Porter [this message]
2024-07-27 20:47 ` [PATCH v4 4/7] Convert 'info tlb' to use generic iterator Dr. David Alan Gilbert
2024-07-23 1:05 ` [PATCH v4 5/7] Convert 'info mem' " Don Porter
2024-07-23 1:05 ` [PATCH v4 6/7] Convert x86_cpu_get_memory_mapping() to use generic iterators Don Porter
2024-07-23 1:05 ` [PATCH v4 7/7] Convert x86_mmu_translate() to use common code Don Porter
2024-07-24 3:39 ` [PATCH v4 0/7] Rework x86 page table walks Richard Henderson
2024-08-02 16:53 ` Don Porter
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=20240723010545.3648706-5-porter@cs.unc.edu \
--to=porter@cs.unc.edu \
--cc=berrange@redhat.com \
--cc=dave@treblig.org \
--cc=nadav.amit@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/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.