Merge branch 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 31 Mar 2019 15:22:12 +0000 (08:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 31 Mar 2019 15:22:12 +0000 (08:22 -0700)
Pull CPU hotplug fixes from Thomas Gleixner:
 "Two SMT/hotplug related fixes:

   - Prevent crash when HOTPLUG_CPU is disabled and the CPU bringup
     aborts. This is triggered with the 'nosmt' command line option, but
     can happen by any abort condition. As the real unplug code is not
     compiled in, prevent the fail by keeping the CPU in zombie state.

   - Enforce HOTPLUG_CPU for SMP on x86 to avoid the above situation
     completely. With 'nosmt' being a popular option it's required to
     unplug the half brought up sibling CPUs (due to the MCE wreckage)
     completely"

* 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/smp: Enforce CONFIG_HOTPLUG_CPU when SMP=y
  cpu/hotplug: Prevent crash when CPU bringup fails on CONFIG_HOTPLUG_CPU=n

arch/x86/Kconfig
kernel/cpu.c

index c1f9b3cf437c3aa9018ff3288282e575f870424c..5ad92419be19c5d67fae37158bac2b93e105d1bc 100644 (file)
@@ -2217,14 +2217,8 @@ config RANDOMIZE_MEMORY_PHYSICAL_PADDING
           If unsure, leave at the default value.
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs"
+       def_bool y
        depends on SMP
-       ---help---
-         Say Y here to allow turning CPUs off and on. CPUs can be
-         controlled through /sys/devices/system/cpu.
-         ( Note: power management support will enable this option
-           automatically on SMP systems. )
-         Say N if you want to disable CPU hotplug.
 
 config BOOTPARAM_HOTPLUG_CPU0
        bool "Set default setting of cpu0_hotpluggable"
index 025f419d16f68be3e70cfcbdabe113ed655af6e4..6754f3ecfd943c97af0b865197d01366abac7c73 100644 (file)
@@ -564,6 +564,20 @@ static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
                cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
 }
 
+static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st)
+{
+       if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
+               return true;
+       /*
+        * When CPU hotplug is disabled, then taking the CPU down is not
+        * possible because takedown_cpu() and the architecture and
+        * subsystem specific mechanisms are not available. So the CPU
+        * which would be completely unplugged again needs to stay around
+        * in the current state.
+        */
+       return st->state <= CPUHP_BRINGUP_CPU;
+}
+
 static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
                              enum cpuhp_state target)
 {
@@ -574,8 +588,10 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
                st->state++;
                ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
                if (ret) {
-                       st->target = prev_state;
-                       undo_cpu_up(cpu, st);
+                       if (can_rollback_cpu(st)) {
+                               st->target = prev_state;
+                               undo_cpu_up(cpu, st);
+                       }
                        break;
                }
        }