[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |