KVM: arm64: vgic: Use atomics to count LPIs
authorOliver Upton <oliver.upton@linux.dev>
Wed, 21 Feb 2024 05:42:49 +0000 (05:42 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Fri, 23 Feb 2024 21:46:02 +0000 (21:46 +0000)
Switch to using atomics for LPI accounting, allowing vgic_irq references
to be dropped in parallel.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240221054253.3848076-7-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/vgic/vgic-debug.c
arch/arm64/kvm/vgic/vgic-its.c
arch/arm64/kvm/vgic/vgic.c
include/kvm/arm_vgic.h

index 85606a531dc3987fc04c18a179c577efd2113ff8..389025ce7749bc32e889f80f2a395552831b0f77 100644 (file)
@@ -149,7 +149,7 @@ static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
        seq_printf(s, "vgic_model:\t%s\n", v3 ? "GICv3" : "GICv2");
        seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
        if (v3)
-               seq_printf(s, "nr_lpis:\t%d\n", dist->lpi_list_count);
+               seq_printf(s, "nr_lpis:\t%d\n", atomic_read(&dist->lpi_count));
        seq_printf(s, "enabled:\t%d\n", dist->enabled);
        seq_printf(s, "\n");
 
index 3d0208162bcdac11d075633ad392d0c1542c304a..0be3c33676c396f9e3e394bf2547fd5cb690e2cf 100644 (file)
@@ -96,7 +96,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
                goto out_unlock;
        }
 
-       dist->lpi_list_count++;
+       atomic_inc(&dist->lpi_count);
 
 out_unlock:
        raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
@@ -346,7 +346,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
         * command). If coming from another path (such as enabling LPIs),
         * we must be careful not to overrun the array.
         */
-       irq_count = READ_ONCE(dist->lpi_list_count);
+       irq_count = atomic_read(&dist->lpi_count);
        intids = kmalloc_array(irq_count, sizeof(intids[0]), GFP_KERNEL_ACCOUNT);
        if (!intids)
                return -ENOMEM;
index 6240faab0127025472adddefc0abbe7be6e2be3e..15dbd17b3a9e21324d9246e7684b7221eca233cf 100644 (file)
@@ -123,7 +123,7 @@ void __vgic_put_lpi_locked(struct kvm *kvm, struct vgic_irq *irq)
                return;
 
        xa_erase(&dist->lpi_xa, irq->intid);
-       dist->lpi_list_count--;
+       atomic_dec(&dist->lpi_count);
 
        kfree(irq);
 }
index aeff363e3ba6019efb44c09ad735aabb54d21129..71e9d719533b687d1c96be6cb8eb056b5bbd9dfe 100644 (file)
@@ -273,10 +273,10 @@ struct vgic_dist {
         */
        u64                     propbaser;
 
-       /* Protects the lpi_list and the count value below. */
+       /* Protects the lpi_list. */
        raw_spinlock_t          lpi_list_lock;
        struct xarray           lpi_xa;
-       int                     lpi_list_count;
+       atomic_t                lpi_count;
 
        /* LPI translation cache */
        struct list_head        lpi_translation_cache;