xen/arm: gic-v3: Introduce CONFIG_GICV3_NR_LRS

Add a Kconfig option that lets an integrator hard-code the number of
GICv3 List 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 <ayan.kumar.halder@amd.com>
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Bertrand Marquis <bertrand.marquis@arm.com>
This commit is contained in:
Ayan Kumar Halder authored and Michal Orzel committed 2026-10-12 08:50:11 +02:00
1 parent 0d3bb3c98b
commit a0b958f45f
2 files changed
+58 -1

No files matched your search

+9
View File
@@ -145,6 +145,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 List Registers used" if EXPERT
depends on GICV3
range 0 16
default 0
help
Controls the number of List 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
+49 -1
View File
@@ -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:
@@ -1043,9 +1061,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;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.