Skip to content

Fix issues with vGIC LR management#334

Open
josecm wants to merge 7 commits into
bao-project:mainfrom
josecm:fix/vgic_misc
Open

Fix issues with vGIC LR management#334
josecm wants to merge 7 commits into
bao-project:mainfrom
josecm:fix/vgic_misc

Conversation

@josecm

@josecm josecm commented Mar 19, 2026

Copy link
Copy Markdown
Member

This PR introduces a set of fixes related to issues with vGIC List Register management. Among others, it addresses issues #162.

josecm added 7 commits March 19, 2026 10:17
When a guest disables an interrupt that is currently active in an LR,
vgic_route() and vgic_add_lr() were returning early due to the
!interrupt->enabled check, leaving the interrupt untracked. On re-enable,
Bao would re-inject it as active causing incorrect state.

Allow disabled-but-active interrupts through so the guest can EOI them
directly via the LR, avoiding a spurious LRENP maintenance interrupt trap.

Signed-off-by: Jose Martins <josemartins90@gmail.com>
vgic_eoir_highest_spilled_active() was clearing the ACT state of the
highest-priority spilled active interrupt but never removing it from the
spilled list, causing it to be re-processed on subsequent maintenance
interrupts or LR refills.

Add list_rm() after gaining ownership. vgic_spilled_lock is held around
the search and removal; it is released before vgic_add_lr() to avoid a
deadlock with vgic_add_spilled() on the SW+PEND path.

Signed-off-by: Jose Martins <josemartins90@gmail.com>
When vgic_route() fails to place an interrupt in an LR or forward it to
another CPU (e.g. no target configured), the interrupt was left untracked
— not in any LR and not in the spilled list — causing it to be missed
on future LR refills.

Add in_spilled flag to vgic_int to prevent double-adds. vgic_add_spilled()
guards on !in_lr && !in_spilled, and clears/sets the flag alongside
list operations. vgic_route() unconditionally calls vgic_add_spilled() as
a fallback after routing, which is a no-op if the interrupt was already
placed in an LR or spilled by vgic_add_lr().

Signed-off-by: Jose Martins <josemartins90@gmail.com>
When vgic_add_lr() successfully placed an interrupt into an LR, it left
a stale entry in the spilled list, causing vgic_refill_lrs() to find and
attempt to re-process an already-tracked interrupt.

Introduce vgic_remove_spilled() to wrap list_rm() and the in_spilled flag
update in one place. Call it in vgic_add_lr() before vgic_write_lr(), and
replace the open-coded equivalents in vgic_refill_lrs() and
vgic_eoir_highest_spilled_active(). Drop the now-unused outlist parameter
from vgic_highest_prio_spilled().

Signed-off-by: Jose Martins <josemartins90@gmail.com>
Sending an IPI for an active interrupt is pointless: vgic_yield_ownership()
refuses to yield ownership while the interrupt is active, so the receiving
CPU will fail to acquire ownership and do nothing. Avoid the unnecessary
IPI by guarding the forwarding path with !(interrupt->state & ACT).

Signed-off-by: Jose Martins <josemartins90@gmail.com>
… state

When a disabled PENDACT interrupt is placed in an LR, the LR was written
with both ACT and PEND set. On guest EOI the LR would transition from
PENDACT to PEND and re-deliver the interrupt even though it is disabled.

Strip PEND from the LR state written for disabled non-HW interrupts, and
preserve it in interrupt->state so it is restored when the interrupt is
re-enabled. HW PENDACT is impossible (the physical GIC prevents re-assertion
while active), so state & PEND is always 0 for HW — no special case needed.

Also fix vgic_remove_lr() to OR in the preserved PEND when updating
interrupt->state from the LR, so that an early removal (e.g. on re-enable
before the guest EOIs) does not overwrite the preserved pending state.

Signed-off-by: Jose Martins <josemartins90@gmail.com>
…illed

When all LRs are full and pend_found > 1 but all pending LRs have higher
priority than the new interrupt (pend_ind == -1), the spill selection set
lr_ind = -1 and skipped eviction entirely, even if a lower-priority active
LR was available to spill.

Add pend_ind >= 0 to the condition so the selection falls through to
act_ind when no eligible pending candidate exists.

Signed-off-by: Jose Martins <josemartins90@gmail.com>

@irenebus irenebus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @josecm. This successfully fixes the issue described in #371 . Thanks for pointing me to it!

@josecm

josecm commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

Hi, @josecm. This successfully fixes the issue described in #371 . Thanks for pointing me to it!

Thanks for your feedback @irenebus. Glad your issue is solved!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants