[Xen-devel,PATCH-4.5,v2,10/10] xen/arm: print more info in gic_dump_info, keep gic_lr sync'ed

Message ID 1392393098-7351-10-git-send-email-stefano.stabellini@eu.citrix.com
State New
Headers show

Commit Message

Stefano Stabellini Feb. 14, 2014, 3:51 p.m.
For each inflight and pending irqs print GIC_IRQ_GUEST_ENABLED,
GIC_IRQ_GUEST_PENDING and GIC_IRQ_GUEST_VISIBLE.

In order to get consistent information from gic_dump_info, we need to
get the vgic.lock before walking the inflight and lr_pending lists.

We also need to keep v->arch.gic_lr in sync with GICH_LR registers.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 xen/arch/arm/gic.c |   19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

Comments

Julien Grall Feb. 16, 2014, 8:31 p.m. | #1
Hi Stefano,

On 14/02/14 15:51, Stefano Stabellini wrote:
> @@ -986,6 +991,8 @@ void gic_dump_info(struct vcpu *v)
>       struct pending_irq *p;
>
>       printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask);
> +
> +    spin_lock(&v->arch.vgic.lock);

interrupts need to be disabled here. If not, it's possible to receive an 
interrupt while the lock is taken. Xen might deadlock if the interrupt 
is inject to this vcpu "v" (see vgic_vcpu_inject_irq).

Regards,

Patch

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index b00f77c..af0994a 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -642,6 +642,7 @@  static inline void gic_set_lr(struct vcpu *v, int lr, unsigned int irq,
             ((p->desc->irq & GICH_LR_PHYSICAL_MASK) << GICH_LR_PHYSICAL_SHIFT);
 
     GICH[GICH_LR + lr] = lr_reg;
+    v->arch.gic_lr[lr] = lr_reg;
 
     set_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
     clear_bit(GIC_IRQ_GUEST_PENDING, &p->status);
@@ -708,11 +709,15 @@  static void _gic_clear_lr(struct vcpu *v, int i, int vgic_locked)
     {
         if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
              test_and_clear_bit(GIC_IRQ_GUEST_PENDING, &p->status) )
+        {
             GICH[GICH_LR + i] = lr | GICH_LR_PENDING;
+            v->arch.gic_lr[i] = lr | GICH_LR_PENDING;
+        }
     } else if ( lr & GICH_LR_PENDING ) {
         clear_bit(GIC_IRQ_GUEST_PENDING, &p->status);
     } else {
         GICH[GICH_LR + i] = 0;
+        v->arch.gic_lr[i] = 0;
         clear_bit(i, &this_cpu(lr_mask));
 
         if ( !vgic_locked ) spin_lock(&v->arch.vgic.lock);
@@ -986,6 +991,8 @@  void gic_dump_info(struct vcpu *v)
     struct pending_irq *p;
 
     printk("GICH_LRs (vcpu %d) mask=%"PRIx64"\n", v->vcpu_id, v->arch.lr_mask);
+
+    spin_lock(&v->arch.vgic.lock);
     if ( v == current )
     {
         for ( i = 0; i < nr_lrs; i++ )
@@ -997,14 +1004,20 @@  void gic_dump_info(struct vcpu *v)
 
     list_for_each_entry ( p, &v->arch.vgic.inflight_irqs, inflight )
     {
-        printk("Inflight irq=%d lr=%u\n", p->irq, p->lr);
+        printk("Inflight irq=%d lr=%u enable=%d pending=%d visible=%d\n",
+                p->irq, p->lr, test_bit(GIC_IRQ_GUEST_ENABLED, &p->status),
+                test_bit(GIC_IRQ_GUEST_PENDING, &p->status),
+                test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status));
     }
 
     list_for_each_entry( p, &v->arch.vgic.lr_pending, lr_queue )
     {
-        printk("Pending irq=%d lr=%u\n", p->irq, p->lr);
+        printk("Pending irq=%d lr=%u enable=%d pending=%d visible=%d\n",
+                p->irq, p->lr, test_bit(GIC_IRQ_GUEST_ENABLED, &p->status),
+                test_bit(GIC_IRQ_GUEST_PENDING, &p->status),
+                test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status));
     }
-
+    spin_unlock(&v->arch.vgic.lock);
 }
 
 void __cpuinit init_maintenance_interrupt(void)