LoongArch: KVM: Inject interrupts with batch method

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>
This commit is contained in:
Bibo Mao 2026-06-11 20:46:42 +08:00 committed by Huacai Chen
parent 33c6da26d8
commit 3179253ad5

View 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)