public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel
@ 2026-02-06  1:20 Song Gao
  2026-02-06  1:20 ` [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support Song Gao
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Song Gao @ 2026-02-06  1:20 UTC (permalink / raw)
  To: maobibo, chenhuacai; +Cc: kvm, loongarch, kernel, linux-kernel

Hi,

This series  implements the DMSINTC in-kernel irqchip device,
enables irqfd to deliver MSI to DMSINTC, and supports injecting MSI interrupts
to the target vCPU.
applied this series.  use netperf test.
VM with one CPU and start netserver, host run netperf.
disable dmsintc
taskset 0x2f  netperf -H 192.168.122.204 -t UDP_RR  -l 36000
Local /Remote
Socket Size   Request  Resp.   Elapsed  Trans.
Send   Recv   Size     Size    Time     Rate
bytes  Bytes  bytes    bytes   secs.    per sec   

212992 212992 1        1       36000.00   27107.36   

enable dmsintc
Local /Remote
Socket Size   Request  Resp.   Elapsed  Trans.
Send   Recv   Size     Size    Time     Rate         
bytes  Bytes  bytes    bytes   secs.    per sec   

212992 212992 1        1       36000.00   28831.14  (+6.3%)

v6: 
  Fix kvm_device leak in kvm_dmsintc_destroy(). 

v5:
  Combine patch2 and patch3
  Add check msgint feature when register DMSINT device. 

V4: Rebase and R-b; 
   replace DINTC to DMSINTC.


V3: Fix kvm_arch_set_irq_inatomic() missing dmsintc set msi.(patch3)

V2:
https://patchew.org/linux/20251128091125.2720148-1-gaosong@loongson.cn/

Thanks.
Song Gao

Song Gao (2):
  LongArch: KVM: Add DMSINTC device support
  LongArch: KVM: Add dmsintc inject msi to the dest vcpu

 arch/loongarch/include/asm/kvm_dmsintc.h |  22 +++++
 arch/loongarch/include/asm/kvm_host.h    |   8 ++
 arch/loongarch/include/uapi/asm/kvm.h    |   4 +
 arch/loongarch/kvm/Makefile              |   1 +
 arch/loongarch/kvm/intc/dmsintc.c        | 117 +++++++++++++++++++++++
 arch/loongarch/kvm/interrupt.c           |   1 +
 arch/loongarch/kvm/irqfd.c               |  42 +++++++-
 arch/loongarch/kvm/main.c                |   6 ++
 arch/loongarch/kvm/vcpu.c                |  58 +++++++++++
 include/uapi/linux/kvm.h                 |   2 +
 10 files changed, 257 insertions(+), 4 deletions(-)
 create mode 100644 arch/loongarch/include/asm/kvm_dmsintc.h
 create mode 100644 arch/loongarch/kvm/intc/dmsintc.c

-- 
2.39.3


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support
  2026-02-06  1:20 [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Song Gao
@ 2026-02-06  1:20 ` Song Gao
  2026-03-05  7:31   ` Huacai Chen
  2026-02-06  1:20 ` [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu Song Gao
  2026-02-06  3:34 ` [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Yao Zi
  2 siblings, 1 reply; 10+ messages in thread
From: Song Gao @ 2026-02-06  1:20 UTC (permalink / raw)
  To: maobibo, chenhuacai; +Cc: kvm, loongarch, kernel, linux-kernel

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@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 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        | 111 +++++++++++++++++++++++
 arch/loongarch/kvm/main.c                |   6 ++
 include/uapi/linux/kvm.h                 |   2 +
 7 files changed, 148 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..1d4f66996f3c
--- /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 e4fe5b8e8149..5e9e2af7312f 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
@@ -134,6 +135,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
@@ -244,6 +246,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 de6c3f18e40a..0a370d018b08 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -154,4 +154,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..00e401de0464
--- /dev/null
+++ b/arch/loongarch/kvm/intc/dmsintc.c
@@ -0,0 +1,111 @@
+// 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;
+
+	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;
+		}
+		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 80ea63d465b8..f363a3b24903 100644
--- a/arch/loongarch/kvm/main.c
+++ b/arch/loongarch/kvm/main.c
@@ -408,6 +408,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)
+		ret = kvm_loongarch_register_dmsintc_device();
 
 	return ret;
 }
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index dddb781b0507..7c56e7e36265 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1209,6 +1209,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


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu
  2026-02-06  1:20 [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Song Gao
  2026-02-06  1:20 ` [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support Song Gao
@ 2026-02-06  1:20 ` Song Gao
  2026-03-05  7:33   ` Huacai Chen
  2026-02-06  3:34 ` [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Yao Zi
  2 siblings, 1 reply; 10+ messages in thread
From: Song Gao @ 2026-02-06  1:20 UTC (permalink / raw)
  To: maobibo, chenhuacai; +Cc: kvm, loongarch, kernel, linux-kernel

Implement irqfd deliver msi to vcpu and vcpu dmsintc inject irq.
Add irqfd choice dmsintc to set msi irq by the msg_addr and
implement dmsintc set msi irq.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 arch/loongarch/include/asm/kvm_dmsintc.h |  1 +
 arch/loongarch/include/asm/kvm_host.h    |  5 ++
 arch/loongarch/kvm/intc/dmsintc.c        |  6 +++
 arch/loongarch/kvm/interrupt.c           |  1 +
 arch/loongarch/kvm/irqfd.c               | 42 +++++++++++++++--
 arch/loongarch/kvm/vcpu.c                | 58 ++++++++++++++++++++++++
 6 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/arch/loongarch/include/asm/kvm_dmsintc.h b/arch/loongarch/include/asm/kvm_dmsintc.h
index 1d4f66996f3c..9b5436a2fcbe 100644
--- a/arch/loongarch/include/asm/kvm_dmsintc.h
+++ b/arch/loongarch/include/asm/kvm_dmsintc.h
@@ -11,6 +11,7 @@ struct loongarch_dmsintc  {
 	struct kvm *kvm;
 	uint64_t msg_addr_base;
 	uint64_t msg_addr_size;
+	uint32_t cpu_mask;
 };
 
 struct dmsintc_state {
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 5e9e2af7312f..91e0190aeaec 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -258,6 +258,11 @@ struct kvm_vcpu_arch {
 	} st;
 };
 
+void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu);
+int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
+				struct kvm_vcpu *vcpu,
+				u32 vector, int level);
+
 static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
 {
 	return csr->csrs[reg];
diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c
index 00e401de0464..1bb61e55d061 100644
--- a/arch/loongarch/kvm/intc/dmsintc.c
+++ b/arch/loongarch/kvm/intc/dmsintc.c
@@ -15,6 +15,7 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
 	void __user *data;
 	struct loongarch_dmsintc *s = dev->kvm->arch.dmsintc;
 	u64 tmp;
+	u32 cpu_bit;
 
 	data = (void __user *)attr->addr;
 	switch (addr) {
@@ -30,6 +31,11 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
 				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:
diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
index a6d42d399a59..893a81ca1079 100644
--- a/arch/loongarch/kvm/interrupt.c
+++ b/arch/loongarch/kvm/interrupt.c
@@ -33,6 +33,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
 		irq = priority_to_irq[priority];
 
 	if (cpu_has_msgint && (priority == INT_AVEC)) {
+		loongarch_dmsintc_inject_irq(vcpu);
 		set_gcsr_estat(irq);
 		return 1;
 	}
diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c
index 9a39627aecf0..3bbb26f4e2b7 100644
--- a/arch/loongarch/kvm/irqfd.c
+++ b/arch/loongarch/kvm/irqfd.c
@@ -6,6 +6,7 @@
 #include <linux/kvm_host.h>
 #include <trace/events/kvm.h>
 #include <asm/kvm_pch_pic.h>
+#include <asm/kvm_vcpu.h>
 
 static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
 		struct kvm *kvm, int irq_source_id, int level, bool line_status)
@@ -16,6 +17,38 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
 	return 0;
 }
 
+static int kvm_dmsintc_set_msi_irq(struct kvm *kvm, u32 addr, int data, int level)
+{
+	unsigned int virq, dest;
+	struct kvm_vcpu *vcpu;
+
+	virq = (addr >> AVEC_IRQ_SHIFT) & AVEC_IRQ_MASK;
+	dest = (addr >> AVEC_CPU_SHIFT) & kvm->arch.dmsintc->cpu_mask;
+	if (dest > KVM_MAX_VCPUS)
+		return -EINVAL;
+	vcpu = kvm_get_vcpu_by_cpuid(kvm, dest);
+	if (!vcpu)
+		return -EINVAL;
+	return kvm_loongarch_deliver_msi_to_vcpu(kvm, vcpu, virq, level);
+}
+
+static int loongarch_set_msi(struct kvm_kernel_irq_routing_entry *e,
+			struct kvm *kvm, int level)
+{
+	u64 msg_addr;
+
+	msg_addr = (((u64)e->msi.address_hi) << 32) | e->msi.address_lo;
+	if (cpu_has_msgint && kvm->arch.dmsintc &&
+		msg_addr >= kvm->arch.dmsintc->msg_addr_base &&
+		msg_addr < (kvm->arch.dmsintc->msg_addr_base  + kvm->arch.dmsintc->msg_addr_size)) {
+		return kvm_dmsintc_set_msi_irq(kvm, msg_addr, e->msi.data, level);
+	} else {
+		pch_msi_set_irq(kvm, e->msi.data, level);
+	}
+
+	return 0;
+}
+
 /*
  * kvm_set_msi: inject the MSI corresponding to the
  * MSI routing entry
@@ -29,9 +62,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 	if (!level)
 		return -1;
 
-	pch_msi_set_irq(kvm, e->msi.data, level);
-
-	return 0;
+	return loongarch_set_msi(e, kvm, level);
 }
 
 /*
@@ -71,12 +102,15 @@ int kvm_set_routing_entry(struct kvm *kvm,
 int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
 		struct kvm *kvm, int irq_source_id, int level, bool line_status)
 {
+	if (!level)
+		return -EWOULDBLOCK;
+
 	switch (e->type) {
 	case KVM_IRQ_ROUTING_IRQCHIP:
 		pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
 		return 0;
 	case KVM_IRQ_ROUTING_MSI:
-		pch_msi_set_irq(kvm, e->msi.data, level);
+		loongarch_set_msi(e, kvm, level);
 		return 0;
 	default:
 		return -EWOULDBLOCK;
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 656b954c1134..325bb084d704 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -14,6 +14,64 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
+void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu)
+{
+	struct dmsintc_state *ds = &vcpu->arch.dmsintc_state;
+	unsigned int i;
+	unsigned long temp[4], old;
+
+	if (!ds)
+		return;
+
+	for (i = 0; i < 4; i++) {
+		old = atomic64_read(&(ds->vector_map[i]));
+		if (old)
+			temp[i] = atomic64_xchg(&(ds->vector_map[i]), 0);
+	}
+
+	if (temp[0]) {
+		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR0);
+		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR0, temp[0]|old);
+	}
+
+	if (temp[1]) {
+		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR1);
+		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR1, temp[1]|old);
+	}
+
+	if (temp[2]) {
+		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR2);
+		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR2, temp[2]|old);
+	}
+
+	if (temp[3]) {
+		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR3);
+		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR3, temp[3]|old);
+	}
+}
+
+int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
+				struct kvm_vcpu *vcpu,
+				u32 vector, int level)
+{
+	struct kvm_interrupt vcpu_irq;
+	struct dmsintc_state *ds;
+
+	if (!level)
+		return 0;
+	if (!vcpu || vector >= 256)
+		return -EINVAL;
+	ds = &vcpu->arch.dmsintc_state;
+	if (!ds)
+		return -ENODEV;
+	set_bit(vector, (unsigned long *)&ds->vector_map);
+	vcpu_irq.irq = INT_AVEC;
+	kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq);
+	kvm_vcpu_kick(vcpu);
+	return 0;
+}
+
+
 const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, int_exits),
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel
  2026-02-06  1:20 [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Song Gao
  2026-02-06  1:20 ` [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support Song Gao
  2026-02-06  1:20 ` [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu Song Gao
@ 2026-02-06  3:34 ` Yao Zi
  2026-03-03  3:54   ` gaosong
  2 siblings, 1 reply; 10+ messages in thread
From: Yao Zi @ 2026-02-06  3:34 UTC (permalink / raw)
  To: Song Gao, maobibo, chenhuacai; +Cc: kvm, loongarch, kernel, linux-kernel

On Fri, Feb 06, 2026 at 09:20:26AM +0800, Song Gao wrote:
> Hi,
> 
> This series  implements the DMSINTC in-kernel irqchip device,
> enables irqfd to deliver MSI to DMSINTC, and supports injecting MSI interrupts
> to the target vCPU.
> applied this series.  use netperf test.
> VM with one CPU and start netserver, host run netperf.
> disable dmsintc
> taskset 0x2f  netperf -H 192.168.122.204 -t UDP_RR  -l 36000
> Local /Remote
> Socket Size   Request  Resp.   Elapsed  Trans.
> Send   Recv   Size     Size    Time     Rate
> bytes  Bytes  bytes    bytes   secs.    per sec   
> 
> 212992 212992 1        1       36000.00   27107.36   
> 
> enable dmsintc
> Local /Remote
> Socket Size   Request  Resp.   Elapsed  Trans.
> Send   Recv   Size     Size    Time     Rate         
> bytes  Bytes  bytes    bytes   secs.    per sec   
> 
> 212992 212992 1        1       36000.00   28831.14  (+6.3%)
> 
> v6: 
>   Fix kvm_device leak in kvm_dmsintc_destroy(). 
> 
> v5:
>   Combine patch2 and patch3
>   Add check msgint feature when register DMSINT device. 
> 
> V4: Rebase and R-b; 
>    replace DINTC to DMSINTC.
> 
> 
> V3: Fix kvm_arch_set_irq_inatomic() missing dmsintc set msi.(patch3)
> 
> V2:
> https://patchew.org/linux/20251128091125.2720148-1-gaosong@loongson.cn/
> 
> Thanks.
> Song Gao
> 
> Song Gao (2):
>   LongArch: KVM: Add DMSINTC device support
>   LongArch: KVM: Add dmsintc inject msi to the dest vcpu

There's a typo in the titles, it should be LoongArch instead of
"LongArch".

Best regards,
Yao Zi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel
  2026-02-06  3:34 ` [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Yao Zi
@ 2026-03-03  3:54   ` gaosong
  2026-03-03  4:14     ` Huacai Chen
  0 siblings, 1 reply; 10+ messages in thread
From: gaosong @ 2026-03-03  3:54 UTC (permalink / raw)
  To: Yao Zi, maobibo, chenhuacai; +Cc: kvm, loongarch, kernel, linux-kernel

在 2026/2/6 上午11:34, Yao Zi 写道:
> On Fri, Feb 06, 2026 at 09:20:26AM +0800, Song Gao wrote:
>> Hi,
>>
>> This series  implements the DMSINTC in-kernel irqchip device,
>> enables irqfd to deliver MSI to DMSINTC, and supports injecting MSI interrupts
>> to the target vCPU.
>> applied this series.  use netperf test.
>> VM with one CPU and start netserver, host run netperf.
>> disable dmsintc
>> taskset 0x2f  netperf -H 192.168.122.204 -t UDP_RR  -l 36000
>> Local /Remote
>> Socket Size   Request  Resp.   Elapsed  Trans.
>> Send   Recv   Size     Size    Time     Rate
>> bytes  Bytes  bytes    bytes   secs.    per sec
>>
>> 212992 212992 1        1       36000.00   27107.36
>>
>> enable dmsintc
>> Local /Remote
>> Socket Size   Request  Resp.   Elapsed  Trans.
>> Send   Recv   Size     Size    Time     Rate
>> bytes  Bytes  bytes    bytes   secs.    per sec
>>
>> 212992 212992 1        1       36000.00   28831.14  (+6.3%)
>>
>> v6:
>>    Fix kvm_device leak in kvm_dmsintc_destroy().
>>
>> v5:
>>    Combine patch2 and patch3
>>    Add check msgint feature when register DMSINT device.
>>
>> V4: Rebase and R-b;
>>     replace DINTC to DMSINTC.
>>
>>
>> V3: Fix kvm_arch_set_irq_inatomic() missing dmsintc set msi.(patch3)
>>
>> V2:
>> https://patchew.org/linux/20251128091125.2720148-1-gaosong@loongson.cn/
>>
>> Thanks.
>> Song Gao
>>
>> Song Gao (2):
>>    LongArch: KVM: Add DMSINTC device support
>>    LongArch: KVM: Add dmsintc inject msi to the dest vcpu
> There's a typo in the titles, it should be LoongArch instead of
> "LongArch".

Hi,   huacai

Should I need send v7 to fix this typo error?

Thanks.

Song Gao
>
> Best regards,
> Yao Zi
>
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel
  2026-03-03  3:54   ` gaosong
@ 2026-03-03  4:14     ` Huacai Chen
  0 siblings, 0 replies; 10+ messages in thread
From: Huacai Chen @ 2026-03-03  4:14 UTC (permalink / raw)
  To: gaosong; +Cc: Yao Zi, maobibo, kvm, loongarch, kernel, linux-kernel

On Tue, Mar 3, 2026 at 11:54 AM gaosong <gaosong@loongson.cn> wrote:
>
> 在 2026/2/6 上午11:34, Yao Zi 写道:
> > On Fri, Feb 06, 2026 at 09:20:26AM +0800, Song Gao wrote:
> >> Hi,
> >>
> >> This series  implements the DMSINTC in-kernel irqchip device,
> >> enables irqfd to deliver MSI to DMSINTC, and supports injecting MSI interrupts
> >> to the target vCPU.
> >> applied this series.  use netperf test.
> >> VM with one CPU and start netserver, host run netperf.
> >> disable dmsintc
> >> taskset 0x2f  netperf -H 192.168.122.204 -t UDP_RR  -l 36000
> >> Local /Remote
> >> Socket Size   Request  Resp.   Elapsed  Trans.
> >> Send   Recv   Size     Size    Time     Rate
> >> bytes  Bytes  bytes    bytes   secs.    per sec
> >>
> >> 212992 212992 1        1       36000.00   27107.36
> >>
> >> enable dmsintc
> >> Local /Remote
> >> Socket Size   Request  Resp.   Elapsed  Trans.
> >> Send   Recv   Size     Size    Time     Rate
> >> bytes  Bytes  bytes    bytes   secs.    per sec
> >>
> >> 212992 212992 1        1       36000.00   28831.14  (+6.3%)
> >>
> >> v6:
> >>    Fix kvm_device leak in kvm_dmsintc_destroy().
> >>
> >> v5:
> >>    Combine patch2 and patch3
> >>    Add check msgint feature when register DMSINT device.
> >>
> >> V4: Rebase and R-b;
> >>     replace DINTC to DMSINTC.
> >>
> >>
> >> V3: Fix kvm_arch_set_irq_inatomic() missing dmsintc set msi.(patch3)
> >>
> >> V2:
> >> https://patchew.org/linux/20251128091125.2720148-1-gaosong@loongson.cn/
> >>
> >> Thanks.
> >> Song Gao
> >>
> >> Song Gao (2):
> >>    LongArch: KVM: Add DMSINTC device support
> >>    LongArch: KVM: Add dmsintc inject msi to the dest vcpu
> > There's a typo in the titles, it should be LoongArch instead of
> > "LongArch".
>
> Hi,   huacai
>
> Should I need send v7 to fix this typo error?
Wait a moment, maybe there are other comments.

Huacai

>
> Thanks.
>
> Song Gao
> >
> > Best regards,
> > Yao Zi
> >
> >
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support
  2026-02-06  1:20 ` [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support Song Gao
@ 2026-03-05  7:31   ` Huacai Chen
  2026-03-05 12:38     ` gaosong
  0 siblings, 1 reply; 10+ messages in thread
From: Huacai Chen @ 2026-03-05  7:31 UTC (permalink / raw)
  To: Song Gao; +Cc: maobibo, kvm, loongarch, kernel, linux-kernel

Hi, Song,

On Fri, Feb 6, 2026 at 9:45 AM Song Gao <gaosong@loongson.cn> 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@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>  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        | 111 +++++++++++++++++++++++
>  arch/loongarch/kvm/main.c                |   6 ++
>  include/uapi/linux/kvm.h                 |   2 +
>  7 files changed, 148 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..1d4f66996f3c
> --- /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  {
Here is an extra space.

> +       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 e4fe5b8e8149..5e9e2af7312f 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
> @@ -134,6 +135,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
> @@ -244,6 +246,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 de6c3f18e40a..0a370d018b08 100644
> --- a/arch/loongarch/include/uapi/asm/kvm.h
> +++ b/arch/loongarch/include/uapi/asm/kvm.h
> @@ -154,4 +154,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..00e401de0464
> --- /dev/null
> +++ b/arch/loongarch/kvm/intc/dmsintc.c
> @@ -0,0 +1,111 @@
> +// 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;
> +
> +       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;
> +               }
> +               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 80ea63d465b8..f363a3b24903 100644
> --- a/arch/loongarch/kvm/main.c
> +++ b/arch/loongarch/kvm/main.c
> @@ -408,6 +408,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'm not sure, but there is kvm_guest_has_msgint(), I don't know which
one is really needed.


Huacai

> +               ret = kvm_loongarch_register_dmsintc_device();
>
>         return ret;
>  }
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index dddb781b0507..7c56e7e36265 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1209,6 +1209,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
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu
  2026-02-06  1:20 ` [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu Song Gao
@ 2026-03-05  7:33   ` Huacai Chen
  2026-03-09  8:24     ` gaosong
  0 siblings, 1 reply; 10+ messages in thread
From: Huacai Chen @ 2026-03-05  7:33 UTC (permalink / raw)
  To: Song Gao; +Cc: maobibo, kvm, loongarch, kernel, linux-kernel

Hi, Song,

On Fri, Feb 6, 2026 at 9:45 AM Song Gao <gaosong@loongson.cn> wrote:
>
> Implement irqfd deliver msi to vcpu and vcpu dmsintc inject irq.
> Add irqfd choice dmsintc to set msi irq by the msg_addr and
> implement dmsintc set msi irq.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>  arch/loongarch/include/asm/kvm_dmsintc.h |  1 +
>  arch/loongarch/include/asm/kvm_host.h    |  5 ++
>  arch/loongarch/kvm/intc/dmsintc.c        |  6 +++
>  arch/loongarch/kvm/interrupt.c           |  1 +
>  arch/loongarch/kvm/irqfd.c               | 42 +++++++++++++++--
>  arch/loongarch/kvm/vcpu.c                | 58 ++++++++++++++++++++++++
>  6 files changed, 109 insertions(+), 4 deletions(-)
>
> diff --git a/arch/loongarch/include/asm/kvm_dmsintc.h b/arch/loongarch/include/asm/kvm_dmsintc.h
> index 1d4f66996f3c..9b5436a2fcbe 100644
> --- a/arch/loongarch/include/asm/kvm_dmsintc.h
> +++ b/arch/loongarch/include/asm/kvm_dmsintc.h
> @@ -11,6 +11,7 @@ struct loongarch_dmsintc  {
>         struct kvm *kvm;
>         uint64_t msg_addr_base;
>         uint64_t msg_addr_size;
> +       uint32_t cpu_mask;
>  };
>
>  struct dmsintc_state {
> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
> index 5e9e2af7312f..91e0190aeaec 100644
> --- a/arch/loongarch/include/asm/kvm_host.h
> +++ b/arch/loongarch/include/asm/kvm_host.h
> @@ -258,6 +258,11 @@ struct kvm_vcpu_arch {
>         } st;
>  };
>
> +void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu);
> +int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
> +                               struct kvm_vcpu *vcpu,
> +                               u32 vector, int level);
> +
>  static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
>  {
>         return csr->csrs[reg];
> diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c
> index 00e401de0464..1bb61e55d061 100644
> --- a/arch/loongarch/kvm/intc/dmsintc.c
> +++ b/arch/loongarch/kvm/intc/dmsintc.c
> @@ -15,6 +15,7 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
>         void __user *data;
>         struct loongarch_dmsintc *s = dev->kvm->arch.dmsintc;
>         u64 tmp;
> +       u32 cpu_bit;
>
>         data = (void __user *)attr->addr;
>         switch (addr) {
> @@ -30,6 +31,11 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
>                                 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:
I'm not sure but maybe this part should go to the first patch?

> diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
> index a6d42d399a59..893a81ca1079 100644
> --- a/arch/loongarch/kvm/interrupt.c
> +++ b/arch/loongarch/kvm/interrupt.c
> @@ -33,6 +33,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
>                 irq = priority_to_irq[priority];
>
>         if (cpu_has_msgint && (priority == INT_AVEC)) {
> +               loongarch_dmsintc_inject_irq(vcpu);
>                 set_gcsr_estat(irq);
>                 return 1;
>         }
> diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c
> index 9a39627aecf0..3bbb26f4e2b7 100644
> --- a/arch/loongarch/kvm/irqfd.c
> +++ b/arch/loongarch/kvm/irqfd.c
> @@ -6,6 +6,7 @@
>  #include <linux/kvm_host.h>
>  #include <trace/events/kvm.h>
>  #include <asm/kvm_pch_pic.h>
> +#include <asm/kvm_vcpu.h>
>
>  static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
>                 struct kvm *kvm, int irq_source_id, int level, bool line_status)
> @@ -16,6 +17,38 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
>         return 0;
>  }
>
> +static int kvm_dmsintc_set_msi_irq(struct kvm *kvm, u32 addr, int data, int level)
> +{
> +       unsigned int virq, dest;
> +       struct kvm_vcpu *vcpu;
> +
> +       virq = (addr >> AVEC_IRQ_SHIFT) & AVEC_IRQ_MASK;
> +       dest = (addr >> AVEC_CPU_SHIFT) & kvm->arch.dmsintc->cpu_mask;
> +       if (dest > KVM_MAX_VCPUS)
> +               return -EINVAL;
> +       vcpu = kvm_get_vcpu_by_cpuid(kvm, dest);
> +       if (!vcpu)
> +               return -EINVAL;
> +       return kvm_loongarch_deliver_msi_to_vcpu(kvm, vcpu, virq, level);
> +}
> +
> +static int loongarch_set_msi(struct kvm_kernel_irq_routing_entry *e,
> +                       struct kvm *kvm, int level)
> +{
> +       u64 msg_addr;
> +
> +       msg_addr = (((u64)e->msi.address_hi) << 32) | e->msi.address_lo;
> +       if (cpu_has_msgint && kvm->arch.dmsintc &&
> +               msg_addr >= kvm->arch.dmsintc->msg_addr_base &&
> +               msg_addr < (kvm->arch.dmsintc->msg_addr_base  + kvm->arch.dmsintc->msg_addr_size)) {
> +               return kvm_dmsintc_set_msi_irq(kvm, msg_addr, e->msi.data, level);
> +       } else {
> +               pch_msi_set_irq(kvm, e->msi.data, level);
> +       }
> +
> +       return 0;
> +}
Rename loongarch_set_msi() to loongarch_msi_set_irq(), rename
kvm_dmsintc_set_msi_irq() to dmsintc_msi_set_irq(), this makes the
naming more consistent.

> +
>  /*
>   * kvm_set_msi: inject the MSI corresponding to the
>   * MSI routing entry
> @@ -29,9 +62,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
>         if (!level)
>                 return -1;
>
> -       pch_msi_set_irq(kvm, e->msi.data, level);
> -
> -       return 0;
> +       return loongarch_set_msi(e, kvm, level);
>  }
>
>  /*
> @@ -71,12 +102,15 @@ int kvm_set_routing_entry(struct kvm *kvm,
>  int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
>                 struct kvm *kvm, int irq_source_id, int level, bool line_status)
>  {
> +       if (!level)
> +               return -EWOULDBLOCK;
> +
>         switch (e->type) {
>         case KVM_IRQ_ROUTING_IRQCHIP:
>                 pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
>                 return 0;
>         case KVM_IRQ_ROUTING_MSI:
> -               pch_msi_set_irq(kvm, e->msi.data, level);
> +               loongarch_set_msi(e, kvm, level);
>                 return 0;
>         default:
>                 return -EWOULDBLOCK;
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 656b954c1134..325bb084d704 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -14,6 +14,64 @@
>  #define CREATE_TRACE_POINTS
>  #include "trace.h"
>
> +void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu)
> +{
> +       struct dmsintc_state *ds = &vcpu->arch.dmsintc_state;
> +       unsigned int i;
> +       unsigned long temp[4], old;
> +
> +       if (!ds)
> +               return;
> +
> +       for (i = 0; i < 4; i++) {
> +               old = atomic64_read(&(ds->vector_map[i]));
> +               if (old)
> +                       temp[i] = atomic64_xchg(&(ds->vector_map[i]), 0);
> +       }
> +
> +       if (temp[0]) {
> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR0);
> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR0, temp[0]|old);
> +       }
> +
> +       if (temp[1]) {
> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR1);
> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR1, temp[1]|old);
> +       }
> +
> +       if (temp[2]) {
> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR2);
> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR2, temp[2]|old);
> +       }
> +
> +       if (temp[3]) {
> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR3);
> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR3, temp[3]|old);
> +       }
> +}
The only caller is in interrupt.c, so rename
loongarch_dmsintc_inject_irq() to msgint_inject_irq() (or
dmsintc_inject_irq() if you prefer), and move it to interrupt.c, then
we don't need to declare it as a extern function.

> +
> +int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
> +                               struct kvm_vcpu *vcpu,
> +                               u32 vector, int level)
> +{
> +       struct kvm_interrupt vcpu_irq;
> +       struct dmsintc_state *ds;
> +
> +       if (!level)
> +               return 0;
> +       if (!vcpu || vector >= 256)
> +               return -EINVAL;
> +       ds = &vcpu->arch.dmsintc_state;
> +       if (!ds)
> +               return -ENODEV;
> +       set_bit(vector, (unsigned long *)&ds->vector_map);
> +       vcpu_irq.irq = INT_AVEC;
> +       kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq);
> +       kvm_vcpu_kick(vcpu);
> +       return 0;
> +}
The only caller is in irqfd.c, so rename
kvm_loongarch_deliver_msi_to_vcpu() to dmsintc_deliver_msi_to_vcpu(),
and move it to irqfd.c, then we don't need to declare it as a extern
function.

And in addition, from Documentation/arch/loongarch/irq-chip-model.rst,
all msi irq are triggered from "pch_msi_irq", which means it is not
reasonable to dispatch the dmsintc/pch_msi paths in
loongarch_set_msi(). Instead, we should dispatch the dmsintc/eiointc
paths in pch_msi_set_irq(), this needs a rework...


Huacai

> +
> +
>  const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>         KVM_GENERIC_VCPU_STATS(),
>         STATS_DESC_COUNTER(VCPU, int_exits),
> --
> 2.39.3
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support
  2026-03-05  7:31   ` Huacai Chen
@ 2026-03-05 12:38     ` gaosong
  0 siblings, 0 replies; 10+ messages in thread
From: gaosong @ 2026-03-05 12:38 UTC (permalink / raw)
  To: Huacai Chen; +Cc: maobibo, kvm, loongarch, kernel, linux-kernel

Hi, Huacai

在 2026/3/5 下午3:31, Huacai Chen 写道:
> Hi, Song,
>
> On Fri, Feb 6, 2026 at 9:45 AM Song Gao <gaosong@loongson.cn> 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@loongson.cn>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   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        | 111 +++++++++++++++++++++++
>>   arch/loongarch/kvm/main.c                |   6 ++
>>   include/uapi/linux/kvm.h                 |   2 +
>>   7 files changed, 148 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..1d4f66996f3c
>> --- /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  {
> Here is an extra space.
I'll correct it on v7.
>> +       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 e4fe5b8e8149..5e9e2af7312f 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
>> @@ -134,6 +135,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
>> @@ -244,6 +246,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 de6c3f18e40a..0a370d018b08 100644
>> --- a/arch/loongarch/include/uapi/asm/kvm.h
>> +++ b/arch/loongarch/include/uapi/asm/kvm.h
>> @@ -154,4 +154,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..00e401de0464
>> --- /dev/null
>> +++ b/arch/loongarch/kvm/intc/dmsintc.c
>> @@ -0,0 +1,111 @@
>> +// 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;
>> +
>> +       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;
>> +               }
>> +               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 80ea63d465b8..f363a3b24903 100644
>> --- a/arch/loongarch/kvm/main.c
>> +++ b/arch/loongarch/kvm/main.c
>> @@ -408,6 +408,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'm not sure, but there is kvm_guest_has_msgint(), I don't know which
> one is really needed.
>
It should be cpu_has_msgint.

1.kvm_loongarch_env_init is part of module initialization, runs when KVM 
module is loaded.
  At that time, no VM or vCPU objects exist yet.
2.cpu_has_msgint is a global flag indicating physical CPU capability 
(detected early, e.g., via cpucfg).
3.kvm_guest_has_msgint() typically depends on a specific vCPU's 
configuration (e.g., whether the guest has PMU enabled via userspace 
settings).
It requires a valid vCPU pointer and cannot be used before any vCPU is 
created.

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 dddb781b0507..7c56e7e36265 100644
>> --- a/include/uapi/linux/kvm.h
>> +++ b/include/uapi/linux/kvm.h
>> @@ -1209,6 +1209,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
>>
>>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu
  2026-03-05  7:33   ` Huacai Chen
@ 2026-03-09  8:24     ` gaosong
  0 siblings, 0 replies; 10+ messages in thread
From: gaosong @ 2026-03-09  8:24 UTC (permalink / raw)
  To: Huacai Chen; +Cc: maobibo, kvm, loongarch, kernel, linux-kernel

在 2026/3/5 下午3:33, Huacai Chen 写道:
> Hi, Song,
>
> On Fri, Feb 6, 2026 at 9:45 AM Song Gao <gaosong@loongson.cn> wrote:
>> Implement irqfd deliver msi to vcpu and vcpu dmsintc inject irq.
>> Add irqfd choice dmsintc to set msi irq by the msg_addr and
>> implement dmsintc set msi irq.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   arch/loongarch/include/asm/kvm_dmsintc.h |  1 +
>>   arch/loongarch/include/asm/kvm_host.h    |  5 ++
>>   arch/loongarch/kvm/intc/dmsintc.c        |  6 +++
>>   arch/loongarch/kvm/interrupt.c           |  1 +
>>   arch/loongarch/kvm/irqfd.c               | 42 +++++++++++++++--
>>   arch/loongarch/kvm/vcpu.c                | 58 ++++++++++++++++++++++++
>>   6 files changed, 109 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/loongarch/include/asm/kvm_dmsintc.h b/arch/loongarch/include/asm/kvm_dmsintc.h
>> index 1d4f66996f3c..9b5436a2fcbe 100644
>> --- a/arch/loongarch/include/asm/kvm_dmsintc.h
>> +++ b/arch/loongarch/include/asm/kvm_dmsintc.h
>> @@ -11,6 +11,7 @@ struct loongarch_dmsintc  {
>>          struct kvm *kvm;
>>          uint64_t msg_addr_base;
>>          uint64_t msg_addr_size;
>> +       uint32_t cpu_mask;
>>   };
>>
>>   struct dmsintc_state {
>> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
>> index 5e9e2af7312f..91e0190aeaec 100644
>> --- a/arch/loongarch/include/asm/kvm_host.h
>> +++ b/arch/loongarch/include/asm/kvm_host.h
>> @@ -258,6 +258,11 @@ struct kvm_vcpu_arch {
>>          } st;
>>   };
>>
>> +void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu);
>> +int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
>> +                               struct kvm_vcpu *vcpu,
>> +                               u32 vector, int level);
>> +
>>   static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
>>   {
>>          return csr->csrs[reg];
>> diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c
>> index 00e401de0464..1bb61e55d061 100644
>> --- a/arch/loongarch/kvm/intc/dmsintc.c
>> +++ b/arch/loongarch/kvm/intc/dmsintc.c
>> @@ -15,6 +15,7 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
>>          void __user *data;
>>          struct loongarch_dmsintc *s = dev->kvm->arch.dmsintc;
>>          u64 tmp;
>> +       u32 cpu_bit;
>>
>>          data = (void __user *)attr->addr;
>>          switch (addr) {
>> @@ -30,6 +31,11 @@ static int kvm_dmsintc_ctrl_access(struct kvm_device *dev,
>>                                  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:
> I'm not sure but maybe this part should go to the first patch?
I'll move it to patch1.
>> diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c
>> index a6d42d399a59..893a81ca1079 100644
>> --- a/arch/loongarch/kvm/interrupt.c
>> +++ b/arch/loongarch/kvm/interrupt.c
>> @@ -33,6 +33,7 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
>>                  irq = priority_to_irq[priority];
>>
>>          if (cpu_has_msgint && (priority == INT_AVEC)) {
>> +               loongarch_dmsintc_inject_irq(vcpu);
>>                  set_gcsr_estat(irq);
>>                  return 1;
>>          }
>> diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c
>> index 9a39627aecf0..3bbb26f4e2b7 100644
>> --- a/arch/loongarch/kvm/irqfd.c
>> +++ b/arch/loongarch/kvm/irqfd.c
>> @@ -6,6 +6,7 @@
>>   #include <linux/kvm_host.h>
>>   #include <trace/events/kvm.h>
>>   #include <asm/kvm_pch_pic.h>
>> +#include <asm/kvm_vcpu.h>
>>
>>   static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
>>                  struct kvm *kvm, int irq_source_id, int level, bool line_status)
>> @@ -16,6 +17,38 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
>>          return 0;
>>   }
>>
>> +static int kvm_dmsintc_set_msi_irq(struct kvm *kvm, u32 addr, int data, int level)
>> +{
>> +       unsigned int virq, dest;
>> +       struct kvm_vcpu *vcpu;
>> +
>> +       virq = (addr >> AVEC_IRQ_SHIFT) & AVEC_IRQ_MASK;
>> +       dest = (addr >> AVEC_CPU_SHIFT) & kvm->arch.dmsintc->cpu_mask;
>> +       if (dest > KVM_MAX_VCPUS)
>> +               return -EINVAL;
>> +       vcpu = kvm_get_vcpu_by_cpuid(kvm, dest);
>> +       if (!vcpu)
>> +               return -EINVAL;
>> +       return kvm_loongarch_deliver_msi_to_vcpu(kvm, vcpu, virq, level);
>> +}
>> +
>> +static int loongarch_set_msi(struct kvm_kernel_irq_routing_entry *e,
>> +                       struct kvm *kvm, int level)
>> +{
>> +       u64 msg_addr;
>> +
>> +       msg_addr = (((u64)e->msi.address_hi) << 32) | e->msi.address_lo;
>> +       if (cpu_has_msgint && kvm->arch.dmsintc &&
>> +               msg_addr >= kvm->arch.dmsintc->msg_addr_base &&
>> +               msg_addr < (kvm->arch.dmsintc->msg_addr_base  + kvm->arch.dmsintc->msg_addr_size)) {
>> +               return kvm_dmsintc_set_msi_irq(kvm, msg_addr, e->msi.data, level);
>> +       } else {
>> +               pch_msi_set_irq(kvm, e->msi.data, level);
>> +       }
>> +
>> +       return 0;
>> +}
> Rename loongarch_set_msi() to loongarch_msi_set_irq(), rename
> kvm_dmsintc_set_msi_irq() to dmsintc_msi_set_irq(), this makes the
> naming more consistent.
Got it .
>> +
>>   /*
>>    * kvm_set_msi: inject the MSI corresponding to the
>>    * MSI routing entry
>> @@ -29,9 +62,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
>>          if (!level)
>>                  return -1;
>>
>> -       pch_msi_set_irq(kvm, e->msi.data, level);
>> -
>> -       return 0;
>> +       return loongarch_set_msi(e, kvm, level);
>>   }
>>
>>   /*
>> @@ -71,12 +102,15 @@ int kvm_set_routing_entry(struct kvm *kvm,
>>   int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
>>                  struct kvm *kvm, int irq_source_id, int level, bool line_status)
>>   {
>> +       if (!level)
>> +               return -EWOULDBLOCK;
>> +
>>          switch (e->type) {
>>          case KVM_IRQ_ROUTING_IRQCHIP:
>>                  pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
>>                  return 0;
>>          case KVM_IRQ_ROUTING_MSI:
>> -               pch_msi_set_irq(kvm, e->msi.data, level);
>> +               loongarch_set_msi(e, kvm, level);
>>                  return 0;
>>          default:
>>                  return -EWOULDBLOCK;
>> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
>> index 656b954c1134..325bb084d704 100644
>> --- a/arch/loongarch/kvm/vcpu.c
>> +++ b/arch/loongarch/kvm/vcpu.c
>> @@ -14,6 +14,64 @@
>>   #define CREATE_TRACE_POINTS
>>   #include "trace.h"
>>
>> +void loongarch_dmsintc_inject_irq(struct kvm_vcpu *vcpu)
>> +{
>> +       struct dmsintc_state *ds = &vcpu->arch.dmsintc_state;
>> +       unsigned int i;
>> +       unsigned long temp[4], old;
>> +
>> +       if (!ds)
>> +               return;
>> +
>> +       for (i = 0; i < 4; i++) {
>> +               old = atomic64_read(&(ds->vector_map[i]));
>> +               if (old)
>> +                       temp[i] = atomic64_xchg(&(ds->vector_map[i]), 0);
>> +       }
>> +
>> +       if (temp[0]) {
>> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR0);
>> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR0, temp[0]|old);
>> +       }
>> +
>> +       if (temp[1]) {
>> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR1);
>> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR1, temp[1]|old);
>> +       }
>> +
>> +       if (temp[2]) {
>> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR2);
>> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR2, temp[2]|old);
>> +       }
>> +
>> +       if (temp[3]) {
>> +               old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR3);
>> +               kvm_write_hw_gcsr(LOONGARCH_CSR_ISR3, temp[3]|old);
>> +       }
>> +}
> The only caller is in interrupt.c, so rename
> loongarch_dmsintc_inject_irq() to msgint_inject_irq() (or
> dmsintc_inject_irq() if you prefer), and move it to interrupt.c, then
> we don't need to declare it as a extern function.
Got it.
>> +
>> +int kvm_loongarch_deliver_msi_to_vcpu(struct kvm *kvm,
>> +                               struct kvm_vcpu *vcpu,
>> +                               u32 vector, int level)
>> +{
>> +       struct kvm_interrupt vcpu_irq;
>> +       struct dmsintc_state *ds;
>> +
>> +       if (!level)
>> +               return 0;
>> +       if (!vcpu || vector >= 256)
>> +               return -EINVAL;
>> +       ds = &vcpu->arch.dmsintc_state;
>> +       if (!ds)
>> +               return -ENODEV;
>> +       set_bit(vector, (unsigned long *)&ds->vector_map);
>> +       vcpu_irq.irq = INT_AVEC;
>> +       kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq);
>> +       kvm_vcpu_kick(vcpu);
>> +       return 0;
>> +}
> The only caller is in irqfd.c, so rename
> kvm_loongarch_deliver_msi_to_vcpu() to dmsintc_deliver_msi_to_vcpu(),
> and move it to irqfd.c, then we don't need to declare it as a extern
> function.
Got it .
> And in addition, from Documentation/arch/loongarch/irq-chip-model.rst,
> all msi irq are triggered from "pch_msi_irq", which means it is not
> reasonable to dispatch the dmsintc/pch_msi paths in
> loongarch_set_msi(). Instead, we should dispatch the dmsintc/eiointc
> paths in pch_msi_set_irq(), this needs a rework...

longarch_set_msi() is equivalent to what you mentioned as pch_msi_set_irq(). I will correct it in the next version.

Thanks.
Song Gao

>
> Huacai
>
>> +
>> +
>>   const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>>          KVM_GENERIC_VCPU_STATS(),
>>          STATS_DESC_COUNTER(VCPU, int_exits),
>> --
>> 2.39.3
>>
>>


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-03-09  8:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-06  1:20 [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Song Gao
2026-02-06  1:20 ` [PATCH v6 1/2] LongArch: KVM: Add DMSINTC device support Song Gao
2026-03-05  7:31   ` Huacai Chen
2026-03-05 12:38     ` gaosong
2026-02-06  1:20 ` [PATCH v6 2/2] LongArch: KVM: Add dmsintc inject msi to the dest vcpu Song Gao
2026-03-05  7:33   ` Huacai Chen
2026-03-09  8:24     ` gaosong
2026-02-06  3:34 ` [PATCH v6 0/2] LongArch: KVM: Add DMSINTC support irqchip in kernel Yao Zi
2026-03-03  3:54   ` gaosong
2026-03-03  4:14     ` Huacai Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox