Re: [PATCH v7 1/2] LoongArch: KVM: Add DMSINTC device support

From: gaosong

Date: Fri Mar 20 2026 - 03:27:28 EST


Hi Huacai,

Thank you for your review and the insightful question.


在 2026/3/19 下午8:48, Huacai Chen 写道:
Hi, Song,

On Wed, Mar 11, 2026 at 5:16 PM Song Gao <gaosong@xxxxxxxxxxx> wrote:
Add device model for DMSINTC interrupt controller, implement basic
create/destroy/set_attr interfaces, and register device model to kvm
device table.

Reviewed-by: Bibo Mao <maobibo@xxxxxxxxxxx>
Signed-off-by: Song Gao <gaosong@xxxxxxxxxxx>
---
arch/loongarch/include/asm/kvm_dmsintc.h | 21 ++++
arch/loongarch/include/asm/kvm_host.h | 3 +
arch/loongarch/include/uapi/asm/kvm.h | 4 +
arch/loongarch/kvm/Makefile | 1 +
arch/loongarch/kvm/intc/dmsintc.c | 117 +++++++++++++++++++++++
arch/loongarch/kvm/main.c | 6 ++
include/uapi/linux/kvm.h | 2 +
7 files changed, 154 insertions(+)
create mode 100644 arch/loongarch/include/asm/kvm_dmsintc.h
create mode 100644 arch/loongarch/kvm/intc/dmsintc.c

diff --git a/arch/loongarch/include/asm/kvm_dmsintc.h b/arch/loongarch/include/asm/kvm_dmsintc.h
new file mode 100644
index 000000000000..b04b89dd2a35
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_dmsintc.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_KVM_DMSINTC_H
+#define __ASM_KVM_DMSINTC_H
+
+
+struct loongarch_dmsintc {
+ struct kvm *kvm;
+ uint64_t msg_addr_base;
+ uint64_t msg_addr_size;
+};
+
+struct dmsintc_state {
+ atomic64_t vector_map[4];
+};
+
+int kvm_loongarch_register_dmsintc_device(void);
+#endif
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 19eb5e5c3984..6a8d72cf8e4e 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -22,6 +22,7 @@
#include <asm/kvm_ipi.h>
#include <asm/kvm_eiointc.h>
#include <asm/kvm_pch_pic.h>
+#include <asm/kvm_dmsintc.h>
#include <asm/loongarch.h>

#define __KVM_HAVE_ARCH_INTC_INITIALIZED
@@ -135,6 +136,7 @@ struct kvm_arch {
struct loongarch_ipi *ipi;
struct loongarch_eiointc *eiointc;
struct loongarch_pch_pic *pch_pic;
+ struct loongarch_dmsintc *dmsintc;
};

#define CSR_MAX_NUMS 0x800
@@ -247,6 +249,7 @@ struct kvm_vcpu_arch {
struct kvm_mp_state mp_state;
/* ipi state */
struct ipi_state ipi_state;
+ struct dmsintc_state dmsintc_state;
/* cpucfg */
u32 cpucfg[KVM_MAX_CPUCFG_REGS];

diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index 419647aacdf3..c39b8ac7a90a 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -155,4 +155,8 @@ struct kvm_iocsr_entry {
#define KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL 0x40000006
#define KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT 0

+#define KVM_DEV_LOONGARCH_DMSINTC_CTRL 0x40000007
+#define KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_BASE 0x0
+#define KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_SIZE 0x1
+
#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile
index cb41d9265662..6e184e24443c 100644
--- a/arch/loongarch/kvm/Makefile
+++ b/arch/loongarch/kvm/Makefile
@@ -19,6 +19,7 @@ kvm-y += vm.o
kvm-y += intc/ipi.o
kvm-y += intc/eiointc.o
kvm-y += intc/pch_pic.o
+kvm-y += intc/dmsintc.o
kvm-y += irqfd.o

CFLAGS_exit.o += $(call cc-disable-warning, override-init)
diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c
new file mode 100644
index 000000000000..1bb61e55d061
--- /dev/null
+++ b/arch/loongarch/kvm/intc/dmsintc.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_dmsintc.h>
+#include <asm/kvm_vcpu.h>
+
+static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+{
+ int addr = attr->attr;
+ void __user *data;
+ struct loongarch_dmsintc *s = dev->kvm->arch.dmsintc;
+ u64 tmp;
+ u32 cpu_bit;
+
+ data = (void __user *)attr->addr;
+ switch (addr) {
+ case KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_BASE:
+ if (is_write) {
+ if (copy_from_user(&tmp, data, sizeof(s->msg_addr_base)))
+ return -EFAULT;
+ if (s->msg_addr_base) {
+ /* Duplicate setting are not allowed. */
+ return -EFAULT;
+ }
+ if ((tmp & (BIT(AVEC_CPU_SHIFT) - 1)) == 0)
+ s->msg_addr_base = tmp;
+ else
+ return -EFAULT;
+ s->msg_addr_base = tmp;
+ cpu_bit = find_first_bit((unsigned long *)&(s->msg_addr_base), 64)
+ - AVEC_CPU_SHIFT;
+ cpu_bit = min(cpu_bit, AVEC_CPU_BIT);
+ s->cpu_mask = GENMASK(cpu_bit - 1, 0) & AVEC_CPU_MASK;
+ }
+ break;
+ case KVM_DEV_LOONGARCH_DMSINTC_MSG_ADDR_SIZE:
+ if (is_write) {
+ if (copy_from_user(&tmp, data, sizeof(s->msg_addr_size)))
+ return -EFAULT;
+ if (s->msg_addr_size) {
+ /*Duplicate setting are not allowed. */
+ return -EFAULT;
+ }
+ s->msg_addr_size = tmp;
+ }
+ break;
+ default:
+ kvm_err("%s: unknown dmsintc register, addr = %d\n", __func__, addr);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int kvm_dmsintc_set_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_DMSINTC_CTRL:
+ return kvm_dmsintc_ctrl_access(dev, attr, true);
+ default:
+ kvm_err("%s: unknown group (%d)\n", __func__, attr->group);
+ return -EINVAL;
+ }
+}
+
+static int kvm_dmsintc_create(struct kvm_device *dev, u32 type)
+{
+ struct kvm *kvm;
+ struct loongarch_dmsintc *s;
+
+ if (!dev) {
+ kvm_err("%s: kvm_device ptr is invalid!\n", __func__);
+ return -EINVAL;
+ }
+
+ kvm = dev->kvm;
+ if (kvm->arch.dmsintc) {
+ kvm_err("%s: LoongArch DMSINTC has already been created!\n", __func__);
+ return -EINVAL;
+ }
+
+ s = kzalloc(sizeof(struct loongarch_dmsintc), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->kvm = kvm;
+ kvm->arch.dmsintc = s;
+ return 0;
+}
+
+static void kvm_dmsintc_destroy(struct kvm_device *dev)
+{
+
+ if (!dev || !dev->kvm || !dev->kvm->arch.dmsintc)
+ return;
+
+ kfree(dev->kvm->arch.dmsintc);
+ kfree(dev);
+}
+
+static struct kvm_device_ops kvm_dmsintc_dev_ops = {
+ .name = "kvm-loongarch-dmsintc",
+ .create = kvm_dmsintc_create,
+ .destroy = kvm_dmsintc_destroy,
+ .set_attr = kvm_dmsintc_set_attr,
+};
+
+int kvm_loongarch_register_dmsintc_device(void)
+{
+ return kvm_register_device_ops(&kvm_dmsintc_dev_ops, KVM_DEV_TYPE_LOONGARCH_DMSINTC);
+}
diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c
index 2c593ac7892f..713771a93d90 100644
--- a/arch/loongarch/kvm/main.c
+++ b/arch/loongarch/kvm/main.c
@@ -416,6 +416,12 @@ static int kvm_loongarch_env_init(void)

/* Register LoongArch PCH-PIC interrupt controller interface. */
ret = kvm_loongarch_register_pch_pic_device();
+ if (ret)
+ return ret;
+
+ /* Register LoongArch DMSINTC interrupt contrroller interface */
+ if (cpu_has_msgint)
I still have some questions here. If we always create dmsintc when
cpu_has_msgint, then kvm_guest_has_msgint() is completely useless.
Because there will be no guest without dmsintc while the host has
dmsintc.

I'd like to clarify two points:

1. Registration vs. Instantiation:
In kvm_loongarch_env_init(), the call to kvm_loongarch_register_dmsintc_device()
(guarded by cpu_has_msgint) only registers the dmsintc device type with KVM.
This makes the device type available for userspace to create instances via KVM_CREATE_DEVICE.
It does not automatically instantiate the device for every VM. The actual creation of
a dmsintc device for a specific VM is explicitly controlled by userspace (e.g., QEMU).
Therefore, a VM may or may not have dmsintc depending on userspace configuration,
even on hosts that support MSGINT.

2.Purpose of kvm_guest_has_msgint():
This function is intended to reflect the userspace configuration for the guest,
i.e., whether the guest VM has MSGINT enabled.

With this in mind, the registration condition does not force every guest to have dmsintc,
and kvm_guest_has_msgint() remains meaningful as long as it queries per-VM state.

Please let me know if you have further concerns or suggestions.

Thanks.
Song Gao


Huacai

+ ret = kvm_loongarch_register_dmsintc_device();

return ret;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 65500f5db379..f2aa9d6ad7d3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1220,6 +1220,8 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_LOONGARCH_EIOINTC KVM_DEV_TYPE_LOONGARCH_EIOINTC
KVM_DEV_TYPE_LOONGARCH_PCHPIC,
#define KVM_DEV_TYPE_LOONGARCH_PCHPIC KVM_DEV_TYPE_LOONGARCH_PCHPIC
+ KVM_DEV_TYPE_LOONGARCH_DMSINTC,
+#define KVM_DEV_TYPE_LOONGARCH_DMSINTC KVM_DEV_TYPE_LOONGARCH_DMSINTC

KVM_DEV_TYPE_MAX,

--
2.39.3