The lr_mask bitmap tracks which List Registers (LRs) are in use for virtual interrupt injection. Previously, lr_mask always used uint64_t (8 bytes) to support the maximum number of LRs across both GIC versions.
However, GICv2 and GICv3 have different hardware limits: - GICv3: ICH_VTR_EL2[3:0] encodes LR count -> max 16 LRs (4 bits) - GICv2: GICH_VTR[5:0] encodes LR count -> max 64 LRs (6 bits) This patch introduces conditional compilation to optimize lr_mask size: - CONFIG_GICV3=y: Use uint16_t (2 bytes) - sufficient for 16 LRs - CONFIG_GICV3=n: Use uint64_t (8 bytes) - required for 64 LRs With this, parameter 'lr' in gicv3_ich_read_lr(), gicv3_ich_write_lr() cannot have a value > 15. Thus, it should not possible to hit the BUG() in the default case. Signed-off-by: Ayan Kumar Halder <[email protected]> --- xen/arch/arm/gic-vgic.c | 11 ++++++++++- xen/arch/arm/gic.c | 10 +++++++++- xen/arch/arm/include/asm/domain.h | 4 ++++ xen/arch/arm/include/asm/gic.h | 8 ++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c index ea48c5375a..80d3beb225 100644 --- a/xen/arch/arm/gic-vgic.c +++ b/xen/arch/arm/gic-vgic.c @@ -16,8 +16,13 @@ #include <asm/gic.h> #include <asm/vgic.h> +#ifdef CONFIG_GICV3 #define lr_all_full() \ - (this_cpu(lr_mask) == (-1ULL >> (64 - gic_get_nr_lrs()))) + (this_cpu(lr_mask) == ((uint16_t)-1 >> (16 - gic_get_nr_lrs()))) +#else +#define lr_all_full() \ + (this_cpu(lr_mask) == ((uint64_t)-1 >> (64 - gic_get_nr_lrs()))) +#endif #undef GIC_DEBUG @@ -102,7 +107,11 @@ static unsigned int gic_find_unused_lr(struct vcpu *v, struct pending_irq *p, unsigned int lr) { +#ifdef CONFIG_GICV3 + uint16_t *lr_mask = &this_cpu(lr_mask); +#else uint64_t *lr_mask = &this_cpu(lr_mask); +#endif ASSERT(spin_is_locked(&v->arch.vgic.lock)); diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index ee75258fc3..e1121a5bb3 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -29,7 +29,11 @@ #include <asm/vgic.h> #include <asm/acpi.h> +#ifdef CONFIG_GICV3 +DEFINE_PER_CPU(uint16_t, lr_mask); +#else DEFINE_PER_CPU(uint64_t, lr_mask); +#endif #undef GIC_DEBUG @@ -48,7 +52,7 @@ void register_gic_ops(const struct gic_hw_operations *ops) static void clear_cpu_lr_mask(void) { - this_cpu(lr_mask) = 0ULL; + this_cpu(lr_mask) = 0; } enum gic_version gic_hw_version(void) @@ -382,7 +386,11 @@ static void maintenance_interrupt(int irq, void *dev_id) void gic_dump_info(struct vcpu *v) { +#ifdef CONFIG_GICV3 + printk("GICH_LRs (vcpu %d) mask=%"PRIx16"\n", v->vcpu_id, v->arch.lr_mask); +#else printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask); +#endif gic_hw_ops->dump_state(v); } diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h index 758ad807e4..8654ef89ef 100644 --- a/xen/arch/arm/include/asm/domain.h +++ b/xen/arch/arm/include/asm/domain.h @@ -228,7 +228,11 @@ struct arch_vcpu /* Holds gic context data */ union gic_state_data gic; +#ifdef CONFIG_GICV3 + uint16_t lr_mask; +#else uint64_t lr_mask; +#endif struct vgic_cpu vgic; diff --git a/xen/arch/arm/include/asm/gic.h b/xen/arch/arm/include/asm/gic.h index 8e713aa477..e1559ec98c 100644 --- a/xen/arch/arm/include/asm/gic.h +++ b/xen/arch/arm/include/asm/gic.h @@ -237,7 +237,15 @@ enum gic_version { GIC_V3, }; +/* + * GICv3 supports up to 16 LRs (4 bits in ICH_VTR_EL2), can use uint16_t + * GICv2 supports up to 64 LRs (6 bits in GICH_VTR), requires uint64_t + */ +#ifdef CONFIG_GICV3 +DECLARE_PER_CPU(uint16_t, lr_mask); +#else DECLARE_PER_CPU(uint64_t, lr_mask); +#endif extern enum gic_version gic_hw_version(void); -- 2.25.1
