mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
0d3bb3c98b
commit
a0b958f45f
2 files changed
+58
-1
No files matched your search
@@ -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
@@ -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;
|
||||
|
||||
|
||||