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

Re: [Xen-devel] [PATCH] x86/smp: use APIC ALLBUT destination shorthand when possible



On 16.01.2020 16:05, Roger Pau Monné  wrote:
> On Thu, Jan 16, 2020 at 11:44:51AM +0100, Jan Beulich wrote:
>> Thinking about it, what about the period of time between a CPU having
>> got physically hot-added (and hence known at the hardware level) and
>> it actually getting brought up for the first time? IOW - do you
>> perhaps need to exclude use of the shortcut also when disabled_cpus
>> is non-zero?
> 
> Yes, I guess there's no signal to Xen that a new CPU is going to be
> physically hot-added, and hence as long as there are empty slots the
> scenario you describe above is possible.
> 
> I don't think there's also anyway to figure out if a system is capable
> of physical CPU hotplug, so as long as there are disabled_cpus we
> shouldn't use the shortcut (that's kind of a shame, because I think
> there are many systems reporting disabled CPUs in MADT).

We may want to provide a command line control to assert "I'm not going
to".

>>> @@ -30,7 +56,40 @@
>>>  
>>>  void send_IPI_mask(const cpumask_t *mask, int vector)
>>>  {
>>> -    alternative_vcall(genapic.send_IPI_mask, mask, vector);
>>> +    bool cpus_locked = false;
>>> +
>>> +    /*
>>> +     * Prevent any CPU hot{un}plug while sending the IPIs if we are to use
>>> +     * a shorthand, also refuse to use a shorthand if not all CPUs are
>>> +     * online or have been parked.
>>> +     */
>>> +    if ( system_state > SYS_STATE_smp_boot && !cpu_overflow &&
>>> +         /* NB: get_cpu_maps lock requires enabled interrupts. */
>>> +         local_irq_is_enabled() && (cpus_locked = get_cpu_maps()) &&
>>> +         (park_offline_cpus ||
>>> +          cpumask_equal(&cpu_online_map, &cpu_present_map)) )
>>
>> On the first and second pass I thought this contradicts the description.
>> To disambiguate (and assuming I understand it correctly), how about
>> saying something like "This can only be safely used when no CPU hotplug
>> or unplug operations are taking place, there are no offline CPUs (unless
>> those have been onlined and parked) and finally ..."?
> 
> I'm not sure I understand what should come after the finally ...

That was to continue with what you had in your text.

>>> +    else
>>> +    {
>>> +        if ( cpus_locked )
>>> +        {
>>> +            put_cpu_maps();
>>> +            cpus_locked = false;
>>> +        }
>>> +        cpumask_clear(this_cpu(scratch_cpumask));
>>
>> Is there a guarantee that the function won't be called with an
>> empty mask? All backing functions look to gracefully deal with
>> this case, yet ...
>>
>>> +    }
>>> +
>>> +    if ( cpumask_equal(mask, this_cpu(scratch_cpumask)) )> +        
>>> __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector,
>>> +                                    APIC_DEST_PHYSICAL);
>>
>> ... you'd make this an "all-but" message then. Adding a
>> !cpumask_empty() check would seem a little expensive, so how
>> about you copy cpumask_of(smp_processor_id()) above and add
>> !cpumask_test_cpu(smp_processor_id(), ...) here?
> 
> A cpumask_empty check at the top of the function would be easier to
> parse, but it could incur in more overhead, I've implemented what you
> describe.
> 
>>> +    else
>>> +        alternative_vcall(genapic.send_IPI_mask, mask, vector);
>>
>> Is there no reason at all to also check here whether APIC_DEST_ALL
>> could be used? Oh, I see - the backing functions all exclude the
>> local CPU. I wonder why e.g. flush_area_mask() then clears the
>> CPU off the mask it passes on. And with this behavior the
>> single cpumask_equal() check above is too restrictive - you'll
>> want to check whether mask matches the calculated all-but one or
>> cpu_online_map. I.e. perhaps you want
>>
>>         cpumask_or(this_cpu(scratch_cpumask), mask,
>>                    cpumask_of(smp_processor_id()));
>>
>> and then
>>
>>     if ( cpumask_equal(this_cpu(scratch_cpumask), &cpu_online_map) )
>>
>> ?
> 
> Oh, OK, in which case most of the comments above are moot if we go
> this route. What I have now if I properly parsed your comments is:
> 
>     bool cpus_locked = false;
>     cpumask_t *scratch = this_cpu(scratch_cpumask);
> 
>     /*
>      * This can only be safely used when no CPU hotplug or unplug operations
>      * are taking place, there are no offline CPUs (unless those have been
>      * onlined and parked), there are no disabled CPUs and all possible CPUs 
> in
>      * the system have been accounted for.
>      */
>     if ( system_state > SYS_STATE_smp_boot &&
>          !unaccounted_cpus && !disabled_cpus &&
>          /* NB: get_cpu_maps lock requires enabled interrupts. */
>          local_irq_is_enabled() && (cpus_locked = get_cpu_maps()) &&
>          (park_offline_cpus ||
>           cpumask_equal(&cpu_online_map, &cpu_present_map)) )
>         cpumask_or(scratch, mask, cpumask_of(smp_processor_id()));
>     else
>     {
>         if ( cpus_locked )
>         {
>             put_cpu_maps();
>             cpus_locked = false;
>         }
>         cpumask_clear(scratch);
>     }
> 
>     if ( cpumask_equal(scratch, &cpu_online_map) )
>         send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_PHYSICAL);
>     else
>         alternative_vcall(genapic.send_IPI_mask, mask, vector);
> 
>     if ( cpus_locked )
>         put_cpu_maps();
> 
> Can assert this matches your expectations? I think it fixes your
> comments about empty masks and a mask containing the current pCPU ID.

Looks like so.

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