These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / s390 / kernel / smp.c
index efd2c19..9062df5 100644 (file)
@@ -31,7 +31,9 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/crash_dump.h>
+#include <linux/memblock.h>
 #include <asm/asm-offsets.h>
+#include <asm/diag.h>
 #include <asm/switch_to.h>
 #include <asm/facility.h>
 #include <asm/ipl.h>
@@ -69,7 +71,7 @@ struct pcpu {
        u16 address;                    /* physical cpu address */
 };
 
-static u8 boot_cpu_type;
+static u8 boot_core_type;
 static struct pcpu pcpu_devices[NR_CPUS];
 
 unsigned int smp_cpu_mt_shift;
@@ -260,6 +262,8 @@ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
                + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->thread_info = (unsigned long) task_thread_info(tsk);
        lc->current_task = (unsigned long) tsk;
+       lc->lpp = LPP_MAGIC;
+       lc->current_pid = tsk->pid;
        lc->user_timer = ti->user_timer;
        lc->system_timer = ti->system_timer;
        lc->steal_timer = 0;
@@ -374,11 +378,14 @@ int smp_vcpu_scheduled(int cpu)
 
 void smp_yield_cpu(int cpu)
 {
-       if (MACHINE_HAS_DIAG9C)
+       if (MACHINE_HAS_DIAG9C) {
+               diag_stat_inc_norecursion(DIAG_STAT_X09C);
                asm volatile("diag %0,0,0x9c"
                             : : "d" (pcpu_devices[cpu].address));
-       else if (MACHINE_HAS_DIAG44)
+       } else if (MACHINE_HAS_DIAG44) {
+               diag_stat_inc_norecursion(DIAG_STAT_X044);
                asm volatile("diag 0,0,0x44");
+       }
 }
 
 /*
@@ -531,15 +538,12 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
 
 #ifdef CONFIG_CRASH_DUMP
 
-static inline void __smp_store_cpu_state(int cpu, u16 address, int is_boot_cpu)
+static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext,
+                                        u16 address, int is_boot_cpu)
 {
-       void *lc = pcpu_devices[0].lowcore;
-       struct save_area_ext *sa_ext;
+       void *lc = (void *)(unsigned long) store_prefix();
        unsigned long vx_sa;
 
-       sa_ext = dump_save_area_create(cpu);
-       if (!sa_ext)
-               panic("could not allocate memory for save area\n");
        if (is_boot_cpu) {
                /* Copy the registers of the boot CPU. */
                copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa),
@@ -554,14 +558,33 @@ static inline void __smp_store_cpu_state(int cpu, u16 address, int is_boot_cpu)
        if (!MACHINE_HAS_VX)
                return;
        /* Get the VX registers */
-       vx_sa = __get_free_page(GFP_KERNEL);
+       vx_sa = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
        if (!vx_sa)
                panic("could not allocate memory for VX save area\n");
        __pcpu_sigp_relax(address, SIGP_STORE_ADDITIONAL_STATUS, vx_sa, NULL);
        memcpy(sa_ext->vx_regs, (void *) vx_sa, sizeof(sa_ext->vx_regs));
-       free_page(vx_sa);
+       memblock_free(vx_sa, PAGE_SIZE);
+}
+
+int smp_store_status(int cpu)
+{
+       unsigned long vx_sa;
+       struct pcpu *pcpu;
+
+       pcpu = pcpu_devices + cpu;
+       if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
+                             0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
+               return -EIO;
+       if (!MACHINE_HAS_VX)
+               return 0;
+       vx_sa = __pa(pcpu->lowcore->vector_save_area_addr);
+       __pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS,
+                         vx_sa, NULL);
+       return 0;
 }
 
+#endif /* CONFIG_CRASH_DUMP */
+
 /*
  * Collect CPU state of the previous, crashed system.
  * There are four cases:
@@ -589,10 +612,12 @@ static inline void __smp_store_cpu_state(int cpu, u16 address, int is_boot_cpu)
  *    old system. The ELF sections are picked up by the crash_dump code
  *    via elfcorehdr_addr.
  */
-static void __init smp_store_cpu_states(struct sclp_cpu_info *info)
+void __init smp_save_dump_cpus(void)
 {
-       unsigned int cpu, address, i, j;
-       int is_boot_cpu;
+#ifdef CONFIG_CRASH_DUMP
+       int addr, cpu, boot_cpu_addr, max_cpu_addr;
+       struct save_area_ext *sa_ext;
+       bool is_boot_cpu;
 
        if (is_kdump_kernel())
                /* Previous system stored the CPU states. Nothing to do. */
@@ -601,43 +626,37 @@ static void __init smp_store_cpu_states(struct sclp_cpu_info *info)
                /* No previous system present, normal boot. */
                return;
        /* Set multi-threading state to the previous system. */
-       pcpu_set_smt(sclp_get_mtid_prev());
-       /* Collect CPU states. */
-       cpu = 0;
-       for (i = 0; i < info->configured; i++) {
-               /* Skip CPUs with different CPU type. */
-               if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type)
+       pcpu_set_smt(sclp.mtid_prev);
+       max_cpu_addr = SCLP_MAX_CORES << sclp.mtid_prev;
+       for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) {
+               if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0, NULL) ==
+                   SIGP_CC_NOT_OPERATIONAL)
                        continue;
-               for (j = 0; j <= smp_cpu_mtid; j++, cpu++) {
-                       address = (info->cpu[i].core_id << smp_cpu_mt_shift) + j;
-                       is_boot_cpu = (address == pcpu_devices[0].address);
-                       if (is_boot_cpu && !OLDMEM_BASE)
-                               /* Skip boot CPU for standard zfcp dump. */
-                               continue;
-                       /* Get state for this CPu. */
-                       __smp_store_cpu_state(cpu, address, is_boot_cpu);
-               }
+               cpu += 1;
        }
-}
-
-int smp_store_status(int cpu)
-{
-       unsigned long vx_sa;
-       struct pcpu *pcpu;
-
-       pcpu = pcpu_devices + cpu;
-       if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
-                             0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
-               return -EIO;
-       if (!MACHINE_HAS_VX)
-               return 0;
-       vx_sa = __pa(pcpu->lowcore->vector_save_area_addr);
-       __pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS,
-                         vx_sa, NULL);
-       return 0;
-}
-
+       dump_save_areas.areas = (void *)memblock_alloc(sizeof(void *) * cpu, 8);
+       dump_save_areas.count = cpu;
+       boot_cpu_addr = stap();
+       for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) {
+               if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0, NULL) ==
+                   SIGP_CC_NOT_OPERATIONAL)
+                       continue;
+               sa_ext = (void *) memblock_alloc(sizeof(*sa_ext), 8);
+               dump_save_areas.areas[cpu] = sa_ext;
+               if (!sa_ext)
+                       panic("could not allocate memory for save area\n");
+               is_boot_cpu = (addr == boot_cpu_addr);
+               cpu += 1;
+               if (is_boot_cpu && !OLDMEM_BASE)
+                       /* Skip boot CPU for standard zfcp dump. */
+                       continue;
+               /* Get state for this CPU. */
+               __smp_store_cpu_state(sa_ext, addr, is_boot_cpu);
+       }
+       diag308_reset();
+       pcpu_set_smt(0);
 #endif /* CONFIG_CRASH_DUMP */
+}
 
 void smp_cpu_set_polarization(int cpu, int val)
 {
@@ -649,21 +668,22 @@ int smp_cpu_get_polarization(int cpu)
        return pcpu_devices[cpu].polarization;
 }
 
-static struct sclp_cpu_info *smp_get_cpu_info(void)
+static struct sclp_core_info *smp_get_core_info(void)
 {
        static int use_sigp_detection;
-       struct sclp_cpu_info *info;
+       struct sclp_core_info *info;
        int address;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
-       if (info && (use_sigp_detection || sclp_get_cpu_info(info))) {
+       if (info && (use_sigp_detection || sclp_get_core_info(info))) {
                use_sigp_detection = 1;
-               for (address = 0; address <= MAX_CPU_ADDRESS;
+               for (address = 0;
+                    address < (SCLP_MAX_CORES << smp_cpu_mt_shift);
                     address += (1U << smp_cpu_mt_shift)) {
                        if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) ==
                            SIGP_CC_NOT_OPERATIONAL)
                                continue;
-                       info->cpu[info->configured].core_id =
+                       info->core[info->configured].core_id =
                                address >> smp_cpu_mt_shift;
                        info->configured++;
                }
@@ -674,7 +694,7 @@ static struct sclp_cpu_info *smp_get_cpu_info(void)
 
 static int smp_add_present_cpu(int cpu);
 
-static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add)
+static int __smp_rescan_cpus(struct sclp_core_info *info, int sysfs_add)
 {
        struct pcpu *pcpu;
        cpumask_t avail;
@@ -685,9 +705,9 @@ static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add)
        cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask);
        cpu = cpumask_first(&avail);
        for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) {
-               if (info->has_cpu_type && info->cpu[i].type != boot_cpu_type)
+               if (sclp.has_core_type && info->core[i].type != boot_core_type)
                        continue;
-               address = info->cpu[i].core_id << smp_cpu_mt_shift;
+               address = info->core[i].core_id << smp_cpu_mt_shift;
                for (j = 0; j <= smp_cpu_mtid; j++) {
                        if (pcpu_find_address(cpu_present_mask, address + j))
                                continue;
@@ -713,41 +733,37 @@ static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add)
 static void __init smp_detect_cpus(void)
 {
        unsigned int cpu, mtid, c_cpus, s_cpus;
-       struct sclp_cpu_info *info;
+       struct sclp_core_info *info;
        u16 address;
 
        /* Get CPU information */
-       info = smp_get_cpu_info();
+       info = smp_get_core_info();
        if (!info)
                panic("smp_detect_cpus failed to allocate memory\n");
 
        /* Find boot CPU type */
-       if (info->has_cpu_type) {
+       if (sclp.has_core_type) {
                address = stap();
                for (cpu = 0; cpu < info->combined; cpu++)
-                       if (info->cpu[cpu].core_id == address) {
+                       if (info->core[cpu].core_id == address) {
                                /* The boot cpu dictates the cpu type. */
-                               boot_cpu_type = info->cpu[cpu].type;
+                               boot_core_type = info->core[cpu].type;
                                break;
                        }
                if (cpu >= info->combined)
                        panic("Could not find boot CPU type");
        }
 
-#ifdef CONFIG_CRASH_DUMP
-       /* Collect CPU state of previous system */
-       smp_store_cpu_states(info);
-#endif
-
        /* Set multi-threading state for the current system */
-       mtid = sclp_get_mtid(boot_cpu_type);
+       mtid = boot_core_type ? sclp.mtid : sclp.mtid_cp;
        mtid = (mtid < smp_max_threads) ? mtid : smp_max_threads - 1;
        pcpu_set_smt(mtid);
 
        /* Print number of CPUs */
        c_cpus = s_cpus = 0;
        for (cpu = 0; cpu < info->combined; cpu++) {
-               if (info->has_cpu_type && info->cpu[cpu].type != boot_cpu_type)
+               if (sclp.has_core_type &&
+                   info->core[cpu].type != boot_core_type)
                        continue;
                if (cpu < info->configured)
                        c_cpus += smp_cpu_mtid + 1;
@@ -880,12 +896,13 @@ void __noreturn cpu_die(void)
 
 void __init smp_fill_possible_mask(void)
 {
-       unsigned int possible, sclp, cpu;
+       unsigned int possible, sclp_max, cpu;
 
-       sclp = min(smp_max_threads, sclp_get_mtid_max() + 1);
-       sclp = sclp_get_max_cpu()*sclp ?: nr_cpu_ids;
+       sclp_max = max(sclp.mtid, sclp.mtid_cp) + 1;
+       sclp_max = min(smp_max_threads, sclp_max);
+       sclp_max = sclp.max_cores * sclp_max ?: nr_cpu_ids;
        possible = setup_possible_cpus ?: nr_cpu_ids;
-       possible = min(possible, sclp);
+       possible = min(possible, sclp_max);
        for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
                set_cpu_possible(cpu, true);
 }
@@ -976,7 +993,7 @@ static ssize_t cpu_configure_store(struct device *dev,
        case 0:
                if (pcpu->state != CPU_STATE_CONFIGURED)
                        break;
-               rc = sclp_cpu_deconfigure(pcpu->address >> smp_cpu_mt_shift);
+               rc = sclp_core_deconfigure(pcpu->address >> smp_cpu_mt_shift);
                if (rc)
                        break;
                for (i = 0; i <= smp_cpu_mtid; i++) {
@@ -991,7 +1008,7 @@ static ssize_t cpu_configure_store(struct device *dev,
        case 1:
                if (pcpu->state != CPU_STATE_STANDBY)
                        break;
-               rc = sclp_cpu_configure(pcpu->address >> smp_cpu_mt_shift);
+               rc = sclp_core_configure(pcpu->address >> smp_cpu_mt_shift);
                if (rc)
                        break;
                for (i = 0; i <= smp_cpu_mtid; i++) {
@@ -1106,10 +1123,10 @@ out:
 
 int __ref smp_rescan_cpus(void)
 {
-       struct sclp_cpu_info *info;
+       struct sclp_core_info *info;
        int nr;
 
-       info = smp_get_cpu_info();
+       info = smp_get_core_info();
        if (!info)
                return -ENOMEM;
        get_online_cpus();