|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 01/10] ARM: vGIC: remove rank lock from IRQ routing functions
Hi,
On 04/05/17 16:53, Julien Grall wrote:
> Hi Andre,
>
> On 04/05/17 16:31, Andre Przywara wrote:
>> gic_route_irq_to_guest() and gic_remove_irq_from_guest() take the rank
>> lock, however never actually access the rank structure.
>> Avoid taking the lock in those two functions and remove some more
>> unneeded code on the way.
>
> The rank is here to protect p->desc when checking that the virtual
> interrupt was not yet routed to another physical interrupt.
Really? To me that sounds quite surprising.
My understanding is that the VGIC VCPU lock protected the pending_irq
(and thus the desc pointer?) so far, and the desc itself has its own lock.
According to the comment in the struct irq_rank declaration the lock
protects the members of this struct only.
Looking briefly at users of pending_irq->desc (for instance
gicv[23]_update_lr() or gic_update_one_lr()) I can't see any hint that
they care about the lock.
So should that be fixed or at least documented?
> Without this locking, you can have two concurrent call of
> gic_route_irq_to_guest that will update the same virtual interrupt but
> with different physical interrupts.
>
> You would have to replace the rank lock by the per-pending_irq lock to
> keep the code safe.
That indeed sounds reasonable.
Cheers,
Andre.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
>> ---
>> xen/arch/arm/gic.c | 28 ++++------------------------
>> 1 file changed, 4 insertions(+), 24 deletions(-)
>>
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index da19130..c734f66 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -136,25 +136,19 @@ void gic_route_irq_to_xen(struct irq_desc *desc,
>> unsigned int priority)
>> int gic_route_irq_to_guest(struct domain *d, unsigned int virq,
>> struct irq_desc *desc, unsigned int priority)
>> {
>> - unsigned long flags;
>> /* Use vcpu0 to retrieve the pending_irq struct. Given that we only
>> * route SPIs to guests, it doesn't make any difference. */
>> - struct vcpu *v_target = vgic_get_target_vcpu(d->vcpu[0], virq);
>> - struct vgic_irq_rank *rank = vgic_rank_irq(v_target, virq);
>> - struct pending_irq *p = irq_to_pending(v_target, virq);
>> - int res = -EBUSY;
>> + struct pending_irq *p = irq_to_pending(d->vcpu[0], virq);
>>
>> ASSERT(spin_is_locked(&desc->lock));
>> /* Caller has already checked that the IRQ is an SPI */
>> ASSERT(virq >= 32);
>> ASSERT(virq < vgic_num_irqs(d));
>>
>> - vgic_lock_rank(v_target, rank, flags);
>> -
>> if ( p->desc ||
>> /* The VIRQ should not be already enabled by the guest */
>> test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) )
>> - goto out;
>> + return -EBUSY;
>>
>> desc->handler = gic_hw_ops->gic_guest_irq_type;
>> set_bit(_IRQ_GUEST, &desc->status);
>> @@ -164,29 +158,20 @@ int gic_route_irq_to_guest(struct domain *d,
>> unsigned int virq,
>> gic_set_irq_priority(desc, priority);
>>
>> p->desc = desc;
>> - res = 0;
>>
>> -out:
>> - vgic_unlock_rank(v_target, rank, flags);
>> -
>> - return res;
>> + return 0;
>> }
>>
>> /* This function only works with SPIs for now */
>> int gic_remove_irq_from_guest(struct domain *d, unsigned int virq,
>> struct irq_desc *desc)
>> {
>> - struct vcpu *v_target = vgic_get_target_vcpu(d->vcpu[0], virq);
>> - struct vgic_irq_rank *rank = vgic_rank_irq(v_target, virq);
>> - struct pending_irq *p = irq_to_pending(v_target, virq);
>> - unsigned long flags;
>> + struct pending_irq *p = irq_to_pending(d->vcpu[0], virq);
>>
>> ASSERT(spin_is_locked(&desc->lock));
>> ASSERT(test_bit(_IRQ_GUEST, &desc->status));
>> ASSERT(p->desc == desc);
>>
>> - vgic_lock_rank(v_target, rank, flags);
>> -
>> if ( d->is_dying )
>> {
>> desc->handler->shutdown(desc);
>> @@ -204,10 +189,7 @@ int gic_remove_irq_from_guest(struct domain *d,
>> unsigned int virq,
>> */
>> if ( test_bit(_IRQ_INPROGRESS, &desc->status) ||
>> !test_bit(_IRQ_DISABLED, &desc->status) )
>> - {
>> - vgic_unlock_rank(v_target, rank, flags);
>> return -EBUSY;
>> - }
>> }
>>
>> clear_bit(_IRQ_GUEST, &desc->status);
>> @@ -215,8 +197,6 @@ int gic_remove_irq_from_guest(struct domain *d,
>> unsigned int virq,
>>
>> p->desc = NULL;
>>
>> - vgic_unlock_rank(v_target, rank, flags);
>> -
>> return 0;
>> }
>>
>>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |