@@ -689,7 +689,7 @@ void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
gic_add_to_lr_pending(v, irq, priority);
}
-static void _gic_clear_lr(struct vcpu *v, int i)
+static void _gic_clear_lr(struct vcpu *v, int i, int vgic_locked)
{
int irq;
uint32_t lr;
@@ -711,6 +711,7 @@ static void _gic_clear_lr(struct vcpu *v, int i)
GICH[GICH_LR + i] = 0;
clear_bit(i, &this_cpu(lr_mask));
+ if ( !vgic_locked ) spin_lock(&v->arch.vgic.lock);
if ( p->desc != NULL )
p->desc->status &= ~IRQ_INPROGRESS;
clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
@@ -721,6 +722,7 @@ static void _gic_clear_lr(struct vcpu *v, int i)
gic_add_to_lr_pending(v, irq, p->priority);
} else
list_del_init(&p->inflight);
+ if ( !vgic_locked ) spin_unlock(&v->arch.vgic.lock);
}
}
@@ -731,16 +733,14 @@ static void gic_clear_lrs(struct vcpu *v)
while ((i = find_next_bit((const long unsigned int *) &this_cpu(lr_mask),
nr_lrs, i)) < nr_lrs) {
- spin_lock(&v->arch.vgic.lock);
- _gic_clear_lr(v, i);
- spin_unlock(&v->arch.vgic.lock);
+ _gic_clear_lr(v, i, 0);
i++;
}
}
void gic_set_clear_lr(struct vcpu *v, struct pending_irq *p)
{
- _gic_clear_lr(v, p->lr);
+ _gic_clear_lr(v, p->lr, 1);
}
static void gic_restore_pending_irqs(struct vcpu *v)
We don't actually need to call _gic_clear_lr with the vgic.lock taken, only in case the GICH_LR has to be free'ed we need the lock. Add a boolean vgic_locked parameter to _gic_clear_lr, so that we can avoid taking the lock if it has been already taken, or take the lock only in the necessary case if it hasn't. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/gic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)