diff --git a/hmp-commands.hx b/hmp-commands.hx index 573b823347..454d6198a0 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1341,7 +1341,7 @@ show i8259 (PIC) state @item info pci show emulated PCI device info @item info tlb -show virtual to physical memory mappings (i386, SH4, SPARC, and PPC only) +show virtual to physical memory mappings (i386, SH4, SPARC, PPC, and Xtensa only) @item info mem show the active virtual memory mappings (i386 only) @item info jit diff --git a/monitor.c b/monitor.c index aadbdcbf33..2ac196561f 100644 --- a/monitor.c +++ b/monitor.c @@ -1935,7 +1935,7 @@ static void tlb_info(Monitor *mon) #endif -#if defined(TARGET_SPARC) || defined(TARGET_PPC) +#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA) static void tlb_info(Monitor *mon) { CPUState *env1 = mon_get_cpu(); @@ -2382,7 +2382,7 @@ static mon_cmd_t info_cmds[] = { .mhandler.info = hmp_info_pci, }, #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \ - defined(TARGET_PPC) + defined(TARGET_PPC) || defined(TARGET_XTENSA) { .name = "tlb", .args_type = "", diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 0db83a6fd7..c32bf35a19 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -344,6 +344,7 @@ void xtensa_tlb_set_entry(CPUState *env, bool dtlb, int xtensa_get_physical_addr(CPUState *env, uint32_t vaddr, int is_write, int mmu_idx, uint32_t *paddr, uint32_t *page_size, unsigned *access); +void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env); #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt)) diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 2a0cb1a562..973c268db5 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -540,3 +540,70 @@ int xtensa_get_physical_addr(CPUState *env, return 0; } } + +static void dump_tlb(FILE *f, fprintf_function cpu_fprintf, + CPUState *env, bool dtlb) +{ + unsigned wi, ei; + const xtensa_tlb *conf = + dtlb ? &env->config->dtlb : &env->config->itlb; + unsigned (*attr_to_access)(uint32_t) = + xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) ? + mmu_attr_to_access : region_attr_to_access; + + for (wi = 0; wi < conf->nways; ++wi) { + uint32_t sz = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1; + const char *sz_text; + bool print_header = true; + + if (sz >= 0x100000) { + sz >>= 20; + sz_text = "MB"; + } else { + sz >>= 10; + sz_text = "KB"; + } + + for (ei = 0; ei < conf->way_size[wi]; ++ei) { + const xtensa_tlb_entry *entry = + xtensa_tlb_get_entry(env, dtlb, wi, ei); + + if (entry->asid) { + unsigned access = attr_to_access(entry->attr); + + if (print_header) { + print_header = false; + cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text); + cpu_fprintf(f, + "\tVaddr Paddr ASID Attr RWX\n" + "\t---------- ---------- ---- ---- ---\n"); + } + cpu_fprintf(f, + "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c\n", + entry->vaddr, + entry->paddr, + entry->asid, + entry->attr, + (access & PAGE_READ) ? 'R' : '-', + (access & PAGE_WRITE) ? 'W' : '-', + (access & PAGE_EXEC) ? 'X' : '-'); + } + } + } +} + +void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) +{ + if (xtensa_option_bits_enabled(env->config, + XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | + XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION) | + XTENSA_OPTION_BIT(XTENSA_OPTION_MMU))) { + + cpu_fprintf(f, "ITLB:\n"); + dump_tlb(f, cpu_fprintf, env, false); + cpu_fprintf(f, "\nDTLB:\n"); + dump_tlb(f, cpu_fprintf, env, true); + } else { + cpu_fprintf(f, "No TLB for this CPU core\n"); + } +}