[PATCH v4 2/2] KVM: arm64: vgic: Mitigate potential LPI registration failure
Carlos López
clopez at suse.de
Fri Jul 3 05:26:01 PDT 2026
Mitigate a potential failure when inserting a new LPI into the VGIC LPI
xarray.
When vgic_add_lpi() is preparing to register a new LPI, it pre-allocates
an xarray entry using xa_reserve_irq(), so that it can later perform the
insertion under the xarray lock without allocating.
However, since xa_reserve_irq() is called before acquiring such lock,
there is a potential race where xa_reserve_irq() observes a populated
entry, thus not performing the allocation, and another CPU removes that
entry before the xarray lock is grabbed to perform the insertion.
CPU0 (Adding new LPI) CPU1 (Releasing LPI)
===================== ===================
vgic_add_lpi()
/* Entry populated, does not allocate */
xa_reserve_irq(.., intid, ..)
vgic_release_deleted_lpis()
xa_lock_irqsave()
vgic_release_lpi_locked()
xarray node freed --> __xa_erase(.., intid)
xa_unlock_irqrestore()
xa_lock_irqsave()
xa_load(.., intid) == NULL
vgic_try_get_irq_ref(NULL) == false
__xa_store(.., intid, irq, 0) <-- xarray node was freed, gfp=0
cannot allocate, returns -ENOMEM
This can happen e.g. if the guest issues a DISCARD while the LPI is
still referenced from a vCPU's active-pending list (ap_list), and the
same INTID is re-mapped via MAPTI.
Mitigate this by passing GFP_NOWAIT to __xa_store(), so that the
allocation can happen under the lock in the rare case that this
condition is hit. Add __GFP_ACCOUNT as well to match xa_reserve_irq()'s
flags.
Reported-by: Sashiko <sashiko-bot at kernel.org>
Fixes: 1d6f83f60f79 ("KVM: arm64: vgic: Store LPIs in an xarray")
Signed-off-by: Carlos López <clopez at suse.de>
---
arch/arm64/kvm/vgic/vgic-its.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 577286069368..327418477c51 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -121,7 +121,8 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
* from the deferred release path, pending cleanup by
* vgic_release_deleted_lpis(). Evict and free it if present.
*/
- oldirq = __xa_store(&dist->lpi_xa, intid, irq, 0);
+ oldirq = __xa_store(&dist->lpi_xa, intid, irq,
+ GFP_NOWAIT | __GFP_ACCOUNT);
ret = xa_err(oldirq);
if (!ret && oldirq)
kfree_rcu(oldirq, rcu);
--
2.51.0
More information about the linux-arm-kernel
mailing list