[PATCH v5 0/4] xen/arm: Fix eSPI IRQ handling

Mykola Kvach posted 4 patches 23 hours ago
xen/arch/arm/gic-v2.c          | 15 ++++---
xen/arch/arm/gic-v3.c          | 15 ++++---
xen/arch/arm/gic.c             |  6 +++
xen/arch/arm/include/asm/irq.h | 11 ------
xen/arch/arm/irq.c             | 28 +++++++++++--
xen/arch/arm/tee/ffa_notif.c   | 11 +++++-
xen/arch/arm/time.c            | 18 +++++++--
xen/arch/arm/vgic.c            | 72 +++++++++++++++++++++++-----------
xen/arch/arm/vgic/vgic.c       |  5 ++-
xen/drivers/char/ns16550.c     |  8 +++-
xen/drivers/char/pl011.c       |  4 +-
11 files changed, 135 insertions(+), 58 deletions(-)
[PATCH v5 0/4] xen/arm: Fix eSPI IRQ handling
Posted by Mykola Kvach 23 hours ago
This series fixes sparse eSPI INTID handling and checks errors returned by
irq_set_type().

Patch 1 checks irq_set_type() failures in the GTDT, MADT, SPCR, and FF-A
paths. GTDT and MADT could retain rejected timer or maintenance INTIDs
and later use them in direct descriptor lookups. This patch also fixes
MISRA C Rule 17.7 violations. It is now first in the series, as requested
during review, so callers handle errors before stricter IRQ validation
is introduced.

Patch 2 makes is_espi() check the architectural INTID range regardless of
CONFIG_GICV3_ESPI. If the GIC reports an eSPI without compiled-in support,
Xen stops with BUG_ON(), as there is no descriptor or pending_irq storage
for it. Virtual eSPI pending lookups without support are treated as
unreachable: the stub asserts in debug builds and retains a NULL return.

Xen has IRQ descriptors for INTIDs below NR_IRQS and, with eSPI support,
for eSPIs starting at 4096. It has no descriptors for INTIDs 1024 through
4095. Patch 3 checks INTIDs in setup_irq() and irq_set_spi_type() before
descriptor lookup. irq_set_spi_type() checks descriptor-backed ranges
because it can run before the GIC line counts are known. setup_irq()
checks implemented lines using those counts.

Patch 4 fixes the vGIC allocation bitmap. Reserving an eSPI used a compact
bitmap index, but freeing it used the raw virtual INTID. This could write
past the bitmap and leave the eSPI reserved. Both vGIC implementations now
use vgic_is_valid_line() when reserving and freeing vIRQs.

Testing of the v5 review changes, before the latest rebase and reordering:

- Arm64 build with CONFIG_NEW_VGIC=y, CONFIG_GICV2=y, and CONFIG_DEBUG=y.
- QEMU GICv2 guest tests: 10 checks passed, covering SPI delivery,
  enable/disable behavior, affinity changes, SGIs, and the virtual timer.

Testing from earlier revisions, before the final v5 edits:

- QEMU and FVP tests with CONFIG_GICV3_ESPI, CONFIG_HAS_ITS, and
  CONFIG_DEBUG enabled and disabled.
- Physical and virtual eSPI delivery on FVP, including delivery to both
  vCPUs and retriggering an active eSPI.
- Injected an unsupported physical eSPI and confirmed BUG_ON() in both
  debug and release builds.
- Arm64 builds with CONFIG_GICV3_ESPI and CONFIG_DEBUG enabled and disabled.
- Arm64 debug builds with CONFIG_ACPI=y and CONFIG_FFA=y, both with and
  without CONFIG_GICV3_ESPI.
- FVP Device Tree boot with 64 eSPIs; Linux dom0 started.
- QEMU virt UEFI/ACPI boot to a dom0 initramfs shell, covering the GTDT,
  GICv3 MADT, and PL011 SPCR paths.

Changes in v5:

- Move the irq_set_type() error-handling patch to the beginning.
- Explain why an eSPI cannot be handled without compiled-in support.
- Make both espi_to_pending() helpers static inline and constify d.
- Add ASSERT_UNREACHABLE() to the disabled-eSPI stub.
- Preserve the unmapped LPI comment and clarify that eSPI lookup without
  support must not occur.
- Add the vgic_is_valid_line() guard to vgic_free_virq() in the new vGIC
  implementation and use the same helper in vgic_reserve_virq().

Changes in v4:

- Use BUG_ON() when the GIC reports an eSPI without compiled-in support.
- Return NULL for virtual eSPI pending lookups when support is disabled.
- Remove the redundant CONFIG_GICV3_ESPI check in IRQ dispatch.
- Share irq_has_desc() with the assertion in __irq_to_desc().
- Log invalid IRQs rejected by setup_irq().
- Document the compressed vIRQ allocation bitmap above the conversion
  helpers, with an ASCII diagram and a reference to struct vgic_dist.
- Clarify the is_espi() commit message and drop unrelated blank-line
  removals.
- Add Reviewed-by tags.

Changes in v3:

- Add a preparatory patch making is_espi() a pure range predicate and move
  configuration policy and debug checks to callers.
- Add the requested assertion before regular descriptor lookup.
- Avoid partial MADT and UART state updates after irq_set_type() failures.
- Apply cosmetic cleanups from review.

Changes in v2:

- Check descriptor ranges in irq_set_spi_type() and implemented GIC lines
  in setup_irq().
- Keep the is_espi() debug check when CONFIG_GICV3_ESPI is disabled.
- Remove a redundant CONFIG_GICV3_ESPI guard from the vGIC code.
- Add a patch checking irq_set_type() errors in the GTDT, MADT, SPCR, and
  FF-A paths.
- Target master instead of the 4.22 release.

Mykola Kvach (4):
  xen/arm: handle irq_set_type() failures
  xen/arm: make is_espi() a pure range predicate
  xen/arm: validate IRQs before descriptor lookup
  xen/arm: vgic: free eSPIs using the bitmap index

 xen/arch/arm/gic-v2.c          | 15 ++++---
 xen/arch/arm/gic-v3.c          | 15 ++++---
 xen/arch/arm/gic.c             |  6 +++
 xen/arch/arm/include/asm/irq.h | 11 ------
 xen/arch/arm/irq.c             | 28 +++++++++++--
 xen/arch/arm/tee/ffa_notif.c   | 11 +++++-
 xen/arch/arm/time.c            | 18 +++++++--
 xen/arch/arm/vgic.c            | 72 +++++++++++++++++++++++-----------
 xen/arch/arm/vgic/vgic.c       |  5 ++-
 xen/drivers/char/ns16550.c     |  8 +++-
 xen/drivers/char/pl011.c       |  4 +-
 11 files changed, 135 insertions(+), 58 deletions(-)

-- 
2.53.0