|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH] dpci: Put the dpci back on the list if running on another CPU.
>>> On 02.02.15 at 15:29, <konrad.wilk@xxxxxxxxxx> wrote:
> On Tue, Jan 13, 2015 at 10:20:00AM +0000, Jan Beulich wrote:
>> >>> On 12.01.15 at 17:45, <konrad.wilk@xxxxxxxxxx> wrote:
>> > There is race when we clear the STATE_SCHED in the softirq
>> > - which allows the 'raise_softirq_for' to progress and
>> > schedule another dpci. During that time the other CPU could
>> > receive an interrupt and calls 'raise_softirq_for' and put
>> > the dpci on its per-cpu list. There would be two 'dpci_softirq'
>> > running at the same time (on different CPUs) where the
>> > dpci state is STATE_RUN (and STATE_SCHED is cleared). This
>> > ends up hitting:
>> >
>> > if ( test_and_set_bit(STATE_RUN, &pirq_dpci->state) )
>> > BUG()
>> >
>> > Instead of that put the dpci back on the per-cpu list to deal
>> > with later.
>> >
>> > The reason we can get his with this is when an interrupt
>> > affinity is set over multiple CPUs.
>> >
>> > Another potential fix would be to add a guard in the raise_softirq_for
>> > to check for 'STATE_RUN' bit being set and not schedule the
>> > dpci until that bit has been cleared.
>>
>> I indeed think this should be investigated, because it would make
>> explicit what ...
>>
>> > --- a/xen/drivers/passthrough/io.c
>> > +++ b/xen/drivers/passthrough/io.c
>> > @@ -804,7 +804,17 @@ static void dpci_softirq(void)
>> > d = pirq_dpci->dom;
>> > smp_mb(); /* 'd' MUST be saved before we set/clear the bits. */
>> > if ( test_and_set_bit(STATE_RUN, &pirq_dpci->state) )
>> > - BUG();
>> > + {
>> > + unsigned long flags;
>> > +
>> > + /* Put back on the list and retry. */
>> > + local_irq_save(flags);
>> > + list_add_tail(&pirq_dpci->softirq_list, &this_cpu(dpci_list));
>> > + local_irq_restore(flags);
>> > +
>> > + raise_softirq(HVM_DPCI_SOFTIRQ);
>> > + continue;
>> > + }
>>
>> ... this does implicitly - spin until the bad condition cleared.
>
> I still haven't gotten to trying to reproduce the issues Malcolm
> saw which is easier for me to do (use Intel super-fast storage
> in a Windows guest) - since I've one of those boxes.
>
> However in lieu of that, here is a patch that does pass my testing
> of SR-IOV, and I believe should work fine. I _think_ it covers
> what you want it to have Jan, but of course please correct me
> if I made a mistake in the logic.
Since the code quoted above is still there in the new patch, the new
patch can at best be half of what I suggested.
> --- a/xen/drivers/passthrough/io.c
> +++ b/xen/drivers/passthrough/io.c
> @@ -63,10 +63,37 @@ enum {
> static void raise_softirq_for(struct hvm_pirq_dpci *pirq_dpci)
> {
> unsigned long flags;
> + unsigned long old, new, val = pirq_dpci->state;
>
> - if ( test_and_set_bit(STATE_SCHED, &pirq_dpci->state) )
> - return;
> + /*
> + * This cmpxch is a more clear version of:
> + * if ( test_and_set_bit(STATE_SCHED, &pirq_dpci->state) )
> + * return;
> + * since it also checks for STATE_RUN conditions.
> + */
> + for ( ;; )
> + {
> + new = 1 << STATE_SCHED;
> + if ( val )
> + new |= val;
Why the if()?
>
> + old = cmpxchg(&pirq_dpci->state, val, new);
> + switch ( old )
> + {
> + case (1 << STATE_SCHED):
> + case (1 << STATE_RUN) | (1 << STATE_SCHED):
> + /*
> + * Whenever STATE_SCHED is set we MUST not schedule it.
> + */
> + return;
> + }
> + /*
> + * If the 'state' is 0 or (1 << STATE_RUN) we can schedule it.
> + */
Really? Wasn't the intention to _not_ schedule when STATE_RUN is
set? (Also the above is a only line comment, i.e. wants different style.)
I.e. with what you do now you could as well keep the old code.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |