summaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2015-02-12 18:09:23 +0100
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-02-18 09:37:14 +0100
commitbab58bf0921ef5da3c5c764920f152ac7c914c41 (patch)
tree285c7e822a88a1d8c196c29f088bfb8f520efc60 /target-s390x
parente3e09d87c6e69c2da684d5aacabe3124ebcb6f8e (diff)
downloadqemu-bab58bf0921ef5da3c5c764920f152ac7c914c41.zip
s390x/mmu: Fix translation exception code in lowcore
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> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/mmu_helper.c48
1 files changed, 15 insertions, 33 deletions
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 67ad3ccad0..109a2d3c85 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;
}