Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 6 May 2019 21:44:49 +0000 (14:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 6 May 2019 21:44:49 +0000 (14:44 -0700)
Pull CPU hotplug updates from Ingo Molnar:
 "Two changes in this cycle:

   - Make the /sys/devices/system/cpu/smt/* files available on all
     arches, so user space has a consistent way to detect whether SMT is
     enabled.

   - Sparse annotation fix"

* 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  smpboot: Place the __percpu annotation correctly
  cpu/hotplug: Create SMT sysfs interface for all arches

1  2 
include/linux/cpu.h
kernel/cpu.c

diff --combined include/linux/cpu.h
@@@ -137,26 -137,9 +137,26 @@@ static inline int disable_nonboot_cpus(
        return freeze_secondary_cpus(0);
  }
  extern void enable_nonboot_cpus(void);
 +
 +static inline int suspend_disable_secondary_cpus(void)
 +{
 +      int cpu = 0;
 +
 +      if (IS_ENABLED(CONFIG_PM_SLEEP_SMP_NONZERO_CPU))
 +              cpu = -1;
 +
 +      return freeze_secondary_cpus(cpu);
 +}
 +static inline void suspend_enable_secondary_cpus(void)
 +{
 +      return enable_nonboot_cpus();
 +}
 +
  #else /* !CONFIG_PM_SLEEP_SMP */
  static inline int disable_nonboot_cpus(void) { return 0; }
  static inline void enable_nonboot_cpus(void) {}
 +static inline int suspend_disable_secondary_cpus(void) { return 0; }
 +static inline void suspend_enable_secondary_cpus(void) { }
  #endif /* !CONFIG_PM_SLEEP_SMP */
  
  void cpu_startup_entry(enum cpuhp_state state);
@@@ -192,6 -175,7 +192,7 @@@ enum cpuhp_smt_control 
        CPU_SMT_DISABLED,
        CPU_SMT_FORCE_DISABLED,
        CPU_SMT_NOT_SUPPORTED,
+       CPU_SMT_NOT_IMPLEMENTED,
  };
  
  #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
@@@ -199,33 -183,9 +200,33 @@@ extern enum cpuhp_smt_control cpu_smt_c
  extern void cpu_smt_disable(bool force);
  extern void cpu_smt_check_topology(void);
  #else
- # define cpu_smt_control              (CPU_SMT_ENABLED)
+ # define cpu_smt_control              (CPU_SMT_NOT_IMPLEMENTED)
  static inline void cpu_smt_disable(bool force) { }
  static inline void cpu_smt_check_topology(void) { }
  #endif
  
 +/*
 + * 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,
 +};
 +
 +extern enum cpu_mitigations cpu_mitigations;
 +
 +/* mitigations=off */
 +static inline bool cpu_mitigations_off(void)
 +{
 +      return cpu_mitigations == CPU_MITIGATIONS_OFF;
 +}
 +
 +/* mitigations=auto,nosmt */
 +static inline bool cpu_mitigations_auto_nosmt(void)
 +{
 +      return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
 +}
 +
  #endif /* _LINUX_CPU_H_ */
diff --combined kernel/cpu.c
@@@ -9,7 -9,6 +9,7 @@@
  #include <linux/notifier.h>
  #include <linux/sched/signal.h>
  #include <linux/sched/hotplug.h>
 +#include <linux/sched/isolation.h>
  #include <linux/sched/task.h>
  #include <linux/sched/smt.h>
  #include <linux/unistd.h>
@@@ -1200,15 -1199,8 +1200,15 @@@ int freeze_secondary_cpus(int primary
        int cpu, error = 0;
  
        cpu_maps_update_begin();
 -      if (!cpu_online(primary))
 +      if (primary == -1) {
                primary = cpumask_first(cpu_online_mask);
 +              if (!housekeeping_cpu(primary, HK_FLAG_TIMER))
 +                      primary = housekeeping_any_cpu(HK_FLAG_TIMER);
 +      } else {
 +              if (!cpu_online(primary))
 +                      primary = cpumask_first(cpu_online_mask);
 +      }
 +
        /*
         * We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
@@@ -2041,19 -2033,6 +2041,6 @@@ static const struct attribute_group cpu
  
  #ifdef CONFIG_HOTPLUG_SMT
  
- static const char *smt_states[] = {
-       [CPU_SMT_ENABLED]               = "on",
-       [CPU_SMT_DISABLED]              = "off",
-       [CPU_SMT_FORCE_DISABLED]        = "forceoff",
-       [CPU_SMT_NOT_SUPPORTED]         = "notsupported",
- };
- static ssize_t
- show_smt_control(struct device *dev, struct device_attribute *attr, char *buf)
- {
-       return snprintf(buf, PAGE_SIZE - 2, "%s\n", smt_states[cpu_smt_control]);
- }
  static void cpuhp_offline_cpu_device(unsigned int cpu)
  {
        struct device *dev = get_cpu_device(cpu);
@@@ -2124,9 -2103,10 +2111,10 @@@ static int cpuhp_smt_enable(void
        return ret;
  }
  
  static ssize_t
- store_smt_control(struct device *dev, struct device_attribute *attr,
-                 const char *buf, size_t count)
__store_smt_control(struct device *dev, struct device_attribute *attr,
+                   const char *buf, size_t count)
  {
        int ctrlval, ret;
  
        unlock_device_hotplug();
        return ret ? ret : count;
  }
+ #else /* !CONFIG_HOTPLUG_SMT */
+ static ssize_t
+ __store_smt_control(struct device *dev, struct device_attribute *attr,
+                   const char *buf, size_t count)
+ {
+       return -ENODEV;
+ }
+ #endif /* CONFIG_HOTPLUG_SMT */
+ static const char *smt_states[] = {
+       [CPU_SMT_ENABLED]               = "on",
+       [CPU_SMT_DISABLED]              = "off",
+       [CPU_SMT_FORCE_DISABLED]        = "forceoff",
+       [CPU_SMT_NOT_SUPPORTED]         = "notsupported",
+       [CPU_SMT_NOT_IMPLEMENTED]       = "notimplemented",
+ };
+ static ssize_t
+ show_smt_control(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+       const char *state = smt_states[cpu_smt_control];
+       return snprintf(buf, PAGE_SIZE - 2, "%s\n", state);
+ }
+ static ssize_t
+ store_smt_control(struct device *dev, struct device_attribute *attr,
+                 const char *buf, size_t count)
+ {
+       return __store_smt_control(dev, attr, buf, count);
+ }
  static DEVICE_ATTR(control, 0644, show_smt_control, store_smt_control);
  
  static ssize_t
  show_smt_active(struct device *dev, struct device_attribute *attr, char *buf)
  {
-       bool active = topology_max_smt_threads() > 1;
-       return snprintf(buf, PAGE_SIZE - 2, "%d\n", active);
+       return snprintf(buf, PAGE_SIZE - 2, "%d\n", sched_smt_active());
  }
  static DEVICE_ATTR(active, 0444, show_smt_active, NULL);
  
@@@ -2187,21 -2197,17 +2205,17 @@@ static const struct attribute_group cpu
        NULL
  };
  
- static int __init cpu_smt_state_init(void)
+ static int __init cpu_smt_sysfs_init(void)
  {
        return sysfs_create_group(&cpu_subsys.dev_root->kobj,
                                  &cpuhp_smt_attr_group);
  }
  
- #else
- static inline int cpu_smt_state_init(void) { return 0; }
- #endif
  static int __init cpuhp_sysfs_init(void)
  {
        int cpu, ret;
  
-       ret = cpu_smt_state_init();
+       ret = cpu_smt_sysfs_init();
        if (ret)
                return ret;
  
        return 0;
  }
  device_initcall(cpuhp_sysfs_init);
- #endif
+ #endif /* CONFIG_SYSFS && CONFIG_HOTPLUG_CPU */
  
  /*
   * cpu_bit_bitmap[] is a special, "compressed" data structure that
@@@ -2312,18 -2318,3 +2326,18 @@@ void __init boot_cpu_hotplug_init(void
  #endif
        this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
  }
 +
 +enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
 +
 +static int __init mitigations_parse_cmdline(char *arg)
 +{
 +      if (!strcmp(arg, "off"))
 +              cpu_mitigations = CPU_MITIGATIONS_OFF;
 +      else if (!strcmp(arg, "auto"))
 +              cpu_mitigations = CPU_MITIGATIONS_AUTO;
 +      else if (!strcmp(arg, "auto,nosmt"))
 +              cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
 +
 +      return 0;
 +}
 +early_param("mitigations", mitigations_parse_cmdline);