aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/misc_helper.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2017-06-09 16:21:56 +0200
committerRichard Henderson <rth@twiddle.net>2017-06-13 11:09:39 -0700
commitbecf8217deb2afc347d5172d9f30c8a8964b8b27 (patch)
tree47f7da6a3210b63ee7346bbf5f143abc9358d7f3 /target/s390x/misc_helper.c
parent465aec461726d5157d458acee94584f8cdfbe4b7 (diff)
target/s390x: rework PGM interrupt psw.addr handling
We can tell from the program interrupt code, whether a program interrupt has to forward the address in the PGM new PSW (suppressing/terminated/completed) to point at the next instruction, or if it is nullifying and the PSW address does not have to be incremented. So let's not modify the PSW address outside of the injection path and handle this internally. We just have to handle instruction length auto detection if no valid instruction length can be provided. This should fix various program interrupt injection paths, where the PSW was not properly forwarded. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20170609142156.18767-3-david@redhat.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target/s390x/misc_helper.c')
-rw-r--r--target/s390x/misc_helper.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index d6eda832eb..4daa01632e 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -54,19 +54,14 @@ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
uintptr_t retaddr)
{
CPUState *cs = CPU(s390_env_get_cpu(env));
- int t;
cs->exception_index = EXCP_PGM;
env->int_pgm_code = excp;
+ env->int_pgm_ilen = ILEN_AUTO;
/* Use the (ultimate) callers address to find the insn that trapped. */
cpu_restore_state(cs, retaddr);
- /* Advance past the insn. */
- t = cpu_ldub_code(env, env->psw.addr);
- env->int_pgm_ilen = t = get_ilen(t);
- env->psw.addr += t;
-
cpu_loop_exit(cs);
}
@@ -199,12 +194,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
IplParameterBlock *iplb;
if (env->psw.mask & PSW_MASK_PSTATE) {
- program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC);
+ program_interrupt(env, PGM_PRIVILEGED, ILEN_AUTO);
return;
}
if ((subcode & ~0x0ffffULL) || (subcode > 6)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
+ program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
return;
}
@@ -229,12 +224,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3)
break;
case 5:
if ((r1 & 1) || (addr & 0x0fffULL)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
+ program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
return;
}
if (!address_space_access_valid(&address_space_memory, addr,
sizeof(IplParameterBlock), false)) {
- program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
+ program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO);
return;
}
iplb = g_malloc0(sizeof(IplParameterBlock));
@@ -258,12 +253,12 @@ out:
return;
case 6:
if ((r1 & 1) || (addr & 0x0fffULL)) {
- program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC);
+ program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
return;
}
if (!address_space_access_valid(&address_space_memory, addr,
sizeof(IplParameterBlock), true)) {
- program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC);
+ program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO);
return;
}
iplb = s390_ipl_get_iplb();
@@ -307,7 +302,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
}
if (r) {
- program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
+ program_interrupt(env, PGM_OPERATION, ILEN_AUTO);
}
}