Re: [PATCH v3] xen/arm: gic-v3: Introduce CONFIG_GICV3_NR_LRS
Bertrand Marquis <[email protected]> Wed, 29 Jul 2026 07:33:12 +0000
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, > On 6 Jul 2026, at 15:35, Ayan Kumar Halder <[email protected]> wrote: > > Add a Kconfig option that lets an integrator hard-code the number of > GICv3 Link Registers Xen uses. The default (0) keeps reading the count > from ICH_VTR_EL2.ListRegs at boot. A non-zero value is validated > against the hardware count in gicv3_hyp_init() and replaces > gicv3_info.nr_lrs. > > gicv3_hyp_init() now panics if CONFIG_GICV3_NR_LRS exceeds the > hardware count, and zeroes all hardware LRs (once per CPU) as defensive > hardening, so any interrupt left in an LR that Xen will not manage > cannot be picked up by the GIC. > > gicv3_ich_read_lr()/gicv3_ich_write_lr() now reject out-of-range > indices with an error message, ASSERT_UNREACHABLE() and WARN() instead > of silently returning RAZ/WI; reaching this path indicates a bug. > > Signed-off-by: Ayan Kumar Halder <[email protected]> > Signed-off-by: Michal Orzel <[email protected]> With the typo Link/List registers fixed: Reviewed-by: Bertrand Marquis <[email protected]> Cheers Bertrand > --- > Changes in > v3: > - Validate CONFIG_GICV3_NR_LRS against the hardware count in > gicv3_hyp_init() and panic if it exceeds it (Julien, Luca). > - Allow an integrator to select fewer LRs than the hardware supports; > gicv3_info.nr_lrs is replaced with the clamped value (Julien). > - Zero all hardware LRs in gicv3_hyp_init() as defensive hardening. > - Replace the silent RAZ/WI out-of-range path in gicv3_ich_read_lr()/ > gicv3_ich_write_lr() with gprintk() + ASSERT_UNREACHABLE() + WARN() > (Julien). > - Renamed the Kconfig from LRS to NR_LRS (Julien). > - The link-time dead-code-elimination guard is split out into a > separate follow-up patch. > > v2: > - s/lrs/LRS. > - Implement RAZ/WI instead of panic. > > xen/arch/arm/Kconfig | 9 ++++++++ > xen/arch/arm/gic-v3.c | 50 ++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 58 insertions(+), 1 deletion(-) > > diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig > index 5fa89fcb24..798bc8e9b2 100644 > --- a/xen/arch/arm/Kconfig > +++ b/xen/arch/arm/Kconfig > @@ -143,6 +143,15 @@ config GICV3_ESPI > range, from 4096 to 5119. This feature is introduced in GICv3.1 > architecture. > > +config GICV3_NR_LRS > + int "Number of GICv3 Link Registers used" if EXPERT > + depends on GICV3 > + range 0 16 > + default 0 > + help > + Controls the number of Link registers to be used. > + Keep it set to 0 to use a value obtained from a hardware register. > + > config HAS_ITS > bool "GICv3 ITS MSI controller support (UNSUPPORTED)" if UNSUPPORTED > depends on GICV3 && !NEW_VGIC && !ARM_32 > diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c > index acdac22953..46ab0b6329 100644 > --- a/xen/arch/arm/gic-v3.c > +++ b/xen/arch/arm/gic-v3.c > @@ -178,6 +178,15 @@ static inline void gicv3_restore_lrs(const struct vcpu *v) > > static uint64_t gicv3_ich_read_lr(int lr) > { > + if ( lr < 0 || lr >= gicv3_info.nr_lrs ) > + { > + gprintk(XENLOG_ERR, "GICv3: LR read index %d out of range (nr_lrs %u)\n", > + lr, gicv3_info.nr_lrs); > + ASSERT_UNREACHABLE(); > + WARN(); > + return 0; > + } > + > switch ( lr ) > { > case 0: return READ_SYSREG_LR(0); > @@ -203,6 +212,15 @@ static uint64_t gicv3_ich_read_lr(int lr) > > static void gicv3_ich_write_lr(int lr, uint64_t val) > { > + if ( lr < 0 || lr >= gicv3_info.nr_lrs ) > + { > + gprintk(XENLOG_ERR, "GICv3: LR write index %d out of range (nr_lrs %u)\n", > + lr, gicv3_info.nr_lrs); > + ASSERT_UNREACHABLE(); > + WARN(); > + return; > + } > + > switch ( lr ) > { > case 0: > @@ -1041,9 +1059,39 @@ static void gicv3_cpu_disable(void) > static void gicv3_hyp_init(void) > { > register_t vtr; > + uint8_t hw_nr_lrs; > > vtr = READ_SYSREG(ICH_VTR_EL2); > - gicv3_info.nr_lrs = (vtr & ICH_VTR_NRLRGS) + 1; > + hw_nr_lrs = (vtr & ICH_VTR_NRLRGS) + 1; > + > + if ( CONFIG_GICV3_NR_LRS && CONFIG_GICV3_NR_LRS > hw_nr_lrs ) > + panic("GICv3: CONFIG_GICV3_NR_LRS (%u) exceeds hardware nr_lrs (%u)\n", > + CONFIG_GICV3_NR_LRS, hw_nr_lrs); > + > + gicv3_info.nr_lrs = CONFIG_GICV3_NR_LRS ?: hw_nr_lrs; > + > + /* Zero all hardware LRs. */ > + switch ( hw_nr_lrs ) > + { > + case 16: WRITE_SYSREG_LR(0, 15); fallthrough; > + case 15: WRITE_SYSREG_LR(0, 14); fallthrough; > + case 14: WRITE_SYSREG_LR(0, 13); fallthrough; > + case 13: WRITE_SYSREG_LR(0, 12); fallthrough; > + case 12: WRITE_SYSREG_LR(0, 11); fallthrough; > + case 11: WRITE_SYSREG_LR(0, 10); fallthrough; > + case 10: WRITE_SYSREG_LR(0, 9); fallthrough; > + case 9: WRITE_SYSREG_LR(0, 8); fallthrough; > + case 8: WRITE_SYSREG_LR(0, 7); fallthrough; > + case 7: WRITE_SYSREG_LR(0, 6); fallthrough; > + case 6: WRITE_SYSREG_LR(0, 5); fallthrough; > + case 5: WRITE_SYSREG_LR(0, 4); fallthrough; > + case 4: WRITE_SYSREG_LR(0, 3); fallthrough; > + case 3: WRITE_SYSREG_LR(0, 2); fallthrough; > + case 2: WRITE_SYSREG_LR(0, 1); fallthrough; > + case 1: WRITE_SYSREG_LR(0, 0); break; > + default: BUG(); > + } > + > gicv3.nr_priorities = ((vtr >> ICH_VTR_PRIBITS_SHIFT) & > ICH_VTR_PRIBITS_MASK) + 1; > > -- > 2.25.1 >