aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/tcg/excp_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/tcg/excp_helper.c')
-rw-r--r--target/s390x/tcg/excp_helper.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
index 3da337f..b7116d0 100644
--- a/target/s390x/tcg/excp_helper.c
+++ b/target/s390x/tcg/excp_helper.c
@@ -190,11 +190,6 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
return false;
}
- if (excp != PGM_ADDRESSING) {
- stq_phys(env_cpu(env)->as,
- env->psa + offsetof(LowCore, trans_exc_code), tec);
- }
-
/*
* For data accesses, ILEN will be filled in from the unwind info,
* within cpu_loop_exit_restore. For code accesses, retaddr == 0,
@@ -211,20 +206,33 @@ static void do_program_interrupt(CPUS390XState *env)
uint64_t mask, addr;
LowCore *lowcore;
int ilen = env->int_pgm_ilen;
+ bool set_trans_exc_code = false;
+ bool advance = false;
assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
ilen == 2 || ilen == 4 || ilen == 6);
switch (env->int_pgm_code) {
case PGM_PER:
- if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
- break;
- }
- /* FALL THROUGH */
+ advance = !(env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION);
+ break;
+ case PGM_ASCE_TYPE:
+ case PGM_REG_FIRST_TRANS:
+ case PGM_REG_SEC_TRANS:
+ case PGM_REG_THIRD_TRANS:
+ case PGM_SEGMENT_TRANS:
+ case PGM_PAGE_TRANS:
+ assert(env->int_pgm_code == env->tlb_fill_exc);
+ set_trans_exc_code = true;
+ break;
+ case PGM_PROTECTION:
+ assert(env->int_pgm_code == env->tlb_fill_exc);
+ set_trans_exc_code = true;
+ advance = true;
+ break;
case PGM_OPERATION:
case PGM_PRIVILEGED:
case PGM_EXECUTE:
- case PGM_PROTECTION:
case PGM_ADDRESSING:
case PGM_SPECIFICATION:
case PGM_DATA:
@@ -243,11 +251,15 @@ static void do_program_interrupt(CPUS390XState *env)
case PGM_PC_TRANS_SPEC:
case PGM_ALET_SPEC:
case PGM_MONITOR:
- /* advance the PSW if our exception is not nullifying */
- env->psw.addr += ilen;
+ advance = true;
break;
}
+ /* advance the PSW if our exception is not nullifying */
+ if (advance) {
+ env->psw.addr += ilen;
+ }
+
qemu_log_mask(CPU_LOG_INT,
"%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
__func__, env->int_pgm_code, ilen, env->psw.mask,
@@ -263,6 +275,10 @@ static void do_program_interrupt(CPUS390XState *env)
env->per_perc_atmid = 0;
}
+ if (set_trans_exc_code) {
+ lowcore->trans_exc_code = cpu_to_be64(env->tlb_fill_tec);
+ }
+
lowcore->pgm_ilen = cpu_to_be16(ilen);
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
lowcore->program_old_psw.mask = cpu_to_be64(s390_cpu_get_psw_mask(env));