Message ID | 20170703061948.18220-4-sjitindarsingh@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Jul 03, 2017 at 04:19:48PM +1000, Suraj Jitindar Singh wrote: > In target/ppc/mmu-hash64.c there already exists the function > dump_slb() to dump the hash translation entries (for effective to > virtual translation at least). > > Implement the function ppc_radix64_dump() to allow all the kernel > effective to real address mappings and corresponding ptes to be dumped. > This is called when "info tlb" is invoked in the qemu console. Previously > this command had no output when invoked with a radix guest. > > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com> This doesn't really seem equivalent to the other dump_mmu() paths. For HPT, it just dumps the SLB, which is 32 entries. The RPT is likely to have thousands of PTEs. Similarly the other embedded paths generally just dump a (software loaded) TLB, which will have a fixed number of entries. 6xx dumps a TLB and various metadata, but not its whole hash table. In the other direction the info dumped for other platforms *is* affected by the process context (or equivalent), whereas here you just dump the RPT for the kernel (PID 0). So instead of dumping the RPT itself, what I think you want is to pretty print: PID LPID partition table entry 0 partition table entry LPID process table entry 0 process table entry PID and maybe any other context relevant registers I've forgotten. Obviously some of that will need to be omitted for the 'pseries' (vhyp != 0) case. In fact most of the info above would make sense to always dump for a v3.00 MMU, regardless of HPT vs RPT mode. Obviously dumping the SLB only makes sense for HPT mode, though. > --- > target/ppc/mmu-radix64.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ > target/ppc/mmu-radix64.h | 1 + > target/ppc/mmu_helper.c | 2 +- > 3 files changed, 51 insertions(+), 1 deletion(-) > > diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c > index bbd37e3..f7eeead 100644 > --- a/target/ppc/mmu-radix64.c > +++ b/target/ppc/mmu-radix64.c > @@ -296,3 +296,52 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) > > return raddr & TARGET_PAGE_MASK; > } > + > +static void ppc_radix64_dump_level(FILE *f, fprintf_function cpu_fprintf, > + PowerPCCPU *cpu, uint64_t eaddr, > + uint64_t base_addr, uint64_t nls, > + uint64_t psize, int *num) > +{ > + CPUState *cs = CPU(cpu); > + uint64_t i, pte; > + > + for (i = 0; i < (1 << nls); i++) { > + eaddr &= ~((1ULL << psize) - 1); /* Clear the low bits */ > + eaddr |= (i << (psize - nls)); > + > + pte = ldq_phys(cs->as, base_addr + (i * sizeof(pte))); > + if (!(pte & R_PTE_VALID)) { /* Invalid Entry */ > + continue; > + } > + > + if (pte & R_PTE_LEAF) { > + uint64_t mask = (1ULL << (psize - nls)) - 1; > + cpu_fprintf(f, "%d\t0x%.16" PRIx64 " -> 0x%.16" PRIx64 > + " pte: 0x%.16" PRIx64 "\n", (*num)++, > + eaddr, pte & R_PTE_RPN & ~mask, pte); > + } else { > + ppc_radix64_dump_level(f, cpu_fprintf, cpu, eaddr, pte & R_PDE_NLB, > + pte & R_PDE_NLS, psize - nls, num); > + } > + } > +} > + > +void ppc_radix64_dump(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu) > +{ > + CPUState *cs = CPU(cpu); > + PPCVirtualHypervisorClass *vhc = > + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); > + uint64_t patbe, prtbe0; > + int num = 0; > + > + /* Get Process Table */ > + patbe = vhc->get_patbe(cpu->vhyp); > + > + /* Load the first entry -> Guest kernel mappings (all we dump for now) */ > + prtbe0 = ldq_phys(cs->as, patbe & PATBE1_R_PRTB); > + > + cpu_fprintf(f, "\tEADDR\t\t RADDR\n"); > + ppc_radix64_dump_level(f, cpu_fprintf, cpu, 0ULL, prtbe0 & PRTBE_R_RPDB, > + prtbe0 & PRTBE_R_RPDS, PRTBE_R_GET_RTS(prtbe0), > + &num); > +} > diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h > index 0ecf063..c6c22bd 100644 > --- a/target/ppc/mmu-radix64.h > +++ b/target/ppc/mmu-radix64.h > @@ -47,6 +47,7 @@ > int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, > int mmu_idx); > hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); > +void ppc_radix64_dump(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu); > > static inline int ppc_radix64_get_prot_eaa(uint64_t pte) > { > diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c > index b7b9088..9587b07 100644 > --- a/target/ppc/mmu_helper.c > +++ b/target/ppc/mmu_helper.c > @@ -1287,7 +1287,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) > break; > case POWERPC_MMU_VER_3_00: > if (ppc64_radix_guest(ppc_env_get_cpu(env))) { > - /* TODO - Unsupported */ > + ppc_radix64_dump(f, cpu_fprintf, ppc_env_get_cpu(env)); > } else { > dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); > break;
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index bbd37e3..f7eeead 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -296,3 +296,52 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) return raddr & TARGET_PAGE_MASK; } + +static void ppc_radix64_dump_level(FILE *f, fprintf_function cpu_fprintf, + PowerPCCPU *cpu, uint64_t eaddr, + uint64_t base_addr, uint64_t nls, + uint64_t psize, int *num) +{ + CPUState *cs = CPU(cpu); + uint64_t i, pte; + + for (i = 0; i < (1 << nls); i++) { + eaddr &= ~((1ULL << psize) - 1); /* Clear the low bits */ + eaddr |= (i << (psize - nls)); + + pte = ldq_phys(cs->as, base_addr + (i * sizeof(pte))); + if (!(pte & R_PTE_VALID)) { /* Invalid Entry */ + continue; + } + + if (pte & R_PTE_LEAF) { + uint64_t mask = (1ULL << (psize - nls)) - 1; + cpu_fprintf(f, "%d\t0x%.16" PRIx64 " -> 0x%.16" PRIx64 + " pte: 0x%.16" PRIx64 "\n", (*num)++, + eaddr, pte & R_PTE_RPN & ~mask, pte); + } else { + ppc_radix64_dump_level(f, cpu_fprintf, cpu, eaddr, pte & R_PDE_NLB, + pte & R_PDE_NLS, psize - nls, num); + } + } +} + +void ppc_radix64_dump(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu) +{ + CPUState *cs = CPU(cpu); + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + uint64_t patbe, prtbe0; + int num = 0; + + /* Get Process Table */ + patbe = vhc->get_patbe(cpu->vhyp); + + /* Load the first entry -> Guest kernel mappings (all we dump for now) */ + prtbe0 = ldq_phys(cs->as, patbe & PATBE1_R_PRTB); + + cpu_fprintf(f, "\tEADDR\t\t RADDR\n"); + ppc_radix64_dump_level(f, cpu_fprintf, cpu, 0ULL, prtbe0 & PRTBE_R_RPDB, + prtbe0 & PRTBE_R_RPDS, PRTBE_R_GET_RTS(prtbe0), + &num); +} diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 0ecf063..c6c22bd 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -47,6 +47,7 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); +void ppc_radix64_dump(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) { diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index b7b9088..9587b07 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1287,7 +1287,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env) break; case POWERPC_MMU_VER_3_00: if (ppc64_radix_guest(ppc_env_get_cpu(env))) { - /* TODO - Unsupported */ + ppc_radix64_dump(f, cpu_fprintf, ppc_env_get_cpu(env)); } else { dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env)); break;
In target/ppc/mmu-hash64.c there already exists the function dump_slb() to dump the hash translation entries (for effective to virtual translation at least). Implement the function ppc_radix64_dump() to allow all the kernel effective to real address mappings and corresponding ptes to be dumped. This is called when "info tlb" is invoked in the qemu console. Previously this command had no output when invoked with a radix guest. Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com> --- target/ppc/mmu-radix64.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ target/ppc/mmu-radix64.h | 1 + target/ppc/mmu_helper.c | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-)