Merge tag 's390-5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-2.6-microblaze.git] / arch / s390 / kernel / processor.c
index 82df39b..d9d4a80 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/cpufeature.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
+#include <linux/random.h>
 #include <linux/sched/mm.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <asm/elf.h>
 #include <asm/lowcore.h>
 #include <asm/param.h>
+#include <asm/sclp.h>
 #include <asm/smp.h>
 
+unsigned long __read_mostly elf_hwcap;
+char elf_platform[ELF_PLATFORM_SIZE];
+
 struct cpu_info {
        unsigned int cpu_mhz_dynamic;
        unsigned int cpu_mhz_static;
@@ -113,15 +118,33 @@ static void show_facilities(struct seq_file *m)
 static void show_cpu_summary(struct seq_file *m, void *v)
 {
        static const char *hwcap_str[] = {
-               "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
-               "edat", "etf3eh", "highgprs", "te", "vx", "vxd", "vxe", "gs",
-               "vxe2", "vxp", "sort", "dflt"
-       };
-       static const char * const int_hwcap_str[] = {
-               "sie"
+               [HWCAP_NR_ESAN3]        = "esan3",
+               [HWCAP_NR_ZARCH]        = "zarch",
+               [HWCAP_NR_STFLE]        = "stfle",
+               [HWCAP_NR_MSA]          = "msa",
+               [HWCAP_NR_LDISP]        = "ldisp",
+               [HWCAP_NR_EIMM]         = "eimm",
+               [HWCAP_NR_DFP]          = "dfp",
+               [HWCAP_NR_HPAGE]        = "edat",
+               [HWCAP_NR_ETF3EH]       = "etf3eh",
+               [HWCAP_NR_HIGH_GPRS]    = "highgprs",
+               [HWCAP_NR_TE]           = "te",
+               [HWCAP_NR_VXRS]         = "vx",
+               [HWCAP_NR_VXRS_BCD]     = "vxd",
+               [HWCAP_NR_VXRS_EXT]     = "vxe",
+               [HWCAP_NR_GS]           = "gs",
+               [HWCAP_NR_VXRS_EXT2]    = "vxe2",
+               [HWCAP_NR_VXRS_PDE]     = "vxp",
+               [HWCAP_NR_SORT]         = "sort",
+               [HWCAP_NR_DFLT]         = "dflt",
+               [HWCAP_NR_VXRS_PDE2]    = "vxp2",
+               [HWCAP_NR_NNPA]         = "nnpa",
+               [HWCAP_NR_PCI_MIO]      = "pcimio",
+               [HWCAP_NR_SIE]          = "sie",
        };
        int i, cpu;
 
+       BUILD_BUG_ON(ARRAY_SIZE(hwcap_str) != HWCAP_NR_MAX);
        seq_printf(m, "vendor_id       : IBM/S390\n"
                   "# processors    : %i\n"
                   "bogomips per cpu: %lu.%02lu\n",
@@ -132,9 +155,6 @@ static void show_cpu_summary(struct seq_file *m, void *v)
        for (i = 0; i < ARRAY_SIZE(hwcap_str); i++)
                if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
                        seq_printf(m, "%s ", hwcap_str[i]);
-       for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++)
-               if (int_hwcap_str[i] && (int_hwcap & (1UL << i)))
-                       seq_printf(m, "%s ", int_hwcap_str[i]);
        seq_puts(m, "\n");
        show_facilities(m);
        show_cacheinfo(m);
@@ -149,6 +169,141 @@ static void show_cpu_summary(struct seq_file *m, void *v)
        }
 }
 
+static int __init setup_hwcaps(void)
+{
+       /* instructions named N3, "backported" to esa-mode */
+       if (test_facility(0))
+               elf_hwcap |= HWCAP_ESAN3;
+
+       /* z/Architecture mode active */
+       elf_hwcap |= HWCAP_ZARCH;
+
+       /* store-facility-list-extended */
+       if (test_facility(7))
+               elf_hwcap |= HWCAP_STFLE;
+
+       /* message-security assist */
+       if (test_facility(17))
+               elf_hwcap |= HWCAP_MSA;
+
+       /* long-displacement */
+       if (test_facility(19))
+               elf_hwcap |= HWCAP_LDISP;
+
+       /* extended-immediate */
+       if (test_facility(21))
+               elf_hwcap |= HWCAP_EIMM;
+
+       /* extended-translation facility 3 enhancement */
+       if (test_facility(22) && test_facility(30))
+               elf_hwcap |= HWCAP_ETF3EH;
+
+       /* decimal floating point & perform floating point operation */
+       if (test_facility(42) && test_facility(44))
+               elf_hwcap |= HWCAP_DFP;
+
+       /* huge page support */
+       if (MACHINE_HAS_EDAT1)
+               elf_hwcap |= HWCAP_HPAGE;
+
+       /* 64-bit register support for 31-bit processes */
+       elf_hwcap |= HWCAP_HIGH_GPRS;
+
+       /* transactional execution */
+       if (MACHINE_HAS_TE)
+               elf_hwcap |= HWCAP_TE;
+
+       /*
+        * Vector extension can be disabled with the "novx" parameter.
+        * Use MACHINE_HAS_VX instead of facility bit 129.
+        */
+       if (MACHINE_HAS_VX) {
+               elf_hwcap |= HWCAP_VXRS;
+               if (test_facility(134))
+                       elf_hwcap |= HWCAP_VXRS_BCD;
+               if (test_facility(135))
+                       elf_hwcap |= HWCAP_VXRS_EXT;
+               if (test_facility(148))
+                       elf_hwcap |= HWCAP_VXRS_EXT2;
+               if (test_facility(152))
+                       elf_hwcap |= HWCAP_VXRS_PDE;
+               if (test_facility(192))
+                       elf_hwcap |= HWCAP_VXRS_PDE2;
+       }
+
+       if (test_facility(150))
+               elf_hwcap |= HWCAP_SORT;
+
+       if (test_facility(151))
+               elf_hwcap |= HWCAP_DFLT;
+
+       if (test_facility(165))
+               elf_hwcap |= HWCAP_NNPA;
+
+       /* guarded storage */
+       if (MACHINE_HAS_GS)
+               elf_hwcap |= HWCAP_GS;
+
+       if (MACHINE_HAS_PCI_MIO)
+               elf_hwcap |= HWCAP_PCI_MIO;
+
+       /* virtualization support */
+       if (sclp.has_sief2)
+               elf_hwcap |= HWCAP_SIE;
+
+       return 0;
+}
+arch_initcall(setup_hwcaps);
+
+static int __init setup_elf_platform(void)
+{
+       struct cpuid cpu_id;
+
+       get_cpu_id(&cpu_id);
+       add_device_randomness(&cpu_id, sizeof(cpu_id));
+       switch (cpu_id.machine) {
+       case 0x2064:
+       case 0x2066:
+       default:        /* Use "z900" as default for 64 bit kernels. */
+               strcpy(elf_platform, "z900");
+               break;
+       case 0x2084:
+       case 0x2086:
+               strcpy(elf_platform, "z990");
+               break;
+       case 0x2094:
+       case 0x2096:
+               strcpy(elf_platform, "z9-109");
+               break;
+       case 0x2097:
+       case 0x2098:
+               strcpy(elf_platform, "z10");
+               break;
+       case 0x2817:
+       case 0x2818:
+               strcpy(elf_platform, "z196");
+               break;
+       case 0x2827:
+       case 0x2828:
+               strcpy(elf_platform, "zEC12");
+               break;
+       case 0x2964:
+       case 0x2965:
+               strcpy(elf_platform, "z13");
+               break;
+       case 0x3906:
+       case 0x3907:
+               strcpy(elf_platform, "z14");
+               break;
+       case 0x8561:
+       case 0x8562:
+               strcpy(elf_platform, "z15");
+               break;
+       }
+       return 0;
+}
+arch_initcall(setup_elf_platform);
+
 static void show_cpu_topology(struct seq_file *m, unsigned long n)
 {
 #ifdef CONFIG_SCHED_TOPOLOGY
@@ -210,7 +365,7 @@ static inline void *c_update(loff_t *pos)
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-       get_online_cpus();
+       cpus_read_lock();
        return c_update(pos);
 }
 
@@ -222,7 +377,7 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void c_stop(struct seq_file *m, void *v)
 {
-       put_online_cpus();
+       cpus_read_unlock();
 }
 
 const struct seq_operations cpuinfo_op = {