With bitmask method, interrupt can be injected with batch mode, rather than one by one. Also remove unused array priority_to_irqp[] here. Signed-off-by: Bibo Mao --- arch/loongarch/kvm/interrupt.c | 95 ++++++++++------------------------ 1 file changed, 28 insertions(+), 67 deletions(-) diff --git a/arch/loongarch/kvm/interrupt.c b/arch/loongarch/kvm/interrupt.c index 48dd56aa4dc5..380aabb3d4d0 100644 --- a/arch/loongarch/kvm/interrupt.c +++ b/arch/loongarch/kvm/interrupt.c @@ -9,39 +9,16 @@ #include #include -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: - dmsintc_inject_irq(vcpu); - fallthrough; - case INT_TI: - case INT_IPI: - case INT_SWI0: - case INT_SWI1: + irq = mask & KVM_ESTAT_IRQ_MASK; + if (irq) { + if (irq & CPU_AVEC) + dmsintc_inject_irq(vcpu); + 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 >> 2) & 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_IRQ_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 >> 2) & 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) -- 2.39.3