Improve handling of multi-source SGIs: instead of only inserting one source per SGI per run, try to insert them all at once. Hopefully this is a rare case. Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> --- virt/kvm/arm/vgic/vgic.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index c6f04a1..052f917 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c @@ -371,15 +371,22 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu) struct vgic_irq *irq; int count = 0; - list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) - count++; - + list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { + spin_lock(&irq->irq_lock); + /* GICv2 SGIs can count for more than one... */ + if (irq->intid < VGIC_NR_SGIS && irq->source) + count += hweight8(irq->source); + else + count++; + spin_unlock(&irq->irq_lock); + } return count; } static void vgic_populate_lrs(struct kvm_vcpu *vcpu) { struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + u32 model = vcpu->kvm->arch.vgic.vgic_model; struct vgic_irq *irq; int count = 0; @@ -390,8 +397,23 @@ static void vgic_populate_lrs(struct kvm_vcpu *vcpu) list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { spin_lock(&irq->irq_lock); - if (vgic_target_oracle(irq) == vcpu) + + if (unlikely(vgic_target_oracle(irq) != vcpu)) + goto next; + + /* + * If we get an SGI with multiple sources, try to get + * them in all at once. + */ + if (model == KVM_DEV_TYPE_ARM_VGIC_V2 && + irq->intid < VGIC_NR_SGIS) { + while(irq->source && count < vcpu->arch.vgic_cpu.nr_lr) + vgic_populate_lr(vcpu, irq, count++); + } else { vgic_populate_lr(vcpu, irq, count++); + } + + next: spin_unlock(&irq->irq_lock); if (count == vcpu->arch.vgic_cpu.nr_lr) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html