[Xen-devel,PATCH-4.5,v3,08/12] xen/arm: call gic_clear_lrs on entry to the hypervisor

Message ID 1393439997-26936-8-git-send-email-stefano.stabellini@eu.citrix.com
State New
Headers show

Commit Message

Stefano Stabellini Feb. 26, 2014, 6:39 p.m.
This change is needed by other patches later on. It is going to make
sure that the calculation in Xen of the highest priority interrupt
currently inflight is correct and accurate and not based on stale data.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 xen/arch/arm/gic.c        |   12 +++++-------
 xen/arch/arm/traps.c      |   10 ++++++++++
 xen/include/asm-arm/gic.h |    1 +
 3 files changed, 16 insertions(+), 7 deletions(-)

Patch

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index d1e7ed3..0e429c8 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -67,8 +67,6 @@  static DEFINE_PER_CPU(u8, gic_cpu_id);
 /* Maximum cpu interface per GIC */
 #define NR_GIC_CPU_IF 8
 
-static void gic_clear_lrs(struct vcpu *v);
-
 static unsigned int gic_cpu_mask(const cpumask_t *cpumask)
 {
     unsigned int cpu;
@@ -130,7 +128,6 @@  void gic_restore_state(struct vcpu *v)
     GICH[GICH_HCR] = GICH_HCR_EN;
     isb();
 
-    gic_clear_lrs(v);
     gic_restore_pending_irqs(v);
 }
 
@@ -700,14 +697,15 @@  out:
     return;
 }
 
-static void gic_clear_lrs(struct vcpu *v)
+void gic_clear_lrs(struct vcpu *v)
 {
     struct pending_irq *p;
     int i = 0, irq;
     uint32_t lr;
     bool_t inflight;
+    unsigned long flags;
 
-    ASSERT(!local_irq_is_enabled());
+    spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
     while ((i = find_next_bit((const long unsigned int *) &this_cpu(lr_mask),
                               nr_lrs, i)) < nr_lrs) {
@@ -743,6 +741,8 @@  static void gic_clear_lrs(struct vcpu *v)
 
         i++;
     }
+
+    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
 }
 
 static void gic_restore_pending_irqs(struct vcpu *v)
@@ -785,8 +785,6 @@  int gic_events_need_delivery(void)
 
 void gic_inject(void)
 {
-    gic_clear_lrs(current);
-
     if ( vcpu_info(current, evtchn_upcall_pending) )
         vgic_vcpu_inject_irq(current, current->domain->arch.evtchn_irq);
 
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index ea77cb8..7663114 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -70,6 +70,7 @@  static int debug_stack_lines = 40;
 
 integer_param("debug_stack_lines", debug_stack_lines);
 
+static void enter_hypervisor_head(void);
 
 void __cpuinit init_traps(void)
 {
@@ -1701,6 +1702,8 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
 {
     union hsr hsr = { .bits = READ_SYSREG32(ESR_EL2) };
 
+    enter_hypervisor_head();
+
     switch (hsr.ec) {
     case HSR_EC_WFI_WFE:
         if ( !check_conditional_instr(regs, hsr) )
@@ -1778,11 +1781,13 @@  asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
 
 asmlinkage void do_trap_irq(struct cpu_user_regs *regs)
 {
+    enter_hypervisor_head();
     gic_interrupt(regs, 0);
 }
 
 asmlinkage void do_trap_fiq(struct cpu_user_regs *regs)
 {
+    enter_hypervisor_head();
     gic_interrupt(regs, 1);
 }
 
@@ -1800,6 +1805,11 @@  asmlinkage void leave_hypervisor_tail(void)
     }
 }
 
+static void enter_hypervisor_head(void)
+{
+    gic_clear_lrs(current);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 4834cd6..5a9dc77 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -220,6 +220,7 @@  extern unsigned int gic_number_lines(void);
 /* IRQ translation function for the device tree */
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq, unsigned int *out_type);
+void gic_clear_lrs(struct vcpu *v);
 
 #endif /* __ASSEMBLY__ */
 #endif