----- Forwarded Message -----
From: "Zaslonko Mikhail" <zaslonko(a)linux.vnet.ibm.com>
To: "Dave Anderson" <anderson(a)redhat.com>
Cc: "Michael Holzheu" <holzheu(a)linux.vnet.ibm.com>
Sent: Tuesday, August 15, 2017 1:41:25 PM
Subject: [PATCH] s390x : Display-hardware-flags-for-RTE-STE-PTE
Hello Dave,
Please find enclosed patch below.
Enhancement to the S390X "vtop" command to display binary values of
hardware flags for region, segment and page table entries along with
page table walk information.
For example:
crash> vtop -u 0x60000000000000
VIRTUAL PHYSICAL
60000000000000 5b50a000
PAGE DIRECTORY: 000000005cea0000
RFTE: 000000005cea0018 => 000000006612400f (flags = 00f)
flags in binary : P=0; TF=00; I=0; TT=11; TL=11
RSTE: 0000000066124000 => 000000005d91800b (flags = 00b)
flags in binary : P=0; TF=00; I=0; TT=10; TL=11
RTTE: 000000005d918000 => 000000006615c007 (flags = 007)
flags in binary : FC=0; P=0; TF=00; I=0; CR=0; TT=01; TL=11
STE: 000000006615c000 => 000000005ce48800 (flags = 800)
flags in binary : FC=0; P=0; I=0; CS=0; TT=00
PTE: 000000005ce48800 => 000000005b50a03f (flags = 03f)
flags in binary : I=0; P=0
PAGE: 000000005b50a000
or, for large pages:
crash> vtop -k 0x3d100000000
VIRTUAL PHYSICAL
3d100000000 77c00000
PAGE DIRECTORY: 0000000001210000
RTTE: 0000000001213d10 => 0000000077dc4007 (flags = 007)
flags in binary : FC=0; P=0; TF=00; I=0; CR=0; TT=01; TL=11
STE: 0000000077dc4000 => 0000000077c03403 (flags = 03403)
flags in binary : AV=0, ACC=0011; F=0; FC=1; P=0; I=0; CS=0; TT=00
Reviewed-by: Michael Holzheu <holzheu(a)linux.vnet.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.vnet.ibm.com>
---
s390x.c | 183
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 175 insertions(+), 8 deletions(-)
diff --git a/s390x.c b/s390x.c
index 9246f75..fa202bc 100644
--- a/s390x.c
+++ b/s390x.c
@@ -26,7 +26,8 @@
/* Flags used in entries of page dirs and page tables.
*/
-#define S390X_PAGE_PRESENT 0x001ULL /* set: loaded in physical memory
+#define S390X_PTE_FLAG_BITS 0xfffULL /* Page table entry flag bits */
+#define S390X_PAGE_PRESENT 0x001ULL /* set: loaded in physical memory
* clear: not loaded in
physical mem */
#define S390X_PAGE_RO 0x200ULL /* HW read-only */
#define S390X_PAGE_INVALID 0x400ULL /* HW invalid */
@@ -46,6 +47,49 @@
#define S390X_PSW_MASK_PSTATE 0x0001000000000000UL
/*
+ * Flags for Region and Segment table entries.
+ */
+#define S390X_RTE_FLAG_BITS_FC0 0xfffULL
+#define S390X_RTE_FLAG_BITS_FC1 0x7fffffffULL
+#define S390X_RTE_TL 0x3ULL
+#define S390X_RTE_TL_10 0x2ULL
+#define S390X_RTE_TL_01 0x1ULL
+#define S390X_RTE_TT 0xcULL
+#define S390X_RTE_TT_10 0x8ULL
+#define S390X_RTE_TT_01 0x4ULL
+#define S390X_RTE_CR 0x10ULL
+#define S390X_RTE_I 0x20ULL
+#define S390X_RTE_TF 0xc0ULL
+#define S390X_RTE_TF_10 0x80ULL
+#define S390X_RTE_TF_01 0x40ULL
+#define S390X_RTE_P 0x200ULL
+#define S390X_RTE_FC 0x400ULL
+#define S390X_RTE_F 0x800ULL
+#define S390X_RTE_ACC 0xf000ULL
+#define S390X_RTE_ACC_1000 0x8000ULL
+#define S390X_RTE_ACC_0100 0x4000ULL
+#define S390X_RTE_ACC_0010 0x2000ULL
+#define S390X_RTE_ACC_0001 0x1000ULL
+#define S390X_RTE_AV 0x10000ULL
+
+#define S390X_STE_FLAG_BITS_FC0 0x7ffULL
+#define S390X_STE_FLAG_BITS_FC1 0xfffffULL
+#define S390X_STE_TT 0xcULL
+#define S390X_STE_TT_10 0x8ULL
+#define S390X_STE_TT_01 0x4ULL
+#define S390X_STE_CS 0x10ULL
+#define S390X_STE_I 0x20ULL
+#define S390X_STE_P 0x200ULL
+#define S390X_STE_FC 0x400ULL
+#define S390X_STE_F 0x800ULL
+#define S390X_STE_ACC 0xf000ULL
+#define S390X_STE_ACC_1000 0x8000ULL
+#define S390X_STE_ACC_0100 0x4000ULL
+#define S390X_STE_ACC_0010 0x2000ULL
+#define S390X_STE_ACC_0001 0x1000ULL
+#define S390X_STE_AV 0x10000ULL
+
+/*
* S390x prstatus ELF Note
*/
struct s390x_nt_prstatus {
@@ -611,12 +655,115 @@ static inline int s390x_pte_present(unsigned long x){
* page table traversal functions
*/
+/* Print flags of Segment-Table entry with format control = 1 */
+static void print_segment_entry_fc1(ulong val)
+{
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CS=%u;
TT=%u%u\n",
+ !!(val & S390X_STE_AV),
+ !!(val & S390X_STE_ACC_1000),
+ !!(val & S390X_STE_ACC_0100),
+ !!(val & S390X_STE_ACC_0010),
+ !!(val & S390X_STE_ACC_0001),
+ !!(val & S390X_STE_F),
+ !!(val & S390X_STE_FC),
+ !!(val & S390X_STE_P),
+ !!(val & S390X_STE_I),
+ !!(val & S390X_STE_CS),
+ !!(val & S390X_STE_TT_10),
+ !!(val & S390X_STE_TT_01));
+}
+
+/* Print flags of Segment-Table entry with format control = 0 */
+static void print_segment_entry_fc0(ulong val)
+{
+ fprintf(fp, "FC=%u; P=%u; I=%u; CS=%u; TT=%u%u\n",
+ !!(val & S390X_STE_FC),
+ !!(val & S390X_STE_P),
+ !!(val & S390X_STE_I),
+ !!(val & S390X_STE_CS),
+ !!(val & S390X_STE_TT_10),
+ !!(val & S390X_STE_TT_01));
+}
+
+/* Print flags of Region-Third-Table entry with format control = 1 */
+static void print_region_third_entry_fc1(ulong val)
+{
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CR=%u;
TT=%u%u\n",
+ !!(val & S390X_RTE_AV),
+ !!(val & S390X_RTE_ACC_1000),
+ !!(val & S390X_RTE_ACC_0100),
+ !!(val & S390X_RTE_ACC_0010),
+ !!(val & S390X_RTE_ACC_0001),
+ !!(val & S390X_RTE_F),
+ !!(val & S390X_RTE_FC),
+ !!(val & S390X_RTE_P),
+ !!(val & S390X_RTE_I),
+ !!(val & S390X_RTE_CR),
+ !!(val & S390X_RTE_TT_10),
+ !!(val & S390X_RTE_TT_01));
+}
+
+/* Print flags of Region-Third-Table entry with format control = 0 */
+static void print_region_third_entry_fc0(ulong val)
+{
+ fprintf(fp, "FC=%u; P=%u; TF=%u%u; I=%u; CR=%u; TT=%u%u; TL=%u%u\n",
+ !!(val & S390X_RTE_FC),
+ !!(val & S390X_RTE_P),
+ !!(val & S390X_RTE_TF_10),
+ !!(val & S390X_RTE_TF_01),
+ !!(val & S390X_RTE_I),
+ !!(val & S390X_RTE_CR),
+ !!(val & S390X_RTE_TT_10),
+ !!(val & S390X_RTE_TT_01),
+ !!(val & S390X_RTE_TL_10),
+ !!(val & S390X_RTE_TL_01));
+}
+
+/* Print flags of Region-First/Second-Table entry */
+static void print_region_first_second_entry(ulong val)
+{
+ fprintf(fp, "P=%u; TF=%u%u; I=%u; TT=%u%u; TL=%u%u\n",
+ !!(val & S390X_RTE_P),
+ !!(val & S390X_RTE_TF_10),
+ !!(val & S390X_RTE_TF_01),
+ !!(val & S390X_RTE_I),
+ !!(val & S390X_RTE_TT_10),
+ !!(val & S390X_RTE_TT_01),
+ !!(val & S390X_RTE_TL_10),
+ !!(val & S390X_RTE_TL_01));
+}
+
+/* Print the binary flags for Region or Segment table entry */
+static void s390x_print_te_binary_flags(ulong val, int level)
+{
+ fprintf(fp, " flags in binary : ");
+ switch (level) {
+ case 0:
+ if (val & S390X_STE_FC)
+ print_segment_entry_fc1(val);
+ else
+ print_segment_entry_fc0(val);
+ break;
+ case 1:
+ if (val & S390X_RTE_FC)
+ print_region_third_entry_fc1(val);
+ else
+ print_region_third_entry_fc0(val);
+ break;
+ case 2:
+ case 3:
+ print_region_first_second_entry(val);
+ break;
+ }
+}
+
/* Region or segment table traversal function */
static ulong _kl_rsg_table_deref_s390x(ulong vaddr, ulong table,
int len, int level, int verbose)
{
const char *name_vec[] = {"STE", "RTTE", "RSTE",
"RFTE"};
- ulong offset, entry, addr;
+ ulong offset, entry, flags, addr;
+ int flags_prt_len;
offset = ((vaddr >> (11*level + 20)) & 0x7ffULL) * 8;
if (offset >= (len + 1)*4096)
@@ -624,16 +771,33 @@ static ulong _kl_rsg_table_deref_s390x(ulong
vaddr, ulong table,
return 0;
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);
+ if (verbose) {
+ flags_prt_len = 3;
+ if (entry & S390X_RTE_FC)
+ if (level) {
+ flags = entry & S390X_RTE_FLAG_BITS_FC1;
+ flags_prt_len = 8;
+ } else {
+ flags = entry & S390X_STE_FLAG_BITS_FC1;
+ flags_prt_len = 5;
+ }
+ else
+ if (level)
+ flags = entry & S390X_RTE_FLAG_BITS_FC0;
+ else
+ flags = entry & S390X_STE_FLAG_BITS_FC0;
+ fprintf(fp, "%5s: %016lx => %016lx (flags = %0*lx)\n",
+ name_vec[level], addr, entry, flags_prt_len, flags);
+ s390x_print_te_binary_flags(entry, level);
+ }
/*
* Check if the segment table entry could be read and doesn't have
* any of the reserved bits set.
*/
- if ((entry & 0xcULL) != (level << 2))
+ if ((entry & S390X_RTE_TT) != (level << 2))
return 0;
/* Check if the region table entry has the invalid bit set. */
- if (entry & 0x20ULL)
+ if (entry & S390X_RTE_I)
return 0;
/* Region table entry is valid and well formed. */
return entry;
@@ -664,8 +828,11 @@ static ulong _kl_pg_table_deref_s390x(ulong vaddr,
ulong table, int verbose)
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);
+ fprintf(fp, "%5s: %016lx => %016lx (flags = %03llx)\n",
+ "PTE", addr, entry, entry & S390X_PTE_FLAG_BITS);
+ fprintf(fp, " flags in binary : I=%u; P=%u\n",
+ !!(entry & S390X_PAGE_INVALID), !!(entry & S390X_PAGE_RO));
+ fprintf(fp, "%5s: %016llx\n", "PAGE", entry &
~S390X_PTE_FLAG_BITS);
}
/*
* Return zero if the page table entry has the reserved (0x800) or
--
2.11.2