diff mbox

[Qemu-PPC,3/3] target/ppc: Add debug function to dump radix mmu translations

Message ID 20170703061948.18220-4-sjitindarsingh@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Suraj Jitindar Singh July 3, 2017, 6:19 a.m. UTC
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(-)

Comments

David Gibson July 3, 2017, 7:51 a.m. UTC | #1
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 mbox

Patch

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;