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

Re: [Xen-devel] [PATCH v8 03/27] ARM: GIC: Add checks for NULL pointer pending_irq's



Hi,

On 12/04/17 11:25, Julien Grall wrote:
> Hi Andre,
> 
> On 12/04/17 01:44, Andre Przywara wrote:
>> For LPIs the struct pending_irq's are dynamically allocated and the
>> pointers will be stored in a radix tree. Since an LPI can be "unmapped"
>> at any time, teach the VGIC how to handle with irq_to_pending() returning
>> a NULL pointer.
>> We just do nothing in this case or clean up the LR if the virtual LPI
>> number was still in an LR.
> 
> Why not all the irq_to_pending call are not protected (such as
> vgic_irq_to_migrate)?

Some of them are never called by LPIs.
Is it worth the put ASSERTs in there everywhere?
I can copy the table with all call sites and their evaluations from that
other email into this commit message, if that sounds good.

Fixed the rest.

Cheers,
Andre.

> This is a call to forget to check NULL if we
> decide to use the function in the future.
> 
> Also, I would like a comment on top of irq_to_pending stating this can
> return NULL as you change the semantic of the function.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
>> ---
>>  xen/arch/arm/gic.c  | 37 ++++++++++++++++++++++++++++++++-----
>>  xen/arch/arm/vgic.c |  6 ++++++
>>  2 files changed, 38 insertions(+), 5 deletions(-)
>>
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index dcb1783..62ae3b8 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -408,9 +408,15 @@ void gic_remove_from_queues(struct vcpu *v,
>> unsigned int virtual_irq)
>>      spin_lock_irqsave(&v->arch.vgic.lock, flags);
>>
>>      p = irq_to_pending(v, virtual_irq);
>> -
>> -    if ( !list_empty(&p->lr_queue) )
>> -        list_del_init(&p->lr_queue);
>> +    /*
>> +     * If an LPIs has been removed meanwhile, it has been cleaned up
>> +     * already, so nothing to remove here.
>> +     */
>> +    if ( p )
>> +    {
>> +        if ( !list_empty(&p->lr_queue) )
>> +            list_del_init(&p->lr_queue);
>> +    }
> 
> This could be simplified with:
> 
> if ( p && !list_empty(&p->lr_queue) )
>   list_del_init(...);
> 
> Also, you probably want a likely(p).
> 
>>      spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
>>  }
>>
>> @@ -418,6 +424,10 @@ void gic_raise_inflight_irq(struct vcpu *v,
>> unsigned int virtual_irq)
>>  {
>>      struct pending_irq *n = irq_to_pending(v, virtual_irq);
>>
>> +    /* If an LPI has been removed meanwhile, there is nothing left to
>> raise. */
>> +    if ( !n )
> 
> if ( unlikely(!n) )
> 
>> +        return;
>> +
>>      ASSERT(spin_is_locked(&v->arch.vgic.lock));
>>
>>      if ( list_empty(&n->lr_queue) )
>> @@ -437,6 +447,11 @@ void gic_raise_guest_irq(struct vcpu *v, unsigned
>> int virtual_irq,
>>  {
>>      int i;
>>      unsigned int nr_lrs = gic_hw_ops->info->nr_lrs;
>> +    struct pending_irq *p = irq_to_pending(v, virtual_irq);
>> +
>> +    if ( !p )
> 
> if ( unlikely(!p) )
> 
>> +        /* An unmapped LPI does not need to be raised. */
>> +        return;
> 
> Please move this check after the ASSERT to keep the check on all the paths.
> 
>>
>>      ASSERT(spin_is_locked(&v->arch.vgic.lock));
>>
>> @@ -445,12 +460,12 @@ void gic_raise_guest_irq(struct vcpu *v,
>> unsigned int virtual_irq,
>>          i = find_first_zero_bit(&this_cpu(lr_mask), nr_lrs);
>>          if (i < nr_lrs) {
>>              set_bit(i, &this_cpu(lr_mask));
>> -            gic_set_lr(i, irq_to_pending(v, virtual_irq),
>> GICH_LR_PENDING);
>> +            gic_set_lr(i, p, GICH_LR_PENDING);
>>              return;
>>          }
>>      }
>>
>> -    gic_add_to_lr_pending(v, irq_to_pending(v, virtual_irq));
>> +    gic_add_to_lr_pending(v, p);
>>  }
>>
>>  static void gic_update_one_lr(struct vcpu *v, int i)
>> @@ -464,7 +479,19 @@ static void gic_update_one_lr(struct vcpu *v, int i)
>>
>>      gic_hw_ops->read_lr(i, &lr_val);
>>      irq = lr_val.virq;
>> +
> 
> 4th time I am saying this.... Spurious line.
> 
>>      p = irq_to_pending(v, irq);
>> +    /* An LPI might have been unmapped, in which case we just clean
>> up here. */
>> +    if ( !p )
> 
> unlikely(!p)
> 
>> +    {
>> +        ASSERT(is_lpi(irq));
>> +
>> +        gic_hw_ops->clear_lr(i);
>> +        clear_bit(i, &this_cpu(lr_mask));
>> +
>> +        return;
>> +    }
>> +
>>      if ( lr_val.state & GICH_LR_ACTIVE )
>>      {
>>          set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
>> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
>> index c953f13..b9fc837 100644
>> --- a/xen/arch/arm/vgic.c
>> +++ b/xen/arch/arm/vgic.c
>> @@ -473,6 +473,12 @@ void vgic_vcpu_inject_irq(struct vcpu *v,
>> unsigned int virq)
>>      spin_lock_irqsave(&v->arch.vgic.lock, flags);
>>
>>      n = irq_to_pending(v, virq);
>> +    /* If an LPI has been removed, there is nothing to inject here. */
>> +    if ( !n )
> 
> unlikely(...)
> 
>> +    {
>> +        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
>> +        return;
>> +    }
>>
>>      priority = vgic_get_virq_priority(v, virq);
>>
>>
> 
> Cheers,
> 

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

 


Rackspace

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