Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull CPU hotplug updates from Thomas Gleixner: "A small update for the SMP hotplug code code: - Track "booted once" CPUs in a cpumask so the x86 APIC code has an easy way to decide whether broadcast IPIs are safe to use or not. - Implement a cpumask_or_equal() helper for the IPI broadcast evaluation. The above two changes have been also pulled into the x86/apic branch for implementing the conditional IPI broadcast feature. - Cache the number of online CPUs instead of reevaluating it over and over. num_online_cpus() is an unreliable snapshot anyway except when it is used outside a cpu hotplug locked region. The cached access is not changing this, but it's definitely faster than calculating the bitmap wheight especially in hot paths" * 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: cpu/hotplug: Cache number of online CPUs cpumask: Implement cpumask_or_equal() smp/hotplug: Track booted once CPUs in a cpumask
This commit is contained in:
35
kernel/cpu.c
35
kernel/cpu.c
@@ -62,7 +62,6 @@ struct cpuhp_cpu_state {
|
||||
bool rollback;
|
||||
bool single;
|
||||
bool bringup;
|
||||
bool booted_once;
|
||||
struct hlist_node *node;
|
||||
struct hlist_node *last;
|
||||
enum cpuhp_state cb_state;
|
||||
@@ -76,6 +75,10 @@ static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = {
|
||||
.fail = CPUHP_INVALID,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpumask_t cpus_booted_once_mask;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP)
|
||||
static struct lockdep_map cpuhp_state_up_map =
|
||||
STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map);
|
||||
@@ -433,7 +436,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu)
|
||||
* CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any
|
||||
* core will shutdown the machine.
|
||||
*/
|
||||
return !per_cpu(cpuhp_state, cpu).booted_once;
|
||||
return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
|
||||
}
|
||||
#else
|
||||
static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
|
||||
@@ -1066,7 +1069,7 @@ void notify_cpu_starting(unsigned int cpu)
|
||||
int ret;
|
||||
|
||||
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
|
||||
st->booted_once = true;
|
||||
cpumask_set_cpu(cpu, &cpus_booted_once_mask);
|
||||
while (st->state < target) {
|
||||
st->state++;
|
||||
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
|
||||
@@ -2295,6 +2298,9 @@ EXPORT_SYMBOL(__cpu_present_mask);
|
||||
struct cpumask __cpu_active_mask __read_mostly;
|
||||
EXPORT_SYMBOL(__cpu_active_mask);
|
||||
|
||||
atomic_t __num_online_cpus __read_mostly;
|
||||
EXPORT_SYMBOL(__num_online_cpus);
|
||||
|
||||
void init_cpu_present(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(&__cpu_present_mask, src);
|
||||
@@ -2310,6 +2316,27 @@ void init_cpu_online(const struct cpumask *src)
|
||||
cpumask_copy(&__cpu_online_mask, src);
|
||||
}
|
||||
|
||||
void set_cpu_online(unsigned int cpu, bool online)
|
||||
{
|
||||
/*
|
||||
* atomic_inc/dec() is required to handle the horrid abuse of this
|
||||
* function by the reboot and kexec code which invoke it from
|
||||
* IPI/NMI broadcasts when shutting down CPUs. Invocation from
|
||||
* regular CPU hotplug is properly serialized.
|
||||
*
|
||||
* Note, that the fact that __num_online_cpus is of type atomic_t
|
||||
* does not protect readers which are not serialized against
|
||||
* concurrent hotplug operations.
|
||||
*/
|
||||
if (online) {
|
||||
if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask))
|
||||
atomic_inc(&__num_online_cpus);
|
||||
} else {
|
||||
if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask))
|
||||
atomic_dec(&__num_online_cpus);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate the first processor.
|
||||
*/
|
||||
@@ -2334,7 +2361,7 @@ void __init boot_cpu_init(void)
|
||||
void __init boot_cpu_hotplug_init(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
this_cpu_write(cpuhp_state.booted_once, true);
|
||||
cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
|
||||
#endif
|
||||
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
|
||||
}
|
||||
|
Reference in New Issue
Block a user