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

Re: [Xen-devel] [PATCH for-4.12 V2] x86/altp2m: fix HVMOP_altp2m_set_domain_state race



>>> On 08.02.19 at 18:02, <rcojocaru@xxxxxxxxxxxxxxx> wrote:
> On 2/8/19 6:44 PM, Jan Beulich wrote:
>>>>> On 08.02.19 at 17:30, <rcojocaru@xxxxxxxxxxxxxxx> wrote:
>>> On 2/8/19 5:50 PM, Jan Beulich wrote:
>>>>>>> On 08.02.19 at 15:00, <rcojocaru@xxxxxxxxxxxxxxx> wrote:
>>>>>          /* If the alternate p2m state has changed, handle appropriately 
>>>>> */
>>>>> -        if ( d->arch.altp2m_active != ostate &&
>>>>> +        if ( nstate != ostate &&
>>>>>               (ostate || !(rc = p2m_init_altp2m_by_id(d, 0))) )
>>>>>          {
>>>>> +            /* First mark altp2m as disabled, then 
>>>>> altp2m_vcpu_destroy(). */
>>>>> +            if ( ostate )
>>>>> +                d->arch.altp2m_active = false;
>>>>
>>>> Why the if()? In the opposite case you'd simply write false into
>>>> what already holds false.
>>>
>>> The value written into d->arch.altp2m_active is not the point here. The
>>> point is that if ( ostate ), then we are disabling altp2m (because the
>>> if above this one makes sure ostate != nstate).
>>>
>>> So in the disable case, first I wanted to set d->arch.altp2m_active to
>>> false (which immediately causes altp2m_active(d) to return false as
>>> well), and then actually perform the work.
>> 
>> Sure - I'm not asking to remove everything above, just the if()
>> (and keep what is now the body). That is because
>> - in the enable case the value is false and writing false into it is
>>   benign,
>> - in the disable case you want to actively change from true to
>>   false.
>> 
>>>>> @@ -4550,7 +4554,14 @@ static int do_altp2m_op(
>>>>>  
>>>>>              if ( ostate )
>>>>>                  p2m_flush_altp2m(d);
>>>>> +            else
>>>>> +                /*
>>>>> +                 * Wait until altp2m_vcpu_initialise() is done before 
>>>>> marking
>>>>> +                 * altp2m as being enabled for the domain.
>>>>> +                 */
>>>>> +                d->arch.altp2m_active = true;
>>>>
>>>> Similarly here you could omit the "else" and simply store "nstate" afaict.
>>>
>>> As above, in the enable case I wanted to first setup altp2m on all VCPUs
>>> with altp2m_vcpu_initialise(), and only after that set
>>> d->arch.altp2m_active = true.
>>>
>>> In summary, if ( ostate ) we want to set d->arch.altp2m_active before
>>> the for (we're disabling altp2m), and if ( !ostate ) (which is the else
>>> above) we want to set d->arch.altp2m_active after said for.
>>>
>>> We can indeed store nstate. I just thought things look clearer with
>>> "true" and "false", but if you prefer there's no problem assigning nstate.
>> 
>> Well, as always with mm and altp2m code, I'm not the maintainer, so
>> I don't have the final say. It's just that I think unnecessary conditionals
>> would better be avoided, even if they're not on a performance critical
>> path.
>> 
>[...]
>> 
>> Hmm, according to the change further up in this patch, altp2m_active()
>> returns false before v->p2midx can be set to INVALID_ALTP2M (you
>> don't change this property). So (related to the change further up)
>> there's a period of time during which p2m_get_altp2m() will return
>> non-NULL despite altp2m_active() returning false. Afaict, that is.
> 
> Right, I now understand what you meant by removing "if ( ostate )" -
> you'd like d->arch.altp2m_active to only be set _after_ the for, for the
> enable, as well as for the disable case.

No, certainly not. Exactly because of ...

> However, I wanted to keep both if()s to avoid another problem with this
> code:
>[...]
> So for the disable case, I wanted altp2m_active(v->domain) to return
> false immediately so that this code won't be triggered. Otherwise,
> assuming the following scenario:

... this. Apparently "and keep what is now the body" was still not clear
enough.

Taking your original code, I mean

        if ( nstate != ostate &&
             (ostate || !(rc = p2m_init_altp2m_by_id(d, 0))) )
        {
            /* First mark altp2m as disabled, then altp2m_vcpu_destroy(). */
            d->arch.altp2m_active = false;

            for_each_vcpu( d, v )
            [...]

            if ( ostate )
                p2m_flush_altp2m(d);
            /*
             * Wait until altp2m_vcpu_initialise() is done before marking
             * altp2m as being enabled for the domain.
             */
            d->arch.altp2m_active = nstate;
        }

> Now, you're right that p2m_get_altp2m() may hand over a pointer to an
> altp2m between the moment where d->arch.altp2m_active is false and the
> point where v->p2midx actually becomes INVALID_ALTP2M with my code; but
> I think it can be argued that I should rather fix p2m_get_altp2m(), to
> return NULL if altp2m_active() == false and keep the if()s (which I've
> hopefully been more eloquent about now).

Yes, that looks to be an option, provided it doesn't violate assumptions
elsewhere.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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