This new method will check if any pending interrupt was unmasked and then call cpu_interrupt/cpu_reset_interrupt accordingly. Code that raises/lowers or masks/unmasks interrupts should call this method to keep CPU_INTERRUPT_HARD coherent with env->pending_interrupts.
Signed-off-by: Matheus Ferst <matheus.fe...@eldorado.org.br> --- hw/ppc/ppc.c | 7 +------ target/ppc/cpu.h | 1 + target/ppc/excp_helper.c | 19 +++++++++++++++++++ target/ppc/helper_regs.c | 2 ++ target/ppc/translate.c | 8 ++++++-- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 77e611e81c..dc86c1c7db 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -42,7 +42,6 @@ static void cpu_ppc_tb_start (CPUPPCState *env); void ppc_set_irq(PowerPCCPU *cpu, int irq, int level) { - CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; unsigned int old_pending; bool locked = false; @@ -57,19 +56,15 @@ void ppc_set_irq(PowerPCCPU *cpu, int irq, int level) if (level) { env->pending_interrupts |= irq; - cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { env->pending_interrupts &= ~irq; - if (env->pending_interrupts == 0) { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } } if (old_pending != env->pending_interrupts) { + ppc_maybe_interrupt(env); kvmppc_set_interrupt(cpu, irq, level); } - trace_ppc_irq_set_exit(env, irq, level, env->pending_interrupts, CPU(cpu)->interrupt_request); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 5018296f02..f65e0d7de8 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1358,6 +1358,7 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); #ifndef CONFIG_USER_ONLY +void ppc_maybe_interrupt(CPUPPCState *env); void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); void ppc_cpu_do_system_reset(CPUState *cs); diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index b4c1198ea2..788dcd732a 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2143,6 +2143,23 @@ static int ppc_pending_interrupt(CPUPPCState *env) } } +void ppc_maybe_interrupt(CPUPPCState *env) +{ + CPUState *cs = env_cpu(env); + + if (ppc_pending_interrupt(env)) { + if (!qemu_mutex_iothread_locked()) { + qemu_mutex_lock_iothread(); + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + qemu_mutex_unlock_iothread(); + } else { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + static void ppc_hw_interrupt(CPUPPCState *env, int pending_interrupt) { PowerPCCPU *cpu = env_archcpu(env); @@ -2380,6 +2397,8 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) /* Condition for waking up at 0x100 */ env->resume_as_sreset = (insn != PPC_PM_STOP) || (env->spr[SPR_PSSCR] & PSSCR_EC); + + ppc_maybe_interrupt(env); } #endif /* defined(TARGET_PPC64) */ diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index 12235ea2e9..2e85e124ab 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -260,6 +260,8 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv) env->msr = value; hreg_compute_hflags(env); #if !defined(CONFIG_USER_ONLY) + ppc_maybe_interrupt(env); + if (unlikely(FIELD_EX64(env->msr, MSR, POW))) { if (!env->pending_interrupts && (*env->check_pow)(env)) { cs->halted = 1; diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 388337f81b..60dd66f736 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6174,7 +6174,8 @@ static void gen_wrtee(DisasContext *ctx) t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE)); tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE)); - tcg_gen_or_tl(cpu_msr, cpu_msr, t0); + tcg_gen_or_tl(t0, cpu_msr, t0); + gen_helper_store_msr(cpu_env, t0); tcg_temp_free(t0); /* * Stop translation to have a chance to raise an exception if we @@ -6192,7 +6193,10 @@ static void gen_wrteei(DisasContext *ctx) #else CHK_SV(ctx); if (ctx->opcode & 0x00008000) { - tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE)); + TCGv t0 = tcg_temp_new(); + tcg_gen_ori_tl(t0, cpu_msr, (1 << MSR_EE)); + gen_helper_store_msr(cpu_env, t0); + tcg_temp_free(t0); /* Stop translation to have a chance to raise an exception */ ctx->base.is_jmp = DISAS_EXIT_UPDATE; } else { -- 2.25.1