diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 77d55c9e1e5758dc471a457442eee7f066d8089d..b0517475fab422de84fd5208677585b8014ded53 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -56,10 +56,12 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value) 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) diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index 44e9b2c6a67621ab7ecdbadceb42346e35b6b4bd..050d5a61f174ec5390e998faefd232e00418cc5f 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -435,24 +435,16 @@ void s390_cpu_do_interrupt(CPUState *cs) 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) { @@ -474,6 +466,7 @@ void s390_cpu_do_interrupt(CPUState *cs) } cs->exception_index = -1; + /* we might still have pending interrupts, but not deliverable */ if (!env->pending_int) { cs->interrupt_request &= ~CPU_INTERRUPT_HARD; } @@ -490,7 +483,7 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 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; } diff --git a/target/s390x/internal.h b/target/s390x/internal.h index f67c2a1785a06b70aa2a478ae00d76e0daae1005..e41fb2e38eb4f2fa141f70688e5cc9a51d775160 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -364,6 +364,10 @@ void cpu_inject_clock_comparator(S390CPU *cpu); 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 */ diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c index bb7cc7f87fc8abc48376b08610b3f1cf20bb4181..0cb65a8c469eeda31f8aed8876b2c5a7cb3e432a 100644 --- a/target/s390x/interrupt.c +++ b/target/s390x/interrupt.c @@ -190,4 +190,50 @@ void s390_crw_mchk(void) } } +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 +}