All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/3] PowerPC interrupt rework
@ 2022-10-21 14:21 Matheus Ferst
  2022-10-21 14:21 ` [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt Matheus Ferst
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Matheus Ferst @ 2022-10-21 14:21 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: clg, danielhb413, david, groug, fbarrat, alex.bennee, farosas,
	Matheus Ferst

This version fixes the problems found by Daniel with e500 tests and
rebases on ppc-next.

Based-on: https://gitlab.com/danielhb/qemu/-/tree/ppc-next

Matheus Ferst (3):
  target/ppc: introduce ppc_maybe_interrupt
  target/ppc: unify cpu->has_work based on cs->interrupt_request
  target/ppc: move the p*_interrupt_powersave methods to excp_helper.c

 hw/ppc/pnv_core.c        |   1 +
 hw/ppc/ppc.c             |   7 +-
 hw/ppc/spapr_hcall.c     |   6 ++
 hw/ppc/spapr_rtas.c      |   2 +-
 target/ppc/cpu.c         |   2 +
 target/ppc/cpu.h         |   1 +
 target/ppc/cpu_init.c    | 196 +--------------------------------------
 target/ppc/excp_helper.c | 144 ++++++++++++++++++++++++++++
 target/ppc/helper.h      |   1 +
 target/ppc/helper_regs.c |   2 +
 target/ppc/internal.h    |   6 --
 target/ppc/translate.c   |  11 ++-
 12 files changed, 170 insertions(+), 209 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt
  2022-10-21 14:21 [PATCH v4 0/3] PowerPC interrupt rework Matheus Ferst
@ 2022-10-21 14:21 ` Matheus Ferst
  2022-10-22 18:28   ` Daniel Henrique Barboza
  2022-10-21 14:21 ` [PATCH v4 2/3] target/ppc: unify cpu->has_work based on cs->interrupt_request Matheus Ferst
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Matheus Ferst @ 2022-10-21 14:21 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: clg, danielhb413, david, groug, fbarrat, alex.bennee, farosas,
	Matheus Ferst

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>
---
v4:
  - Call gen_icount_io_start before helper_ppc_maybe_interrupt to avoid
    the cpu_abort("Raised interrupt while not in I/O function")
    in icount_handle_interrupt
---
 hw/ppc/pnv_core.c        |  1 +
 hw/ppc/ppc.c             |  7 +------
 hw/ppc/spapr_hcall.c     |  6 ++++++
 hw/ppc/spapr_rtas.c      |  2 +-
 target/ppc/cpu.c         |  2 ++
 target/ppc/cpu.h         |  1 +
 target/ppc/excp_helper.c | 42 ++++++++++++++++++++++++++++++++++++++++
 target/ppc/helper.h      |  1 +
 target/ppc/helper_regs.c |  2 ++
 target/ppc/translate.c   | 11 ++++++++++-
 10 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 19e8eb885f..9ee79192dd 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -58,6 +58,7 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
     env->msr |= MSR_HVB; /* Hypervisor mode */
     env->spr[SPR_HRMOR] = pc->hrmor;
     hreg_compute_hflags(env);
+    ppc_maybe_interrupt(env);
 
     pcc->intc_reset(pc->chip, cpu);
 }
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/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 891206e893..925ff523cc 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -490,6 +490,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr,
 
     env->msr |= (1ULL << MSR_EE);
     hreg_compute_hflags(env);
+    ppc_maybe_interrupt(env);
 
     if (spapr_cpu->prod) {
         spapr_cpu->prod = false;
@@ -500,6 +501,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr,
         cs->halted = 1;
         cs->exception_index = EXCP_HLT;
         cs->exit_request = 1;
+        ppc_maybe_interrupt(env);
     }
 
     return H_SUCCESS;
@@ -521,6 +523,7 @@ static target_ulong h_confer_self(PowerPCCPU *cpu)
     cs->halted = 1;
     cs->exception_index = EXCP_HALTED;
     cs->exit_request = 1;
+    ppc_maybe_interrupt(&cpu->env);
 
     return H_SUCCESS;
 }
@@ -633,6 +636,7 @@ static target_ulong h_prod(PowerPCCPU *cpu, SpaprMachineState *spapr,
     spapr_cpu = spapr_cpu_state(tcpu);
     spapr_cpu->prod = true;
     cs->halted = 0;
+    ppc_maybe_interrupt(&cpu->env);
     qemu_cpu_kick(cs);
 
     return H_SUCCESS;
@@ -1669,6 +1673,7 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu,
     spapr_cpu->in_nested = true;
 
     hreg_compute_hflags(env);
+    ppc_maybe_interrupt(env);
     tlb_flush(cs);
     env->reserve_addr = -1; /* Reset the reservation */
 
@@ -1810,6 +1815,7 @@ out_restore_l1:
     spapr_cpu->in_nested = false;
 
     hreg_compute_hflags(env);
+    ppc_maybe_interrupt(env);
     tlb_flush(cs);
     env->reserve_addr = -1; /* Reset the reservation */
 
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index d58b65e88f..3f664ea02c 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -214,9 +214,9 @@ static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
      * guest.
      * For the same reason, set PSSCR_EC.
      */
-    ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
     env->spr[SPR_PSSCR] |= PSSCR_EC;
     cs->halted = 1;
+    ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
     kvmppc_set_reg_ppc_online(cpu, 0);
     qemu_cpu_kick(cs);
 }
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index e95b4c5ee1..1a97b41c6b 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -82,6 +82,8 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
     env->spr[SPR_LPCR] = val & pcc->lpcr_mask;
     /* The gtse bit affects hflags */
     hreg_compute_hflags(env);
+
+    ppc_maybe_interrupt(env);
 }
 #endif
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index ad758b00e5..cc2d0305ff 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, DumpState *s);
 #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 e9beb002e3..8b67053728 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -390,6 +390,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
     env->nip = vector;
     env->msr = msr;
     hreg_compute_hflags(env);
+    ppc_maybe_interrupt(env);
 
     powerpc_reset_excp_state(cpu);
 
@@ -2050,6 +2051,40 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
     }
 }
 
+/*
+ * Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
+ * delivered and clears CPU_INTERRUPT_HARD otherwise.
+ *
+ * This method is called by ppc_set_interrupt when an interrupt is raised or
+ * lowered, and should also be called whenever an interrupt masking condition
+ * is changed, e.g.:
+ *  - When relevant bits of MSR are altered, like EE, HV, PR, etc.;
+ *  - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.;
+ *  - When PSSCR[EC] or env->resume_as_sreset are changed;
+ *  - When cs->halted is changed and the CPU has a different interrupt masking
+ *    logic in power-saving mode (e.g., POWER7/8/9/10);
+ */
+void ppc_maybe_interrupt(CPUPPCState *env)
+{
+    CPUState *cs = env_cpu(env);
+    bool locked = false;
+
+    if (!qemu_mutex_iothread_locked()) {
+        locked = true;
+        qemu_mutex_lock_iothread();
+    }
+
+    if (ppc_next_unmasked_interrupt(env)) {
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
+
+    if (locked) {
+        qemu_mutex_unlock_iothread();
+    }
+}
+
 #if defined(TARGET_PPC64)
 static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
 {
@@ -2497,6 +2532,11 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
     }
 }
 
+void helper_ppc_maybe_interrupt(CPUPPCState *env)
+{
+    ppc_maybe_interrupt(env);
+}
+
 #if defined(TARGET_PPC64)
 void helper_scv(CPUPPCState *env, uint32_t lev)
 {
@@ -2517,6 +2557,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.h b/target/ppc/helper.h
index 8344fe39c6..25533b8f33 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -10,6 +10,7 @@ DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl)
 DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl)
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_2(store_msr, void, env, tl)
+DEF_HELPER_1(ppc_maybe_interrupt, void, env)
 DEF_HELPER_1(rfi, void, env)
 DEF_HELPER_1(40x_rfci, void, env)
 DEF_HELPER_1(rfci, void, env)
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 64893e3670..aa9f47d7d1 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -305,6 +305,14 @@ static void gen_icount_io_start(DisasContext *ctx)
     }
 }
 
+#if !defined(CONFIG_USER_ONLY)
+static void gen_ppc_maybe_interrupt(DisasContext *ctx)
+{
+    gen_icount_io_start(ctx);
+    gen_helper_ppc_maybe_interrupt(cpu_env);
+}
+#endif
+
 /*
  * Tells the caller what is the appropriate exception to generate and prepares
  * SPR registers for this exception.
@@ -6161,7 +6169,6 @@ static void gen_tlbilx_booke206(DisasContext *ctx)
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
-
 /* wrtee */
 static void gen_wrtee(DisasContext *ctx)
 {
@@ -6175,6 +6182,7 @@ static void gen_wrtee(DisasContext *ctx)
     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);
+    gen_ppc_maybe_interrupt(ctx);
     tcg_temp_free(t0);
     /*
      * Stop translation to have a chance to raise an exception if we
@@ -6193,6 +6201,7 @@ static void gen_wrteei(DisasContext *ctx)
     CHK_SV(ctx);
     if (ctx->opcode & 0x00008000) {
         tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
+        gen_ppc_maybe_interrupt(ctx);
         /* Stop translation to have a chance to raise an exception */
         ctx->base.is_jmp = DISAS_EXIT_UPDATE;
     } else {
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 2/3] target/ppc: unify cpu->has_work based on cs->interrupt_request
  2022-10-21 14:21 [PATCH v4 0/3] PowerPC interrupt rework Matheus Ferst
  2022-10-21 14:21 ` [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt Matheus Ferst
@ 2022-10-21 14:21 ` Matheus Ferst
  2022-10-21 14:21 ` [PATCH v4 3/3] target/ppc: move the p*_interrupt_powersave methods to excp_helper.c Matheus Ferst
  2022-10-22 18:29 ` [PATCH v4 0/3] PowerPC interrupt rework Daniel Henrique Barboza
  3 siblings, 0 replies; 6+ messages in thread
From: Matheus Ferst @ 2022-10-21 14:21 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: clg, danielhb413, david, groug, fbarrat, alex.bennee, farosas,
	Matheus Ferst

Now that cs->interrupt_request indicates if there is any unmasked
interrupt, checking if the CPU has work to do can be simplified to a
single check that works for all CPU models.

Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br>
---
 target/ppc/cpu_init.c | 94 +------------------------------------------
 1 file changed, 1 insertion(+), 93 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 0adc866485..15d549ad38 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5984,27 +5984,10 @@ int p7_interrupt_powersave(CPUPPCState *env)
     return 0;
 }
 
-static bool cpu_has_work_POWER7(CPUState *cs)
-{
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    CPUPPCState *env = &cpu->env;
-
-    if (cs->halted) {
-        if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
-            return false;
-        }
-        return p7_interrupt_powersave(env) != 0;
-    } else {
-        return FIELD_EX64(env->msr, MSR, EE) &&
-               (cs->interrupt_request & CPU_INTERRUPT_HARD);
-    }
-}
-
 POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    CPUClass *cc = CPU_CLASS(oc);
 
     dc->fw_name = "PowerPC,POWER7";
     dc->desc = "POWER7";
@@ -6013,7 +5996,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
-    cc->has_work = cpu_has_work_POWER7;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6170,27 +6152,10 @@ int p8_interrupt_powersave(CPUPPCState *env)
     return 0;
 }
 
-static bool cpu_has_work_POWER8(CPUState *cs)
-{
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    CPUPPCState *env = &cpu->env;
-
-    if (cs->halted) {
-        if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
-            return false;
-        }
-        return p8_interrupt_powersave(env) != 0;
-    } else {
-        return FIELD_EX64(env->msr, MSR, EE) &&
-               (cs->interrupt_request & CPU_INTERRUPT_HARD);
-    }
-}
-
 POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    CPUClass *cc = CPU_CLASS(oc);
 
     dc->fw_name = "PowerPC,POWER8";
     dc->desc = "POWER8";
@@ -6199,7 +6164,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
     pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER8;
     pcc->check_pow = check_pow_nocheck;
-    cc->has_work = cpu_has_work_POWER8;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6407,35 +6371,10 @@ int p9_interrupt_powersave(CPUPPCState *env)
     return 0;
 }
 
-static bool cpu_has_work_POWER9(CPUState *cs)
-{
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    CPUPPCState *env = &cpu->env;
-
-    if (cs->halted) {
-        uint64_t psscr = env->spr[SPR_PSSCR];
-
-        if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
-            return false;
-        }
-
-        /* If EC is clear, just return true on any pending interrupt */
-        if (!(psscr & PSSCR_EC)) {
-            return true;
-        }
-
-        return p9_interrupt_powersave(env) != 0;
-    } else {
-        return FIELD_EX64(env->msr, MSR, EE) &&
-               (cs->interrupt_request & CPU_INTERRUPT_HARD);
-    }
-}
-
 POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    CPUClass *cc = CPU_CLASS(oc);
 
     dc->fw_name = "PowerPC,POWER9";
     dc->desc = "POWER9";
@@ -6445,7 +6384,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
                          PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER9;
     pcc->check_pow = check_pow_nocheck;
-    cc->has_work = cpu_has_work_POWER9;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -6604,35 +6542,10 @@ static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
     return false;
 }
 
-static bool cpu_has_work_POWER10(CPUState *cs)
-{
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    CPUPPCState *env = &cpu->env;
-
-    if (cs->halted) {
-        uint64_t psscr = env->spr[SPR_PSSCR];
-
-        if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
-            return false;
-        }
-
-        /* If EC is clear, just return true on any pending interrupt */
-        if (!(psscr & PSSCR_EC)) {
-            return true;
-        }
-
-        return p9_interrupt_powersave(env) != 0;
-    } else {
-        return FIELD_EX64(env->msr, MSR, EE) &&
-               (cs->interrupt_request & CPU_INTERRUPT_HARD);
-    }
-}
-
 POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    CPUClass *cc = CPU_CLASS(oc);
 
     dc->fw_name = "PowerPC,POWER10";
     dc->desc = "POWER10";
@@ -6643,7 +6556,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
                          PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
     pcc->init_proc = init_proc_POWER10;
     pcc->check_pow = check_pow_nocheck;
-    cc->has_work = cpu_has_work_POWER10;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -7207,11 +7119,7 @@ static vaddr ppc_cpu_get_pc(CPUState *cs)
 
 static bool ppc_cpu_has_work(CPUState *cs)
 {
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    CPUPPCState *env = &cpu->env;
-
-    return FIELD_EX64(env->msr, MSR, EE) &&
-           (cs->interrupt_request & CPU_INTERRUPT_HARD);
+    return cs->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 static void ppc_cpu_reset(DeviceState *dev)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 3/3] target/ppc: move the p*_interrupt_powersave methods to excp_helper.c
  2022-10-21 14:21 [PATCH v4 0/3] PowerPC interrupt rework Matheus Ferst
  2022-10-21 14:21 ` [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt Matheus Ferst
  2022-10-21 14:21 ` [PATCH v4 2/3] target/ppc: unify cpu->has_work based on cs->interrupt_request Matheus Ferst
@ 2022-10-21 14:21 ` Matheus Ferst
  2022-10-22 18:29 ` [PATCH v4 0/3] PowerPC interrupt rework Daniel Henrique Barboza
  3 siblings, 0 replies; 6+ messages in thread
From: Matheus Ferst @ 2022-10-21 14:21 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: clg, danielhb413, david, groug, fbarrat, alex.bennee, farosas,
	Matheus Ferst

Move the methods to excp_helper.c and make them static.

Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br>
---
 target/ppc/cpu_init.c    | 102 ---------------------------------------
 target/ppc/excp_helper.c | 102 +++++++++++++++++++++++++++++++++++++++
 target/ppc/internal.h    |   6 ---
 3 files changed, 102 insertions(+), 108 deletions(-)

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 15d549ad38..6f3539f13a 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5960,30 +5960,6 @@ static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
     return true;
 }
 
-int p7_interrupt_powersave(CPUPPCState *env)
-{
-    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
-        (env->spr[SPR_LPCR] & LPCR_P7_PECE0)) {
-        return PPC_INTERRUPT_EXT;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
-        (env->spr[SPR_LPCR] & LPCR_P7_PECE1)) {
-        return PPC_INTERRUPT_DECR;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
-        (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
-        return PPC_INTERRUPT_MCK;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
-        (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
-        return PPC_INTERRUPT_HMI;
-    }
-    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
-        return PPC_INTERRUPT_RESET;
-    }
-    return 0;
-}
-
 POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -6120,38 +6096,6 @@ static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
     return true;
 }
 
-int p8_interrupt_powersave(CPUPPCState *env)
-{
-    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE2)) {
-        return PPC_INTERRUPT_EXT;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE3)) {
-        return PPC_INTERRUPT_DECR;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
-        return PPC_INTERRUPT_MCK;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
-        return PPC_INTERRUPT_HMI;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE0)) {
-        return PPC_INTERRUPT_DOORBELL;
-    }
-    if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
-        (env->spr[SPR_LPCR] & LPCR_P8_PECE1)) {
-        return PPC_INTERRUPT_HDOORBELL;
-    }
-    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
-        return PPC_INTERRUPT_RESET;
-    }
-    return 0;
-}
-
 POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -6325,52 +6269,6 @@ static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
     return false;
 }
 
-int p9_interrupt_powersave(CPUPPCState *env)
-{
-    /* External Exception */
-    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
-        (env->spr[SPR_LPCR] & LPCR_EEE)) {
-        bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
-        if (!heic || !FIELD_EX64_HV(env->msr) ||
-            FIELD_EX64(env->msr, MSR, PR)) {
-            return PPC_INTERRUPT_EXT;
-        }
-    }
-    /* Decrementer Exception */
-    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
-        (env->spr[SPR_LPCR] & LPCR_DEE)) {
-        return PPC_INTERRUPT_DECR;
-    }
-    /* Machine Check or Hypervisor Maintenance Exception */
-    if (env->spr[SPR_LPCR] & LPCR_OEE) {
-        if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
-            return PPC_INTERRUPT_MCK;
-        }
-        if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
-            return PPC_INTERRUPT_HMI;
-        }
-    }
-    /* Privileged Doorbell Exception */
-    if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
-        (env->spr[SPR_LPCR] & LPCR_PDEE)) {
-        return PPC_INTERRUPT_DOORBELL;
-    }
-    /* Hypervisor Doorbell Exception */
-    if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
-        (env->spr[SPR_LPCR] & LPCR_HDEE)) {
-        return PPC_INTERRUPT_HDOORBELL;
-    }
-    /* Hypervisor virtualization exception */
-    if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
-        (env->spr[SPR_LPCR] & LPCR_HVEE)) {
-        return PPC_INTERRUPT_HVIRT;
-    }
-    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
-        return PPC_INTERRUPT_RESET;
-    }
-    return 0;
-}
-
 POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 8b67053728..abe2669d8e 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1692,6 +1692,30 @@ void ppc_cpu_do_interrupt(CPUState *cs)
      PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
      PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
 
+static int p7_interrupt_powersave(CPUPPCState *env)
+{
+    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
+        (env->spr[SPR_LPCR] & LPCR_P7_PECE0)) {
+        return PPC_INTERRUPT_EXT;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
+        (env->spr[SPR_LPCR] & LPCR_P7_PECE1)) {
+        return PPC_INTERRUPT_DECR;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
+        (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
+        return PPC_INTERRUPT_MCK;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
+        (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
+        return PPC_INTERRUPT_HMI;
+    }
+    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+        return PPC_INTERRUPT_RESET;
+    }
+    return 0;
+}
+
 static int p7_next_unmasked_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = env_archcpu(env);
@@ -1756,6 +1780,38 @@ static int p7_next_unmasked_interrupt(CPUPPCState *env)
     PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL |  \
     PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
 
+static int p8_interrupt_powersave(CPUPPCState *env)
+{
+    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE2)) {
+        return PPC_INTERRUPT_EXT;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE3)) {
+        return PPC_INTERRUPT_DECR;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
+        return PPC_INTERRUPT_MCK;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
+        return PPC_INTERRUPT_HMI;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE0)) {
+        return PPC_INTERRUPT_DOORBELL;
+    }
+    if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
+        (env->spr[SPR_LPCR] & LPCR_P8_PECE1)) {
+        return PPC_INTERRUPT_HDOORBELL;
+    }
+    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+        return PPC_INTERRUPT_RESET;
+    }
+    return 0;
+}
+
 static int p8_next_unmasked_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = env_archcpu(env);
@@ -1831,6 +1887,52 @@ static int p8_next_unmasked_interrupt(CPUPPCState *env)
      PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT |  \
      PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
 
+static int p9_interrupt_powersave(CPUPPCState *env)
+{
+    /* External Exception */
+    if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
+        (env->spr[SPR_LPCR] & LPCR_EEE)) {
+        bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
+        if (!heic || !FIELD_EX64_HV(env->msr) ||
+            FIELD_EX64(env->msr, MSR, PR)) {
+            return PPC_INTERRUPT_EXT;
+        }
+    }
+    /* Decrementer Exception */
+    if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
+        (env->spr[SPR_LPCR] & LPCR_DEE)) {
+        return PPC_INTERRUPT_DECR;
+    }
+    /* Machine Check or Hypervisor Maintenance Exception */
+    if (env->spr[SPR_LPCR] & LPCR_OEE) {
+        if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+            return PPC_INTERRUPT_MCK;
+        }
+        if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
+            return PPC_INTERRUPT_HMI;
+        }
+    }
+    /* Privileged Doorbell Exception */
+    if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
+        (env->spr[SPR_LPCR] & LPCR_PDEE)) {
+        return PPC_INTERRUPT_DOORBELL;
+    }
+    /* Hypervisor Doorbell Exception */
+    if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
+        (env->spr[SPR_LPCR] & LPCR_HDEE)) {
+        return PPC_INTERRUPT_HDOORBELL;
+    }
+    /* Hypervisor virtualization exception */
+    if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
+        (env->spr[SPR_LPCR] & LPCR_HVEE)) {
+        return PPC_INTERRUPT_HVIRT;
+    }
+    if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+        return PPC_INTERRUPT_RESET;
+    }
+    return 0;
+}
+
 static int p9_next_unmasked_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = env_archcpu(env);
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 25827ebf6f..337a362205 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -306,10 +306,4 @@ static inline int ger_pack_masks(int pmsk, int ymsk, int xmsk)
     return msk;
 }
 
-#if defined(TARGET_PPC64)
-int p9_interrupt_powersave(CPUPPCState *env);
-int p8_interrupt_powersave(CPUPPCState *env);
-int p7_interrupt_powersave(CPUPPCState *env);
-#endif
-
 #endif /* PPC_INTERNAL_H */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt
  2022-10-21 14:21 ` [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt Matheus Ferst
@ 2022-10-22 18:28   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Henrique Barboza @ 2022-10-22 18:28 UTC (permalink / raw)
  To: Matheus Ferst, qemu-devel, qemu-ppc
  Cc: clg, david, groug, fbarrat, alex.bennee, farosas



On 10/21/22 11:21, Matheus Ferst wrote:
> 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>
> ---

Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>

> v4:
>    - Call gen_icount_io_start before helper_ppc_maybe_interrupt to avoid
>      the cpu_abort("Raised interrupt while not in I/O function")
>      in icount_handle_interrupt
> ---
>   hw/ppc/pnv_core.c        |  1 +
>   hw/ppc/ppc.c             |  7 +------
>   hw/ppc/spapr_hcall.c     |  6 ++++++
>   hw/ppc/spapr_rtas.c      |  2 +-
>   target/ppc/cpu.c         |  2 ++
>   target/ppc/cpu.h         |  1 +
>   target/ppc/excp_helper.c | 42 ++++++++++++++++++++++++++++++++++++++++
>   target/ppc/helper.h      |  1 +
>   target/ppc/helper_regs.c |  2 ++
>   target/ppc/translate.c   | 11 ++++++++++-
>   10 files changed, 67 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
> index 19e8eb885f..9ee79192dd 100644
> --- a/hw/ppc/pnv_core.c
> +++ b/hw/ppc/pnv_core.c
> @@ -58,6 +58,7 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
>       env->msr |= MSR_HVB; /* Hypervisor mode */
>       env->spr[SPR_HRMOR] = pc->hrmor;
>       hreg_compute_hflags(env);
> +    ppc_maybe_interrupt(env);
>   
>       pcc->intc_reset(pc->chip, cpu);
>   }
> 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/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 891206e893..925ff523cc 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -490,6 +490,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr,
>   
>       env->msr |= (1ULL << MSR_EE);
>       hreg_compute_hflags(env);
> +    ppc_maybe_interrupt(env);
>   
>       if (spapr_cpu->prod) {
>           spapr_cpu->prod = false;
> @@ -500,6 +501,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, SpaprMachineState *spapr,
>           cs->halted = 1;
>           cs->exception_index = EXCP_HLT;
>           cs->exit_request = 1;
> +        ppc_maybe_interrupt(env);
>       }
>   
>       return H_SUCCESS;
> @@ -521,6 +523,7 @@ static target_ulong h_confer_self(PowerPCCPU *cpu)
>       cs->halted = 1;
>       cs->exception_index = EXCP_HALTED;
>       cs->exit_request = 1;
> +    ppc_maybe_interrupt(&cpu->env);
>   
>       return H_SUCCESS;
>   }
> @@ -633,6 +636,7 @@ static target_ulong h_prod(PowerPCCPU *cpu, SpaprMachineState *spapr,
>       spapr_cpu = spapr_cpu_state(tcpu);
>       spapr_cpu->prod = true;
>       cs->halted = 0;
> +    ppc_maybe_interrupt(&cpu->env);
>       qemu_cpu_kick(cs);
>   
>       return H_SUCCESS;
> @@ -1669,6 +1673,7 @@ static target_ulong h_enter_nested(PowerPCCPU *cpu,
>       spapr_cpu->in_nested = true;
>   
>       hreg_compute_hflags(env);
> +    ppc_maybe_interrupt(env);
>       tlb_flush(cs);
>       env->reserve_addr = -1; /* Reset the reservation */
>   
> @@ -1810,6 +1815,7 @@ out_restore_l1:
>       spapr_cpu->in_nested = false;
>   
>       hreg_compute_hflags(env);
> +    ppc_maybe_interrupt(env);
>       tlb_flush(cs);
>       env->reserve_addr = -1; /* Reset the reservation */
>   
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index d58b65e88f..3f664ea02c 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -214,9 +214,9 @@ static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
>        * guest.
>        * For the same reason, set PSSCR_EC.
>        */
> -    ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
>       env->spr[SPR_PSSCR] |= PSSCR_EC;
>       cs->halted = 1;
> +    ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
>       kvmppc_set_reg_ppc_online(cpu, 0);
>       qemu_cpu_kick(cs);
>   }
> diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
> index e95b4c5ee1..1a97b41c6b 100644
> --- a/target/ppc/cpu.c
> +++ b/target/ppc/cpu.c
> @@ -82,6 +82,8 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
>       env->spr[SPR_LPCR] = val & pcc->lpcr_mask;
>       /* The gtse bit affects hflags */
>       hreg_compute_hflags(env);
> +
> +    ppc_maybe_interrupt(env);
>   }
>   #endif
>   
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index ad758b00e5..cc2d0305ff 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, DumpState *s);
>   #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 e9beb002e3..8b67053728 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -390,6 +390,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
>       env->nip = vector;
>       env->msr = msr;
>       hreg_compute_hflags(env);
> +    ppc_maybe_interrupt(env);
>   
>       powerpc_reset_excp_state(cpu);
>   
> @@ -2050,6 +2051,40 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
>       }
>   }
>   
> +/*
> + * Sets CPU_INTERRUPT_HARD if there is at least one unmasked interrupt to be
> + * delivered and clears CPU_INTERRUPT_HARD otherwise.
> + *
> + * This method is called by ppc_set_interrupt when an interrupt is raised or
> + * lowered, and should also be called whenever an interrupt masking condition
> + * is changed, e.g.:
> + *  - When relevant bits of MSR are altered, like EE, HV, PR, etc.;
> + *  - When relevant bits of LPCR are altered, like PECE, HDICE, HVICE, etc.;
> + *  - When PSSCR[EC] or env->resume_as_sreset are changed;
> + *  - When cs->halted is changed and the CPU has a different interrupt masking
> + *    logic in power-saving mode (e.g., POWER7/8/9/10);
> + */
> +void ppc_maybe_interrupt(CPUPPCState *env)
> +{
> +    CPUState *cs = env_cpu(env);
> +    bool locked = false;
> +
> +    if (!qemu_mutex_iothread_locked()) {
> +        locked = true;
> +        qemu_mutex_lock_iothread();
> +    }
> +
> +    if (ppc_next_unmasked_interrupt(env)) {
> +        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> +    } else {
> +        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> +    }
> +
> +    if (locked) {
> +        qemu_mutex_unlock_iothread();
> +    }
> +}
> +
>   #if defined(TARGET_PPC64)
>   static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
>   {
> @@ -2497,6 +2532,11 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
>       }
>   }
>   
> +void helper_ppc_maybe_interrupt(CPUPPCState *env)
> +{
> +    ppc_maybe_interrupt(env);
> +}
> +
>   #if defined(TARGET_PPC64)
>   void helper_scv(CPUPPCState *env, uint32_t lev)
>   {
> @@ -2517,6 +2557,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.h b/target/ppc/helper.h
> index 8344fe39c6..25533b8f33 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -10,6 +10,7 @@ DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl)
>   DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl)
>   #if !defined(CONFIG_USER_ONLY)
>   DEF_HELPER_2(store_msr, void, env, tl)
> +DEF_HELPER_1(ppc_maybe_interrupt, void, env)
>   DEF_HELPER_1(rfi, void, env)
>   DEF_HELPER_1(40x_rfci, void, env)
>   DEF_HELPER_1(rfci, void, env)
> 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 64893e3670..aa9f47d7d1 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -305,6 +305,14 @@ static void gen_icount_io_start(DisasContext *ctx)
>       }
>   }
>   
> +#if !defined(CONFIG_USER_ONLY)
> +static void gen_ppc_maybe_interrupt(DisasContext *ctx)
> +{
> +    gen_icount_io_start(ctx);
> +    gen_helper_ppc_maybe_interrupt(cpu_env);
> +}
> +#endif
> +
>   /*
>    * Tells the caller what is the appropriate exception to generate and prepares
>    * SPR registers for this exception.
> @@ -6161,7 +6169,6 @@ static void gen_tlbilx_booke206(DisasContext *ctx)
>   #endif /* defined(CONFIG_USER_ONLY) */
>   }
>   
> -
>   /* wrtee */
>   static void gen_wrtee(DisasContext *ctx)
>   {
> @@ -6175,6 +6182,7 @@ static void gen_wrtee(DisasContext *ctx)
>       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);
> +    gen_ppc_maybe_interrupt(ctx);
>       tcg_temp_free(t0);
>       /*
>        * Stop translation to have a chance to raise an exception if we
> @@ -6193,6 +6201,7 @@ static void gen_wrteei(DisasContext *ctx)
>       CHK_SV(ctx);
>       if (ctx->opcode & 0x00008000) {
>           tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
> +        gen_ppc_maybe_interrupt(ctx);
>           /* Stop translation to have a chance to raise an exception */
>           ctx->base.is_jmp = DISAS_EXIT_UPDATE;
>       } else {


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 0/3] PowerPC interrupt rework
  2022-10-21 14:21 [PATCH v4 0/3] PowerPC interrupt rework Matheus Ferst
                   ` (2 preceding siblings ...)
  2022-10-21 14:21 ` [PATCH v4 3/3] target/ppc: move the p*_interrupt_powersave methods to excp_helper.c Matheus Ferst
@ 2022-10-22 18:29 ` Daniel Henrique Barboza
  3 siblings, 0 replies; 6+ messages in thread
From: Daniel Henrique Barboza @ 2022-10-22 18:29 UTC (permalink / raw)
  To: Matheus Ferst, qemu-devel, qemu-ppc
  Cc: clg, david, groug, fbarrat, alex.bennee, farosas

Queued in gitlab.com/danielhb/qemu/tree/ppc-next. Thanks,


Daniel

On 10/21/22 11:21, Matheus Ferst wrote:
> This version fixes the problems found by Daniel with e500 tests and
> rebases on ppc-next.
> 
> Based-on: https://gitlab.com/danielhb/qemu/-/tree/ppc-next
> 
> Matheus Ferst (3):
>    target/ppc: introduce ppc_maybe_interrupt
>    target/ppc: unify cpu->has_work based on cs->interrupt_request
>    target/ppc: move the p*_interrupt_powersave methods to excp_helper.c
> 
>   hw/ppc/pnv_core.c        |   1 +
>   hw/ppc/ppc.c             |   7 +-
>   hw/ppc/spapr_hcall.c     |   6 ++
>   hw/ppc/spapr_rtas.c      |   2 +-
>   target/ppc/cpu.c         |   2 +
>   target/ppc/cpu.h         |   1 +
>   target/ppc/cpu_init.c    | 196 +--------------------------------------
>   target/ppc/excp_helper.c | 144 ++++++++++++++++++++++++++++
>   target/ppc/helper.h      |   1 +
>   target/ppc/helper_regs.c |   2 +
>   target/ppc/internal.h    |   6 --
>   target/ppc/translate.c   |  11 ++-
>   12 files changed, 170 insertions(+), 209 deletions(-)
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-10-24  2:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-21 14:21 [PATCH v4 0/3] PowerPC interrupt rework Matheus Ferst
2022-10-21 14:21 ` [PATCH v4 1/3] target/ppc: introduce ppc_maybe_interrupt Matheus Ferst
2022-10-22 18:28   ` Daniel Henrique Barboza
2022-10-21 14:21 ` [PATCH v4 2/3] target/ppc: unify cpu->has_work based on cs->interrupt_request Matheus Ferst
2022-10-21 14:21 ` [PATCH v4 3/3] target/ppc: move the p*_interrupt_powersave methods to excp_helper.c Matheus Ferst
2022-10-22 18:29 ` [PATCH v4 0/3] PowerPC interrupt rework Daniel Henrique Barboza

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.