>From f6904d299589b9639963fcb1fafe58c3577d27a6 Mon Sep 17 00:00:00 2001
From: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Date: Fri, 21 Jul 2017 16:02:00 +0200
Subject: [PATCH] [PATCH] s390x: Add page table walk information to vtop
 command

Hello Dave,

This patch adds some output to the vtop command on s390x. Like on x86 we now
print information on the page table walk:

 * "Region-First-Table Entry" (RFTE)
 * "Region-Second-Table Entry" (RSTE)
 * "Region-Third-Table Entry" (RTTE)
 * "Segment Table Entry" (STE)
 * "Page Table Entry" (PTE)
 * "Read address of page" (PAGE)

Depending on the size of the address space, the page tables can start at
different levels.

Example:

crash> vtop 3ff8000c000
VIRTUAL           PHYSICAL
3ff8000c000       2e3832000

PAGE DIRECTORY: 0000000000aaa000
 RTTE: 0000000000aadff8 => 00000002e3c00007
  STE: 00000002e3c00000 => 00000002e3df7000
  PTE: 00000002e3df7060 => 00000002e383203d
 PAGE: 00000002e3832000

      PAGE        PHYSICAL      MAPPING       INDEX CNT FLAGS
3d10b8e0c80      2e3832000                0        0  1 7fffc0000000000

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
---
 s390x.c | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/s390x.c b/s390x.c
index 96ce3dc..9246f75 100644
--- a/s390x.c
+++ b/s390x.c
@@ -613,16 +613,19 @@ static inline int s390x_pte_present(unsigned long x){
 
 /* Region or segment table traversal function */
 static ulong _kl_rsg_table_deref_s390x(ulong vaddr, ulong table,
-					 int len, int level)
+				       int len, int level, int verbose)
 {
-	ulong offset, entry;
+	const char *name_vec[] = {"STE", "RTTE", "RSTE", "RFTE"};
+	ulong offset, entry, addr;
 
 	offset = ((vaddr >> (11*level + 20)) & 0x7ffULL) * 8;
 	if (offset >= (len + 1)*4096)
 		/* Offset is over the table limit. */
 		return 0;
-	readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry",
-		FAULT_ON_ERROR);
+	addr = table + offset;
+	readmem(addr, KVADDR, &entry, sizeof(entry), "entry", FAULT_ON_ERROR);
+	if (verbose)
+		fprintf(fp, "%5s: %016lx => %016lx\n", name_vec[level], addr, entry);
 	/*
 	 * Check if the segment table entry could be read and doesn't have
 	 * any of the reserved bits set.
@@ -653,13 +656,17 @@ static int swap_entry(ulong entry)
 }
 
 /* Page table traversal function */
-static ulong _kl_pg_table_deref_s390x(ulong vaddr, ulong table)
+static ulong _kl_pg_table_deref_s390x(ulong vaddr, ulong table, int verbose)
 {
-	ulong offset, entry;
+	ulong offset, entry, addr;
 
 	offset = ((vaddr >> 12) & 0xffULL) * 8;
-	readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry",
-		FAULT_ON_ERROR);
+	addr = table + offset;
+	readmem(addr, KVADDR, &entry, sizeof(entry), "entry", FAULT_ON_ERROR);
+	if (verbose) {
+		fprintf(fp, "%5s: %016lx => %016lx\n", "PTE", addr, entry);
+		fprintf(fp, "%5s: %016llx\n", "PAGE", entry & ~0xfffULL);
+	}
 	/*
 	 * Return zero if the page table entry has the reserved (0x800) or
 	 * the invalid (0x400) bit set and it is not a swap entry.
@@ -676,6 +683,9 @@ int s390x_vtop(ulong table, ulong vaddr, physaddr_t *phys_addr, int verbose)
 	ulong entry, paddr;
 	int level, len;
 
+	if (verbose)
+		fprintf(fp, "PAGE DIRECTORY: %016lx\n", table);
+
 	*phys_addr = 0;
 	/*
 	 * Walk the region and segment tables.
@@ -693,7 +703,8 @@ int s390x_vtop(ulong table, ulong vaddr, physaddr_t *phys_addr, int verbose)
 		return FALSE;
 	}
 	while (level >= 0) {
-		entry = _kl_rsg_table_deref_s390x(vaddr, table, len, level);
+		entry = _kl_rsg_table_deref_s390x(vaddr, table, len, level,
+						  verbose);
 		if (!entry)
 			return FALSE;
 		table = entry & ~0xfffULL;
@@ -717,7 +728,7 @@ int s390x_vtop(ulong table, ulong vaddr, physaddr_t *phys_addr, int verbose)
 	}
 
 	/* Get the page table entry */
-	entry = _kl_pg_table_deref_s390x(vaddr, entry & ~0x7ffULL);
+	entry = _kl_pg_table_deref_s390x(vaddr, entry & ~0x7ffULL, verbose);
 	if (!entry)
 		return FALSE;
 
-- 
2.11.2

