From: David Hildenbrand Date: Thu, 28 Sep 2017 20:36:42 +0000 (+0200) Subject: s390x/tcg: rework checking for deliverable interrupts X-Git-Tag: v2.11.0-rc0~34^2~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8417f904bad50021b432dfea12613345d9fb1f68;p=thirdparty%2Fqemu.git s390x/tcg: rework checking for deliverable interrupts 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 Message-Id: <20170928203708.9376-5-david@redhat.com> Reviewed-by: Richard Henderson Signed-off-by: Cornelia Huck --- diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 77d55c9e1e5..b0517475fab 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 44e9b2c6a67..050d5a61f17 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 f67c2a1785a..e41fb2e38eb 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 bb7cc7f87fc..0cb65a8c469 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 +}