In order to find out whether a vcpu is likely to be the target of VLPIs (and to further optimize the way we deal with those), let's track the number of VLPIs a vcpu can receive. This gets implemented with an atomic variable that gets incremented or decremented on map, unmap and move of a VLPI.
Unified · Split
| @@ -32,6 +32,8 @@ struct its_vm { · 31 unmodified lines | |||
| 32 | struct its_vpe { | 32 | struct its_vpe { |
| 33 | struct page *vpt_page; | 33 | struct page *vpt_page; |
| 34 | struct its_vm *its_vm; | 34 | struct its_vm *its_vm; |
| 35 | /* per-vPE VLPI tracking */ | ||
| 36 | atomic_t vlpi_count; | ||
| 35 | /* Doorbell interrupt */ | 37 | /* Doorbell interrupt */ |
| 36 | int irq; | 38 | int irq; |
| 37 | irq_hw_number_t vpe_db_lpi; | 39 | irq_hw_number_t vpe_db_lpi; |
| @@ -203,6 +203,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) · 202 unmodified lines | |||
| 203 | 203 | ||
| 204 | INIT_LIST_HEAD(&vgic_cpu->ap_list_head); | 204 | INIT_LIST_HEAD(&vgic_cpu->ap_list_head); |
| 205 | raw_spin_lock_init(&vgic_cpu->ap_list_lock); | 205 | raw_spin_lock_init(&vgic_cpu->ap_list_lock); |
| 206 | atomic_set(&vgic_cpu->vgic_v3.its_vpe.vlpi_count, 0); | ||
| 206 | 207 | ||
| 207 | /* | 208 | /* |
| 208 | * Enable and configure all SGIs to be edge-triggered and | 209 | * Enable and configure all SGIs to be edge-triggered and |
| @@ -360,7 +360,10 @@ static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu) · 359 unmodified lines | |||
| 360 | if (ret) | 360 | if (ret) |
| 361 | return ret; | 361 | return ret; |
| 362 | 362 | ||
| 363 | if (map.vpe) | ||
| 364 | atomic_dec(&map.vpe->vlpi_count); | ||
| 363 | map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe; | 365 | map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe; |
| 366 | atomic_inc(&map.vpe->vlpi_count); | ||
| 364 | 367 | ||
| 365 | ret = its_map_vlpi(irq->host_irq, &map); | 368 | ret = its_map_vlpi(irq->host_irq, &map); |
| 366 | } | 369 | } |
| @@ -309,6 +309,7 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq, · 308 unmodified lines | |||
| 309 | 309 | ||
| 310 | irq->hw = true; | 310 | irq->hw = true; |
| 311 | irq->host_irq = virq; | 311 | irq->host_irq = virq; |
| 312 | atomic_inc(&map.vpe->vlpi_count); | ||
| 312 | 313 | ||
| 313 | out: | 314 | out: |
| 314 | mutex_unlock(&its->its_lock); | 315 | mutex_unlock(&its->its_lock); |
| @@ -342,6 +343,7 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq, · 27 unmodified lines | |||
| 342 | 343 | ||
| 343 | WARN_ON(!(irq->hw && irq->host_irq == virq)); | 344 | WARN_ON(!(irq->hw && irq->host_irq == virq)); |
| 344 | if (irq->hw) { | 345 | if (irq->hw) { |
| 346 | atomic_dec(&irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count); | ||
| 345 | irq->hw = false; | 347 | irq->hw = false; |
| 346 | ret = its_unmap_vlpi(virq); | 348 | ret = its_unmap_vlpi(virq); |
| 347 | } | 349 | } |