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
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),
>
© 2016 - 2025 Red Hat, Inc.