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