[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |