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);
+}
+
 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;
 
-- 
2.41.0


Reply via email to