On 2025/9/4 下午8:18, Song Gao wrote:
Implement avec set irq and update CSR_MSIS.
Signed-off-by: Song Gao <gaos...@loongson.cn>
---
hw/intc/loongarch_avec.c | 58 ++++++++++++++++++++++++++++++--
include/hw/intc/loongarch_avec.h | 3 ++
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 1f9f376898..03a20a7b60 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -16,6 +16,13 @@
#include "migration/vmstate.h"
#include "trace.h"
#include "hw/qdev-properties.h"
+#include "target/loongarch/cpu.h"
+#include "qemu/error-report.h"
+
+/* msg addr field */
+FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
+FIELD(MSG_ADDR, CPU_NUM, 12, 8)
+FIELD(MSG_ADDR, FIX, 28, 12)
static uint64_t loongarch_avec_mem_read(void *opaque,
hwaddr addr, unsigned size)
@@ -23,13 +30,60 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
return 0;
}
+static void do_set_vcpu_avec_irq(CPUState *cs, run_on_cpu_data data)
+{
+ AVECCore *core = data.host_ptr;
+ CPULoongArchState *env;
+
+ assert(cs->cpu_index == core->dest_cpu);
+ env = &LOONGARCH_CPU(cs)->env;
+ if (core->level) {
+ set_bit(core->pending, &env->CSR_MSGIS[core->pending / 64]);
+ }
+ g_free(core);
+}
+
+
+static void avec_update_csr(AVECCore *core, int cpu_num,
+ int irq_num, int level)
+{
+ CPUState *cs = qemu_get_cpu(cpu_num);
+
+ core->pending = irq_num;
+ core->dest_cpu = cpu_num;
+ core->level = level;
+ async_run_on_cpu(cs, do_set_vcpu_avec_irq,
+ RUN_ON_CPU_HOST_PTR(core));
+}
+
+static void avec_set_irq(LoongArchAVECState *s, int cpu_num,
+ int irq_num, int level)
+{
+ AVECCore *core;
+
+ core = g_new(AVECCore, 1);
+
+ if (level) {
+ avec_update_csr(core, cpu_num, irq_num, level);
+ }
+ qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
Is it possible that qemu_set_irq reaches before async_run_on_cpu?
since it is async function.
Regargs
Bibo Mao
+}
+
static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- return;
+ int irq_num, cpu_num = 0;
+ LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+ uint64_t msg_addr = addr + VIRT_AVEC_BASE;
+ CPUState *cs;
+
+ cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+ cs = cpu_by_arch_id(cpu_num);
+ cpu_num = cs->cpu_index;
+ irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+ avec_set_irq(s, cpu_num, irq_num, 1);
}
-
static const MemoryRegionOps loongarch_avec_ops = {
.read = loongarch_avec_mem_read,
.write = loongarch_avec_mem_write,
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
index 3e8cf7d2c1..83656f8df4 100644
--- a/include/hw/intc/loongarch_avec.h
+++ b/include/hw/intc/loongarch_avec.h
@@ -18,6 +18,9 @@ OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass,
LOONGARCH_AVEC)
typedef struct AVECCore {
CPUState *cpu;
qemu_irq parent_irq;
+ uint64_t pending;
+ uint64_t dest_cpu;
+ bool level;
uint64_t arch_id;
} AVECCore;