All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access
@ 2015-02-12 17:09 Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file Jens Freimann
                   ` (25 more replies)
  0 siblings, 26 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel

Cornelia, Alex, Christian,

this patches are a rework of guest memory access to allow access to 
guest logical address space.

Frank Blaschka (1):
  s390x/pci: Rework memory access in zpci instruction

Thomas Huth (24):
  s390x/mmu: Move mmu_translate() and friends to separate file
  s390x/mmu: Fix the check for the real-space designation bit
  s390x/mmu: Fix the handling of the table levels
  s390x/mmu: Check table length and offset fields
  s390x/mmu: Skip exceptions properly when translating addresses for
    debug
  s390x/mmu: Fix translation exception code in lowcore
  s390x/mmu: Fix exception types when checking the ASCEs
  s390x/mmu: Fix the exception codes for illegal table entries
  s390x/mmu: Add support for read-only regions
  s390x/mmu: Renaming related to the ASCE confusion
  s390x/mmu: Check bit 52 in page table entry
  s390x/mmu: Clean up mmu_translate_asc()
  s390x/kvm: Add function for injecting pgm access exceptions
  s390x/mmu: Add function for accessing guest memory
  s390x/css: Make schib parameter of css_do_msch const
  s390x/ioinst: Rework memory access in MSCH instruction
  s390x/ioinst: Rework memory access in SSCH instruction
  s390x/ioinst: Rework memory access in STSCH instruction
  s390x/ioinst: Set condition code in ioinst_handle_tsch() handler
  s390x/ioinst: Rework memory access in TSCH instruction
  s390x/ioinst: Rework memory access in STCRW instruction
  s390x/ioinst: Rework memory access in CHSC instruction
  s390x/ioinst: Rework memory access in TPI instruction
  s390x/helper: Remove s390_cpu_physical_memory_map

 hw/s390x/css.c             |  60 ++++--
 hw/s390x/s390-pci-inst.c   |  37 +++-
 target-s390x/Makefile.objs |   2 +-
 target-s390x/cpu.h         |  32 ++-
 target-s390x/helper.c      | 356 +---------------------------------
 target-s390x/ioinst.c      | 172 ++++++++---------
 target-s390x/ioinst.h      |   4 +-
 target-s390x/kvm.c         |  21 +-
 target-s390x/mem_helper.c  |  12 +-
 target-s390x/mmu_helper.c  | 472 +++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 681 insertions(+), 487 deletions(-)
 create mode 100644 target-s390x/mmu_helper.c

-- 
2.1.4

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-17 12:35   ` Alexander Graf
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 02/25] s390x/mmu: Fix the check for the real-space designation bit Jens Freimann
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

helper.c is quite overcrowded already, so let's move the MMU
translation to a separate file instead (like it has been done
with the other targets already).

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 target-s390x/Makefile.objs |   2 +-
 target-s390x/cpu.h         |   1 +
 target-s390x/helper.c      | 323 +---------------------------------------
 target-s390x/mmu_helper.c  | 356 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 359 insertions(+), 323 deletions(-)
 create mode 100644 target-s390x/mmu_helper.c

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 2c57494..dd62cbd 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += translate.o helper.o cpu.o interrupt.o
 obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-y += gdbstub.o
-obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o
+obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2e2554c..95d0f3b 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -331,6 +331,7 @@ static inline int get_ilen(uint8_t opc)
    to re-compute the length by examining the insn in memory.  */
 #define ILEN_LATER       0x20
 #define ILEN_LATER_INC   0x21
+void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
 #endif
 
 S390CPU *cpu_s390x_init(const char *cpu_model);
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 5958343..76b4b36 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -27,7 +27,6 @@
 #endif
 
 //#define DEBUG_S390
-//#define DEBUG_S390_PTE
 //#define DEBUG_S390_STDOUT
 
 #ifdef DEBUG_S390
@@ -44,12 +43,6 @@
     do { } while (0)
 #endif
 
-#ifdef DEBUG_S390_PTE
-#define PTE_DPRINTF DPRINTF
-#else
-#define PTE_DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
 
 #ifndef CONFIG_USER_ONLY
 void s390x_tod_timer(void *opaque)
@@ -105,8 +98,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
 #else /* !CONFIG_USER_ONLY */
 
 /* Ensure to exit the TB after this call! */
-static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
-                                  uint32_t ilen)
+void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
 
@@ -115,319 +107,6 @@ static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
     env->int_pgm_ilen = ilen;
 }
 
-static int trans_bits(CPUS390XState *env, uint64_t mode)
-{
-    S390CPU *cpu = s390_env_get_cpu(env);
-    int bits = 0;
-
-    switch (mode) {
-    case PSW_ASC_PRIMARY:
-        bits = 1;
-        break;
-    case PSW_ASC_SECONDARY:
-        bits = 2;
-        break;
-    case PSW_ASC_HOME:
-        bits = 3;
-        break;
-    default:
-        cpu_abort(CPU(cpu), "unknown asc mode\n");
-        break;
-    }
-
-    return bits;
-}
-
-static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
-                               uint64_t mode)
-{
-    CPUState *cs = CPU(s390_env_get_cpu(env));
-    int ilen = ILEN_LATER_INC;
-    int bits = trans_bits(env, mode) | 4;
-
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
-
-    stq_phys(cs->as,
-             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
-    trigger_pgm_exception(env, PGM_PROTECTION, ilen);
-}
-
-static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
-                               uint32_t type, uint64_t asc, int rw)
-{
-    CPUState *cs = CPU(s390_env_get_cpu(env));
-    int ilen = ILEN_LATER;
-    int bits = trans_bits(env, asc);
-
-    /* Code accesses have an undefined ilc.  */
-    if (rw == 2) {
-        ilen = 2;
-    }
-
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
-
-    stq_phys(cs->as,
-             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
-    trigger_pgm_exception(env, type, ilen);
-}
-
-/**
- * Translate real address to absolute (= physical)
- * address by taking care of the prefix mapping.
- */
-static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
-{
-    if (raddr < 0x2000) {
-        return raddr + env->psa;    /* Map the lowcore. */
-    } else if (raddr >= env->psa && raddr < env->psa + 0x2000) {
-        return raddr - env->psa;    /* Map the 0 page. */
-    }
-    return raddr;
-}
-
-/* Decode page table entry (normal 4KB page) */
-static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
-                             uint64_t asc, uint64_t asce,
-                             target_ulong *raddr, int *flags, int rw)
-{
-    if (asce & _PAGE_INVALID) {
-        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, asce);
-        trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw);
-        return -1;
-    }
-
-    if (asce & _PAGE_RO) {
-        *flags &= ~PAGE_WRITE;
-    }
-
-    *raddr = asce & _ASCE_ORIGIN;
-
-    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, asce);
-
-    return 0;
-}
-
-/* Decode EDAT1 segment frame absolute address (1MB page) */
-static int mmu_translate_sfaa(CPUS390XState *env, target_ulong vaddr,
-                              uint64_t asc, uint64_t asce, target_ulong *raddr,
-                              int *flags, int rw)
-{
-    if (asce & _SEGMENT_ENTRY_INV) {
-        DPRINTF("%s: SEG=0x%" PRIx64 " invalid\n", __func__, asce);
-        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
-        return -1;
-    }
-
-    if (asce & _SEGMENT_ENTRY_RO) {
-        *flags &= ~PAGE_WRITE;
-    }
-
-    *raddr = (asce & 0xfffffffffff00000ULL) | (vaddr & 0xfffff);
-
-    PTE_DPRINTF("%s: SEG=0x%" PRIx64 "\n", __func__, asce);
-
-    return 0;
-}
-
-static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
-                              uint64_t asc, uint64_t asce, int level,
-                              target_ulong *raddr, int *flags, int rw)
-{
-    CPUState *cs = CPU(s390_env_get_cpu(env));
-    uint64_t offs = 0;
-    uint64_t origin;
-    uint64_t new_asce;
-
-    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);
-
-    if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||
-        ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {
-        /* XXX different regions have different faults */
-        DPRINTF("%s: invalid region\n", __func__);
-        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
-        return -1;
-    }
-
-    if ((level <= _ASCE_TYPE_MASK) && ((asce & _ASCE_TYPE_MASK) != level)) {
-        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
-        return -1;
-    }
-
-    if (asce & _ASCE_REAL_SPACE) {
-        /* direct mapping */
-
-        *raddr = vaddr;
-        return 0;
-    }
-
-    origin = asce & _ASCE_ORIGIN;
-
-    switch (level) {
-    case _ASCE_TYPE_REGION1 + 4:
-        offs = (vaddr >> 50) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION1:
-        offs = (vaddr >> 39) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION2:
-        offs = (vaddr >> 28) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION3:
-        offs = (vaddr >> 17) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_SEGMENT:
-        offs = (vaddr >> 9) & 0x07f8;
-        origin = asce & _SEGMENT_ENTRY_ORIGIN;
-        break;
-    }
-
-    /* XXX region protection flags */
-    /* *flags &= ~PAGE_WRITE */
-
-    new_asce = ldq_phys(cs->as, origin + offs);
-    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
-                __func__, origin, offs, new_asce);
-
-    if (level == _ASCE_TYPE_SEGMENT) {
-        /* 4KB page */
-        return mmu_translate_pte(env, vaddr, asc, new_asce, raddr, flags, rw);
-    } else if (level - 4 == _ASCE_TYPE_SEGMENT &&
-               (new_asce & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
-        /* 1MB page */
-        return mmu_translate_sfaa(env, vaddr, asc, new_asce, raddr, flags, rw);
-    } else {
-        /* yet another region */
-        return mmu_translate_asce(env, vaddr, asc, new_asce, level - 4, raddr,
-                                  flags, rw);
-    }
-}
-
-static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
-                             uint64_t asc, target_ulong *raddr, int *flags,
-                             int rw)
-{
-    uint64_t asce = 0;
-    int level, new_level;
-    int r;
-
-    switch (asc) {
-    case PSW_ASC_PRIMARY:
-        PTE_DPRINTF("%s: asc=primary\n", __func__);
-        asce = env->cregs[1];
-        break;
-    case PSW_ASC_SECONDARY:
-        PTE_DPRINTF("%s: asc=secondary\n", __func__);
-        asce = env->cregs[7];
-        break;
-    case PSW_ASC_HOME:
-        PTE_DPRINTF("%s: asc=home\n", __func__);
-        asce = env->cregs[13];
-        break;
-    }
-
-    switch (asce & _ASCE_TYPE_MASK) {
-    case _ASCE_TYPE_REGION1:
-        break;
-    case _ASCE_TYPE_REGION2:
-        if (vaddr & 0xffe0000000000000ULL) {
-            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                    " 0xffe0000000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
-            return -1;
-        }
-        break;
-    case _ASCE_TYPE_REGION3:
-        if (vaddr & 0xfffffc0000000000ULL) {
-            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                    " 0xfffffc0000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
-            return -1;
-        }
-        break;
-    case _ASCE_TYPE_SEGMENT:
-        if (vaddr & 0xffffffff80000000ULL) {
-            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                    " 0xffffffff80000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
-            return -1;
-        }
-        break;
-    }
-
-    /* fake level above current */
-    level = asce & _ASCE_TYPE_MASK;
-    new_level = level + 4;
-    asce = (asce & ~_ASCE_TYPE_MASK) | (new_level & _ASCE_TYPE_MASK);
-
-    r = mmu_translate_asce(env, vaddr, asc, asce, new_level, raddr, flags, rw);
-
-    if ((rw == 1) && !(*flags & PAGE_WRITE)) {
-        trigger_prot_fault(env, vaddr, asc);
-        return -1;
-    }
-
-    return r;
-}
-
-int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
-                  target_ulong *raddr, int *flags)
-{
-    int r = -1;
-    uint8_t *sk;
-
-    *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-    vaddr &= TARGET_PAGE_MASK;
-
-    if (!(env->psw.mask & PSW_MASK_DAT)) {
-        *raddr = vaddr;
-        r = 0;
-        goto out;
-    }
-
-    switch (asc) {
-    case PSW_ASC_PRIMARY:
-    case PSW_ASC_HOME:
-        r = mmu_translate_asc(env, vaddr, asc, raddr, flags, rw);
-        break;
-    case PSW_ASC_SECONDARY:
-        /*
-         * Instruction: Primary
-         * Data: Secondary
-         */
-        if (rw == 2) {
-            r = mmu_translate_asc(env, vaddr, PSW_ASC_PRIMARY, raddr, flags,
-                                  rw);
-            *flags &= ~(PAGE_READ | PAGE_WRITE);
-        } else {
-            r = mmu_translate_asc(env, vaddr, PSW_ASC_SECONDARY, raddr, flags,
-                                  rw);
-            *flags &= ~(PAGE_EXEC);
-        }
-        break;
-    case PSW_ASC_ACCREG:
-    default:
-        hw_error("guest switched to unknown asc mode\n");
-        break;
-    }
-
- out:
-    /* Convert real address -> absolute address */
-    *raddr = mmu_real2abs(env, *raddr);
-
-    if (*raddr <= ram_size) {
-        sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
-        if (*flags & PAGE_READ) {
-            *sk |= SK_R;
-        }
-
-        if (*flags & PAGE_WRITE) {
-            *sk |= SK_C;
-        }
-    }
-
-    return r;
-}
-
 int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
                               int rw, int mmu_idx)
 {
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
new file mode 100644
index 0000000..fc4f7c5
--- /dev/null
+++ b/target-s390x/mmu_helper.c
@@ -0,0 +1,356 @@
+/*
+ * S390x MMU related functions
+ *
+ * Copyright (c) 2011 Alexander Graf
+ * Copyright (c) 2015 Thomas Huth, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "cpu.h"
+
+/* #define DEBUG_S390 */
+/* #define DEBUG_S390_PTE */
+/* #define DEBUG_S390_STDOUT */
+
+#ifdef DEBUG_S390
+#ifdef DEBUG_S390_STDOUT
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); \
+         qemu_log(fmt, ##__VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { qemu_log(fmt, ## __VA_ARGS__); } while (0)
+#endif
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+#ifdef DEBUG_S390_PTE
+#define PTE_DPRINTF DPRINTF
+#else
+#define PTE_DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static int trans_bits(CPUS390XState *env, uint64_t mode)
+{
+    S390CPU *cpu = s390_env_get_cpu(env);
+    int bits = 0;
+
+    switch (mode) {
+    case PSW_ASC_PRIMARY:
+        bits = 1;
+        break;
+    case PSW_ASC_SECONDARY:
+        bits = 2;
+        break;
+    case PSW_ASC_HOME:
+        bits = 3;
+        break;
+    default:
+        cpu_abort(CPU(cpu), "unknown asc mode\n");
+        break;
+    }
+
+    return bits;
+}
+
+static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
+                               uint64_t mode)
+{
+    CPUState *cs = CPU(s390_env_get_cpu(env));
+    int ilen = ILEN_LATER_INC;
+    int bits = trans_bits(env, mode) | 4;
+
+    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
+
+    stq_phys(cs->as,
+             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
+    trigger_pgm_exception(env, PGM_PROTECTION, ilen);
+}
+
+static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
+                               uint32_t type, uint64_t asc, int rw)
+{
+    CPUState *cs = CPU(s390_env_get_cpu(env));
+    int ilen = ILEN_LATER;
+    int bits = trans_bits(env, asc);
+
+    /* Code accesses have an undefined ilc.  */
+    if (rw == 2) {
+        ilen = 2;
+    }
+
+    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
+
+    stq_phys(cs->as,
+             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
+    trigger_pgm_exception(env, type, ilen);
+}
+
+/**
+ * Translate real address to absolute (= physical)
+ * address by taking care of the prefix mapping.
+ */
+static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
+{
+    if (raddr < 0x2000) {
+        return raddr + env->psa;    /* Map the lowcore. */
+    } else if (raddr >= env->psa && raddr < env->psa + 0x2000) {
+        return raddr - env->psa;    /* Map the 0 page. */
+    }
+    return raddr;
+}
+
+/* Decode page table entry (normal 4KB page) */
+static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
+                             uint64_t asc, uint64_t asce,
+                             target_ulong *raddr, int *flags, int rw)
+{
+    if (asce & _PAGE_INVALID) {
+        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, asce);
+        trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw);
+        return -1;
+    }
+
+    if (asce & _PAGE_RO) {
+        *flags &= ~PAGE_WRITE;
+    }
+
+    *raddr = asce & _ASCE_ORIGIN;
+
+    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, asce);
+
+    return 0;
+}
+
+/* Decode EDAT1 segment frame absolute address (1MB page) */
+static int mmu_translate_sfaa(CPUS390XState *env, target_ulong vaddr,
+                              uint64_t asc, uint64_t asce, target_ulong *raddr,
+                              int *flags, int rw)
+{
+    if (asce & _SEGMENT_ENTRY_INV) {
+        DPRINTF("%s: SEG=0x%" PRIx64 " invalid\n", __func__, asce);
+        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
+        return -1;
+    }
+
+    if (asce & _SEGMENT_ENTRY_RO) {
+        *flags &= ~PAGE_WRITE;
+    }
+
+    *raddr = (asce & 0xfffffffffff00000ULL) | (vaddr & 0xfffff);
+
+    PTE_DPRINTF("%s: SEG=0x%" PRIx64 "\n", __func__, asce);
+
+    return 0;
+}
+
+static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
+                              uint64_t asc, uint64_t asce, int level,
+                              target_ulong *raddr, int *flags, int rw)
+{
+    CPUState *cs = CPU(s390_env_get_cpu(env));
+    uint64_t offs = 0;
+    uint64_t origin;
+    uint64_t new_asce;
+
+    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);
+
+    if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||
+        ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {
+        /* XXX different regions have different faults */
+        DPRINTF("%s: invalid region\n", __func__);
+        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
+        return -1;
+    }
+
+    if ((level <= _ASCE_TYPE_MASK) && ((asce & _ASCE_TYPE_MASK) != level)) {
+        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+        return -1;
+    }
+
+    if (asce & _ASCE_REAL_SPACE) {
+        /* direct mapping */
+
+        *raddr = vaddr;
+        return 0;
+    }
+
+    origin = asce & _ASCE_ORIGIN;
+
+    switch (level) {
+    case _ASCE_TYPE_REGION1 + 4:
+        offs = (vaddr >> 50) & 0x3ff8;
+        break;
+    case _ASCE_TYPE_REGION1:
+        offs = (vaddr >> 39) & 0x3ff8;
+        break;
+    case _ASCE_TYPE_REGION2:
+        offs = (vaddr >> 28) & 0x3ff8;
+        break;
+    case _ASCE_TYPE_REGION3:
+        offs = (vaddr >> 17) & 0x3ff8;
+        break;
+    case _ASCE_TYPE_SEGMENT:
+        offs = (vaddr >> 9) & 0x07f8;
+        origin = asce & _SEGMENT_ENTRY_ORIGIN;
+        break;
+    }
+
+    /* XXX region protection flags */
+    /* *flags &= ~PAGE_WRITE */
+
+    new_asce = ldq_phys(cs->as, origin + offs);
+    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
+                __func__, origin, offs, new_asce);
+
+    if (level == _ASCE_TYPE_SEGMENT) {
+        /* 4KB page */
+        return mmu_translate_pte(env, vaddr, asc, new_asce, raddr, flags, rw);
+    } else if (level - 4 == _ASCE_TYPE_SEGMENT &&
+               (new_asce & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
+        /* 1MB page */
+        return mmu_translate_sfaa(env, vaddr, asc, new_asce, raddr, flags, rw);
+    } else {
+        /* yet another region */
+        return mmu_translate_asce(env, vaddr, asc, new_asce, level - 4, raddr,
+                                  flags, rw);
+    }
+}
+
+static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
+                             uint64_t asc, target_ulong *raddr, int *flags,
+                             int rw)
+{
+    uint64_t asce = 0;
+    int level, new_level;
+    int r;
+
+    switch (asc) {
+    case PSW_ASC_PRIMARY:
+        PTE_DPRINTF("%s: asc=primary\n", __func__);
+        asce = env->cregs[1];
+        break;
+    case PSW_ASC_SECONDARY:
+        PTE_DPRINTF("%s: asc=secondary\n", __func__);
+        asce = env->cregs[7];
+        break;
+    case PSW_ASC_HOME:
+        PTE_DPRINTF("%s: asc=home\n", __func__);
+        asce = env->cregs[13];
+        break;
+    }
+
+    switch (asce & _ASCE_TYPE_MASK) {
+    case _ASCE_TYPE_REGION1:
+        break;
+    case _ASCE_TYPE_REGION2:
+        if (vaddr & 0xffe0000000000000ULL) {
+            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
+                    " 0xffe0000000000000ULL\n", __func__, vaddr);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            return -1;
+        }
+        break;
+    case _ASCE_TYPE_REGION3:
+        if (vaddr & 0xfffffc0000000000ULL) {
+            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
+                    " 0xfffffc0000000000ULL\n", __func__, vaddr);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            return -1;
+        }
+        break;
+    case _ASCE_TYPE_SEGMENT:
+        if (vaddr & 0xffffffff80000000ULL) {
+            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
+                    " 0xffffffff80000000ULL\n", __func__, vaddr);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            return -1;
+        }
+        break;
+    }
+
+    /* fake level above current */
+    level = asce & _ASCE_TYPE_MASK;
+    new_level = level + 4;
+    asce = (asce & ~_ASCE_TYPE_MASK) | (new_level & _ASCE_TYPE_MASK);
+
+    r = mmu_translate_asce(env, vaddr, asc, asce, new_level, raddr, flags, rw);
+
+    if ((rw == 1) && !(*flags & PAGE_WRITE)) {
+        trigger_prot_fault(env, vaddr, asc);
+        return -1;
+    }
+
+    return r;
+}
+
+int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
+                  target_ulong *raddr, int *flags)
+{
+    int r = -1;
+    uint8_t *sk;
+
+    *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+    vaddr &= TARGET_PAGE_MASK;
+
+    if (!(env->psw.mask & PSW_MASK_DAT)) {
+        *raddr = vaddr;
+        r = 0;
+        goto out;
+    }
+
+    switch (asc) {
+    case PSW_ASC_PRIMARY:
+    case PSW_ASC_HOME:
+        r = mmu_translate_asc(env, vaddr, asc, raddr, flags, rw);
+        break;
+    case PSW_ASC_SECONDARY:
+        /*
+         * Instruction: Primary
+         * Data: Secondary
+         */
+        if (rw == 2) {
+            r = mmu_translate_asc(env, vaddr, PSW_ASC_PRIMARY, raddr, flags,
+                                  rw);
+            *flags &= ~(PAGE_READ | PAGE_WRITE);
+        } else {
+            r = mmu_translate_asc(env, vaddr, PSW_ASC_SECONDARY, raddr, flags,
+                                  rw);
+            *flags &= ~(PAGE_EXEC);
+        }
+        break;
+    case PSW_ASC_ACCREG:
+    default:
+        hw_error("guest switched to unknown asc mode\n");
+        break;
+    }
+
+ out:
+    /* Convert real address -> absolute address */
+    *raddr = mmu_real2abs(env, *raddr);
+
+    if (*raddr <= ram_size) {
+        sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
+        if (*flags & PAGE_READ) {
+            *sk |= SK_R;
+        }
+
+        if (*flags & PAGE_WRITE) {
+            *sk |= SK_C;
+        }
+    }
+
+    return r;
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 02/25] s390x/mmu: Fix the check for the real-space designation bit
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 03/25] s390x/mmu: Fix the handling of the table levels Jens Freimann
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The real-space designation bits live in the ASCEs, not in the table entries,
so the check must be done before we start walking the MMU table.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/mmu_helper.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index fc4f7c5..c845cd4 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -180,13 +180,6 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
         return -1;
     }
 
-    if (asce & _ASCE_REAL_SPACE) {
-        /* direct mapping */
-
-        *raddr = vaddr;
-        return 0;
-    }
-
     origin = asce & _ASCE_ORIGIN;
 
     switch (level) {
@@ -252,6 +245,12 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         break;
     }
 
+    if (asce & _ASCE_REAL_SPACE) {
+        /* direct mapping */
+        *raddr = vaddr;
+        return 0;
+    }
+
     switch (asce & _ASCE_TYPE_MASK) {
     case _ASCE_TYPE_REGION1:
         break;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 03/25] s390x/mmu: Fix the handling of the table levels
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 02/25] s390x/mmu: Fix the check for the real-space designation bit Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 04/25] s390x/mmu: Check table length and offset fields Jens Freimann
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The current code used a wrong and very confusing way of dealing with
the table levels by introducing a "fake level above current". However,
the real problem was simply that the checks for the region/segment
invalid bit and for the matching region/segment level was done at the
wrong spot in the code - it has to be done after the first table entry
has been looked up instead (e.g. there is also no "invalid" bit in the
ASCE itself and the current "level" has to be the same as the level in
the entry that we just looked up).
Also the entries for the segment table are quite a bit different compared
to the region table entries. So this patch moves the related code into the
function mmu_translate_segment() to make it clear at which table level we
currently are and to get rid of the ugly switch-statement in the function
mmu_translate_region().

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 target-s390x/mmu_helper.c | 115 +++++++++++++++++++---------------------------
 1 file changed, 47 insertions(+), 68 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index c845cd4..01d819e 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -134,92 +134,76 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
     return 0;
 }
 
-/* Decode EDAT1 segment frame absolute address (1MB page) */
-static int mmu_translate_sfaa(CPUS390XState *env, target_ulong vaddr,
-                              uint64_t asc, uint64_t asce, target_ulong *raddr,
-                              int *flags, int rw)
+#define VADDR_PX    0xff000         /* Page index bits */
+
+/* Decode segment table entry */
+static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr,
+                                 uint64_t asc, uint64_t st_entry,
+                                 target_ulong *raddr, int *flags, int rw)
 {
-    if (asce & _SEGMENT_ENTRY_INV) {
-        DPRINTF("%s: SEG=0x%" PRIx64 " invalid\n", __func__, asce);
-        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
-        return -1;
-    }
+    CPUState *cs = CPU(s390_env_get_cpu(env));
+    uint64_t origin, offs, pt_entry;
 
-    if (asce & _SEGMENT_ENTRY_RO) {
+    if (st_entry & _SEGMENT_ENTRY_RO) {
         *flags &= ~PAGE_WRITE;
     }
 
-    *raddr = (asce & 0xfffffffffff00000ULL) | (vaddr & 0xfffff);
-
-    PTE_DPRINTF("%s: SEG=0x%" PRIx64 "\n", __func__, asce);
+    if ((st_entry & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
+        /* Decode EDAT1 segment frame absolute address (1MB page) */
+        *raddr = (st_entry & 0xfffffffffff00000ULL) | (vaddr & 0xfffff);
+        PTE_DPRINTF("%s: SEG=0x%" PRIx64 "\n", __func__, st_entry);
+        return 0;
+    }
 
-    return 0;
+    /* Look up 4KB page entry */
+    origin = st_entry & _SEGMENT_ENTRY_ORIGIN;
+    offs  = (vaddr & VADDR_PX) >> 9;
+    pt_entry = ldq_phys(cs->as, origin + offs);
+    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
+                __func__, origin, offs, pt_entry);
+    return mmu_translate_pte(env, vaddr, asc, pt_entry, raddr, flags, rw);
 }
 
-static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
-                              uint64_t asc, uint64_t asce, int level,
-                              target_ulong *raddr, int *flags, int rw)
+/* Decode region table entries */
+static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
+                                uint64_t asc, uint64_t entry, int level,
+                                target_ulong *raddr, int *flags, int rw)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
-    uint64_t offs = 0;
-    uint64_t origin;
-    uint64_t new_asce;
+    uint64_t origin, offs, new_entry;
+
+    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, entry);
 
-    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);
+    origin = entry & _REGION_ENTRY_ORIGIN;
+    offs = (vaddr >> (17 + 11 * level / 4)) & 0x3ff8;
+
+    new_entry = ldq_phys(cs->as, origin + offs);
+    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
+                __func__, origin, offs, new_entry);
 
-    if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||
-        ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {
+    if ((new_entry & _REGION_ENTRY_INV) != 0) {
         /* XXX different regions have different faults */
         DPRINTF("%s: invalid region\n", __func__);
         trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
         return -1;
     }
 
-    if ((level <= _ASCE_TYPE_MASK) && ((asce & _ASCE_TYPE_MASK) != level)) {
+    if ((new_entry & _REGION_ENTRY_TYPE_MASK) != level) {
         trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
         return -1;
     }
 
-    origin = asce & _ASCE_ORIGIN;
-
-    switch (level) {
-    case _ASCE_TYPE_REGION1 + 4:
-        offs = (vaddr >> 50) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION1:
-        offs = (vaddr >> 39) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION2:
-        offs = (vaddr >> 28) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_REGION3:
-        offs = (vaddr >> 17) & 0x3ff8;
-        break;
-    case _ASCE_TYPE_SEGMENT:
-        offs = (vaddr >> 9) & 0x07f8;
-        origin = asce & _SEGMENT_ENTRY_ORIGIN;
-        break;
-    }
-
     /* XXX region protection flags */
     /* *flags &= ~PAGE_WRITE */
 
-    new_asce = ldq_phys(cs->as, origin + offs);
-    PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
-                __func__, origin, offs, new_asce);
-
     if (level == _ASCE_TYPE_SEGMENT) {
-        /* 4KB page */
-        return mmu_translate_pte(env, vaddr, asc, new_asce, raddr, flags, rw);
-    } else if (level - 4 == _ASCE_TYPE_SEGMENT &&
-               (new_asce & _SEGMENT_ENTRY_FC) && (env->cregs[0] & CR0_EDAT)) {
-        /* 1MB page */
-        return mmu_translate_sfaa(env, vaddr, asc, new_asce, raddr, flags, rw);
-    } else {
-        /* yet another region */
-        return mmu_translate_asce(env, vaddr, asc, new_asce, level - 4, raddr,
-                                  flags, rw);
+        return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,
+                                     rw);
     }
+
+    /* yet another region */
+    return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,
+                                raddr, flags, rw);
 }
 
 static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
@@ -227,7 +211,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
                              int rw)
 {
     uint64_t asce = 0;
-    int level, new_level;
+    int level;
     int r;
 
     switch (asc) {
@@ -251,7 +235,8 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         return 0;
     }
 
-    switch (asce & _ASCE_TYPE_MASK) {
+    level = asce & _ASCE_TYPE_MASK;
+    switch (level) {
     case _ASCE_TYPE_REGION1:
         break;
     case _ASCE_TYPE_REGION2:
@@ -280,13 +265,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         break;
     }
 
-    /* fake level above current */
-    level = asce & _ASCE_TYPE_MASK;
-    new_level = level + 4;
-    asce = (asce & ~_ASCE_TYPE_MASK) | (new_level & _ASCE_TYPE_MASK);
-
-    r = mmu_translate_asce(env, vaddr, asc, asce, new_level, raddr, flags, rw);
-
+    r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw);
     if ((rw == 1) && !(*flags & PAGE_WRITE)) {
         trigger_prot_fault(env, vaddr, asc);
         return -1;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 04/25] s390x/mmu: Check table length and offset fields
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (2 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 03/25] s390x/mmu: Fix the handling of the table levels Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 05/25] s390x/mmu: Skip exceptions properly when translating addresses for debug Jens Freimann
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The ACSEs have a table length field and the region entries have
table length and offset fields which must be checked during
translation to see whether the given virtual address is really
covered by the translation table.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 target-s390x/cpu.h        |  1 +
 target-s390x/mmu_helper.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 95d0f3b..5563042 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -837,6 +837,7 @@ struct sysib_322 {
 #define _ASCE_TABLE_LENGTH      0x03      /* region table length              */
 
 #define _REGION_ENTRY_ORIGIN    ~0xfffULL /* region/segment table origin      */
+#define _REGION_ENTRY_TF        0xc0      /* region/segment table offset      */
 #define _REGION_ENTRY_INV       0x20      /* invalid region table entry       */
 #define _REGION_ENTRY_TYPE_MASK 0x0c      /* region/segment table type mask   */
 #define _REGION_ENTRY_TYPE_R1   0x0c      /* region first table type          */
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 01d819e..d4087ba 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -171,6 +171,10 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     uint64_t origin, offs, new_entry;
+    const int pchks[4] = {
+        PGM_SEGMENT_TRANS, PGM_REG_THIRD_TRANS,
+        PGM_REG_SEC_TRANS, PGM_REG_FIRST_TRANS
+    };
 
     PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, entry);
 
@@ -201,6 +205,15 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
                                      rw);
     }
 
+    /* Check region table offset and length */
+    offs = (vaddr >> (28 + 11 * (level - 4) / 4)) & 3;
+    if (offs < ((new_entry & _REGION_ENTRY_TF) >> 6)
+        || offs > (new_entry & _REGION_ENTRY_LENGTH)) {
+        DPRINTF("%s: invalid offset or len (%lx)\n", __func__, new_entry);
+        trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw);
+        return -1;
+    }
+
     /* yet another region */
     return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,
                                 raddr, flags, rw);
@@ -238,6 +251,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
     level = asce & _ASCE_TYPE_MASK;
     switch (level) {
     case _ASCE_TYPE_REGION1:
+        if ((vaddr >> 62) > (asce & _ASCE_TABLE_LENGTH)) {
+            trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw);
+            return -1;
+        }
         break;
     case _ASCE_TYPE_REGION2:
         if (vaddr & 0xffe0000000000000ULL) {
@@ -246,6 +263,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
+        if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
+            trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw);
+            return -1;
+        }
         break;
     case _ASCE_TYPE_REGION3:
         if (vaddr & 0xfffffc0000000000ULL) {
@@ -254,6 +275,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
+        if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
+            trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw);
+            return -1;
+        }
         break;
     case _ASCE_TYPE_SEGMENT:
         if (vaddr & 0xffffffff80000000ULL) {
@@ -262,6 +287,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
+        if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
+            trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
+            return -1;
+        }
         break;
     }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 05/25] s390x/mmu: Skip exceptions properly when translating addresses for debug
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (3 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 04/25] s390x/mmu: Check table length and offset fields Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 06/25] s390x/mmu: Fix translation exception code in lowcore Jens Freimann
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

When a fault occurs during the MMU lookup in s390_cpu_get_phys_page_debug(),
the trigger_page_fault() function writes the translation exception code
into the lowcore - something you would not expect during a memory access
by the debugger. Ease this problem by adding an additional parameter to
mmu_translate() which can be used to specify whether a program check and
the translation exception code should be injected or not.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 target-s390x/cpu.h        |  2 +-
 target-s390x/helper.c     |  8 ++---
 target-s390x/mem_helper.c | 12 ++++----
 target-s390x/mmu_helper.c | 77 ++++++++++++++++++++++++++++++-----------------
 4 files changed, 59 insertions(+), 40 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 5563042..c0016b6 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -885,7 +885,7 @@ struct sysib_322 {
 
 void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
 int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
-                  target_ulong *raddr, int *flags);
+                  target_ulong *raddr, int *flags, bool exc);
 int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
 uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
                  uint64_t vr);
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 76b4b36..f8a3c5a 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -127,7 +127,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
         vaddr &= 0x7fffffff;
     }
 
-    if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot)) {
+    if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) {
         /* Translation ended in exception */
         return 1;
     }
@@ -154,8 +154,7 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
     S390CPU *cpu = S390_CPU(cs);
     CPUS390XState *env = &cpu->env;
     target_ulong raddr;
-    int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-    int old_exc = cs->exception_index;
+    int prot;
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
 
     /* 31-Bit mode */
@@ -163,8 +162,7 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
         vaddr &= 0x7fffffff;
     }
 
-    mmu_translate(env, vaddr, 2, asc, &raddr, &prot);
-    cs->exception_index = old_exc;
+    mmu_translate(env, vaddr, 2, asc, &raddr, &prot, false);
 
     return raddr;
 }
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index d67b345..0e8cd0f 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -65,7 +65,7 @@ static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
     int flags;
 
-    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
+    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags, true)) {
         cpu_stb_data(env, dest, byte);
         cpu_abort(CPU(cpu), "should never reach here");
     }
@@ -90,13 +90,13 @@ static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
     int flags;
 
-    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
+    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags, true)) {
         cpu_stb_data(env, dest, 0);
         cpu_abort(CPU(cpu), "should never reach here");
     }
     dest_phys |= dest & ~TARGET_PAGE_MASK;
 
-    if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
+    if (mmu_translate(env, src, 0, asc, &src_phys, &flags, true)) {
         cpu_ldub_data(env, src);
         cpu_abort(CPU(cpu), "should never reach here");
     }
@@ -967,12 +967,12 @@ static uint32_t mvc_asc(CPUS390XState *env, int64_t l, uint64_t a1,
         cc = 3;
     }
 
-    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
+    if (mmu_translate(env, a1, 1, mode1, &dest, &flags, true)) {
         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
     }
     dest |= a1 & ~TARGET_PAGE_MASK;
 
-    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
+    if (mmu_translate(env, a2, 0, mode2, &src, &flags, true)) {
         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
     }
     src |= a2 & ~TARGET_PAGE_MASK;
@@ -1088,7 +1088,7 @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
     }
 
     cs->exception_index = old_exc;
-    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
+    if (mmu_translate(env, addr, 0, asc, &ret, &flags, true)) {
         cc = 3;
     }
     if (cs->exception_index == EXCP_PGM) {
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index d4087ba..67ad3cc 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -66,7 +66,7 @@ static int trans_bits(CPUS390XState *env, uint64_t mode)
 }
 
 static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
-                               uint64_t mode)
+                               uint64_t mode, bool exc)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     int ilen = ILEN_LATER_INC;
@@ -74,25 +74,33 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
 
     DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
+    if (!exc) {
+        return;
+    }
+
     stq_phys(cs->as,
              env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
     trigger_pgm_exception(env, PGM_PROTECTION, ilen);
 }
 
 static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
-                               uint32_t type, uint64_t asc, int rw)
+                               uint32_t type, uint64_t asc, int rw, bool exc)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     int ilen = ILEN_LATER;
     int bits = trans_bits(env, asc);
 
+    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
+
+    if (!exc) {
+        return;
+    }
+
     /* Code accesses have an undefined ilc.  */
     if (rw == 2) {
         ilen = 2;
     }
 
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
-
     stq_phys(cs->as,
              env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
     trigger_pgm_exception(env, type, ilen);
@@ -115,11 +123,11 @@ static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
 /* Decode page table entry (normal 4KB page) */
 static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
                              uint64_t asc, uint64_t asce,
-                             target_ulong *raddr, int *flags, int rw)
+                             target_ulong *raddr, int *flags, int rw, bool exc)
 {
     if (asce & _PAGE_INVALID) {
         DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, asce);
-        trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw);
+        trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw, exc);
         return -1;
     }
 
@@ -139,7 +147,8 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
 /* Decode segment table entry */
 static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr,
                                  uint64_t asc, uint64_t st_entry,
-                                 target_ulong *raddr, int *flags, int rw)
+                                 target_ulong *raddr, int *flags, int rw,
+                                 bool exc)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     uint64_t origin, offs, pt_entry;
@@ -161,13 +170,14 @@ static int mmu_translate_segment(CPUS390XState *env, target_ulong vaddr,
     pt_entry = ldq_phys(cs->as, origin + offs);
     PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
                 __func__, origin, offs, pt_entry);
-    return mmu_translate_pte(env, vaddr, asc, pt_entry, raddr, flags, rw);
+    return mmu_translate_pte(env, vaddr, asc, pt_entry, raddr, flags, rw, exc);
 }
 
 /* Decode region table entries */
 static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
                                 uint64_t asc, uint64_t entry, int level,
-                                target_ulong *raddr, int *flags, int rw)
+                                target_ulong *raddr, int *flags, int rw,
+                                bool exc)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     uint64_t origin, offs, new_entry;
@@ -188,12 +198,12 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
     if ((new_entry & _REGION_ENTRY_INV) != 0) {
         /* XXX different regions have different faults */
         DPRINTF("%s: invalid region\n", __func__);
-        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
+        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);
         return -1;
     }
 
     if ((new_entry & _REGION_ENTRY_TYPE_MASK) != level) {
-        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
         return -1;
     }
 
@@ -202,7 +212,7 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
 
     if (level == _ASCE_TYPE_SEGMENT) {
         return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,
-                                     rw);
+                                     rw, exc);
     }
 
     /* Check region table offset and length */
@@ -210,18 +220,18 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
     if (offs < ((new_entry & _REGION_ENTRY_TF) >> 6)
         || offs > (new_entry & _REGION_ENTRY_LENGTH)) {
         DPRINTF("%s: invalid offset or len (%lx)\n", __func__, new_entry);
-        trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw);
+        trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw, exc);
         return -1;
     }
 
     /* yet another region */
     return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,
-                                raddr, flags, rw);
+                                raddr, flags, rw, exc);
 }
 
 static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
                              uint64_t asc, target_ulong *raddr, int *flags,
-                             int rw)
+                             int rw, bool exc)
 {
     uint64_t asce = 0;
     int level;
@@ -252,7 +262,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
     switch (level) {
     case _ASCE_TYPE_REGION1:
         if ((vaddr >> 62) > (asce & _ASCE_TABLE_LENGTH)) {
-            trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw, exc);
             return -1;
         }
         break;
@@ -260,11 +270,11 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xffe0000000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xffe0000000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
-            trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw, exc);
             return -1;
         }
         break;
@@ -272,11 +282,11 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xfffffc0000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xfffffc0000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
-            trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw, exc);
             return -1;
         }
         break;
@@ -284,27 +294,38 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xffffffff80000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xffffffff80000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
-            trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
+            trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);
             return -1;
         }
         break;
     }
 
-    r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw);
+    r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
+                             exc);
     if ((rw == 1) && !(*flags & PAGE_WRITE)) {
-        trigger_prot_fault(env, vaddr, asc);
+        trigger_prot_fault(env, vaddr, asc, exc);
         return -1;
     }
 
     return r;
 }
 
+/**
+ * Translate a virtual (logical) address into a physical (absolute) address.
+ * @param vaddr  the virtual address
+ * @param rw     0 = read, 1 = write, 2 = code fetch
+ * @param asc    address space control (one of the PSW_ASC_* modes)
+ * @param raddr  the translated address is stored to this pointer
+ * @param flags  the PAGE_READ/WRITE/EXEC flags are stored to this pointer
+ * @param exc    true = inject a program check if a fault occured
+ * @return       0 if the translation was successfull, -1 if a fault occured
+ */
 int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
-                  target_ulong *raddr, int *flags)
+                  target_ulong *raddr, int *flags, bool exc)
 {
     int r = -1;
     uint8_t *sk;
@@ -321,7 +342,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
     switch (asc) {
     case PSW_ASC_PRIMARY:
     case PSW_ASC_HOME:
-        r = mmu_translate_asc(env, vaddr, asc, raddr, flags, rw);
+        r = mmu_translate_asc(env, vaddr, asc, raddr, flags, rw, exc);
         break;
     case PSW_ASC_SECONDARY:
         /*
@@ -330,11 +351,11 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
          */
         if (rw == 2) {
             r = mmu_translate_asc(env, vaddr, PSW_ASC_PRIMARY, raddr, flags,
-                                  rw);
+                                  rw, exc);
             *flags &= ~(PAGE_READ | PAGE_WRITE);
         } else {
             r = mmu_translate_asc(env, vaddr, PSW_ASC_SECONDARY, raddr, flags,
-                                  rw);
+                                  rw, exc);
             *flags &= ~(PAGE_EXEC);
         }
         break;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 06/25] s390x/mmu: Fix translation exception code in lowcore
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (4 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 05/25] s390x/mmu: Skip exceptions properly when translating addresses for debug Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 07/25] s390x/mmu: Fix exception types when checking the ASCEs Jens Freimann
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The address space bits in the translation exception code were wrong.
In fact, we can simply copy the bits from the PSW, so there's no need
for the trans_bits() function anymore.
Additionally, we now also set the fetch/store bits in the translation
exception code, so a guest can determine whether the exception occured
during a write or during a read.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/mmu_helper.c | 48 +++++++++++++++--------------------------------
 1 file changed, 15 insertions(+), 33 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 67ad3cc..109a2d3 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -42,45 +42,26 @@
     do { } while (0)
 #endif
 
-static int trans_bits(CPUS390XState *env, uint64_t mode)
-{
-    S390CPU *cpu = s390_env_get_cpu(env);
-    int bits = 0;
-
-    switch (mode) {
-    case PSW_ASC_PRIMARY:
-        bits = 1;
-        break;
-    case PSW_ASC_SECONDARY:
-        bits = 2;
-        break;
-    case PSW_ASC_HOME:
-        bits = 3;
-        break;
-    default:
-        cpu_abort(CPU(cpu), "unknown asc mode\n");
-        break;
-    }
-
-    return bits;
-}
+/* Fetch/store bits in the translation exception code: */
+#define FS_READ  0x800
+#define FS_WRITE 0x400
 
 static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
-                               uint64_t mode, bool exc)
+                               uint64_t asc, int rw, bool exc)
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
-    int ilen = ILEN_LATER_INC;
-    int bits = trans_bits(env, mode) | 4;
+    uint64_t tec;
 
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
+    tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | 4 | asc >> 46;
+
+    DPRINTF("%s: trans_exc_code=%016" PRIx64 "\n", __func__, tec);
 
     if (!exc) {
         return;
     }
 
-    stq_phys(cs->as,
-             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
-    trigger_pgm_exception(env, PGM_PROTECTION, ilen);
+    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
+    trigger_pgm_exception(env, PGM_PROTECTION, ILEN_LATER_INC);
 }
 
 static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
@@ -88,7 +69,9 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
 {
     CPUState *cs = CPU(s390_env_get_cpu(env));
     int ilen = ILEN_LATER;
-    int bits = trans_bits(env, asc);
+    uint64_t tec;
+
+    tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | asc >> 46;
 
     DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
@@ -101,8 +84,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
         ilen = 2;
     }
 
-    stq_phys(cs->as,
-             env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
+    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
     trigger_pgm_exception(env, type, ilen);
 }
 
@@ -307,7 +289,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
     r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,
                              exc);
     if ((rw == 1) && !(*flags & PAGE_WRITE)) {
-        trigger_prot_fault(env, vaddr, asc, exc);
+        trigger_prot_fault(env, vaddr, asc, rw, exc);
         return -1;
     }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 07/25] s390x/mmu: Fix exception types when checking the ASCEs
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (5 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 06/25] s390x/mmu: Fix translation exception code in lowcore Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 08/25] s390x/mmu: Fix the exception codes for illegal table entries Jens Freimann
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

If an ASCE has illegal bits set, an ASCE-type exception should be
generated instead of a translation specification exception.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/mmu_helper.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 109a2d3..f9eaf07 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -252,7 +252,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xffe0000000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xffe0000000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
+            trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
@@ -264,7 +264,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xfffffc0000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xfffffc0000000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
+            trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
@@ -276,7 +276,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
         if (vaddr & 0xffffffff80000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
                     " 0xffffffff80000000ULL\n", __func__, vaddr);
-            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
+            trigger_page_fault(env, vaddr, PGM_ASCE_TYPE, asc, rw, exc);
             return -1;
         }
         if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 08/25] s390x/mmu: Fix the exception codes for illegal table entries
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (6 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 07/25] s390x/mmu: Fix exception types when checking the ASCEs Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 09/25] s390x/mmu: Add support for read-only regions Jens Freimann
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Each different level of region/segment table has a dedicated
exception type for illegal entries.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/mmu_helper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index f9eaf07..0c53ae9 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -178,9 +178,8 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
                 __func__, origin, offs, new_entry);
 
     if ((new_entry & _REGION_ENTRY_INV) != 0) {
-        /* XXX different regions have different faults */
         DPRINTF("%s: invalid region\n", __func__);
-        trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);
+        trigger_page_fault(env, vaddr, pchks[level / 4], asc, rw, exc);
         return -1;
     }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 09/25] s390x/mmu: Add support for read-only regions
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (7 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 08/25] s390x/mmu: Fix the exception codes for illegal table entries Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 10/25] s390x/mmu: Renaming related to the ASCE confusion Jens Freimann
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

If the "DAT-protection" bit is set in the region table entry and EDAT is
enabled, only read accesses are allowed in the corresponding memory area.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/cpu.h        | 1 +
 target-s390x/mmu_helper.c | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c0016b6..08cdb15 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -837,6 +837,7 @@ struct sysib_322 {
 #define _ASCE_TABLE_LENGTH      0x03      /* region table length              */
 
 #define _REGION_ENTRY_ORIGIN    ~0xfffULL /* region/segment table origin      */
+#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       */
 #define _REGION_ENTRY_TYPE_MASK 0x0c      /* region/segment table type mask   */
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 0c53ae9..702e8b8 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -188,9 +188,6 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
         return -1;
     }
 
-    /* XXX region protection flags */
-    /* *flags &= ~PAGE_WRITE */
-
     if (level == _ASCE_TYPE_SEGMENT) {
         return mmu_translate_segment(env, vaddr, asc, new_entry, raddr, flags,
                                      rw, exc);
@@ -205,6 +202,10 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
         return -1;
     }
 
+    if ((env->cregs[0] & CR0_EDAT) && (new_entry & _REGION_ENTRY_RO)) {
+        *flags &= ~PAGE_WRITE;
+    }
+
     /* yet another region */
     return mmu_translate_region(env, vaddr, asc, new_entry, level - 4,
                                 raddr, flags, rw, exc);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 10/25] s390x/mmu: Renaming related to the ASCE confusion
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (8 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 09/25] s390x/mmu: Add support for read-only regions Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 11/25] s390x/mmu: Check bit 52 in page table entry Jens Freimann
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

An Address Space Control Element (ASCE) is only the very first unit of
an s390 address translation (normally residing in one of the control
registers). The entries in the page tables are called differently.
So let's call the relevant variable pt_entry instead of asce in
mmu_translate_pte() to avoid future confusion (thus there is no
functional change in this patch, just renaming).

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/mmu_helper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 702e8b8..7dc9900 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -104,22 +104,22 @@ static target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr)
 
 /* Decode page table entry (normal 4KB page) */
 static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
-                             uint64_t asc, uint64_t asce,
+                             uint64_t asc, uint64_t pt_entry,
                              target_ulong *raddr, int *flags, int rw, bool exc)
 {
-    if (asce & _PAGE_INVALID) {
-        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, asce);
+    if (pt_entry & _PAGE_INVALID) {
+        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, pt_entry);
         trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw, exc);
         return -1;
     }
 
-    if (asce & _PAGE_RO) {
+    if (pt_entry & _PAGE_RO) {
         *flags &= ~PAGE_WRITE;
     }
 
-    *raddr = asce & _ASCE_ORIGIN;
+    *raddr = pt_entry & _ASCE_ORIGIN;
 
-    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, asce);
+    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, pt_entry);
 
     return 0;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 11/25] s390x/mmu: Check bit 52 in page table entry
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (9 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 10/25] s390x/mmu: Renaming related to the ASCE confusion Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 12/25] s390x/mmu: Clean up mmu_translate_asc() Jens Freimann
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Bit 52 in a page table entry has always to be zero, or a translation
specification exception is to be recognized.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/cpu.h        | 1 +
 target-s390x/mmu_helper.c | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 08cdb15..c24ca5f 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -853,6 +853,7 @@ struct sysib_322 {
 
 #define _PAGE_RO        0x200            /* HW read-only bit  */
 #define _PAGE_INVALID   0x400            /* HW invalid bit    */
+#define _PAGE_RES0      0x800            /* bit must be zero  */
 
 #define SK_C                    (0x1 << 1)
 #define SK_R                    (0x1 << 2)
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 7dc9900..c183958 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -112,7 +112,10 @@ static int mmu_translate_pte(CPUS390XState *env, target_ulong vaddr,
         trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw, exc);
         return -1;
     }
-
+    if (pt_entry & _PAGE_RES0) {
+        trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);
+        return -1;
+    }
     if (pt_entry & _PAGE_RO) {
         *flags &= ~PAGE_WRITE;
     }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 12/25] s390x/mmu: Clean up mmu_translate_asc()
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (10 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 11/25] s390x/mmu: Check bit 52 in page table entry Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 13/25] s390x/kvm: Add function for injecting pgm access exceptions Jens Freimann
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

We can get rid of the switch(asc) in mmu_translate_asc() by simply
selecting the right control register ASCE in the mmu_translate()
function already.
This patch is based on an original patch/idea by Ralf Hoppe.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/mmu_helper.c | 39 +++++++++++++++------------------------
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index c183958..32a51f3 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -214,29 +214,13 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr,
                                 raddr, flags, rw, exc);
 }
 
-static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
-                             uint64_t asc, target_ulong *raddr, int *flags,
-                             int rw, bool exc)
+static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
+                              uint64_t asc, uint64_t asce, target_ulong *raddr,
+                              int *flags, int rw, bool exc)
 {
-    uint64_t asce = 0;
     int level;
     int r;
 
-    switch (asc) {
-    case PSW_ASC_PRIMARY:
-        PTE_DPRINTF("%s: asc=primary\n", __func__);
-        asce = env->cregs[1];
-        break;
-    case PSW_ASC_SECONDARY:
-        PTE_DPRINTF("%s: asc=secondary\n", __func__);
-        asce = env->cregs[7];
-        break;
-    case PSW_ASC_HOME:
-        PTE_DPRINTF("%s: asc=home\n", __func__);
-        asce = env->cregs[13];
-        break;
-    }
-
     if (asce & _ASCE_REAL_SPACE) {
         /* direct mapping */
         *raddr = vaddr;
@@ -326,21 +310,28 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
 
     switch (asc) {
     case PSW_ASC_PRIMARY:
+        PTE_DPRINTF("%s: asc=primary\n", __func__);
+        r = mmu_translate_asce(env, vaddr, asc, env->cregs[1], raddr, flags,
+                               rw, exc);
+        break;
     case PSW_ASC_HOME:
-        r = mmu_translate_asc(env, vaddr, asc, raddr, flags, rw, exc);
+        PTE_DPRINTF("%s: asc=home\n", __func__);
+        r = mmu_translate_asce(env, vaddr, asc, env->cregs[13], raddr, flags,
+                               rw, exc);
         break;
     case PSW_ASC_SECONDARY:
+        PTE_DPRINTF("%s: asc=secondary\n", __func__);
         /*
          * Instruction: Primary
          * Data: Secondary
          */
         if (rw == 2) {
-            r = mmu_translate_asc(env, vaddr, PSW_ASC_PRIMARY, raddr, flags,
-                                  rw, exc);
+            r = mmu_translate_asce(env, vaddr, PSW_ASC_PRIMARY, env->cregs[1],
+                                   raddr, flags, rw, exc);
             *flags &= ~(PAGE_READ | PAGE_WRITE);
         } else {
-            r = mmu_translate_asc(env, vaddr, PSW_ASC_SECONDARY, raddr, flags,
-                                  rw, exc);
+            r = mmu_translate_asce(env, vaddr, PSW_ASC_SECONDARY, env->cregs[7],
+                                   raddr, flags, rw, exc);
             *flags &= ~(PAGE_EXEC);
         }
         break;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 13/25] s390x/kvm: Add function for injecting pgm access exceptions
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (11 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 12/25] s390x/mmu: Clean up mmu_translate_asc() Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 14/25] s390x/mmu: Add function for accessing guest memory Jens Freimann
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Program access exceptions are defined to deliver a translation exception
code in the low-core. Add a function trigger_access_exception() that
generates the proper program interrupt on both KVM and non-KVM systems
and switch the existing code to use it.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/cpu.h        |  5 +++++
 target-s390x/kvm.c        | 12 ++++++++++++
 target-s390x/mmu_helper.c | 22 ++++++++++++++++------
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index c24ca5f..f8cea30 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -397,6 +397,7 @@ void kvm_s390_service_interrupt(uint32_t parm);
 void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
 void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
 int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
 #else
 static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
 {
@@ -404,6 +405,10 @@ static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
 static inline void kvm_s390_service_interrupt(uint32_t parm)
 {
 }
+static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
+                                             uint64_t te_code)
+{
+}
 #endif
 S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
 unsigned int s390_cpu_halt(S390CPU *cpu);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 6f2d5b4..a9a4c64 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -756,6 +756,18 @@ static void enter_pgmcheck(S390CPU *cpu, uint16_t code)
     kvm_s390_vcpu_interrupt(cpu, &irq);
 }
 
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
+{
+    struct kvm_s390_irq irq = {
+        .type = KVM_S390_PROGRAM_INT,
+        .u.pgm.code = code,
+        .u.pgm.trans_exc_code = te_code,
+        .u.pgm.exc_access_id = te_code & 3,
+    };
+
+    kvm_s390_vcpu_interrupt(cpu, &irq);
+}
+
 static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
                                  uint16_t ipbh0)
 {
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 32a51f3..a1ee992 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -46,10 +46,23 @@
 #define FS_READ  0x800
 #define FS_WRITE 0x400
 
+static void trigger_access_exception(CPUS390XState *env, uint32_t type,
+                                     uint32_t ilen, uint64_t tec)
+{
+    S390CPU *cpu = s390_env_get_cpu(env);
+
+    if (kvm_enabled()) {
+        kvm_s390_access_exception(cpu, type, tec);
+    } else {
+        CPUState *cs = CPU(cpu);
+        stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
+        trigger_pgm_exception(env, type, ilen);
+    }
+}
+
 static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
                                uint64_t asc, int rw, bool exc)
 {
-    CPUState *cs = CPU(s390_env_get_cpu(env));
     uint64_t tec;
 
     tec = vaddr | (rw == 1 ? FS_WRITE : FS_READ) | 4 | asc >> 46;
@@ -60,14 +73,12 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
         return;
     }
 
-    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
-    trigger_pgm_exception(env, PGM_PROTECTION, ILEN_LATER_INC);
+    trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, tec);
 }
 
 static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
                                uint32_t type, uint64_t asc, int rw, bool exc)
 {
-    CPUState *cs = CPU(s390_env_get_cpu(env));
     int ilen = ILEN_LATER;
     uint64_t tec;
 
@@ -84,8 +95,7 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
         ilen = 2;
     }
 
-    stq_phys(cs->as, env->psa + offsetof(LowCore, trans_exc_code), tec);
-    trigger_pgm_exception(env, type, ilen);
+    trigger_access_exception(env, type, ilen, tec);
 }
 
 /**
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 14/25] s390x/mmu: Add function for accessing guest memory
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (12 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 13/25] s390x/kvm: Add function for injecting pgm access exceptions Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 15/25] s390x/css: Make schib parameter of css_do_msch const Jens Freimann
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

According to the POP specification, the parameter blocks of various
functions like the IO instructions are accessed with logical addresses.
Thus we need a function that can read or write a buffer from/to the
guest's logical address space.

This patch now provides a function that can be used to access virtual
guest memory by using the mmu_translate function of QEMU to convert
the virtual addresses to physical.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/cpu.h        |  11 +++++
 target-s390x/mmu_helper.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index f8cea30..a9ab587 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -287,6 +287,7 @@ typedef struct CPUS390XState {
 #define FLAG_MASK_32            0x00001000
 
 /* Control register 0 bits */
+#define CR0_LOWPROT             0x0000000010000000ULL
 #define CR0_EDAT                0x0000000000800000ULL
 
 static inline int cpu_mmu_index (CPUS390XState *env)
@@ -897,6 +898,16 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
 uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
                  uint64_t vr);
 
+int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf, int len,
+                         bool is_write);
+
+#define s390_cpu_virt_mem_read(cpu, laddr, dest, len) \
+        s390_cpu_virt_mem_rw(cpu, laddr, dest, len, false)
+#define s390_cpu_virt_mem_write(cpu, laddr, dest, len) \
+        s390_cpu_virt_mem_rw(cpu, laddr, dest, len, true)
+#define s390_cpu_virt_mem_check_write(cpu, laddr, len) \
+        s390_cpu_virt_mem_rw(cpu, laddr, NULL, len, true)
+
 /* The value of the TOD clock for 1.1.1970. */
 #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
 
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index a1ee992..b061c85 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -15,6 +15,9 @@
  * GNU General Public License for more details.
  */
 
+#include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "sysemu/kvm.h"
 #include "cpu.h"
 
 /* #define DEBUG_S390 */
@@ -368,3 +371,102 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
 
     return r;
 }
+
+/**
+ * lowprot_enabled: Check whether low-address protection is enabled
+ */
+static bool lowprot_enabled(const CPUS390XState *env)
+{
+    if (!(env->cregs[0] & CR0_LOWPROT)) {
+        return false;
+    }
+    if (!(env->psw.mask & PSW_MASK_DAT)) {
+        return true;
+    }
+
+    /* Check the private-space control bit */
+    switch (env->psw.mask & PSW_MASK_ASC) {
+    case PSW_ASC_PRIMARY:
+        return !(env->cregs[1] & _ASCE_PRIVATE_SPACE);
+    case PSW_ASC_SECONDARY:
+        return !(env->cregs[7] & _ASCE_PRIVATE_SPACE);
+    case PSW_ASC_HOME:
+        return !(env->cregs[13] & _ASCE_PRIVATE_SPACE);
+    default:
+        /* We don't support access register mode */
+        error_report("unsupported addressing mode");
+        exit(1);
+    }
+}
+
+/**
+ * translate_pages: Translate a set of consecutive logical page addresses
+ * to absolute addresses
+ */
+static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages,
+                           target_ulong *pages, bool is_write)
+{
+    bool lowprot = is_write && lowprot_enabled(&cpu->env);
+    uint64_t asc = cpu->env.psw.mask & PSW_MASK_ASC;
+    CPUS390XState *env = &cpu->env;
+    int ret, i, pflags;
+
+    for (i = 0; i < nr_pages; i++) {
+        /* Low-address protection? */
+        if (lowprot && (addr < 512 || (addr >= 4096 && addr < 4096 + 512))) {
+            trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, 0);
+            return -EACCES;
+        }
+        ret = mmu_translate(env, addr, is_write, asc, &pages[i], &pflags, true);
+        if (ret) {
+            return ret;
+        }
+        if (!address_space_access_valid(&address_space_memory, pages[i],
+                                        TARGET_PAGE_SIZE, is_write)) {
+            program_interrupt(env, PGM_ADDRESSING, 0);
+            return -EFAULT;
+        }
+        addr += TARGET_PAGE_SIZE;
+    }
+
+    return 0;
+}
+
+/**
+ * s390_cpu_virt_mem_rw:
+ * @laddr:     the logical start address
+ * @hostbuf:   buffer in host memory. NULL = do only checks w/o copying
+ * @len:       length that should be transfered
+ * @is_write:  true = write, false = read
+ * Returns:    0 on success, non-zero if an exception occured
+ *
+ * Copy from/to guest memory using logical addresses. Note that we inject a
+ * program interrupt in case there is an error while accessing the memory.
+ */
+int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf,
+                         int len, bool is_write)
+{
+    int currlen, nr_pages, i;
+    target_ulong *pages;
+    int ret;
+
+    nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
+               + 1;
+    pages = g_malloc(nr_pages * sizeof(*pages));
+
+    ret = translate_pages(cpu, laddr, nr_pages, pages, is_write);
+    if (ret == 0 && hostbuf != NULL) {
+        /* Copy data by stepping through the area page by page */
+        for (i = 0; i < nr_pages; i++) {
+            currlen = MIN(len, TARGET_PAGE_SIZE - (laddr % TARGET_PAGE_SIZE));
+            cpu_physical_memory_rw(pages[i] | (laddr & ~TARGET_PAGE_MASK),
+                                   hostbuf, currlen, is_write);
+            laddr += currlen;
+            hostbuf += currlen;
+            len -= currlen;
+        }
+    }
+
+    g_free(pages);
+    return ret;
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 15/25] s390x/css: Make schib parameter of css_do_msch const
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (13 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 14/25] s390x/mmu: Add function for accessing guest memory Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 16/25] s390x/ioinst: Rework memory access in MSCH instruction Jens Freimann
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The schib parameter of css_do_msch() can be declared as const to
make it clear that it does not get modified by this function.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/css.c     | 2 +-
 target-s390x/cpu.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index d0c5dde..65e6b71 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -584,7 +584,7 @@ static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
     }
 }
 
-int css_do_msch(SubchDev *sch, SCHIB *orig_schib)
+int css_do_msch(SubchDev *sch, const SCHIB *orig_schib)
 {
     SCSW *s = &sch->curr_status.scsw;
     PMCW *p = &sch->curr_status.pmcw;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index a9ab587..7180d68 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -450,7 +450,7 @@ bool css_subch_visible(SubchDev *sch);
 void css_conditional_io_interrupt(SubchDev *sch);
 int css_do_stsch(SubchDev *sch, SCHIB *schib);
 bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
-int css_do_msch(SubchDev *sch, SCHIB *schib);
+int css_do_msch(SubchDev *sch, const SCHIB *schib);
 int css_do_xsch(SubchDev *sch);
 int css_do_csch(SubchDev *sch);
 int css_do_hsch(SubchDev *sch);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 16/25] s390x/ioinst: Rework memory access in MSCH instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (14 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 15/25] s390x/css: Make schib parameter of css_do_msch const Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 17/25] s390x/ioinst: Rework memory access in SSCH instruction Jens Freimann
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the handler for MSCH to use the new logical memory
access functions.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/ioinst.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 1ac5d61..1569df6 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -1,7 +1,7 @@
 /*
  * I/O instructions for S/390
  *
- * Copyright 2012 IBM Corp.
+ * Copyright 2012, 2015 IBM Corp.
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or (at
@@ -144,11 +144,10 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
-    SCHIB *schib;
+    SCHIB schib;
     uint64_t addr;
     int ret = -ENODEV;
     int cc;
-    hwaddr len = sizeof(*schib);
     CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
@@ -156,20 +155,18 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return;
     }
-    schib = s390_cpu_physical_memory_map(env, addr, &len, 0);
-    if (!schib || len != sizeof(*schib)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        goto out;
+    if (s390_cpu_virt_mem_read(cpu, addr, &schib, sizeof(schib))) {
+        return;
     }
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
-        !ioinst_schib_valid(schib)) {
+        !ioinst_schib_valid(&schib)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        goto out;
+        return;
     }
     trace_ioinst_sch_id("msch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
     if (sch && css_subch_visible(sch)) {
-        ret = css_do_msch(sch, schib);
+        ret = css_do_msch(sch, &schib);
     }
     switch (ret) {
     case -ENODEV:
@@ -186,9 +183,6 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         break;
     }
     setcc(cpu, cc);
-
-out:
-    s390_cpu_physical_memory_unmap(env, schib, len, 0);
 }
 
 static void copy_orb_from_guest(ORB *dest, const ORB *src)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 17/25] s390x/ioinst: Rework memory access in SSCH instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (15 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 16/25] s390x/ioinst: Rework memory access in MSCH instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 18/25] s390x/ioinst: Rework memory access in STSCH instruction Jens Freimann
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the handler for SSCH to use the new logical memory
access functions.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/ioinst.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 1569df6..0ef7a93 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -210,11 +210,10 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
     int cssid, ssid, schid, m;
     SubchDev *sch;
-    ORB *orig_orb, orb;
+    ORB orig_orb, orb;
     uint64_t addr;
     int ret = -ENODEV;
     int cc;
-    hwaddr len = sizeof(*orig_orb);
     CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
@@ -222,16 +221,14 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return;
     }
-    orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0);
-    if (!orig_orb || len != sizeof(*orig_orb)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        goto out;
+    if (s390_cpu_virt_mem_read(cpu, addr, &orig_orb, sizeof(orb))) {
+        return;
     }
-    copy_orb_from_guest(&orb, orig_orb);
+    copy_orb_from_guest(&orb, &orig_orb);
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
         !ioinst_orb_valid(&orb)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        goto out;
+        return;
     }
     trace_ioinst_sch_id("ssch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
@@ -253,9 +250,6 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         break;
     }
     setcc(cpu, cc);
-
-out:
-    s390_cpu_physical_memory_unmap(env, orig_orb, len, 0);
 }
 
 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 18/25] s390x/ioinst: Rework memory access in STSCH instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (16 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 17/25] s390x/ioinst: Rework memory access in SSCH instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 19/25] s390x/ioinst: Set condition code in ioinst_handle_tsch() handler Jens Freimann
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the handler for STSCH to use the new logical memory
access functions.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/ioinst.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 0ef7a93..23c2faf 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -284,8 +284,7 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
     SubchDev *sch;
     uint64_t addr;
     int cc;
-    SCHIB *schib;
-    hwaddr len = sizeof(*schib);
+    SCHIB schib;
     CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
@@ -293,21 +292,23 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return;
     }
-    schib = s390_cpu_physical_memory_map(env, addr, &len, 1);
-    if (!schib || len != sizeof(*schib)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        goto out;
-    }
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
-        program_interrupt(env, PGM_OPERAND, 2);
-        goto out;
+        /*
+         * As operand exceptions have a lower priority than access exceptions,
+         * we check whether the memory area is writeable (injecting the
+         * access execption if it is not) first.
+         */
+        if (!s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib))) {
+            program_interrupt(env, PGM_OPERAND, 2);
+        }
+        return;
     }
     trace_ioinst_sch_id("stsch", cssid, ssid, schid);
     sch = css_find_subch(m, cssid, ssid, schid);
     if (sch) {
         if (css_subch_visible(sch)) {
-            css_do_stsch(sch, schib);
+            css_do_stsch(sch, &schib);
             cc = 0;
         } else {
             /* Indicate no more subchannels in this css/ss */
@@ -318,14 +319,21 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
             cc = 3; /* No more subchannels in this css/ss */
         } else {
             /* Store an empty schib. */
-            memset(schib, 0, sizeof(*schib));
+            memset(&schib, 0, sizeof(schib));
             cc = 0;
         }
     }
+    if (cc != 3) {
+        if (s390_cpu_virt_mem_write(cpu, addr, &schib, sizeof(schib)) != 0) {
+            return;
+        }
+    } else {
+        /* Access exceptions have a higher priority than cc3 */
+        if (s390_cpu_virt_mem_check_write(cpu, addr, sizeof(schib)) != 0) {
+            return;
+        }
+    }
     setcc(cpu, cc);
-
-out:
-    s390_cpu_physical_memory_unmap(env, schib, len, 1);
 }
 
 int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 19/25] s390x/ioinst: Set condition code in ioinst_handle_tsch() handler
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (17 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 18/25] s390x/ioinst: Rework memory access in STSCH instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 20/25] s390x/ioinst: Rework memory access in TSCH instruction Jens Freimann
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Move the setting of the condition code from kvm.c into the handler
function in ioinst.c itself, just like it has been done with the other
handlers already (TSCH has just not been changed yet since it is called
from a different dispatcher in kvm.c).

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/ioinst.c | 8 ++++----
 target-s390x/ioinst.h | 2 +-
 target-s390x/kvm.c    | 9 ++-------
 3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 23c2faf..8052886 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -336,13 +336,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
     setcc(cpu, cc);
 }
 
-int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
+int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 {
+    CPUS390XState *env = &cpu->env;
     int cssid, ssid, schid, m;
     SubchDev *sch;
     IRB *irb;
     uint64_t addr;
-    int ret = -ENODEV;
     int cc;
     hwaddr len = sizeof(*irb);
 
@@ -364,12 +364,12 @@ int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
     }
     sch = css_find_subch(m, cssid, ssid, schid);
     if (sch && css_subch_visible(sch)) {
-        ret = css_do_tsch(sch, irb);
+        cc = css_do_tsch(sch, irb);
         /* 0 - status pending, 1 - not status pending */
-        cc = ret;
     } else {
         cc = 3;
     }
+    setcc(cpu, cc);
 out:
     s390_cpu_physical_memory_unmap(env, irb, sizeof(*irb), 1);
     return cc;
diff --git a/target-s390x/ioinst.h b/target-s390x/ioinst.h
index 1efe16c..6746160 100644
--- a/target-s390x/ioinst.h
+++ b/target-s390x/ioinst.h
@@ -234,7 +234,7 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_tsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb);
+int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
 int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb);
 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a9a4c64..195493c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1337,19 +1337,14 @@ static int handle_intercept(S390CPU *cpu)
 
 static int handle_tsch(S390CPU *cpu)
 {
-    CPUS390XState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     struct kvm_run *run = cs->kvm_run;
     int ret;
 
     cpu_synchronize_state(cs);
 
-    ret = ioinst_handle_tsch(env, env->regs[1], run->s390_tsch.ipb);
-    if (ret >= 0) {
-        /* Success; set condition code. */
-        setcc(cpu, ret);
-        ret = 0;
-    } else if (ret < -1) {
+    ret = ioinst_handle_tsch(cpu, cpu->env.regs[1], run->s390_tsch.ipb);
+    if (ret < 0) {
         /*
          * Failure.
          * If an I/O interrupt had been dequeued, we have to reinject it.
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 20/25] s390x/ioinst: Rework memory access in TSCH instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (18 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 19/25] s390x/ioinst: Set condition code in ioinst_handle_tsch() handler Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 21/25] s390x/ioinst: Rework memory access in STCRW instruction Jens Freimann
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the TSCH handler to use the new logical memory access functions.
Since the channel should not be updated in case of a protection or access
exception while writing to the guest memory, the css_do_tsch() has to be
split up into two parts, one for retrieving the IRB and one for the update.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/css.c        | 38 +++++++++++++++++++++++---------------
 target-s390x/cpu.h    |  3 ++-
 target-s390x/ioinst.c | 33 +++++++++++++++++++--------------
 3 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 65e6b71..f6d0c0a 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -801,7 +801,8 @@ out:
     return ret;
 }
 
-static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
+static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
+                              int *irb_len)
 {
     int i;
     uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
@@ -815,6 +816,8 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
     for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
         dest->ecw[i] = cpu_to_be32(src->ecw[i]);
     }
+    *irb_len = sizeof(*dest) - sizeof(dest->emw);
+
     /* extended measurements enabled? */
     if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
         !(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
@@ -832,26 +835,21 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
             dest->emw[i] = cpu_to_be32(src->emw[i]);
         }
     }
+    *irb_len = sizeof(*dest);
 }
 
-int css_do_tsch(SubchDev *sch, IRB *target_irb)
+int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
 {
     SCSW *s = &sch->curr_status.scsw;
     PMCW *p = &sch->curr_status.pmcw;
     uint16_t stctl;
-    uint16_t fctl;
-    uint16_t actl;
     IRB irb;
-    int ret;
 
     if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
-        ret = 3;
-        goto out;
+        return 3;
     }
 
     stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
-    fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
-    actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
 
     /* Prepare the irb for the guest. */
     memset(&irb, 0, sizeof(IRB));
@@ -876,7 +874,22 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
         }
     }
     /* Store the irb to the guest. */
-    copy_irb_to_guest(target_irb, &irb, p);
+    copy_irb_to_guest(target_irb, &irb, p, irb_len);
+
+    return ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
+}
+
+void css_do_tsch_update_subch(SubchDev *sch)
+{
+    SCSW *s = &sch->curr_status.scsw;
+    PMCW *p = &sch->curr_status.pmcw;
+    uint16_t stctl;
+    uint16_t fctl;
+    uint16_t actl;
+
+    stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
+    fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
+    actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
 
     /* Clear conditions on subchannel, if applicable. */
     if (stctl & SCSW_STCTL_STATUS_PEND) {
@@ -913,11 +926,6 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
             memset(sch->sense_data, 0 , sizeof(sch->sense_data));
         }
     }
-
-    ret = ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
-
-out:
-    return ret;
 }
 
 static void copy_crw_to_guest(CRW *dest, const CRW *src)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 7180d68..7c07ca6 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -455,7 +455,8 @@ int css_do_xsch(SubchDev *sch);
 int css_do_csch(SubchDev *sch);
 int css_do_hsch(SubchDev *sch);
 int css_do_ssch(SubchDev *sch, ORB *orb);
-int css_do_tsch(SubchDev *sch, IRB *irb);
+int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len);
+void css_do_tsch_update_subch(SubchDev *sch);
 int css_do_stcrw(CRW *crw);
 int css_do_tpi(IOIntCode *int_code, int lowcore);
 int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 8052886..aa55ca8 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -341,10 +341,9 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
     CPUS390XState *env = &cpu->env;
     int cssid, ssid, schid, m;
     SubchDev *sch;
-    IRB *irb;
+    IRB irb;
     uint64_t addr;
-    int cc;
-    hwaddr len = sizeof(*irb);
+    int cc, irb_len;
 
     if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
         program_interrupt(env, PGM_OPERAND, 2);
@@ -356,23 +355,29 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return -EIO;
     }
-    irb = s390_cpu_physical_memory_map(env, addr, &len, 1);
-    if (!irb || len != sizeof(*irb)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        cc = -EIO;
-        goto out;
-    }
+
     sch = css_find_subch(m, cssid, ssid, schid);
     if (sch && css_subch_visible(sch)) {
-        cc = css_do_tsch(sch, irb);
-        /* 0 - status pending, 1 - not status pending */
+        cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
     } else {
         cc = 3;
     }
+    /* 0 - status pending, 1 - not status pending, 3 - not operational */
+    if (cc != 3) {
+        if (s390_cpu_virt_mem_write(cpu, addr, &irb, irb_len) != 0) {
+            return -EFAULT;
+        }
+        css_do_tsch_update_subch(sch);
+    } else {
+        irb_len = sizeof(irb) - sizeof(irb.emw);
+        /* Access exceptions have a higher priority than cc3 */
+        if (s390_cpu_virt_mem_check_write(cpu, addr, irb_len) != 0) {
+            return -EFAULT;
+        }
+    }
+
     setcc(cpu, cc);
-out:
-    s390_cpu_physical_memory_unmap(env, irb, sizeof(*irb), 1);
-    return cc;
+    return 0;
 }
 
 typedef struct ChscReq {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 21/25] s390x/ioinst: Rework memory access in STCRW instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (19 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 20/25] s390x/ioinst: Rework memory access in TSCH instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 22/25] s390x/ioinst: Rework memory access in CHSC instruction Jens Freimann
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the handler for STCRW to use the new logical memory access
functions. Since STCRW is suppressed on protection/access exceptions,
we also have to make sure to re-queue the CRW in case it could not be
written to the memory.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/s390x/css.c        | 20 ++++++++++++++++++++
 target-s390x/cpu.h    |  1 +
 target-s390x/ioinst.c | 20 +++++++++-----------
 3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index f6d0c0a..9a13b00 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -955,6 +955,26 @@ int css_do_stcrw(CRW *crw)
     return ret;
 }
 
+static void copy_crw_from_guest(CRW *dest, const CRW *src)
+{
+    dest->flags = be16_to_cpu(src->flags);
+    dest->rsid = be16_to_cpu(src->rsid);
+}
+
+void css_undo_stcrw(CRW *crw)
+{
+    CrwContainer *crw_cont;
+
+    crw_cont = g_try_malloc0(sizeof(CrwContainer));
+    if (!crw_cont) {
+        channel_subsys->crws_lost = true;
+        return;
+    }
+    copy_crw_from_guest(&crw_cont->crw, crw);
+
+    QTAILQ_INSERT_HEAD(&channel_subsys->pending_crws, crw_cont, sibling);
+}
+
 int css_do_tpi(IOIntCode *int_code, int lowcore)
 {
     /* No pending interrupts for !KVM. */
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 7c07ca6..1f58312 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -458,6 +458,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb);
 int css_do_tsch_get_irb(SubchDev *sch, IRB *irb, int *irb_len);
 void css_do_tsch_update_subch(SubchDev *sch);
 int css_do_stcrw(CRW *crw);
+void css_undo_stcrw(CRW *crw);
 int css_do_tpi(IOIntCode *int_code, int lowcore);
 int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
                          int rfmt, void *buf);
diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index aa55ca8..157972d 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -254,10 +254,9 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
 
 void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
 {
-    CRW *crw;
+    CRW crw;
     uint64_t addr;
     int cc;
-    hwaddr len = sizeof(*crw);
     CPUS390XState *env = &cpu->env;
 
     addr = decode_basedisp_s(env, ipb);
@@ -265,17 +264,16 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return;
     }
-    crw = s390_cpu_physical_memory_map(env, addr, &len, 1);
-    if (!crw || len != sizeof(*crw)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        goto out;
-    }
-    cc = css_do_stcrw(crw);
+
+    cc = css_do_stcrw(&crw);
     /* 0 - crw stored, 1 - zeroes stored */
-    setcc(cpu, cc);
 
-out:
-    s390_cpu_physical_memory_unmap(env, crw, len, 1);
+    if (s390_cpu_virt_mem_write(cpu, addr, &crw, sizeof(crw)) == 0) {
+        setcc(cpu, cc);
+    } else if (cc == 0) {
+        /* Write failed: requeue CRW since STCRW is a suppressing instruction */
+        css_undo_stcrw(&crw);
+    }
 }
 
 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 22/25] s390x/ioinst: Rework memory access in CHSC instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (20 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 21/25] s390x/ioinst: Rework memory access in STCRW instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 23/25] s390x/ioinst: Rework memory access in TPI instruction Jens Freimann
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the CHSC handler to correctly use logical addresses, too.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/ioinst.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 157972d..7e748c2 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -629,8 +629,8 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
     int reg;
     uint16_t len;
     uint16_t command;
-    hwaddr map_size = TARGET_PAGE_SIZE;
     CPUS390XState *env = &cpu->env;
+    uint8_t buf[TARGET_PAGE_SIZE];
 
     trace_ioinst("chsc");
     reg = (ipb >> 20) & 0x00f;
@@ -640,16 +640,20 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
         program_interrupt(env, PGM_SPECIFICATION, 2);
         return;
     }
-    req = s390_cpu_physical_memory_map(env, addr, &map_size, 1);
-    if (!req || map_size != TARGET_PAGE_SIZE) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        goto out;
+    /*
+     * Reading sizeof(ChscReq) bytes is currently enough for all of our
+     * present CHSC sub-handlers ... if we ever need more, we should take
+     * care of req->len here first.
+     */
+    if (s390_cpu_virt_mem_read(cpu, addr, buf, sizeof(ChscReq))) {
+        return;
     }
+    req = (ChscReq *)buf;
     len = be16_to_cpu(req->len);
     /* Length field valid? */
     if ((len < 16) || (len > 4088) || (len & 7)) {
         program_interrupt(env, PGM_OPERAND, 2);
-        goto out;
+        return;
     }
     memset((char *)req + len, 0, TARGET_PAGE_SIZE - len);
     res = (void *)((char *)req + len);
@@ -673,9 +677,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
         break;
     }
 
-    setcc(cpu, 0);    /* Command execution complete */
-out:
-    s390_cpu_physical_memory_unmap(env, req, map_size, 1);
+    if (!s390_cpu_virt_mem_write(cpu, addr + len, res, be16_to_cpu(res->len))) {
+        setcc(cpu, 0);    /* Command execution complete */
+    }
 }
 
 int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 23/25] s390x/ioinst: Rework memory access in TPI instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (21 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 22/25] s390x/ioinst: Rework memory access in CHSC instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 24/25] s390x/pci: Rework memory access in zpci instruction Jens Freimann
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

Change the handler for TPI to use the new logical memory
access functions.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 target-s390x/ioinst.c | 19 +++++++------------
 target-s390x/ioinst.h |  2 +-
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 7e748c2..b00a00c 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -682,12 +682,13 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb)
     }
 }
 
-int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb)
+int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb)
 {
+    CPUS390XState *env = &cpu->env;
     uint64_t addr;
     int lowcore;
-    IOIntCode *int_code;
-    hwaddr len, orig_len;
+    IOIntCode int_code;
+    hwaddr len;
     int ret;
 
     trace_ioinst("tpi");
@@ -699,16 +700,10 @@ int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb)
 
     lowcore = addr ? 0 : 1;
     len = lowcore ? 8 /* two words */ : 12 /* three words */;
-    orig_len = len;
-    int_code = s390_cpu_physical_memory_map(env, addr, &len, 1);
-    if (!int_code || (len != orig_len)) {
-        program_interrupt(env, PGM_ADDRESSING, 2);
-        ret = -EIO;
-        goto out;
+    ret = css_do_tpi(&int_code, lowcore);
+    if (ret == 1) {
+        s390_cpu_virt_mem_write(cpu, lowcore ? 184 : addr, &int_code, len);
     }
-    ret = css_do_tpi(int_code, lowcore);
-out:
-    s390_cpu_physical_memory_unmap(env, int_code, len, 1);
     return ret;
 }
 
diff --git a/target-s390x/ioinst.h b/target-s390x/ioinst.h
index 6746160..203bdba 100644
--- a/target-s390x/ioinst.h
+++ b/target-s390x/ioinst.h
@@ -236,7 +236,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
 void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
 void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
-int ioinst_handle_tpi(CPUS390XState *env, uint32_t ipb);
+int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
 void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
                         uint32_t ipb);
 void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 24/25] s390x/pci: Rework memory access in zpci instruction
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (22 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 23/25] s390x/ioinst: Rework memory access in TPI instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 25/25] s390x/helper: Remove s390_cpu_physical_memory_map Jens Freimann
  2015-02-18  8:40 ` [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Christian Borntraeger
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Frank Blaschka, Frank Blaschka, qemu-devel, Jens Freimann

From: Frank Blaschka <frank.blaschka@de.ibm.com>

Change zpci instructions to use the new logical memory access
functions.

Signed-off-by: Frank Blaschka <blaschka@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
---
 hw/s390x/s390-pci-inst.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 9e5bc5b..08d8aa6 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -155,7 +155,9 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
         return 0;
     }
 
-    cpu_physical_memory_read(env->regs[r2], buffer, sizeof(*reqh));
+    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer, sizeof(*reqh))) {
+        return 0;
+    }
     reqh = (ClpReqHdr *)buffer;
     req_len = lduw_p(&reqh->len);
     if (req_len < 16 || req_len > 8184 || (req_len % 8 != 0)) {
@@ -163,7 +165,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
         return 0;
     }
 
-    cpu_physical_memory_read(env->regs[r2], buffer, req_len + sizeof(*resh));
+    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
+                               req_len + sizeof(*resh))) {
+        return 0;
+    }
     resh = (ClpRspHdr *)(buffer + req_len);
     res_len = lduw_p(&resh->len);
     if (res_len < 8 || res_len > 8176 || (res_len % 8 != 0)) {
@@ -175,7 +180,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
         return 0;
     }
 
-    cpu_physical_memory_read(env->regs[r2], buffer, req_len + res_len);
+    if (s390_cpu_virt_mem_read(cpu, env->regs[r2], buffer,
+                               req_len + res_len)) {
+        return 0;
+    }
 
     if (req_len != 32) {
         stw_p(&resh->rsp, CLP_RC_LEN);
@@ -269,7 +277,10 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
     }
 
 out:
-    cpu_physical_memory_write(env->regs[r2], buffer, req_len + res_len);
+    if (s390_cpu_virt_mem_write(cpu, env->regs[r2], buffer,
+                                req_len + res_len)) {
+        return 0;
+    }
     setcc(cpu, cc);
     return 0;
 }
@@ -539,10 +550,10 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
     S390PCIBusDevice *pbdev;
     MemoryRegion *mr;
     int i;
-    uint64_t val;
     uint32_t fh;
     uint8_t pcias;
     uint8_t len;
+    uint8_t buffer[128];
 
     if (env->psw.mask & PSW_MASK_PSTATE) {
         program_interrupt(env, PGM_PRIVILEGED, 6);
@@ -590,9 +601,12 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
         return 0;
     }
 
+    if (s390_cpu_virt_mem_read(cpu, gaddr, buffer, len)) {
+        return 0;
+    }
+
     for (i = 0; i < len / 8; i++) {
-        val = ldq_phys(&address_space_memory, gaddr + i * 8);
-        io_mem_write(mr, env->regs[r3] + i * 8, val, 8);
+        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8);
     }
 
     setcc(cpu, ZPCI_PCI_LS_OK);
@@ -709,7 +723,9 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
         return 0;
     }
 
-    cpu_physical_memory_read(fiba, (uint8_t *)&fib, sizeof(fib));
+    if (s390_cpu_virt_mem_read(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
+        return 0;
+    }
 
     switch (oc) {
     case ZPCI_MOD_FC_REG_INT:
@@ -809,7 +825,10 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba)
         fib.fc |= 0x10;
     }
 
-    cpu_physical_memory_write(fiba, (uint8_t *)&fib, sizeof(fib));
+    if (s390_cpu_virt_mem_write(cpu, fiba, (uint8_t *)&fib, sizeof(fib))) {
+        return 0;
+    }
+
     setcc(cpu, cc);
     return 0;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [Qemu-devel] [PATCH 25/25] s390x/helper: Remove s390_cpu_physical_memory_map
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (23 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 24/25] s390x/pci: Rework memory access in zpci instruction Jens Freimann
@ 2015-02-12 17:09 ` Jens Freimann
  2015-02-18  8:40 ` [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Christian Borntraeger
  25 siblings, 0 replies; 28+ messages in thread
From: Jens Freimann @ 2015-02-12 17:09 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel, Thomas Huth

From: Thomas Huth <thuth@linux.vnet.ibm.com>

The function is now not used anymore, so it can be removed safely.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/cpu.h    |  4 ----
 target-s390x/helper.c | 25 -------------------------
 2 files changed, 29 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 1f58312..b6b4632 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -350,10 +350,6 @@ int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 #include "ioinst.h"
 
 #ifndef CONFIG_USER_ONLY
-void *s390_cpu_physical_memory_map(CPUS390XState *env, hwaddr addr, hwaddr *len,
-                                   int is_write);
-void s390_cpu_physical_memory_unmap(CPUS390XState *env, void *addr, hwaddr len,
-                                    int is_write);
 static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb)
 {
     hwaddr addr = 0;
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index f8a3c5a..e0fd8fc 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -229,31 +229,6 @@ static void cpu_unmap_lowcore(LowCore *lowcore)
     cpu_physical_memory_unmap(lowcore, sizeof(LowCore), 1, sizeof(LowCore));
 }
 
-void *s390_cpu_physical_memory_map(CPUS390XState *env, hwaddr addr, hwaddr *len,
-                                   int is_write)
-{
-    hwaddr start = addr;
-
-    /* Mind the prefix area. */
-    if (addr < 8192) {
-        /* Map the lowcore. */
-        start += env->psa;
-        *len = MIN(*len, 8192 - addr);
-    } else if ((addr >= env->psa) && (addr < env->psa + 8192)) {
-        /* Map the 0 page. */
-        start -= env->psa;
-        *len = MIN(*len, 8192 - start);
-    }
-
-    return cpu_physical_memory_map(start, len, is_write);
-}
-
-void s390_cpu_physical_memory_unmap(CPUS390XState *env, void *addr, hwaddr len,
-                                    int is_write)
-{
-    cpu_physical_memory_unmap(addr, len, is_write, len);
-}
-
 static void do_svc_interrupt(CPUS390XState *env)
 {
     uint64_t mask, addr;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file Jens Freimann
@ 2015-02-17 12:35   ` Alexander Graf
  0 siblings, 0 replies; 28+ messages in thread
From: Alexander Graf @ 2015-02-17 12:35 UTC (permalink / raw)
  To: Jens Freimann, Christian Borntraeger, Cornelia Huck
  Cc: qemu-devel, Thomas Huth

On 02/12/2015 06:09 PM, Jens Freimann wrote:
> From: Thomas Huth <thuth@linux.vnet.ibm.com>
>
> helper.c is quite overcrowded already, so let's move the MMU
> translation to a separate file instead (like it has been done
> with the other targets already).
>
> Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
> Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>

Acked-by: Alexander Graf <agraf@suse.de>


Alex

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access
  2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
                   ` (24 preceding siblings ...)
  2015-02-12 17:09 ` [Qemu-devel] [PATCH 25/25] s390x/helper: Remove s390_cpu_physical_memory_map Jens Freimann
@ 2015-02-18  8:40 ` Christian Borntraeger
  25 siblings, 0 replies; 28+ messages in thread
From: Christian Borntraeger @ 2015-02-18  8:40 UTC (permalink / raw)
  To: Jens Freimann, Alexander Graf, Cornelia Huck; +Cc: qemu-devel

Am 12.02.2015 um 18:09 schrieb Jens Freimann:
> Cornelia, Alex, Christian,
> 
> this patches are a rework of guest memory access to allow access to 
> guest logical address space.
> 
> Frank Blaschka (1):
>   s390x/pci: Rework memory access in zpci instruction
> 
> Thomas Huth (24):
>   s390x/mmu: Move mmu_translate() and friends to separate file
>   s390x/mmu: Fix the check for the real-space designation bit
>   s390x/mmu: Fix the handling of the table levels
>   s390x/mmu: Check table length and offset fields
>   s390x/mmu: Skip exceptions properly when translating addresses for
>     debug
>   s390x/mmu: Fix translation exception code in lowcore
>   s390x/mmu: Fix exception types when checking the ASCEs
>   s390x/mmu: Fix the exception codes for illegal table entries
>   s390x/mmu: Add support for read-only regions
>   s390x/mmu: Renaming related to the ASCE confusion
>   s390x/mmu: Check bit 52 in page table entry
>   s390x/mmu: Clean up mmu_translate_asc()
>   s390x/kvm: Add function for injecting pgm access exceptions
>   s390x/mmu: Add function for accessing guest memory
>   s390x/css: Make schib parameter of css_do_msch const
>   s390x/ioinst: Rework memory access in MSCH instruction
>   s390x/ioinst: Rework memory access in SSCH instruction
>   s390x/ioinst: Rework memory access in STSCH instruction
>   s390x/ioinst: Set condition code in ioinst_handle_tsch() handler
>   s390x/ioinst: Rework memory access in TSCH instruction
>   s390x/ioinst: Rework memory access in STCRW instruction
>   s390x/ioinst: Rework memory access in CHSC instruction
>   s390x/ioinst: Rework memory access in TPI instruction
>   s390x/helper: Remove s390_cpu_physical_memory_map
> 
>  hw/s390x/css.c             |  60 ++++--
>  hw/s390x/s390-pci-inst.c   |  37 +++-
>  target-s390x/Makefile.objs |   2 +-
>  target-s390x/cpu.h         |  32 ++-
>  target-s390x/helper.c      | 356 +---------------------------------
>  target-s390x/ioinst.c      | 172 ++++++++---------
>  target-s390x/ioinst.h      |   4 +-
>  target-s390x/kvm.c         |  21 +-
>  target-s390x/mem_helper.c  |  12 +-
>  target-s390x/mmu_helper.c  | 472 +++++++++++++++++++++++++++++++++++++++++++++
>  10 files changed, 681 insertions(+), 487 deletions(-)
>  create mode 100644 target-s390x/mmu_helper.c
> 

Applied to s390-next. 

Thanks

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2015-02-18  8:40 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-12 17:09 [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 01/25] s390x/mmu: Move mmu_translate() and friends to separate file Jens Freimann
2015-02-17 12:35   ` Alexander Graf
2015-02-12 17:09 ` [Qemu-devel] [PATCH 02/25] s390x/mmu: Fix the check for the real-space designation bit Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 03/25] s390x/mmu: Fix the handling of the table levels Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 04/25] s390x/mmu: Check table length and offset fields Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 05/25] s390x/mmu: Skip exceptions properly when translating addresses for debug Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 06/25] s390x/mmu: Fix translation exception code in lowcore Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 07/25] s390x/mmu: Fix exception types when checking the ASCEs Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 08/25] s390x/mmu: Fix the exception codes for illegal table entries Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 09/25] s390x/mmu: Add support for read-only regions Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 10/25] s390x/mmu: Renaming related to the ASCE confusion Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 11/25] s390x/mmu: Check bit 52 in page table entry Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 12/25] s390x/mmu: Clean up mmu_translate_asc() Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 13/25] s390x/kvm: Add function for injecting pgm access exceptions Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 14/25] s390x/mmu: Add function for accessing guest memory Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 15/25] s390x/css: Make schib parameter of css_do_msch const Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 16/25] s390x/ioinst: Rework memory access in MSCH instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 17/25] s390x/ioinst: Rework memory access in SSCH instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 18/25] s390x/ioinst: Rework memory access in STSCH instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 19/25] s390x/ioinst: Set condition code in ioinst_handle_tsch() handler Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 20/25] s390x/ioinst: Rework memory access in TSCH instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 21/25] s390x/ioinst: Rework memory access in STCRW instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 22/25] s390x/ioinst: Rework memory access in CHSC instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 23/25] s390x/ioinst: Rework memory access in TPI instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 24/25] s390x/pci: Rework memory access in zpci instruction Jens Freimann
2015-02-12 17:09 ` [Qemu-devel] [PATCH 25/25] s390x/helper: Remove s390_cpu_physical_memory_map Jens Freimann
2015-02-18  8:40 ` [Qemu-devel] [PATCH 00/25] s390x: rework guest memory access Christian Borntraeger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.