]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
LoongArch: KVM: Inject interrupts with batch method
authorBibo Mao <maobibo@loongson.cn>
Thu, 11 Jun 2026 12:46:42 +0000 (20:46 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 11 Jun 2026 12:46:42 +0000 (20:46 +0800)
With bitmask method, interrupts can be injected with batch mode rather
than one by one. Also remove unused array priority_to_irq[] here.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/kvm/interrupt.c

index 48dd56aa4dc569815a0c94bfd17ffe0353a3de2d..055ac9235b03e6f9194e985b2cbb1ff1a3d999e9 100644 (file)
@@ -9,39 +9,16 @@
 #include <asm/kvm_vcpu.h>
 #include <asm/kvm_dmsintc.h>
 
-static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
-       [INT_TI]        = CPU_TIMER,
-       [INT_IPI]       = CPU_IPI,
-       [INT_SWI0]      = CPU_SIP0,
-       [INT_SWI1]      = CPU_SIP1,
-       [INT_HWI0]      = CPU_IP0,
-       [INT_HWI1]      = CPU_IP1,
-       [INT_HWI2]      = CPU_IP2,
-       [INT_HWI3]      = CPU_IP3,
-       [INT_HWI4]      = CPU_IP4,
-       [INT_HWI5]      = CPU_IP5,
-       [INT_HWI6]      = CPU_IP6,
-       [INT_HWI7]      = CPU_IP7,
-       [INT_AVEC]      = CPU_AVEC,
-};
-
-static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
+static void kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned long mask)
 {
-       unsigned int irq = 0;
+       unsigned long irq;
        unsigned long old, new;
 
-       clear_bit(priority, &vcpu->arch.irq_pending);
-       if (priority < EXCCODE_INT_NUM)
-               irq = priority_to_irq[priority];
-
-       switch (priority) {
-       case INT_AVEC:
+       if (mask & CPU_AVEC)
                dmsintc_inject_irq(vcpu);
-               fallthrough;
-       case INT_TI:
-       case INT_IPI:
-       case INT_SWI0:
-       case INT_SWI1:
+
+       irq = mask & KVM_ESTAT_INTI_MASK;
+       if (irq) {
                old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
                set_gcsr_estat(irq);
                new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
@@ -49,34 +26,20 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
                /* Inject TI if TVAL inverted */
                if (new > old)
                        set_gcsr_estat(CPU_TIMER);
-               break;
-
-       case INT_HWI0 ... INT_HWI7:
-               set_csr_gintc(irq);
-               break;
-
-       default:
-               break;
        }
 
-       return 1;
+       irq = (mask >> VIP_DELTA) & KVM_GINTC_IRQ_MASK;
+       if (irq)
+               set_csr_gintc(irq);
 }
 
-static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
+static void kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned long mask)
 {
-       unsigned int irq = 0;
+       unsigned long irq;
        unsigned long old, new;
 
-       clear_bit(priority, &vcpu->arch.irq_clear);
-       if (priority < EXCCODE_INT_NUM)
-               irq = priority_to_irq[priority];
-
-       switch (priority) {
-       case INT_AVEC:
-       case INT_TI:
-       case INT_IPI:
-       case INT_SWI0:
-       case INT_SWI1:
+       irq = mask & KVM_ESTAT_INTI_MASK;
+       if (irq) {
                old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
                clear_gcsr_estat(irq);
                new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
@@ -84,30 +47,28 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
                /* Inject TI if TVAL inverted */
                if (new > old)
                        set_gcsr_estat(CPU_TIMER);
-               break;
-
-       case INT_HWI0 ... INT_HWI7:
-               clear_csr_gintc(irq);
-               break;
-
-       default:
-               break;
        }
 
-       return 1;
+       irq = (mask >> VIP_DELTA) & KVM_GINTC_IRQ_MASK;
+       if (irq)
+               clear_csr_gintc(irq);
 }
 
 void kvm_deliver_intr(struct kvm_vcpu *vcpu)
 {
-       unsigned int priority;
-       unsigned long *pending = &vcpu->arch.irq_pending;
-       unsigned long *pending_clr = &vcpu->arch.irq_clear;
+       unsigned long mask;
 
-       for_each_set_bit(priority, pending_clr, EXCCODE_INT_NUM)
-               kvm_irq_clear(vcpu, priority);
+       mask = READ_ONCE(vcpu->arch.irq_clear);
+       if (mask) {
+               mask = xchg_relaxed(&vcpu->arch.irq_clear, 0);
+               kvm_irq_clear(vcpu, mask);
+       }
 
-       for_each_set_bit(priority, pending, EXCCODE_INT_NUM)
-               kvm_irq_deliver(vcpu, priority);
+       mask = READ_ONCE(vcpu->arch.irq_pending);
+       if (mask) {
+               mask = xchg_relaxed(&vcpu->arch.irq_pending, 0);
+               kvm_irq_deliver(vcpu, mask);
+       }
 }
 
 int kvm_pending_timer(struct kvm_vcpu *vcpu)