Currently, enabling/disabling of interrupts is not really supported.
Let's improve interrupt handling code by explicitly checking for
deliverable interrupts only. This is the first step. Checking for
external interrupt subclasses will be done next.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <
20170928203708.9376-5-david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
static bool s390_cpu_has_work(CPUState *cs)
{
S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
- return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->psw.mask & PSW_MASK_EXT);
+ if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+ return false;
+ }
+
+ return s390_cpu_has_int(cpu);
}
#if !defined(CONFIG_USER_ONLY)
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
/* handle machine checks */
- if ((env->psw.mask & PSW_MASK_MCHECK) &&
- (cs->exception_index == -1)) {
- if (env->pending_int & INTERRUPT_MCHK) {
- cs->exception_index = EXCP_MCHK;
- }
+ if (cs->exception_index == -1 && s390_cpu_has_mcck_int(cpu)) {
+ cs->exception_index = EXCP_MCHK;
}
/* handle external interrupts */
- if ((env->psw.mask & PSW_MASK_EXT) &&
- cs->exception_index == -1 &&
- (env->pending_int & INTERRUPT_EXT)) {
+ if (cs->exception_index == -1 && s390_cpu_has_ext_int(cpu)) {
cs->exception_index = EXCP_EXT;
}
/* handle I/O interrupts */
- if ((env->psw.mask & PSW_MASK_IO) &&
- (cs->exception_index == -1)) {
- if (env->pending_int & INTERRUPT_IO) {
- cs->exception_index = EXCP_IO;
- }
+ if (cs->exception_index == -1 && s390_cpu_has_io_int(cpu)) {
+ cs->exception_index = EXCP_IO;
}
switch (cs->exception_index) {
}
cs->exception_index = -1;
+ /* we might still have pending interrupts, but not deliverable */
if (!env->pending_int) {
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
}
the parent EXECUTE insn. */
return false;
}
- if (env->psw.mask & PSW_MASK_EXT) {
+ if (s390_cpu_has_int(cpu)) {
s390_cpu_do_interrupt(cs);
return true;
}
void cpu_inject_cpu_timer(S390CPU *cpu);
void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
+bool s390_cpu_has_io_int(S390CPU *cpu);
+bool s390_cpu_has_ext_int(S390CPU *cpu);
+bool s390_cpu_has_mcck_int(S390CPU *cpu);
+bool s390_cpu_has_int(S390CPU *cpu);
/* ioinst.c */
}
}
+bool s390_cpu_has_mcck_int(S390CPU *cpu)
+{
+ CPUS390XState *env = &cpu->env;
+
+ if (!(env->psw.mask & PSW_MASK_MCHECK)) {
+ return false;
+ }
+
+ return env->pending_int & INTERRUPT_MCHK;
+}
+
+bool s390_cpu_has_ext_int(S390CPU *cpu)
+{
+ CPUS390XState *env = &cpu->env;
+
+ if (!(env->psw.mask & PSW_MASK_EXT)) {
+ return false;
+ }
+
+ return env->pending_int & INTERRUPT_EXT;
+}
+
+bool s390_cpu_has_io_int(S390CPU *cpu)
+{
+ CPUS390XState *env = &cpu->env;
+
+ if (!(env->psw.mask & PSW_MASK_IO)) {
+ return false;
+ }
+
+ return env->pending_int & INTERRUPT_IO;
+}
#endif
+
+bool s390_cpu_has_int(S390CPU *cpu)
+{
+#ifndef CONFIG_USER_ONLY
+ if (!tcg_enabled()) {
+ return false;
+ }
+ return s390_cpu_has_mcck_int(cpu) ||
+ s390_cpu_has_ext_int(cpu) ||
+ s390_cpu_has_io_int(cpu);
+#else
+ return false;
+#endif
+}