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

Re: [Xen-devel] [PATCH v4 10/10] xen/arm: gic_events_need_delivery and irq priorities



On Fri, 21 Mar 2014, Ian Campbell wrote:
> On Wed, 2014-03-19 at 12:32 +0000, Stefano Stabellini wrote:
> > gic_events_need_delivery should only return positive if an outstanding
> > pending irq has an higher priority than the currently active irq and the
> > priority mask.
> > Rewrite the function by going through the priority ordered inflight and
> > lr_queue lists.
> > 
> > In gic_restore_pending_irqs replace lower priority pending (and not
> > active) irqs in GICH_LRs with higher priority irqs if no more GICH_LRs
> > are available.
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> > 
> > ---
> > Changes in v4:
> > - in gic_events_need_delivery go through inflight_irqs and only consider
> > enabled irqs.
> > ---
> >  xen/arch/arm/gic.c           |   71 
> > +++++++++++++++++++++++++++++++++++++-----
> >  xen/include/asm-arm/domain.h |    5 +--
> >  xen/include/asm-arm/gic.h    |    3 ++
> >  3 files changed, 70 insertions(+), 9 deletions(-)
> > 
> > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> > index bc9d66d..533964e 100644
> > --- a/xen/arch/arm/gic.c
> > +++ b/xen/arch/arm/gic.c
> > @@ -709,6 +709,7 @@ static void _gic_clear_lr(struct vcpu *v, int i)
> >      p = irq_to_pending(v, irq);
> >      if ( lr & GICH_LR_ACTIVE )
> >      {
> > +        set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
> >          /* HW interrupts cannot be ACTIVE and PENDING */
> >          if ( p->desc == NULL &&
> >               test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
> > @@ -723,6 +724,7 @@ static void _gic_clear_lr(struct vcpu *v, int i)
> >          if ( p->desc != NULL )
> >              p->desc->status &= ~IRQ_INPROGRESS;
> >          clear_bit(GIC_IRQ_GUEST_VISIBLE, &p->status);
> > +        clear_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
> >          p->lr = nr_lrs;
> >          if ( test_bit(GIC_IRQ_GUEST_PENDING, &p->status) &&
> >                  test_bit(GIC_IRQ_GUEST_ENABLED, &p->status))
> > @@ -750,22 +752,47 @@ void gic_clear_lrs(struct vcpu *v)
> >  
> >  static void gic_restore_pending_irqs(struct vcpu *v)
> >  {
> > -    int i;
> > -    struct pending_irq *p, *t;
> > +    int i = 0, lrs = nr_lrs;
> > +    struct pending_irq *p, *t, *p_r;
> >      unsigned long flags;
> >  
> > +    if ( list_empty(&v->arch.vgic.lr_pending) )
> > +        return;
> > +
> > +    spin_lock_irqsave(&v->arch.vgic.lock, flags);
> > +
> > +    p_r = list_entry(v->arch.vgic.inflight_irqs.prev,
> > +                         typeof(*p_r), inflight);
> 
> Is this getting the tail of the list or something else?
> 
> >      list_for_each_entry_safe ( p, t, &v->arch.vgic.lr_pending, lr_queue )
> >      {
> >          i = find_first_zero_bit(&this_cpu(lr_mask), nr_lrs);
> > -        if ( i >= nr_lrs ) return;
> > +        if ( i >= nr_lrs )
> > +        {
> > +            while ( !test_bit(GIC_IRQ_GUEST_VISIBLE, &p_r->status) ||
> > +                    test_bit(GIC_IRQ_GUEST_ACTIVE, &p_r->status) )
> > +            {
> > +                p_r = list_entry(p_r->inflight.prev, typeof(*p_r), 
> > inflight);
> 
> Oh, maybe this (and the thing above) is an open coded list_for_each_prev
> or one of its variants? e.g. list_for_each_entry_reverse?

Yes, it is a list_for_each_entry_reverse that starts from the current
p_r and stops when it finds the first entry that is
GIC_IRQ_GUEST_VISIBLE and GIC_IRQ_GUEST_ACTIVE.

It can also stop if the next entry that would be found going through
inflight in reverse is the same that we are evaluating going through
lr_pending in regular order.


> > +                if ( &p_r->inflight == p->inflight.next )
> > +                    goto out;
> > +            }
> > +            i = p_r->lr;
> > +            p_r->lr = nr_lrs;
> > +            set_bit(GIC_IRQ_GUEST_PENDING, &p_r->status);
> > +            clear_bit(GIC_IRQ_GUEST_VISIBLE, &p_r->status);
> > +            gic_add_to_lr_pending(v, p_r);
> > +        }
> >  
> > -        spin_lock_irqsave(&v->arch.vgic.lock, flags);
> >          gic_set_lr(i, p, GICH_LR_PENDING);
> >          list_del_init(&p->lr_queue);
> >          set_bit(i, &this_cpu(lr_mask));
> > -        spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
> > +
> > +        lrs--;
> > +        if ( lrs == 0 )
> > +            break;
> >      }
> >  
> > +out:
> > +    spin_unlock_irqrestore(&v->arch.vgic.lock, flags);
> >  }
> >  
> >  void gic_clear_pending_irqs(struct vcpu *v)
> 
> 

_______________________________________________
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®.