xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Shanker Donthineni <shankerd@codeaurora.org>
To: xen-devel <xen-devel@lists.xensource.com>
Cc: Philip Elcan <pelcan@codeaurora.org>,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Shanker Donthineni <shankerd@codeaurora.org>,
	Vikram Sethi <vikrams@codeaurora.org>
Subject: [PATCH] arm/acpi: Fix the deadlock in function vgic_lock_rank()
Date: Thu, 26 May 2016 19:39:42 -0500	[thread overview]
Message-ID: <1464309582-22637-1-git-send-email-shankerd@codeaurora.org> (raw)

Commit 9d77b3c01d1261c (Configure SPI interrupt type and route to
Dom0 dynamically) causing dead loop inside the spinlock function.
Note that spinlocks in XEN are not recursive. Re-acquiring a spinlock
that has already held by calling CPU leads to deadlock. This happens
whenever dom0 does writes to GICD regs ISENABLER/ICENABLER.

The following call trace explains the problem.

DOM0 writes GICD_ISENABLER/GICD_ICENABLER
  vgic_v3_distr_common_mmio_write()
    vgic_lock_rank()  -->  acquiring first time
      vgic_enable_irqs()
        route_irq_to_guest()
          gic_route_irq_to_guest()
            vgic_get_target_vcpu()
              vgic_lock_rank()  -->  attemping acquired lock

The simple fix release spinlock before calling vgic_enable_irqs()
and vgic_disable_irqs().

Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
---
 xen/arch/arm/vgic-v2.c | 10 +++++++---
 xen/arch/arm/vgic-v3.c | 10 +++++++---
 xen/arch/arm/vgic.c    |  4 ++--
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 9adb4a9..44cd834 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -415,7 +415,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
     struct hsr_dabt dabt = info->dabt;
     struct vgic_irq_rank *rank;
     int gicd_reg = (int)(info->gpa - v->domain->arch.vgic.dbase);
-    uint32_t tr;
+    uint32_t tr, index;
     unsigned long flags;
 
     perfc_incr(vgicd_writes);
@@ -457,8 +457,10 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
         vgic_reg32_setbits(&rank->ienable, r, info);
-        vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index);
+        index = rank->index;
+        tr = rank->ienable & (~tr);
         vgic_unlock_rank(v, rank, flags);
+        vgic_enable_irqs(v, tr, index);
         return 1;
 
     case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN):
@@ -468,8 +470,10 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info,
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
         vgic_reg32_clearbits(&rank->ienable, r, info);
-        vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index);
+        index = rank->index;
+        tr = (~rank->ienable) & tr;
         vgic_unlock_rank(v, rank, flags);
+        vgic_disable_irqs(v, tr, index);
         return 1;
 
     case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN):
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index b37a7c0..e04e180 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -568,7 +568,7 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
 {
     struct hsr_dabt dabt = info->dabt;
     struct vgic_irq_rank *rank;
-    uint32_t tr;
+    uint32_t tr, index;
     unsigned long flags;
 
     switch ( reg )
@@ -584,8 +584,10 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
         vgic_reg32_setbits(&rank->ienable, r, info);
-        vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index);
+        index = rank->index;
+        tr = rank->ienable & (~tr);
         vgic_unlock_rank(v, rank, flags);
+        vgic_enable_irqs(v, tr, index);
         return 1;
 
     case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN):
@@ -595,8 +597,10 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v,
         vgic_lock_rank(v, rank, flags);
         tr = rank->ienable;
         vgic_reg32_clearbits(&rank->ienable, r, info);
-        vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index);
+        index = rank->index;
+        tr = (~rank->ienable) & tr;
         vgic_unlock_rank(v, rank, flags);
+        vgic_disable_irqs(v, tr, index);
         return 1;
 
     case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN):
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index aa420bb..82758d2 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -322,7 +322,7 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
-        v_target = __vgic_get_target_vcpu(v, irq);
+        v_target = vgic_get_target_vcpu(v, irq);
         p = irq_to_pending(v_target, irq);
         clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
         gic_remove_from_queues(v_target, irq);
@@ -377,7 +377,7 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
                 gprintk(XENLOG_ERR, "Unable to route IRQ %u to domain %u\n",
                         irq, d->domain_id);
         }
-        v_target = __vgic_get_target_vcpu(v, irq);
+        v_target = vgic_get_target_vcpu(v, irq);
         p = irq_to_pending(v_target, irq);
         set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
         spin_lock_irqsave(&v_target->arch.vgic.lock, flags);
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

             reply	other threads:[~2016-05-27  0:39 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-27  0:39 Shanker Donthineni [this message]
2016-05-27 13:56 ` [PATCH] arm/acpi: Fix the deadlock in function vgic_lock_rank() Julien Grall
2016-05-30 13:16   ` Stefano Stabellini
2016-05-30 19:45     ` Julien Grall
2016-05-31  0:55       ` Shannon Zhao
2016-05-31  9:40       ` Stefano Stabellini
2016-05-31 10:11         ` Julien Grall
2016-06-01  9:54           ` Stefano Stabellini
2016-06-01 10:49             ` Julien Grall
2016-06-01 13:55               ` Shannon Zhao
2016-05-31 11:37         ` Wei Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1464309582-22637-1-git-send-email-shankerd@codeaurora.org \
    --to=shankerd@codeaurora.org \
    --cc=julien.grall@arm.com \
    --cc=pelcan@codeaurora.org \
    --cc=sstabellini@kernel.org \
    --cc=vikrams@codeaurora.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).