Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[sfrench/cifs-2.6.git] / arch / s390 / kernel / smp.c
index 092c4154abd74c0ceda7592946f91a64674fdb58..cd4334e80b64cdb7908842f44015183be17c62f2 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/sched/task_stack.h>
 #include <linux/crash_dump.h>
 #include <linux/memblock.h>
+#include <linux/kprobes.h>
 #include <asm/asm-offsets.h>
 #include <asm/diag.h>
 #include <asm/switch_to.h>
@@ -81,8 +82,6 @@ struct pcpu {
 static u8 boot_core_type;
 static struct pcpu pcpu_devices[NR_CPUS];
 
-static struct kmem_cache *pcpu_mcesa_cache;
-
 unsigned int smp_cpu_mt_shift;
 EXPORT_SYMBOL(smp_cpu_mt_shift);
 
@@ -193,10 +192,8 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
 static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
 {
        unsigned long async_stack, panic_stack;
-       unsigned long mcesa_origin, mcesa_bits;
        struct lowcore *lc;
 
-       mcesa_origin = mcesa_bits = 0;
        if (pcpu != &pcpu_devices[0]) {
                pcpu->lowcore = (struct lowcore *)
                        __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
@@ -204,39 +201,30 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
                panic_stack = __get_free_page(GFP_KERNEL);
                if (!pcpu->lowcore || !panic_stack || !async_stack)
                        goto out;
-               if (MACHINE_HAS_VX || MACHINE_HAS_GS) {
-                       mcesa_origin = (unsigned long)
-                               kmem_cache_alloc(pcpu_mcesa_cache, GFP_KERNEL);
-                       if (!mcesa_origin)
-                               goto out;
-                       /* The pointer is stored with mcesa_bits ORed in */
-                       kmemleak_not_leak((void *) mcesa_origin);
-                       mcesa_bits = MACHINE_HAS_GS ? 11 : 0;
-               }
        } else {
                async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET;
                panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET;
-               mcesa_origin = pcpu->lowcore->mcesad & MCESA_ORIGIN_MASK;
-               mcesa_bits = pcpu->lowcore->mcesad & MCESA_LC_MASK;
        }
        lc = pcpu->lowcore;
        memcpy(lc, &S390_lowcore, 512);
        memset((char *) lc + 512, 0, sizeof(*lc) - 512);
        lc->async_stack = async_stack + ASYNC_FRAME_OFFSET;
        lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET;
-       lc->mcesad = mcesa_origin | mcesa_bits;
        lc->cpu_nr = cpu;
        lc->spinlock_lockval = arch_spin_lockval(cpu);
-       if (vdso_alloc_per_cpu(lc))
+       lc->spinlock_index = 0;
+       if (nmi_alloc_per_cpu(lc))
                goto out;
+       if (vdso_alloc_per_cpu(lc))
+               goto out_mcesa;
        lowcore_ptr[cpu] = lc;
        pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, (u32)(unsigned long) lc);
        return 0;
+
+out_mcesa:
+       nmi_free_per_cpu(lc);
 out:
        if (pcpu != &pcpu_devices[0]) {
-               if (mcesa_origin)
-                       kmem_cache_free(pcpu_mcesa_cache,
-                                       (void *) mcesa_origin);
                free_page(panic_stack);
                free_pages(async_stack, ASYNC_ORDER);
                free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
@@ -248,17 +236,12 @@ out:
 
 static void pcpu_free_lowcore(struct pcpu *pcpu)
 {
-       unsigned long mcesa_origin;
-
        pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, 0);
        lowcore_ptr[pcpu - pcpu_devices] = NULL;
        vdso_free_per_cpu(pcpu->lowcore);
+       nmi_free_per_cpu(pcpu->lowcore);
        if (pcpu == &pcpu_devices[0])
                return;
-       if (MACHINE_HAS_VX || MACHINE_HAS_GS) {
-               mcesa_origin = pcpu->lowcore->mcesad & MCESA_ORIGIN_MASK;
-               kmem_cache_free(pcpu_mcesa_cache, (void *) mcesa_origin);
-       }
        free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET);
        free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER);
        free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
@@ -274,6 +257,7 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
        cpumask_set_cpu(cpu, mm_cpumask(&init_mm));
        lc->cpu_nr = cpu;
        lc->spinlock_lockval = arch_spin_lockval(cpu);
+       lc->spinlock_index = 0;
        lc->percpu_offset = __per_cpu_offset[cpu];
        lc->kernel_asce = S390_lowcore.kernel_asce;
        lc->machine_flags = S390_lowcore.machine_flags;
@@ -282,6 +266,7 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
        save_access_regs((unsigned int *) lc->access_regs_save_area);
        memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
               MAX_FACILITY_BIT/8);
+       arch_spin_lock_setup(cpu);
 }
 
 static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
@@ -423,13 +408,17 @@ void smp_yield_cpu(int cpu)
  * Send cpus emergency shutdown signal. This gives the cpus the
  * opportunity to complete outstanding interrupts.
  */
-static void smp_emergency_stop(cpumask_t *cpumask)
+void notrace smp_emergency_stop(void)
 {
+       cpumask_t cpumask;
        u64 end;
        int cpu;
 
+       cpumask_copy(&cpumask, cpu_online_mask);
+       cpumask_clear_cpu(smp_processor_id(), &cpumask);
+
        end = get_tod_clock() + (1000000UL << 12);
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu(cpu, &cpumask) {
                struct pcpu *pcpu = pcpu_devices + cpu;
                set_bit(ec_stop_cpu, &pcpu->ec_mask);
                while (__pcpu_sigp(pcpu->address, SIGP_EMERGENCY_SIGNAL,
@@ -438,21 +427,21 @@ static void smp_emergency_stop(cpumask_t *cpumask)
                        cpu_relax();
        }
        while (get_tod_clock() < end) {
-               for_each_cpu(cpu, cpumask)
+               for_each_cpu(cpu, &cpumask)
                        if (pcpu_stopped(pcpu_devices + cpu))
-                               cpumask_clear_cpu(cpu, cpumask);
-               if (cpumask_empty(cpumask))
+                               cpumask_clear_cpu(cpu, &cpumask);
+               if (cpumask_empty(&cpumask))
                        break;
                cpu_relax();
        }
 }
+NOKPROBE_SYMBOL(smp_emergency_stop);
 
 /*
  * Stop all cpus but the current one.
  */
 void smp_send_stop(void)
 {
-       cpumask_t cpumask;
        int cpu;
 
        /* Disable all interrupts/machine checks */
@@ -460,17 +449,16 @@ void smp_send_stop(void)
        trace_hardirqs_off();
 
        debug_set_critical();
-       cpumask_copy(&cpumask, cpu_online_mask);
-       cpumask_clear_cpu(smp_processor_id(), &cpumask);
 
        if (oops_in_progress)
-               smp_emergency_stop(&cpumask);
+               smp_emergency_stop();
 
        /* stop all processors */
-       for_each_cpu(cpu, &cpumask) {
-               struct pcpu *pcpu = pcpu_devices + cpu;
-               pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
-               while (!pcpu_stopped(pcpu))
+       for_each_online_cpu(cpu) {
+               if (cpu == smp_processor_id())
+                       continue;
+               pcpu_sigp_retry(pcpu_devices + cpu, SIGP_STOP, 0);
+               while (!pcpu_stopped(pcpu_devices + cpu))
                        cpu_relax();
        }
 }
@@ -804,6 +792,8 @@ void __init smp_detect_cpus(void)
  */
 static void smp_start_secondary(void *cpuvoid)
 {
+       int cpu = smp_processor_id();
+
        S390_lowcore.last_update_clock = get_tod_clock();
        S390_lowcore.restart_stack = (unsigned long) restart_stack;
        S390_lowcore.restart_fn = (unsigned long) do_restart;
@@ -817,8 +807,12 @@ static void smp_start_secondary(void *cpuvoid)
        init_cpu_timer();
        vtime_init();
        pfault_init();
-       notify_cpu_starting(smp_processor_id());
-       set_cpu_online(smp_processor_id(), true);
+       notify_cpu_starting(cpu);
+       if (topology_cpu_dedicated(cpu))
+               set_cpu_flag(CIF_DEDICATED_CPU);
+       else
+               clear_cpu_flag(CIF_DEDICATED_CPU);
+       set_cpu_online(cpu, true);
        inc_irq_stat(CPU_RST);
        local_irq_enable();
        cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
@@ -927,22 +921,12 @@ void __init smp_fill_possible_mask(void)
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned long size;
-
        /* request the 0x1201 emergency signal external interrupt */
        if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))
                panic("Couldn't request external interrupt 0x1201");
        /* request the 0x1202 external call external interrupt */
        if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
                panic("Couldn't request external interrupt 0x1202");
-       /* create slab cache for the machine-check-extended-save-areas */
-       if (MACHINE_HAS_VX || MACHINE_HAS_GS) {
-               size = 1UL << (MACHINE_HAS_GS ? 11 : 10);
-               pcpu_mcesa_cache = kmem_cache_create("nmi_save_areas",
-                                                    size, size, 0, NULL);
-               if (!pcpu_mcesa_cache)
-                       panic("Couldn't create nmi save area cache");
-       }
 }
 
 void __init smp_prepare_boot_cpu(void)
@@ -965,6 +949,7 @@ void __init smp_setup_processor_id(void)
        pcpu_devices[0].address = stap();
        S390_lowcore.cpu_nr = 0;
        S390_lowcore.spinlock_lockval = arch_spin_lockval(0);
+       S390_lowcore.spinlock_index = 0;
 }
 
 /*