[PATCH v4 2/3] Add dintc kvm_irqchip_in_kernel support

Song Gao <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Function kvm_dintc_realize() is added if kvm_irqchip_in_kernel is
set. It is to create and initialize DINTC device in kernel mode.
and use kvm_irqchip_send_msi() to send  msi to kernel.

Signed-off-by: Song Gao <[email protected]>
Reviewed-by: Bibo Mao <[email protected]>
---
 hw/intc/loongarch_dintc.c         | 13 +++++++++
 hw/intc/loongarch_dintc_kvm.c     | 48 +++++++++++++++++++++++++++++++
 hw/intc/meson.build               |  2 ++
 include/hw/intc/loongarch_dintc.h | 10 +++++++
 4 files changed, 73 insertions(+)
 create mode 100644 hw/intc/loongarch_dintc_kvm.c

diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c
index e40292887c..94d418261c 100644
--- a/hw/intc/loongarch_dintc.c
+++ b/hw/intc/loongarch_dintc.c
@@ -68,6 +68,15 @@ static void loongarch_dintc_mem_write(void *opaque, hwaddr addr,
     }
     irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
 
+    if (kvm_irqchip_in_kernel()) {
+        MSIMessage msg;
+
+        msg.address = msg_addr;
+        msg.data = val;
+        kvm_irqchip_send_msi(kvm_state, msg);
+        return;
+    }
+
     async_run_on_cpu(cs, do_set_vcpu_dintc_irq,
                          RUN_ON_CPU_HOST_INT(irq_num));
     qemu_set_irq(s->cpu[cpu_num].parent_irq, 1);
@@ -110,6 +119,10 @@ static void loongarch_dintc_realize(DeviceState *dev, Error **errp)
         qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
     }
 
+    if (kvm_irqchip_in_kernel()) {
+        kvm_dintc_realize(dev, errp);
+    }
+
     return;
 }
 
diff --git a/hw/intc/loongarch_dintc_kvm.c b/hw/intc/loongarch_dintc_kvm.c
new file mode 100644
index 0000000000..1137bcd9a6
--- /dev/null
+++ b/hw/intc/loongarch_dintc_kvm.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch DINTC interrupt kvm support
+ *
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/intc/loongarch_dintc.h"
+#include "linux/kvm.h"
+#include "qapi/error.h"
+#include "system/kvm.h"
+
+void kvm_dintc_realize(DeviceState *dev, Error **errp)
+{
+    LoongArchDINTCState *lds = LOONGARCH_DINTC(dev);
+    int ret;
+
+    ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_DMSINTC, false);
+    if (ret < 0) {
+        fprintf(stderr, "create KVM_DEV_TYPE_LOONGARCH_AVEC failed: %s\n",
+               strerror(-ret));
+        abort();
+    }
+    lds->dev_fd = ret;
+
+    /* init dintc config */
+    lds->msg_addr_base = VIRT_DINTC_BASE;
+    lds->msg_addr_size = VIRT_DINTC_SIZE;
+
+    ret = kvm_device_access(lds->dev_fd, KVM_DEV_LOONGARCH_DMSINTC_GRP_CTRL,
+                            KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_BASE,
+                            &lds->msg_addr_base, true, NULL);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_DEV_LOONGARCH_DINTC_MSG_ADDR_BASE failed: %s\n",
+                strerror(ret));
+        abort();
+    }
+
+    ret = kvm_device_access(lds->dev_fd, KVM_DEV_LOONGARCH_DMSINTC_GRP_CTRL,
+                            KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_SIZE,
+                            &lds->msg_addr_size, true, NULL);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_DEV_LOONGARCH_DINTC_MSG_ADDR_SIZE failed: %s\n",
+                strerror(ret));
+        abort();
+    }
+}
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index a1401cb521..4373f16d0b 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -90,3 +90,5 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extio
 specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_EXTIOI'],
                if_true: files('loongarch_extioi_kvm.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_DINTC', if_true: files('loongarch_dintc.c'))
+specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_DINTC'],
+               if_true: files('loongarch_dintc_kvm.c'))
diff --git a/include/hw/intc/loongarch_dintc.h b/include/hw/intc/loongarch_dintc.h
index 1f4f65705a..95a7879e26 100644
--- a/include/hw/intc/loongarch_dintc.h
+++ b/include/hw/intc/loongarch_dintc.h
@@ -9,8 +9,13 @@
 #include "hw/core/sysbus.h"
 #include "hw/loongarch/virt.h"
 #include "system/memory.h"
+#include "hw/pci-host/ls7a.h"
 
 #define NR_VECTORS     256
+#define IRQ_BIT_BASE    5
+#define IRQ_BIT_LEN     8
+#define CPU_BIT_BASE   13
+#define CPU_BIT_LEN     8
 
 #define TYPE_LOONGARCH_DINTC "loongarch_dintc"
 OBJECT_DECLARE_TYPE(LoongArchDINTCState, LoongArchDINTCClass, LOONGARCH_DINTC)
@@ -25,7 +30,10 @@ struct LoongArchDINTCState {
     SysBusDevice parent_obj;
     MemoryRegion dintc_mmio;
     DINTCCore *cpu;
+    int dev_fd;
     uint32_t num_cpu;
+    uint64_t msg_addr_base;
+    uint64_t msg_addr_size;
 };
 
 struct LoongArchDINTCClass {
@@ -34,3 +42,5 @@ struct LoongArchDINTCClass {
     DeviceRealize parent_realize;
     DeviceUnrealize parent_unrealize;
 };
+
+void kvm_dintc_realize(DeviceState *dev, Error **errp);
-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.