aboutsummaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2013-02-07 02:20:50 +0000
committerAnthony Liguori <aliguori@us.ibm.com>2013-02-13 11:56:02 -0600
commitbd9a8d852c857fd19c4626acaac1d4979f816f3a (patch)
tree4674c0dd15685e52b3b14fda44bba2bea7634056 /target-s390x
parent760794f784f66e262a9ca32821ba202cdf3a3e4b (diff)
s390: Keep I/O interrupts enabled for all iscs.
do_io_interrupt() would stop scanning further iscs if it found an I/O interrupt it could inject. This might cause the pending interrupt indication for I/O interrupts to be reset although there might be queued I/O interrupts for subsequent iscs. Fix this by reordering the logic: Inject the I/O interrupt immediately and continue searching all iscs for queued interrupts. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/helper.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 043feb2739..9f9088b040 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -617,7 +617,6 @@ static void do_ext_interrupt(CPUS390XState *env)
static void do_io_interrupt(CPUS390XState *env)
{
- uint64_t mask = 0, addr = 0;
LowCore *lowcore;
IOIntQueue *q;
uint8_t isc;
@@ -642,36 +641,39 @@ static void do_io_interrupt(CPUS390XState *env)
disable = 0;
continue;
}
- found = 1;
- lowcore = cpu_map_lowcore(env);
+ if (!found) {
+ uint64_t mask, addr;
- lowcore->subchannel_id = cpu_to_be16(q->id);
- lowcore->subchannel_nr = cpu_to_be16(q->nr);
- lowcore->io_int_parm = cpu_to_be32(q->parm);
- lowcore->io_int_word = cpu_to_be32(q->word);
- lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
- mask = be64_to_cpu(lowcore->io_new_psw.mask);
- addr = be64_to_cpu(lowcore->io_new_psw.addr);
+ found = 1;
+ lowcore = cpu_map_lowcore(env);
- cpu_unmap_lowcore(lowcore);
+ lowcore->subchannel_id = cpu_to_be16(q->id);
+ lowcore->subchannel_nr = cpu_to_be16(q->nr);
+ lowcore->io_int_parm = cpu_to_be32(q->parm);
+ lowcore->io_int_word = cpu_to_be32(q->word);
+ lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
+ lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
+ mask = be64_to_cpu(lowcore->io_new_psw.mask);
+ addr = be64_to_cpu(lowcore->io_new_psw.addr);
- env->io_index[isc]--;
+ cpu_unmap_lowcore(lowcore);
+
+ env->io_index[isc]--;
+
+ DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
+ env->psw.mask, env->psw.addr);
+ load_psw(env, mask, addr);
+ }
if (env->io_index[isc] >= 0) {
disable = 0;
}
- break;
+ continue;
}
if (disable) {
env->pending_int &= ~INTERRUPT_IO;
}
- if (found) {
- DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
- env->psw.mask, env->psw.addr);
- load_psw(env, mask, addr);
- }
}
static void do_mchk_interrupt(CPUS390XState *env)