From a95c68d0aefc6a1958d9fd548c7005d0fd98a2f5 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 4 Jul 2014 15:39:44 +0100 Subject: [PATCH] xen/arm: introduce PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI GICH_LR_HW doesn't work as expected on X-Gene: request maintenance interrupts and perform EOIs in the hypervisor for hardware interrupts as a workaround. Trigger this behaviour with a per platform option. This patch assumes that GICC_DIR can be written on any pcpu for a given SPI, not matter where GICC_IAR has been read before. Signed-off-by: Stefano Stabellini Acked-by: Julien Grall Acked-by: Ian Campbell CC: psawargaonkar@apm.com CC: apatel@apm.com --- xen/arch/arm/gic-v2.c | 9 +++++++-- xen/arch/arm/gic.c | 4 ++++ xen/arch/arm/platforms/xgene-storm.c | 2 +- xen/include/asm-arm/platform.h | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c index 009307a11f..843f5a1ba1 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -396,8 +396,13 @@ static void gicv2_update_lr(int lr, const struct pending_irq *p, ((p->irq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT)); if ( p->desc != NULL ) - lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK ) - << GICH_V2_LR_PHYSICAL_SHIFT); + { + if ( platform_has_quirk(PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI) ) + lr_reg |= GICH_V2_LR_MAINTENANCE_IRQ; + else + lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK ) + << GICH_V2_LR_PHYSICAL_SHIFT); + } writel_gich(lr_reg, GICH_LR + lr * 4); } diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 83b004c4ea..256d9cf760 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -366,7 +366,11 @@ static void gic_update_one_lr(struct vcpu *v, int i) clear_bit(i, &this_cpu(lr_mask)); if ( p->desc != NULL ) + { p->desc->status &= ~IRQ_INPROGRESS; + if ( platform_has_quirk(PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI) ) + gic_hw_ops->deactivate_irq(p->desc); + } clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status); clear_bit(GIC_IRQ_GUEST_ACTIVE, &p->status); p->lr = GIC_INVALID_LR; diff --git a/xen/arch/arm/platforms/xgene-storm.c b/xen/arch/arm/platforms/xgene-storm.c index c9dd63cd0f..837d8e64ea 100644 --- a/xen/arch/arm/platforms/xgene-storm.c +++ b/xen/arch/arm/platforms/xgene-storm.c @@ -37,7 +37,7 @@ static bool reset_vals_valid = false; static uint32_t xgene_storm_quirks(void) { - return PLATFORM_QUIRK_GIC_64K_STRIDE; + return PLATFORM_QUIRK_GIC_64K_STRIDE|PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI; } static int map_one_mmio(struct domain *d, const char *what, diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h index bcd2097039..eefaca6e04 100644 --- a/xen/include/asm-arm/platform.h +++ b/xen/include/asm-arm/platform.h @@ -55,6 +55,11 @@ struct platform_desc { */ #define PLATFORM_QUIRK_GIC_64K_STRIDE (1 << 0) +/* + * Quirk for platforms where GICH_LR_HW does not work as expected. + */ +#define PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI (1 << 1) + void __init platform_init(void); int __init platform_init_time(void); int __init platform_specific_mapping(struct domain *d); -- 2.30.2