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

Re: [Xen-devel] [PATCH v6 for-xen-4.5 1/3] dpci: Move from domain centric model to hvm_dirq_dpci model.



>>> On 07.10.14 at 17:40, <konrad.wilk@xxxxxxxxxx> wrote:
> @@ -65,10 +69,13 @@ static void schedule_softirq_for(struct hvm_pirq_dpci 
> *pirq_dpci)
>   */
>  int pt_pirq_softirq_active(struct hvm_pirq_dpci *pirq_dpci)
>  {
> -    if ( pirq_dpci->masked )
> -        return -EAGAIN;
> +    if ( test_bit(STATE_RUN, &pirq_dpci->masked) )
> +        return -ERESTART;
> +
> +    if ( test_bit(STATE_SCHED, &pirq_dpci->masked) )
> +        return -ERESTART;

Just check both in one go?

> @@ -230,7 +234,35 @@ int pt_irq_create_bind(
>              {
>                  pirq_dpci->gmsi.gflags = 0;
>                  pirq_dpci->gmsi.gvec = 0;
> -                pirq_dpci->dom = NULL;
> +
> +                /* The softirq has saved it so we are safe to reset it. */
> +                if ( test_bit(STATE_RUN, &pirq_dpci->masked) )
> +                {
> +                    pirq_dpci->dom = NULL;
> +                }
> +                else if ( test_and_clear_bit(STATE_SCHED, 
> &pirq_dpci->masked) )
> +                {
> +                    /* pirq_guest_unbind has made sure we won't be getting
> +                     * any more interrupts (no raise_softirq_for), so the 
> only
> +                     * ones that can be are the ones that got scheduled 
> _right_
> +                     * before the pirq_guest_unbind. If we can de-schedule 
> them
> +                     * that is good. The problem #1 is that the softirq 
> might be
> +                     * running and it has just set STATE_RUN while we cleared
> +                     * STATE_SCHED. That is OK, as right after the STATE_RUN 
> it
> +                     * will check the STATE_SCHED and if cleared it will 
> unclear
> +                     * STATE_RUN and ignore this pirq. We MUST put the 
> refcount
> +                     * down. */
> +                    put_domain(pirq_dpci->dom);
> +                    pirq_dpci->dom = NULL;
> +                }
> +                else
> +                {
> +                    /* !STATE_RUN (stale) and !STATE_SCHED.
> +                     * softirq will ignore this pirq, but we MUST put the 
> refcount
> +                     * down. */
> +                    put_domain(pirq_dpci->dom);
> +                    pirq_dpci->dom = NULL;
> +                }

First of all you don't seem to convert the setting of ->dom back to
what it was before (you said this is an incremental patch).

And then the else path is suspicious: Only when STATE_SCHED
is set there is a ref to be put. I.e. it always has to be the site
clearing that flag which also drops the ref. This is supported by
both else-if and else doing exactly the same (which can't really
be right).

> @@ -332,7 +364,7 @@ int pt_irq_create_bind(
>              {
>                  if ( pt_irq_need_timer(pirq_dpci->flags) )
>                      kill_timer(&pirq_dpci->timer);
> -                pirq_dpci->dom = NULL;
> +                /* TODO - function. pirq_dpci->dom = NULL; */

I wonder whether _here_ you really need this: Is it possible
for the softirq to get invoked when pirq_guest_bind() fails? If not,
only the other error path above would seem to need extra care.

> @@ -725,11 +754,24 @@ static void dpci_softirq(void)
>  
>      while ( !list_empty(&our_list) )
>      {
> +        struct domain *d;
> +
>          pirq_dpci = list_entry(our_list.next, struct hvm_pirq_dpci, 
> softirq_list);
>          list_del(&pirq_dpci->softirq_list);
>  
> -        hvm_dirq_assist(pirq_dpci);
> -        pirq_dpci->masked = 0;
> +        d = pirq_dpci->dom;
> +        barrier(); /* 'd' MUST be saved before we set/clear the bits. */

smp_mb() I think.

> +        if ( test_and_set_bit(STATE_RUN, &pirq_dpci->masked) )
> +            BUG();
> +        /* Asked to be descheduled. */
> +        if ( !test_and_clear_bit(STATE_SCHED, &pirq_dpci->masked) )

Invert the condition and ...

> +        {
> +            clear_bit(STATE_RUN, &pirq_dpci->masked);
> +            continue;
> +        }
> +        hvm_dirq_assist(d, pirq_dpci);
> +        put_domain(d);
> +        clear_bit(STATE_RUN, &pirq_dpci->masked);

... do the clear_bit() just once?

> --- a/xen/include/xen/hvm/irq.h
> +++ b/xen/include/xen/hvm/irq.h
> @@ -93,7 +93,7 @@ struct hvm_irq_dpci {
>  /* Machine IRQ to guest device/intx mapping. */
>  struct hvm_pirq_dpci {
>      uint32_t flags;
> -    bool_t masked;
> +    unsigned long masked;

Perhaps better "state" or some such?

Jan

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