[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/2] xen/arm: take the rank lock before accessing ipriority



Currently we read ipriority from vgic_vcpu_inject_irq without taking the
rank lock. Fix that by taking the rank lock and reading ipriority at the
beginning of the function.

As vgic_vcpu_inject_irq is called from the irq.c upon receiving an
interrupt, we need to change the implementation of vgic_lock/unlock_rank
to spin_lock_irqsave to make it safe in irq context.

Also add a warning to point out that if the irq is already inflight with
a different priority, we are not changing the irq priority for the
second injection.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 xen/arch/arm/vgic.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 1806b72..1f55fcf 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -158,8 +158,8 @@ int vcpu_vgic_init(struct vcpu *v)
 #define vgic_lock(v)   spin_lock_irq(&(v)->domain->arch.vgic.lock)
 #define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock)
 
-#define vgic_lock_rank(v, r) spin_lock(&(r)->lock)
-#define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock)
+#define vgic_lock_rank(v, r) spin_lock_irqsave(&(r)->lock, flags)
+#define vgic_unlock_rank(v, r) spin_unlock_irqrestore(&(r)->lock, flags)
 
 static uint32_t byte_read(uint32_t val, int sign, int offset)
 {
@@ -191,6 +191,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t 
*info)
     struct vgic_irq_rank *rank;
     int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
     int gicd_reg = REG(offset);
+    unsigned long flags;
 
     switch ( gicd_reg )
     {
@@ -403,6 +404,7 @@ struct vcpu *vgic_get_target_vcpu(struct vcpu *v, unsigned 
int irq)
 {
     struct vcpu *v_target;
     struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+    unsigned long flags;
 
     vgic_lock_rank(v, rank);
     v_target = _vgic_get_target_vcpu(v, irq);
@@ -595,6 +597,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, 
mmio_info_t *info)
     uint32_t tr;
     unsigned long trl;
     int i;
+    unsigned long flags;
 
     switch ( gicd_reg )
     {
@@ -856,6 +859,10 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
     unsigned long flags;
     bool_t running;
 
+    vgic_lock_rank(v, rank);
+    priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, idx)], 0, byte);
+    vgic_unlock_rank(v, rank);
+
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
     /* vcpu offline */
@@ -873,12 +880,12 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int 
irq)
 
     if ( !list_empty(&n->inflight) )
     {
+        if ( priority != n->priority )
+            gdprintk(XENLOG_WARNING, "IRQ is already inflight with a different 
priority\n");
         gic_raise_inflight_irq(v, irq);
         goto out;
     }
 
-    priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, idx)], 0, byte);
-
     n->irq = irq;
     n->priority = priority;
 
-- 
1.7.10.4


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.