All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@linaro.org>
To: xen-devel@lists.xenproject.org
Cc: stefano.stabellini@citrix.com,
	Julien Grall <julien.grall@linaro.org>,
	tim@xen.org, ian.campbell@citrix.com
Subject: [PATCH v4 10/18] xen/arm: IRQ: Require desc.lock be held by callers of hw_irq_controller callbacks
Date: Tue, 22 Apr 2014 13:58:42 +0100	[thread overview]
Message-ID: <1398171530-27391-11-git-send-email-julien.grall@linaro.org> (raw)
In-Reply-To: <1398171530-27391-1-git-send-email-julien.grall@linaro.org>

When multiple action are supported, gic_irq_{startup,shutdown} will have
to be called in the same critical section as setup/release.
Otherwise there is a race condition if at the same time CPU A is calling
release_dt_irq and CPU B is calling setup_dt_irq.

This could end up with the IRQ not being enabled.

At the same time, modify gic_irq_{enable,disable} to require desc.lock be held.

With both of theses changes, ARM's locking requirements is the same as x86's.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

---
    Changes in v4:
        - Fix typo in commit message
        - Don't depend on Stefano's interrupt series (will likely be
          pushed before)

    Changes in v3:
        - Update commit message
        - Require desc.lock also for gic_irq_{enable,disable}
        - irqflags is unsigned long not unsigned int

    Changes in v2:
        - Fix typoes in commit message
        - Move this patch earlier in the series => move shutdown() in
        release_irq and gic_route_irq
---
 xen/arch/arm/gic.c  |   21 +++++++++++----------
 xen/arch/arm/irq.c  |    6 ++++--
 xen/arch/arm/vgic.c |   10 ++++++++++
 3 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 77dfecf..29ecb49 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -128,14 +128,14 @@ static void gic_irq_enable(struct irq_desc *desc)
     int irq = desc->irq;
     unsigned long flags;
 
-    spin_lock_irqsave(&desc->lock, flags);
-    spin_lock(&gic.lock);
+    ASSERT(spin_is_locked(&desc->lock));
+
+    spin_lock_irqsave(&gic.lock, flags);
     desc->status &= ~IRQ_DISABLED;
     dsb(sy);
     /* Enable routing */
     GICD[GICD_ISENABLER + irq / 32] = (1u << (irq % 32));
-    spin_unlock(&gic.lock);
-    spin_unlock_irqrestore(&desc->lock, flags);
+    spin_unlock_irqrestore(&gic.lock, flags);
 }
 
 static void gic_irq_disable(struct irq_desc *desc)
@@ -143,18 +143,19 @@ static void gic_irq_disable(struct irq_desc *desc)
     int irq = desc->irq;
     unsigned long flags;
 
-    spin_lock_irqsave(&desc->lock, flags);
-    spin_lock(&gic.lock);
+    ASSERT(spin_is_locked(&desc->lock));
+
+    spin_lock_irqsave(&gic.lock, flags);
     /* Disable routing */
     GICD[GICD_ICENABLER + irq / 32] = (1u << (irq % 32));
     desc->status |= IRQ_DISABLED;
-    spin_unlock(&gic.lock);
-    spin_unlock_irqrestore(&desc->lock, flags);
+    spin_unlock_irqrestore(&gic.lock, flags);
 }
 
 static unsigned int gic_irq_startup(struct irq_desc *desc)
 {
     gic_irq_enable(desc);
+
     return 0;
 }
 
@@ -261,11 +262,11 @@ static int gic_route_irq(unsigned int irq, bool_t level,
     if ( desc->action != NULL )
         return -EBUSY;
 
+    spin_lock_irqsave(&desc->lock, flags);
+
     /* Disable interrupt */
     desc->handler->shutdown(desc);
 
-    spin_lock_irqsave(&desc->lock, flags);
-
     desc->handler = &gic_host_irq_type;
 
     gic_set_irq_properties(irq, level, cpu_mask, priority);
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 26574ca..b6dd9de 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -217,9 +217,10 @@ void release_irq(unsigned int irq)
 
     desc = irq_to_desc(irq);
 
+    spin_lock_irqsave(&desc->lock,flags);
+
     desc->handler->shutdown(desc);
 
-    spin_lock_irqsave(&desc->lock,flags);
     action = desc->action;
     desc->action  = NULL;
     desc->status &= ~IRQ_GUEST;
@@ -254,11 +255,12 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
 
     spin_lock_irqsave(&desc->lock, flags);
     rc = __setup_irq(desc, new);
-    spin_unlock_irqrestore(&desc->lock, flags);
 
     if ( !rc )
         desc->handler->startup(desc);
 
+    spin_unlock_irqrestore(&desc->lock, flags);
+
     return rc;
 }
 
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 4a7f8c0..1b95003 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -374,6 +374,7 @@ static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
     const unsigned long mask = r;
     struct pending_irq *p;
     unsigned int irq;
+    unsigned long flags;
     int i = 0;
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
@@ -382,7 +383,11 @@ static void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
         clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
         gic_remove_from_queues(v, irq);
         if ( p->desc != NULL )
+        {
+            spin_lock_irqsave(&p->desc->lock, flags);
             p->desc->handler->disable(p->desc);
+            spin_unlock_irqrestore(&p->desc->lock, flags);
+        }
         i++;
     }
 }
@@ -392,6 +397,7 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     const unsigned long mask = r;
     struct pending_irq *p;
     unsigned int irq;
+    unsigned long flags;
     int i = 0;
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
@@ -401,7 +407,11 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
         if ( !list_empty(&p->inflight) && !test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status) )
             gic_set_guest_irq(v, irq, GICH_LR_PENDING, p->priority);
         if ( p->desc != NULL )
+        {
+            spin_lock_irqsave(&p->desc->lock, flags);
             p->desc->handler->enable(p->desc);
+            spin_unlock_irqrestore(&p->desc->lock, flags);
+        }
         i++;
     }
 }
-- 
1.7.10.4

  parent reply	other threads:[~2014-04-22 12:59 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-22 12:58 [PATCH v4 00/18] xen/arm: Interrupt management reworking Julien Grall
2014-04-22 12:58 ` [PATCH v4 01/18] xen/arm: timer: replace timer_dt_irq by timer_get_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 02/18] xen/arm: IRQ: Use default irq callback from common code for no_irq_type Julien Grall
2014-04-22 12:58 ` [PATCH v4 03/18] xen/arm: IRQ: Rename irq_cfg into arch_irq_desc Julien Grall
2014-04-22 12:58 ` [PATCH v4 04/18] xen/arm: IRQ: move gic {, un}lock in gic_set_irq_properties Julien Grall
2014-04-22 12:58 ` [PATCH v4 05/18] xen/arm: IRQ: drop irq parameter in __setup_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 06/18] xen/arm: IRQ: remove __init from setup_dt_irq, request_dt_irq and release_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 07/18] xen/arm: IRQ: Rework gic_route_irq_to_guest function Julien Grall
2014-04-22 12:58 ` [PATCH v4 08/18] xen/arm: IRQ: Move IRQ management from gic.c to irq.c Julien Grall
2014-04-22 12:58 ` [PATCH v4 09/18] xen/arm: IRQ Introduce irq_get_domain Julien Grall
2014-04-22 12:58 ` Julien Grall [this message]
2014-04-22 12:58 ` [PATCH v4 11/18] xen/arm: IRQ: Defer routing IRQ to Xen until setup_irq() call Julien Grall
2014-04-22 12:58 ` [PATCH v4 12/18] xen/arm: IRQ: Do not allow IRQ to be shared between domains and XEN Julien Grall
2014-04-22 12:58 ` [PATCH v4 13/18] xen/serial: remove serial_dt_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 14/18] xen/arm: IRQ: Store IRQ type in arch_irq_desc Julien Grall
2014-04-23 12:26   ` Julien Grall
2014-04-23 14:04   ` Ian Campbell
2014-05-02  8:49     ` Julien Grall
2014-05-02  8:57       ` Ian Campbell
2014-05-02  9:00         ` Julien Grall
2014-04-22 12:58 ` [PATCH v4 15/18] xen/arm: IRQ: Replace {request, setup}_dt_irq by {request, setup}_irq Julien Grall
2014-04-22 13:26   ` Julien Grall
2014-04-22 12:58 ` [PATCH v4 16/18] xen: IRQ: Add dev_id parameter to release_irq Julien Grall
2014-04-22 12:58 ` [PATCH v4 17/18] xen/arm: IRQ: extend {request, setup}_irq to take an irqflags in parameter Julien Grall
2014-04-22 12:58 ` [PATCH v4 18/18] xen/arm: IRQ: Handle multiple action per IRQ Julien Grall
2014-04-22 13:36   ` Jan Beulich
2014-04-23 14:07   ` Ian Campbell
2014-04-23 14:56     ` Julien Grall
2014-04-23 15:16       ` Ian Campbell
2014-04-23 15:28         ` Julien Grall
2014-04-23 15:28         ` Julien Grall
2014-05-02  8:52 ` [PATCH v4 00/18] xen/arm: Interrupt management reworking Julien Grall
2014-05-02 12:51 ` Ian Campbell

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=1398171530-27391-11-git-send-email-julien.grall@linaro.org \
    --to=julien.grall@linaro.org \
    --cc=ian.campbell@citrix.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=tim@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.