diff options
| author | Bibo Mao <maobibo@loongson.cn> | 2026-08-10 12:21:58 +0800 |
|---|---|---|
| committer | Huacai Chen <chenhuacai@loongson.cn> | 2026-08-10 12:21:58 +0800 |
| commit | ab382eae730e231021667e26a520ef2fe58f4b33 (patch) | |
| tree | fc56bac1df12b2facbdccecca10d6888b7a491ae | |
| parent | 81aa3a58b542ed88819115c80a17acd86eacb89d (diff) | |
| download | linux-ab382eae730e231021667e26a520ef2fe58f4b33.tar.gz linux-ab382eae730e231021667e26a520ef2fe58f4b33.zip | |
LoongArch: KVM: Use internal API to deliver interrupt in kernel mode
API kvm_vcpu_ioctl_interrupt() is mainly to used to deliver interrupt
from user mode, and internal APIs kvm_queue_irq() and kvm_dequeue_irq()
are used in kernel mode.
Also move IPI inject and ack within lock protection to avoid contention
in ipi_set() and ipi_clear().
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
| -rw-r--r-- | arch/loongarch/kvm/intc/dmsintc.c | 7 | ||||
| -rw-r--r-- | arch/loongarch/kvm/intc/eiointc.c | 14 | ||||
| -rw-r--r-- | arch/loongarch/kvm/intc/ipi.c | 14 | ||||
| -rw-r--r-- | arch/loongarch/kvm/vcpu.c | 3 |
4 files changed, 22 insertions, 16 deletions
diff --git a/arch/loongarch/kvm/intc/dmsintc.c b/arch/loongarch/kvm/intc/dmsintc.c index 5f16fb185831..78407b6df25a 100644 --- a/arch/loongarch/kvm/intc/dmsintc.c +++ b/arch/loongarch/kvm/intc/dmsintc.c @@ -46,7 +46,6 @@ void dmsintc_inject_irq(struct kvm_vcpu *vcpu) int dmsintc_deliver_msi_to_vcpu(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 vector, int level) { - struct kvm_interrupt vcpu_irq; struct dmsintc_state *ds = &vcpu->arch.dmsintc_state; if (!level) @@ -56,9 +55,11 @@ int dmsintc_deliver_msi_to_vcpu(struct kvm *kvm, if (!ds) return -ENODEV; - vcpu_irq.irq = INT_AVEC; + if (!kvm_guest_has_msgint(&vcpu->arch)) + return -EINVAL; + set_bit(vector, (unsigned long *)&ds->vector_map); - kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq); + kvm_queue_irq(vcpu, INT_AVEC); kvm_vcpu_kick(vcpu); return 0; diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index 2b14485d14a7..1f5b299ead9e 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -17,7 +17,8 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { ipnum = count_trailing_zeros(ipnum); ipnum = ipnum < 4 ? ipnum : 0; - } + } else + ipnum = ipnum < LOONGSON_IP_NUM ? ipnum : 0; cpuid = ((u8 *)s->coremap)[irq]; vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); @@ -36,13 +37,13 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) { int ipnum, cpu, found; struct kvm_vcpu *vcpu; - struct kvm_interrupt vcpu_irq; ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff; if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) { ipnum = count_trailing_zeros(ipnum); ipnum = ipnum < 4 ? ipnum : 0; - } + } else + ipnum = ipnum < LOONGSON_IP_NUM ? ipnum : 0; cpu = s->sw_coremap[irq]; vcpu = kvm_get_vcpu_by_id(s->kvm, cpu); @@ -67,8 +68,11 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) if (found < EIOINTC_IRQS) return; /* other irq is handling, needn't update parent irq */ - vcpu_irq.irq = level ? (INT_HWI0 + ipnum) : -(INT_HWI0 + ipnum); - kvm_vcpu_ioctl_interrupt(vcpu, &vcpu_irq); + if (level) + kvm_queue_irq(vcpu, INT_HWI0 + ipnum); + else + kvm_dequeue_irq(vcpu, INT_HWI0 + ipnum); + kvm_vcpu_kick(vcpu); } static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s, diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 80f02c2385bb..90bc42389850 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -10,16 +10,15 @@ static void ipi_set(struct kvm_vcpu *vcpu, uint32_t data) { uint32_t status; - struct kvm_interrupt irq; spin_lock(&vcpu->arch.ipi_state.lock); status = vcpu->arch.ipi_state.status; vcpu->arch.ipi_state.status |= data; - spin_unlock(&vcpu->arch.ipi_state.lock); if ((status == 0) && data) { - irq.irq = LARCH_INT_IPI; - kvm_vcpu_ioctl_interrupt(vcpu, &irq); + kvm_queue_irq(vcpu, LARCH_INT_IPI); + kvm_vcpu_kick(vcpu); } + spin_unlock(&vcpu->arch.ipi_state.lock); } static void ipi_send(struct kvm *kvm, uint64_t data) @@ -40,16 +39,15 @@ static void ipi_send(struct kvm *kvm, uint64_t data) static void ipi_clear(struct kvm_vcpu *vcpu, uint64_t data) { uint32_t status; - struct kvm_interrupt irq; spin_lock(&vcpu->arch.ipi_state.lock); vcpu->arch.ipi_state.status &= ~data; status = vcpu->arch.ipi_state.status; - spin_unlock(&vcpu->arch.ipi_state.lock); if (status == 0) { - irq.irq = -LARCH_INT_IPI; - kvm_vcpu_ioctl_interrupt(vcpu, &irq); + kvm_dequeue_irq(vcpu, LARCH_INT_IPI); + kvm_vcpu_kick(vcpu); } + spin_unlock(&vcpu->arch.ipi_state.lock); } static uint64_t read_mailbox(struct kvm_vcpu *vcpu, int offset, int len) diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index fd0dd22a7162..7d02e0dec897 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -1465,6 +1465,9 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) if (vector >= EXCCODE_INT_NUM) return -EINVAL; + if (kvm_arch_irqchip_in_kernel(vcpu->kvm)) + return -EINVAL; + if (!kvm_guest_has_msgint(&vcpu->arch) && (vector == INT_AVEC)) return -EINVAL; |
