diff options
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 73 | 
1 files changed, 66 insertions, 7 deletions
| diff --git a/kernel/cpu.c b/kernel/cpu.c index e84c0873559e..e2cad3ee2ead 100644 --- a/kernel/cpu.c +++ b/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); @@ -389,8 +392,7 @@ enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;  void __init cpu_smt_disable(bool force)  { -	if (cpu_smt_control == CPU_SMT_FORCE_DISABLED || -		cpu_smt_control == CPU_SMT_NOT_SUPPORTED) +	if (!cpu_smt_possible())  		return;  	if (force) { @@ -433,8 +435,16 @@ 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);  } + +/* Returns true if SMT is not supported of forcefully (irreversibly) disabled */ +bool cpu_smt_possible(void) +{ +	return cpu_smt_control != CPU_SMT_FORCE_DISABLED && +		cpu_smt_control != CPU_SMT_NOT_SUPPORTED; +} +EXPORT_SYMBOL_GPL(cpu_smt_possible);  #else  static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }  #endif @@ -1066,7 +1076,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 +2305,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 +2323,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,12 +2368,23 @@ 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);  } -enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO; +/* + * These are used for a global "mitigations=" cmdline option for toggling + * optional CPU mitigations. + */ +enum cpu_mitigations { +	CPU_MITIGATIONS_OFF, +	CPU_MITIGATIONS_AUTO, +	CPU_MITIGATIONS_AUTO_NOSMT, +}; + +static enum cpu_mitigations cpu_mitigations __ro_after_init = +	CPU_MITIGATIONS_AUTO;  static int __init mitigations_parse_cmdline(char *arg)  { @@ -2356,3 +2401,17 @@ static int __init mitigations_parse_cmdline(char *arg)  	return 0;  }  early_param("mitigations", mitigations_parse_cmdline); + +/* mitigations=off */ +bool cpu_mitigations_off(void) +{ +	return cpu_mitigations == CPU_MITIGATIONS_OFF; +} +EXPORT_SYMBOL_GPL(cpu_mitigations_off); + +/* mitigations=auto,nosmt */ +bool cpu_mitigations_auto_nosmt(void) +{ +	return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT; +} +EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt); | 
