target/loongarch/cpu.c | 14 ++++---------- target/loongarch/internals.h | 2 +- target/loongarch/tcg/csr_helper.c | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-)
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
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>
© 2016 - 2026 Red Hat, Inc.