kvm_vgic_v4_set_forwarding() acquires its_lock to safely map guest LPIs to host IRQs for vLPI upgrades. Future per-vCPU direct vLPI injection requires atomically upgrading multiple LPIs while holding its_lock, which would cause recursive locking when calling kvm_vgic_v4_set_forwarding().
Extract the locked portion to kvm_vgic_v4_set_forwarding_locked() to allow callers already holding its_lock to perform vLPI upgrades without recursive locking.
No functional change.
Signed-off-by: Maximilian Dittgen mdittgen@amazon.com --- arch/arm64/kvm/vgic/vgic-v4.c | 38 +++++++++++++++++++++-------------- include/kvm/arm_vgic.h | 3 +++ 2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c index fb2e6af96aa9..4a1825a1a5d7 100644 --- a/arch/arm64/kvm/vgic/vgic-v4.c +++ b/arch/arm64/kvm/vgic/vgic-v4.c @@ -483,27 +483,15 @@ int kvm_vgic_v4_map_irq_to_host(struct kvm *kvm, int virq, return 0; }
-int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq, - struct kvm_kernel_irq_routing_entry *irq_entry) +int kvm_vgic_v4_set_forwarding_locked(struct kvm *kvm, int virq, + struct kvm_kernel_irq_routing_entry *irq_entry, struct vgic_its *its) { - struct vgic_its *its; struct vgic_irq *irq; struct its_vlpi_map map; unsigned long flags; int ret = 0;
- if (!vgic_supports_direct_msis(kvm)) - return 0; - - /* - * Get the ITS, and escape early on error (not a valid - * doorbell for any of our vITSs). - */ - its = vgic_get_its(kvm, irq_entry); - if (IS_ERR(its)) - return 0; - - guard(mutex)(&its->its_lock); + lockdep_assert_held(&its->its_lock);
/* * Perform the actual DevID/EventID -> LPI translation. @@ -567,6 +555,26 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq, return ret; }
+int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq, + struct kvm_kernel_irq_routing_entry *irq_entry) +{ + struct vgic_its *its; + + if (!vgic_supports_direct_msis(kvm)) + return 0; + + /* + * Get the ITS, and escape early on error (not a valid + * doorbell for any of our vITSs). + */ + its = vgic_get_its(kvm, irq_entry); + if (IS_ERR(its)) + return 0; + + guard(mutex)(&its->its_lock); + return kvm_vgic_v4_set_forwarding_locked(kvm, virq, irq_entry, its); +} + static struct vgic_irq *__vgic_host_irq_get_vlpi(struct kvm *kvm, int host_irq) { struct vgic_irq *irq; diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 02842754627f..18a49c4b83f8 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -454,6 +454,9 @@ int kvm_vgic_v4_map_irq_to_host(struct kvm *kvm, int virq, struct kvm_kernel_irq_routing_entry *irq_entry); int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq, struct kvm_kernel_irq_routing_entry *irq_entry); +int kvm_vgic_v4_set_forwarding_locked(struct kvm *kvm, int virq, + struct kvm_kernel_irq_routing_entry *irq_entry, + struct vgic_its *its);
void kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int host_irq);