diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/s390x/cpu.c | 8 | ||||
-rw-r--r-- | target/s390x/excp_helper.c | 21 | ||||
-rw-r--r-- | target/s390x/internal.h | 4 | ||||
-rw-r--r-- | target/s390x/interrupt.c | 46 |
4 files changed, 62 insertions, 17 deletions
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 77d55c9e1e..b0517475fa 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 44e9b2c6a6..050d5a61f1 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 f67c2a1785..e41fb2e38e 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 bb7cc7f87f..0cb65a8c46 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 +} |