From: sashiko-bot@kernel.org
To: "Fuad Tabba" <fuad.tabba@linux.dev>, kvmarm@lists.linux.dev
Cc: "Oliver Upton" <oupton@kernel.org>, "Marc Zyngier" <maz@kernel.org>
Subject: Re: [PATCH 2/2] KVM: arm64: vgic-v3: Don't drop a pending LPI mapped with LPIs disabled
Date: Mon, 26 Oct 2026 10:33:42 +0000 [thread overview]
Message-ID: <sashiko-outbox-184962@kernel.org> (raw)
In-Reply-To: <20261026092802.2636798-3-fuad.tabba@linux.dev>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] KVM: arm64: vgic-v3: unconsumed pending table bit when LPIs are enabled
- [High] KVM: arm64: vgic-v3: TOCTOU race on vgic_lpis_enabled() drops pending LPI
--
commit 1318a5e945ab06141897d5ffe8f4348f6a0ecf31
Author: Fuad Tabba <fuad.tabba@linux.dev>
KVM: arm64: vgic-v3: Don't drop a pending LPI mapped with LPIs disabled
This commit updates vgic_v3_lpi_sync_pending_status() so that it only clears
the pending bit in the guest redistributor's pending table when LPIs are
enabled on the target vCPU. This ensures that when LPIs are subsequently
enabled and its_sync_lpi_pending_table() reloads pending state from guest
memory, a pending LPI mapped while LPIs were disabled does not lose its
pending status.
> diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
> index 346bacb3198f2..65b77fb35be37 100644
> --- a/arch/arm64/kvm/vgic/vgic-v3.c
> +++ b/arch/arm64/kvm/vgic/vgic-v3.c
> @@ -552,7 +552,8 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq)
> irq->pending_latch = status;
> vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
>
> - if (status) {
> + /* Enabling LPIs resets the latch from the table: leave the bit for it */
> + if (status && vgic_lpis_enabled(vcpu)) {
[Severity: High]
When vgic_lpis_enabled(vcpu) is false, vgic_v3_lpi_sync_pending_status() leaves
the pending bit set in the guest's pending table for its_sync_lpi_pending_table()
to consume later.
However, when the guest enables LPIs on the redistributor via
vgic_mmio_write_v3r_ctlr() -> vgic_enable_lpis() -> its_sync_lpi_pending_table(),
its_sync_lpi_pending_table() reads the pending bit into irq->pending_latch
without clearing the bit in guest memory:
arch/arm64/kvm/vgic/vgic-its.c:its_sync_lpi_pending_table() {
...
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->target_vcpu == vcpu)
irq->pending_latch = pendmask & (1U << bit_nr);
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
vgic_put_irq(vcpu->kvm, irq);
...
}
Could leaving that bit set in guest RAM cause spurious LPI delivery in the
following cases?
1. After the guest acknowledges and deactivates the LPI, only irq->pending_latch
is cleared in software while the bit in guest RAM remains 1. If the guest
later discards and remaps the LPI while LPIs are enabled, vgic_add_lpi() ->
vgic_v3_lpi_sync_pending_status() will read the stale bit from guest RAM and
inject a spurious interrupt (or if the guest disables and re-enables LPIs,
its_sync_lpi_pending_table() will re-inject the already-consumed interrupt).
2. If the guest issues an ITS CLEAR command (vgic_its_cmd_handle_clear())
before enabling LPIs, CLEAR only clears irq->pending_latch, and enabling
LPIs via its_sync_lpi_pending_table() will resurrect the cleared interrupt
from the bit left in guest RAM.
[Severity: High]
Can a race between vgic_v3_lpi_sync_pending_status() on one vCPU and
vgic_mmio_write_v3r_ctlr() enabling LPIs on another vCPU cause the pending LPI
to still be dropped?
In vgic_v3_lpi_sync_pending_status(), vgic_queue_irq_unlock() calls
vgic_target_oracle(irq) while holding irq->irq_lock:
arch/arm64/kvm/vgic/vgic.c:vgic_target_oracle() {
...
if (unlikely(vcpu && irq_is_lpi(vcpu->kvm, irq->intid) && !vgic_lpis_enabled(vcpu)))
return NULL;
...
}
If vgic_lpis_enabled(vcpu) is false at that point, vgic_target_oracle() returns
NULL and vgic_queue_irq_unlock() unlocks irq->irq_lock without queueing the LPI
onto the target vCPU's ap_list.
If another vCPU concurrently writes GICR_CTLR_ENABLE_LPIS in
vgic_mmio_write_v3r_ctlr() right after vgic_queue_irq_unlock() checks
vgic_lpis_enabled(vcpu):
CPU 0 (vgic_v3_lpi_sync_pending_status) CPU 1 (vgic_mmio_write_v3r_ctlr)
--------------------------------------- --------------------------------
vgic_queue_irq_unlock()
vgic_target_oracle()
!vgic_lpis_enabled(vcpu) -> returns NULL
unlocks irq->irq_lock (not queued)
atomic_cmpxchg_acquire(&vgic_cpu->ctlr,
0, GICR_CTLR_ENABLE_LPIS);
if (status && vgic_lpis_enabled(vcpu))
/* now true! */
val &= ~(1 << bit_nr);
vgic_write_guest_lock(kvm, ptr, &val, 1);
vgic_enable_lpis(vcpu)
its_sync_lpi_pending_table(vcpu)
/* reads 0 from guest table */
irq->pending_latch = 0;
Wouldn't CPU 0 observe vgic_lpis_enabled(vcpu) as true on the second check and
clear the bit in the guest pending table before its_sync_lpi_pending_table()
reads it, causing its_sync_lpi_pending_table() to overwrite irq->pending_latch
with 0 and lose the pending interrupt?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261026092802.2636798-1-fuad.tabba@linux.dev?part=2
next prev parent reply other threads:[~2026-10-26 10:33 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 9:28 [PATCH 0/2] KVM: arm64: vgic: LPI fixes for redistributors with LPIs disabled Fuad Tabba
2026-10-26 9:28 ` [PATCH 1/2] KVM: arm64: vgic: Don't forward LPIs to a redistributor " Fuad Tabba
2026-10-26 10:13 ` sashiko-bot
2026-10-26 11:14 ` Fuad Tabba
2026-10-26 9:28 ` [PATCH 2/2] KVM: arm64: vgic-v3: Don't drop a pending LPI mapped " Fuad Tabba
2026-10-26 10:33 ` sashiko-bot [this message]
2026-10-26 11:15 ` Fuad Tabba
2026-10-27 23:53 ` [PATCH 0/2] KVM: arm64: vgic: LPI fixes for redistributors " Oliver Upton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-184962@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=fuad.tabba@linux.dev \
--cc=kvmarm@lists.linux.dev \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.