[PATCH] target/loongarch: Set CPU_INTERRUPT_HARD unless no pending irq

Bibo Mao posted 1 patch 3 days, 16 hours ago
target/loongarch/cpu.c            | 14 ++++----------
target/loongarch/internals.h      |  2 +-
target/loongarch/tcg/csr_helper.c |  2 +-
3 files changed, 6 insertions(+), 12 deletions(-)
[PATCH] target/loongarch: Set CPU_INTERRUPT_HARD unless no pending irq
Posted by Bibo Mao 3 days, 16 hours ago
On LoongArch CPU_INTERRUPT_HARD is set only when interrupt is injected
at the first time. Function cpu_interrupt() is not called if there is
pending irq already, this will not set CPU_INTERRUPT_HARD bit, however
QEMU TCG framework will clear CPU_INTERRUPT_HARD bit when handling IRQ
flow. There will be new interrupt lost issue when handling old one,
the similar with other architectures set CPU_INTERRUPT_HARD bit always if
there is pending interrupt.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 target/loongarch/cpu.c            | 14 ++++----------
 target/loongarch/internals.h      |  2 +-
 target/loongarch/tcg/csr_helper.c |  2 +-
 3 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f22f64efb8..54c2699897 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -58,20 +58,16 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
 #ifndef CONFIG_USER_ONLY
 #include "hw/loongarch/virt.h"
 
-void loongarch_cpu_update_irq(LoongArchCPU *cpu, uint64_t old)
+void loongarch_cpu_update_irq(LoongArchCPU *cpu)
 {
     CPULoongArchState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     CPUSysState *sys = env_sys(env);
 
     if (FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS)) {
-        if (!FIELD_EX64(old, CSR_ESTAT, IS)) {
-            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-        }
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
-        if (FIELD_EX64(old, CSR_ESTAT, IS)) {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-        }
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -81,13 +77,11 @@ static void loongarch_cpu_self_set_irq(CPUState *cs, run_on_cpu_data data)
     CPULoongArchState *env = cpu_env(cs);
     CPUSysState *sys = env_sys(env);
     int irq, level;
-    uint64_t old;
 
     irq = data.host_int & ~BIT(31);
     level = (data.host_int >> 31) & 1;
-    old = sys->CSR_ESTAT;
     sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, irq, 1, level != 0);
-    loongarch_cpu_update_irq(cpu, old);
+    loongarch_cpu_update_irq(cpu);
 }
 
 void loongarch_cpu_set_irq(void *opaque, int irq, int level)
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index f9a0680fe0..ff956823fd 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -31,7 +31,7 @@ void restore_fp_status(CPULoongArchState *env);
 #ifndef CONFIG_USER_ONLY
 extern const VMStateDescription vmstate_loongarch_cpu;
 
-void loongarch_cpu_update_irq(LoongArchCPU *cpu, uint64_t old);
+void loongarch_cpu_update_irq(LoongArchCPU *cpu);
 void loongarch_cpu_set_irq(void *opaque, int irq, int level);
 
 void cpu_loongarch_timer_cb(void *opaque);
diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
index 88656b5344..1a6919417f 100644
--- a/target/loongarch/tcg/csr_helper.c
+++ b/target/loongarch/tcg/csr_helper.c
@@ -111,7 +111,7 @@ target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
      */
     if (sys->CSR_ESTAT != old_v) {
         bql_lock();
-        loongarch_cpu_update_irq(env_archcpu(env), old_v);
+        loongarch_cpu_update_irq(env_archcpu(env));
         bql_unlock();
     }
 

base-commit: 7074591d7954876951f84c15b994a43251d5a3c1
-- 
2.54.0
Re: [PATCH] target/loongarch: Set CPU_INTERRUPT_HARD unless no pending irq
Posted by Philippe Mathieu-Daudé 3 days, 14 hours ago
On 23/9/26 05:10, Bibo Mao wrote:
> On LoongArch CPU_INTERRUPT_HARD is set only when interrupt is injected
> at the first time. Function cpu_interrupt() is not called if there is
> pending irq already, this will not set CPU_INTERRUPT_HARD bit, however
> QEMU TCG framework will clear CPU_INTERRUPT_HARD bit when handling IRQ
> flow. There will be new interrupt lost issue when handling old one,
> the similar with other architectures set CPU_INTERRUPT_HARD bit always if
> there is pending interrupt.
> 
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>   target/loongarch/cpu.c            | 14 ++++----------
>   target/loongarch/internals.h      |  2 +-
>   target/loongarch/tcg/csr_helper.c |  2 +-
>   3 files changed, 6 insertions(+), 12 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>