diff mbox series

s390: support EDAT-2 in mmu_translate_region

Message ID 20190716123446.24039-1-iii@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series s390: support EDAT-2 in mmu_translate_region | expand

Commit Message

Ilya Leoshkevich July 16, 2019, 12:34 p.m. UTC
When debugging s390 linux kernel with qemu kvm gdbstub, dumping memory
contents at addresses in range 0x80000000-0x100000000 results in an
error or all zeroes being returned.

The problem appears to be that linux puts 2G page at that location,
which qemu currently does not know about.

Check FC bit of Region-Third-Table Entry in mmu_translate_region, just
like it's already done for FC bit of Segment-Table Entry in
mmu_translate_segment.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 target/s390x/cpu.h        | 1 +
 target/s390x/mmu_helper.c | 8 ++++++++
 2 files changed, 9 insertions(+)
diff mbox series

Patch

diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index a606547b4d..947553386f 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -548,6 +548,7 @@  QEMU_BUILD_BUG_ON(sizeof(SysIB) != 4096);
 #define ASCE_TABLE_LENGTH     0x03        /* region table length              */
 
 #define REGION_ENTRY_ORIGIN   (~0xfffULL) /* region/segment table origin    */
+#define REGION_ENTRY_FC       0x400       /* region format control          */
 #define REGION_ENTRY_RO       0x200       /* region/segment protection bit  */
 #define REGION_ENTRY_TF       0xc0        /* region/segment table offset    */
 #define REGION_ENTRY_INV      0x20        /* invalid region table entry     */
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index 6e9c4d6151..76cf920cd2 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -242,6 +242,14 @@  static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
         return -1;
     }
 
+    if (level == ASCE_TYPE_REGION3
+        && (new_entry & REGION_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
+        /* Decode EDAT-2 region frame absolute address (2GB page) */
+        *raddr = (new_entry & 0xffffffff80000000ULL) | (vaddr & 0x7fffffff);
+        PTE_DPRINTF("%s: REG=0x%" PRIx64 "\n", __func__, new_entry);
+        return 0;
+    }
+
     if (level == ASCE_TYPE_SEGMENT) {
         return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,
                                      rw, exc);