mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
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>
This commit is contained in:
parent
81aa3a58b5
commit
ab382eae73
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user