[PATCH v3 4/4] LongArch: KVM: Add dintc inject msi to the dest vcpu

Song Gao posted 4 patches 1 week, 6 days ago
[PATCH v3 4/4] LongArch: KVM: Add dintc inject msi to the dest vcpu
Posted by Song Gao 1 week, 6 days ago
Implement irqfd deliver msi to vcpu and
vcpu dintc inject irq.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 arch/loongarch/include/asm/kvm_host.h |  5 +++
 arch/loongarch/kvm/interrupt.c        |  1 +
 arch/loongarch/kvm/vcpu.c             | 55 +++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 26a90f4146ac..8099dd3f71dd 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_dintc_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/interrupt.c b/arch/loongarch/kvm/interrupt.c
index a6d42d399a59..c74e7af3e772 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_dintc_inject_irq(vcpu);
 		set_gcsr_estat(irq);
 		return 1;
 	}
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 6d833599ef2e..356d288799ac 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -13,6 +13,61 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
+void loongarch_dintc_inject_irq(struct kvm_vcpu *vcpu)
+{
+	struct dintc_state *ds = &vcpu->arch.dintc_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 dintc_state *ds;
+
+	if (!level)
+		return 0;
+	if (!vcpu || vector >= 256)
+		return -EINVAL;
+	ds = &vcpu->arch.dintc_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
Re: [PATCH v3 4/4] LongArch: KVM: Add dintc inject msi to the dest vcpu
Posted by Bibo Mao 1 week, 4 days ago

On 2025/12/6 下午2:46, Song Gao wrote:
> Implement irqfd deliver msi to vcpu and
> vcpu dintc inject irq.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   arch/loongarch/include/asm/kvm_host.h |  5 +++
>   arch/loongarch/kvm/interrupt.c        |  1 +
>   arch/loongarch/kvm/vcpu.c             | 55 +++++++++++++++++++++++++++
>   3 files changed, 61 insertions(+)
> 
> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
> index 26a90f4146ac..8099dd3f71dd 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_dintc_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/interrupt.c b/arch/loongarch/kvm/interrupt.c
> index a6d42d399a59..c74e7af3e772 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_dintc_inject_irq(vcpu);
>   		set_gcsr_estat(irq);
>   		return 1;
>   	}
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 6d833599ef2e..356d288799ac 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -13,6 +13,61 @@
>   #define CREATE_TRACE_POINTS
>   #include "trace.h"
>   
> +void loongarch_dintc_inject_irq(struct kvm_vcpu *vcpu)
> +{
> +	struct dintc_state *ds = &vcpu->arch.dintc_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);
> +	}
should there be one extra space line between two if() sentenses?
> +	if (temp[1]) {
> +		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR1);
> +		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR1, temp[1]|old);
> +	}
ditto
> +	if (temp[2]) {
> +		old = kvm_read_hw_gcsr(LOONGARCH_CSR_ISR2);
> +		kvm_write_hw_gcsr(LOONGARCH_CSR_ISR2, temp[2]|old);
> +	}
ditto

the other looks good to me.

Reviewed-by: Bibo Mao <maobibo@loongson.cn>
> +	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 dintc_state *ds;
> +
> +	if (!level)
> +		return 0;
> +	if (!vcpu || vector >= 256)
> +		return -EINVAL;
> +	ds = &vcpu->arch.dintc_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),
>