qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 12/13] target/ppc: introduce ppc_maybe_interrupt


From: Matheus Ferst
Subject: [RFC PATCH 12/13] target/ppc: introduce ppc_maybe_interrupt
Date: Mon, 15 Aug 2022 13:20:18 -0300

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.ferst@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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]