KVM: selftests: test KVM_GET_SUPPORTED_HV_CPUID as a system ioctl
[linux-2.6-microblaze.git] / kernel / cpu.c
index 9c706af..6ff2578 100644 (file)
@@ -3,6 +3,7 @@
  *
  * This code is licenced under the GPL.
  */
+#include <linux/sched/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/smp.h>
 #include <linux/init.h>
@@ -331,12 +332,12 @@ void lockdep_assert_cpus_held(void)
 
 static void lockdep_acquire_cpus_lock(void)
 {
-       rwsem_acquire(&cpu_hotplug_lock.rw_sem.dep_map, 0, 0, _THIS_IP_);
+       rwsem_acquire(&cpu_hotplug_lock.dep_map, 0, 0, _THIS_IP_);
 }
 
 static void lockdep_release_cpus_lock(void)
 {
-       rwsem_release(&cpu_hotplug_lock.rw_sem.dep_map, _THIS_IP_);
+       rwsem_release(&cpu_hotplug_lock.dep_map, _THIS_IP_);
 }
 
 /*
@@ -432,7 +433,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu)
        /*
         * On x86 it's required to boot all logical CPUs at least once so
         * that the init code can get a chance to set CR4.MCE on each
-        * CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any
+        * CPU. Otherwise, a broadcasted MCE observing CR4.MCE=0b on any
         * core will shutdown the machine.
         */
        return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
@@ -564,6 +565,21 @@ static int bringup_cpu(unsigned int cpu)
        return bringup_wait_for_ap(cpu);
 }
 
+static int finish_cpu(unsigned int cpu)
+{
+       struct task_struct *idle = idle_thread_get(cpu);
+       struct mm_struct *mm = idle->active_mm;
+
+       /*
+        * idle_task_exit() will have switched to &init_mm, now
+        * clean up any remaining active_mm state.
+        */
+       if (mm != &init_mm)
+               idle->active_mm = &init_mm;
+       mmdrop(mm);
+       return 0;
+}
+
 /*
  * Hotplug state machine related functions
  */
@@ -1041,7 +1057,7 @@ static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target)
        return _cpu_down(cpu, 0, target);
 }
 
-static int do_cpu_down(unsigned int cpu, enum cpuhp_state target)
+static int cpu_down(unsigned int cpu, enum cpuhp_state target)
 {
        int err;
 
@@ -1051,11 +1067,72 @@ static int do_cpu_down(unsigned int cpu, enum cpuhp_state target)
        return err;
 }
 
-int cpu_down(unsigned int cpu)
+/**
+ * cpu_device_down - Bring down a cpu device
+ * @dev: Pointer to the cpu device to offline
+ *
+ * This function is meant to be used by device core cpu subsystem only.
+ *
+ * Other subsystems should use remove_cpu() instead.
+ */
+int cpu_device_down(struct device *dev)
+{
+       return cpu_down(dev->id, CPUHP_OFFLINE);
+}
+
+int remove_cpu(unsigned int cpu)
 {
-       return do_cpu_down(cpu, CPUHP_OFFLINE);
+       int ret;
+
+       lock_device_hotplug();
+       ret = device_offline(get_cpu_device(cpu));
+       unlock_device_hotplug();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(remove_cpu);
+
+void smp_shutdown_nonboot_cpus(unsigned int primary_cpu)
+{
+       unsigned int cpu;
+       int error;
+
+       cpu_maps_update_begin();
+
+       /*
+        * Make certain the cpu I'm about to reboot on is online.
+        *
+        * This is inline to what migrate_to_reboot_cpu() already do.
+        */
+       if (!cpu_online(primary_cpu))
+               primary_cpu = cpumask_first(cpu_online_mask);
+
+       for_each_online_cpu(cpu) {
+               if (cpu == primary_cpu)
+                       continue;
+
+               error = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
+               if (error) {
+                       pr_err("Failed to offline CPU%d - error=%d",
+                               cpu, error);
+                       break;
+               }
+       }
+
+       /*
+        * Ensure all but the reboot CPU are offline.
+        */
+       BUG_ON(num_online_cpus() > 1);
+
+       /*
+        * Make sure the CPUs won't be enabled by someone else after this
+        * point. Kexec will reboot to a new kernel shortly resetting
+        * everything along the way.
+        */
+       cpu_hotplug_disabled++;
+
+       cpu_maps_update_done();
 }
-EXPORT_SYMBOL(cpu_down);
 
 #else
 #define takedown_cpu           NULL
@@ -1124,8 +1201,8 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
        }
 
        /*
-        * The caller of do_cpu_up might have raced with another
-        * caller. Ignore it for now.
+        * The caller of cpu_up() might have raced with another
+        * caller. Nothing to do.
         */
        if (st->state >= target)
                goto out;
@@ -1169,7 +1246,7 @@ out:
        return ret;
 }
 
-static int do_cpu_up(unsigned int cpu, enum cpuhp_state target)
+static int cpu_up(unsigned int cpu, enum cpuhp_state target)
 {
        int err = 0;
 
@@ -1203,11 +1280,65 @@ out:
        return err;
 }
 
-int cpu_up(unsigned int cpu)
+/**
+ * cpu_device_up - Bring up a cpu device
+ * @dev: Pointer to the cpu device to online
+ *
+ * This function is meant to be used by device core cpu subsystem only.
+ *
+ * Other subsystems should use add_cpu() instead.
+ */
+int cpu_device_up(struct device *dev)
+{
+       return cpu_up(dev->id, CPUHP_ONLINE);
+}
+
+int add_cpu(unsigned int cpu)
 {
-       return do_cpu_up(cpu, CPUHP_ONLINE);
+       int ret;
+
+       lock_device_hotplug();
+       ret = device_online(get_cpu_device(cpu));
+       unlock_device_hotplug();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(add_cpu);
+
+/**
+ * bringup_hibernate_cpu - Bring up the CPU that we hibernated on
+ * @sleep_cpu: The cpu we hibernated on and should be brought up.
+ *
+ * On some architectures like arm64, we can hibernate on any CPU, but on
+ * wake up the CPU we hibernated on might be offline as a side effect of
+ * using maxcpus= for example.
+ */
+int bringup_hibernate_cpu(unsigned int sleep_cpu)
+{
+       int ret;
+
+       if (!cpu_online(sleep_cpu)) {
+               pr_info("Hibernated on a CPU that is offline! Bringing CPU up.\n");
+               ret = cpu_up(sleep_cpu, CPUHP_ONLINE);
+               if (ret) {
+                       pr_err("Failed to bring hibernate-CPU up!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+void bringup_nonboot_cpus(unsigned int setup_max_cpus)
+{
+       unsigned int cpu;
+
+       for_each_present_cpu(cpu) {
+               if (num_online_cpus() >= setup_max_cpus)
+                       break;
+               if (!cpu_online(cpu))
+                       cpu_up(cpu, CPUHP_ONLINE);
+       }
 }
-EXPORT_SYMBOL_GPL(cpu_up);
 
 #ifdef CONFIG_PM_SLEEP_SMP
 static cpumask_var_t frozen_cpus;
@@ -1261,8 +1392,8 @@ int freeze_secondary_cpus(int primary)
 
        /*
         * Make sure the CPUs won't be enabled by someone else. We need to do
-        * this even in case of failure as all disable_nonboot_cpus() users are
-        * supposed to do enable_nonboot_cpus() on the failure path.
+        * this even in case of failure as all freeze_secondary_cpus() users are
+        * supposed to do thaw_secondary_cpus() on the failure path.
         */
        cpu_hotplug_disabled++;
 
@@ -1270,15 +1401,15 @@ int freeze_secondary_cpus(int primary)
        return error;
 }
 
-void __weak arch_enable_nonboot_cpus_begin(void)
+void __weak arch_thaw_secondary_cpus_begin(void)
 {
 }
 
-void __weak arch_enable_nonboot_cpus_end(void)
+void __weak arch_thaw_secondary_cpus_end(void)
 {
 }
 
-void enable_nonboot_cpus(void)
+void thaw_secondary_cpus(void)
 {
        int cpu, error;
 
@@ -1290,7 +1421,7 @@ void enable_nonboot_cpus(void)
 
        pr_info("Enabling non-boot CPUs ...\n");
 
-       arch_enable_nonboot_cpus_begin();
+       arch_thaw_secondary_cpus_begin();
 
        for_each_cpu(cpu, frozen_cpus) {
                trace_suspend_resume(TPS("CPU_ON"), cpu, true);
@@ -1303,7 +1434,7 @@ void enable_nonboot_cpus(void)
                pr_warn("Error taking CPU%d up: %d\n", cpu, error);
        }
 
-       arch_enable_nonboot_cpus_end();
+       arch_thaw_secondary_cpus_end();
 
        cpumask_clear(frozen_cpus);
 out:
@@ -1434,7 +1565,7 @@ static struct cpuhp_step cpuhp_hp_states[] = {
        [CPUHP_BRINGUP_CPU] = {
                .name                   = "cpu:bringup",
                .startup.single         = bringup_cpu,
-               .teardown.single        = NULL,
+               .teardown.single        = finish_cpu,
                .cant_stop              = true,
        },
        /* Final state before CPU kills itself */
@@ -2028,9 +2159,9 @@ static ssize_t write_cpuhp_target(struct device *dev,
                goto out;
 
        if (st->state < target)
-               ret = do_cpu_up(dev->id, target);
+               ret = cpu_up(dev->id, target);
        else
-               ret = do_cpu_down(dev->id, target);
+               ret = cpu_down(dev->id, target);
 out:
        unlock_device_hotplug();
        return ret ? ret : count;