]> xenbits.xensource.com Git - xen.git/commitdiff
xen/arm: introduce PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Fri, 4 Jul 2014 14:39:44 +0000 (15:39 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Thu, 10 Jul 2014 10:30:41 +0000 (11:30 +0100)
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 <stefano.stabellini@eu.citrix.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
CC: psawargaonkar@apm.com
CC: apatel@apm.com
xen/arch/arm/gic-v2.c
xen/arch/arm/gic.c
xen/arch/arm/platforms/xgene-storm.c
xen/include/asm-arm/platform.h

index 009307a11f26f4bc6bfba8bd8e687cae54f59ed9..843f5a1ba17a5181ef34e539e6b66c0b1a71c4ff 100644 (file)
@@ -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);
 }
index 83b004c4eacfb193f8868c0c07538d915fda7c69..256d9cf760b7ec05210d2a5647333bc82e150e97 100644 (file)
@@ -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;
index c9dd63cd0f3108fe9a9c68ef50f16a44935d549c..837d8e64ea027294a721ebaad05ff8be6e5732f3 100644 (file)
@@ -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,
index bcd209703922da45a9f612ce5fc1d9a7ab8466ee..eefaca6e04f5e0adbeb08ba0980aef96d9617a10 100644 (file)
@@ -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);