Merge tag 'arm64-perf' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-block.git] / arch / arm64 / kernel / smp.c
index b2d5f4ee9a1cd6676d7124829fe51a266b68a965..678e0842cb3b72f891684ce502009168fc444627 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/cputype.h>
 #include <asm/cpu_ops.h>
 #include <asm/mmu_context.h>
+#include <asm/numa.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
@@ -75,6 +76,43 @@ enum ipi_msg_type {
        IPI_WAKEUP
 };
 
+#ifdef CONFIG_ARM64_VHE
+
+/* Whether the boot CPU is running in HYP mode or not*/
+static bool boot_cpu_hyp_mode;
+
+static inline void save_boot_cpu_run_el(void)
+{
+       boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
+}
+
+static inline bool is_boot_cpu_in_hyp_mode(void)
+{
+       return boot_cpu_hyp_mode;
+}
+
+/*
+ * Verify that a secondary CPU is running the kernel at the same
+ * EL as that of the boot CPU.
+ */
+void verify_cpu_run_el(void)
+{
+       bool in_el2 = is_kernel_in_hyp_mode();
+       bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
+
+       if (in_el2 ^ boot_cpu_el2) {
+               pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
+                                       smp_processor_id(),
+                                       in_el2 ? 2 : 1,
+                                       boot_cpu_el2 ? 2 : 1);
+               cpu_panic_kernel();
+       }
+}
+
+#else
+static inline void save_boot_cpu_run_el(void) {}
+#endif
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int op_cpu_kill(unsigned int cpu);
 #else
@@ -166,6 +204,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
 static void smp_store_cpu_info(unsigned int cpuid)
 {
        store_cpu_topology(cpuid);
+       numa_store_cpu_info(cpuid);
 }
 
 /*
@@ -225,8 +264,6 @@ asmlinkage void secondary_start_kernel(void)
        pr_info("CPU%u: Booted secondary processor [%08x]\n",
                                         cpu, read_cpuid_id());
        update_cpu_boot_status(CPU_BOOT_SUCCESS);
-       /* Make sure the status update is visible before we complete */
-       smp_wmb();
        set_cpu_online(cpu, true);
        complete(&cpu_running);
 
@@ -401,6 +438,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
 void __init smp_prepare_boot_cpu(void)
 {
        cpuinfo_store_boot_cpu();
+       save_boot_cpu_run_el();
        set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 }
 
@@ -595,6 +633,8 @@ static void __init of_parse_and_init_cpus(void)
 
                pr_debug("cpu logical map 0x%llx\n", hwid);
                cpu_logical_map(cpu_count) = hwid;
+
+               early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
 next:
                cpu_count++;
        }
@@ -647,33 +687,18 @@ void __init smp_init_cpus(void)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        int err;
-       unsigned int cpu, ncores = num_possible_cpus();
+       unsigned int cpu;
 
        init_cpu_topology();
 
        smp_store_cpu_info(smp_processor_id());
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
-       /* Don't bother if we're effectively UP */
-       if (max_cpus <= 1)
-               return;
-
        /*
         * Initialise the present map (which describes the set of CPUs
         * actually populated at the present time) and release the
         * secondaries from the bootloader.
-        *
-        * Make sure we online at most (max_cpus - 1) additional CPUs.
         */
-       max_cpus--;
        for_each_possible_cpu(cpu) {
-               if (max_cpus == 0)
-                       break;
 
                if (cpu == smp_processor_id())
                        continue;
@@ -686,7 +711,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                        continue;
 
                set_cpu_present(cpu, true);
-               max_cpus--;
        }
 }
 
@@ -763,21 +787,11 @@ void arch_irq_work_raise(void)
 }
 #endif
 
-static DEFINE_RAW_SPINLOCK(stop_lock);
-
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-       if (system_state == SYSTEM_BOOTING ||
-           system_state == SYSTEM_RUNNING) {
-               raw_spin_lock(&stop_lock);
-               pr_crit("CPU%u: stopping\n", cpu);
-               dump_stack();
-               raw_spin_unlock(&stop_lock);
-       }
-
        set_cpu_online(cpu, false);
 
        local_irq_disable();
@@ -872,6 +886,9 @@ void smp_send_stop(void)
                cpumask_copy(&mask, cpu_online_mask);
                cpumask_clear_cpu(smp_processor_id(), &mask);
 
+               if (system_state == SYSTEM_BOOTING ||
+                   system_state == SYSTEM_RUNNING)
+                       pr_crit("SMP: stopping secondary CPUs\n");
                smp_cross_call(&mask, IPI_CPU_STOP);
        }
 
@@ -881,7 +898,8 @@ void smp_send_stop(void)
                udelay(1);
 
        if (num_online_cpus() > 1)
-               pr_warning("SMP: failed to stop secondary CPUs\n");
+               pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
+                          cpumask_pr_args(cpu_online_mask));
 }
 
 /*