1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2395d31d4SMartin Schwidefsky /* 3395d31d4SMartin Schwidefsky * Copyright IBM Corp. 2008 4395d31d4SMartin Schwidefsky * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 5395d31d4SMartin Schwidefsky */ 6395d31d4SMartin Schwidefsky 7395d31d4SMartin Schwidefsky #define KMSG_COMPONENT "cpu" 8395d31d4SMartin Schwidefsky #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 9395d31d4SMartin Schwidefsky 104ecf0a43SHeiko Carstens #include <linux/stop_machine.h> 11ca21872eSHeiko Carstens #include <linux/cpufeature.h> 12157467baSHeiko Carstens #include <linux/bitops.h> 13395d31d4SMartin Schwidefsky #include <linux/kernel.h> 14f17a6d5dSHeiko Carstens #include <linux/random.h> 1568e21be2SIngo Molnar #include <linux/sched/mm.h> 16395d31d4SMartin Schwidefsky #include <linux/init.h> 17395d31d4SMartin Schwidefsky #include <linux/seq_file.h> 18589ee628SIngo Molnar #include <linux/mm_types.h> 19395d31d4SMartin Schwidefsky #include <linux/delay.h> 2019726cecSHeiko Carstens #include <linux/cpu.h> 2168e21be2SIngo Molnar 221ec2772eSMartin Schwidefsky #include <asm/diag.h> 23097a116cSHeiko Carstens #include <asm/facility.h> 24395d31d4SMartin Schwidefsky #include <asm/elf.h> 25395d31d4SMartin Schwidefsky #include <asm/lowcore.h> 26395d31d4SMartin Schwidefsky #include <asm/param.h> 27f17a6d5dSHeiko Carstens #include <asm/sclp.h> 284d92f502SHeiko Carstens #include <asm/smp.h> 29395d31d4SMartin Schwidefsky 30f17a6d5dSHeiko Carstens unsigned long __read_mostly elf_hwcap; 31f17a6d5dSHeiko Carstens char elf_platform[ELF_PLATFORM_SIZE]; 32f17a6d5dSHeiko Carstens 33f17a6d5dSHeiko Carstens unsigned long int_hwcap; 34f17a6d5dSHeiko Carstens 35097a116cSHeiko Carstens struct cpu_info { 36097a116cSHeiko Carstens unsigned int cpu_mhz_dynamic; 37097a116cSHeiko Carstens unsigned int cpu_mhz_static; 38097a116cSHeiko Carstens struct cpuid cpu_id; 39097a116cSHeiko Carstens }; 40097a116cSHeiko Carstens 41097a116cSHeiko Carstens static DEFINE_PER_CPU(struct cpu_info, cpu_info); 4238f2c691SMartin Schwidefsky static DEFINE_PER_CPU(int, cpu_relax_retry); 43097a116cSHeiko Carstens 44097a116cSHeiko Carstens static bool machine_has_cpu_mhz; 45097a116cSHeiko Carstens 46097a116cSHeiko Carstens void __init cpu_detect_mhz_feature(void) 47097a116cSHeiko Carstens { 48097a116cSHeiko Carstens if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL) 49970ba6acSHeiko Carstens machine_has_cpu_mhz = true; 50097a116cSHeiko Carstens } 51097a116cSHeiko Carstens 52097a116cSHeiko Carstens static void update_cpu_mhz(void *arg) 53097a116cSHeiko Carstens { 54097a116cSHeiko Carstens unsigned long mhz; 55097a116cSHeiko Carstens struct cpu_info *c; 56097a116cSHeiko Carstens 57097a116cSHeiko Carstens mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0); 58097a116cSHeiko Carstens c = this_cpu_ptr(&cpu_info); 59097a116cSHeiko Carstens c->cpu_mhz_dynamic = mhz >> 32; 60097a116cSHeiko Carstens c->cpu_mhz_static = mhz & 0xffffffff; 61097a116cSHeiko Carstens } 62097a116cSHeiko Carstens 63097a116cSHeiko Carstens void s390_update_cpu_mhz(void) 64097a116cSHeiko Carstens { 65097a116cSHeiko Carstens s390_adjust_jiffies(); 66097a116cSHeiko Carstens if (machine_has_cpu_mhz) 67097a116cSHeiko Carstens on_each_cpu(update_cpu_mhz, NULL, 0); 68097a116cSHeiko Carstens } 6994038a99SMartin Schwidefsky 704ecf0a43SHeiko Carstens void notrace stop_machine_yield(const struct cpumask *cpumask) 714d92f502SHeiko Carstens { 7238f2c691SMartin Schwidefsky int cpu, this_cpu; 7338f2c691SMartin Schwidefsky 7438f2c691SMartin Schwidefsky this_cpu = smp_processor_id(); 7538f2c691SMartin Schwidefsky if (__this_cpu_inc_return(cpu_relax_retry) >= spin_retry) { 7638f2c691SMartin Schwidefsky __this_cpu_write(cpu_relax_retry, 0); 7738f2c691SMartin Schwidefsky cpu = cpumask_next_wrap(this_cpu, cpumask, this_cpu, false); 7838f2c691SMartin Schwidefsky if (cpu >= nr_cpu_ids) 7938f2c691SMartin Schwidefsky return; 8038f2c691SMartin Schwidefsky if (arch_vcpu_is_preempted(cpu)) 8138f2c691SMartin Schwidefsky smp_yield_cpu(cpu); 821ec2772eSMartin Schwidefsky } 834d92f502SHeiko Carstens } 844d92f502SHeiko Carstens 8594038a99SMartin Schwidefsky /* 8694038a99SMartin Schwidefsky * cpu_init - initializes state that is per-CPU. 8794038a99SMartin Schwidefsky */ 88e2741f17SPaul Gortmaker void cpu_init(void) 8994038a99SMartin Schwidefsky { 90097a116cSHeiko Carstens struct cpuid *id = this_cpu_ptr(&cpu_info.cpu_id); 9194038a99SMartin Schwidefsky 9294038a99SMartin Schwidefsky get_cpu_id(id); 93097a116cSHeiko Carstens if (machine_has_cpu_mhz) 94097a116cSHeiko Carstens update_cpu_mhz(NULL); 95f1f10076SVegard Nossum mmgrab(&init_mm); 9694038a99SMartin Schwidefsky current->active_mm = &init_mm; 9794038a99SMartin Schwidefsky BUG_ON(current->mm); 9894038a99SMartin Schwidefsky enter_lazy_tlb(&init_mm, current); 9994038a99SMartin Schwidefsky } 10094038a99SMartin Schwidefsky 10194038a99SMartin Schwidefsky /* 1028f00b3e2SHendrik Brueckner * cpu_have_feature - Test CPU features on module initialization 1038f00b3e2SHendrik Brueckner */ 1048f00b3e2SHendrik Brueckner int cpu_have_feature(unsigned int num) 1058f00b3e2SHendrik Brueckner { 1068f00b3e2SHendrik Brueckner return elf_hwcap & (1UL << num); 1078f00b3e2SHendrik Brueckner } 1088f00b3e2SHendrik Brueckner EXPORT_SYMBOL(cpu_have_feature); 1098f00b3e2SHendrik Brueckner 110157467baSHeiko Carstens static void show_facilities(struct seq_file *m) 111157467baSHeiko Carstens { 112157467baSHeiko Carstens unsigned int bit; 113157467baSHeiko Carstens 114157467baSHeiko Carstens seq_puts(m, "facilities :"); 11517e89e13SSven Schnelle for_each_set_bit_inv(bit, (long *)&stfle_fac_list, MAX_FACILITY_BIT) 116157467baSHeiko Carstens seq_printf(m, " %d", bit); 117157467baSHeiko Carstens seq_putc(m, '\n'); 118157467baSHeiko Carstens } 119157467baSHeiko Carstens 120219a21b3SHeiko Carstens static void show_cpu_summary(struct seq_file *m, void *v) 121395d31d4SMartin Schwidefsky { 122fbf3c542SHeiko Carstens static const char *hwcap_str[] = { 12395655495SHeiko Carstens [HWCAP_NR_ESAN3] = "esan3", 12495655495SHeiko Carstens [HWCAP_NR_ZARCH] = "zarch", 12595655495SHeiko Carstens [HWCAP_NR_STFLE] = "stfle", 12695655495SHeiko Carstens [HWCAP_NR_MSA] = "msa", 12795655495SHeiko Carstens [HWCAP_NR_LDISP] = "ldisp", 12895655495SHeiko Carstens [HWCAP_NR_EIMM] = "eimm", 12995655495SHeiko Carstens [HWCAP_NR_DFP] = "dfp", 13095655495SHeiko Carstens [HWCAP_NR_HPAGE] = "edat", 13195655495SHeiko Carstens [HWCAP_NR_ETF3EH] = "etf3eh", 13295655495SHeiko Carstens [HWCAP_NR_HIGH_GPRS] = "highgprs", 13395655495SHeiko Carstens [HWCAP_NR_TE] = "te", 13495655495SHeiko Carstens [HWCAP_NR_VXRS] = "vx", 13595655495SHeiko Carstens [HWCAP_NR_VXRS_BCD] = "vxd", 13695655495SHeiko Carstens [HWCAP_NR_VXRS_EXT] = "vxe", 13795655495SHeiko Carstens [HWCAP_NR_GS] = "gs", 13895655495SHeiko Carstens [HWCAP_NR_VXRS_EXT2] = "vxe2", 13995655495SHeiko Carstens [HWCAP_NR_VXRS_PDE] = "vxp", 14095655495SHeiko Carstens [HWCAP_NR_SORT] = "sort", 14195655495SHeiko Carstens [HWCAP_NR_DFLT] = "dflt", 14295655495SHeiko Carstens [HWCAP_NR_VXRS_PDE2] = "vxp2", 14395655495SHeiko Carstens [HWCAP_NR_NNPA] = "nnpa", 14495655495SHeiko Carstens [HWCAP_NR_PCI_MIO] = "pcimio", 145395d31d4SMartin Schwidefsky }; 1467f16d7e7SDavid Hildenbrand static const char * const int_hwcap_str[] = { 14795655495SHeiko Carstens [HWCAP_INT_NR_SIE] = "sie", 1487f16d7e7SDavid Hildenbrand }; 149219a21b3SHeiko Carstens int i, cpu; 150395d31d4SMartin Schwidefsky 151c68d4632SHeiko Carstens BUILD_BUG_ON(ARRAY_SIZE(hwcap_str) != HWCAP_NR_MAX); 152c68d4632SHeiko Carstens BUILD_BUG_ON(ARRAY_SIZE(int_hwcap_str) != HWCAP_INT_NR_MAX); 153395d31d4SMartin Schwidefsky seq_printf(m, "vendor_id : IBM/S390\n" 154395d31d4SMartin Schwidefsky "# processors : %i\n" 155395d31d4SMartin Schwidefsky "bogomips per cpu: %lu.%02lu\n", 156395d31d4SMartin Schwidefsky num_online_cpus(), loops_per_jiffy/(500000/HZ), 157395d31d4SMartin Schwidefsky (loops_per_jiffy/(5000/HZ))%100); 15810f4954aSHeiko Carstens seq_printf(m, "max thread id : %d\n", smp_cpu_mtid); 159395d31d4SMartin Schwidefsky seq_puts(m, "features\t: "); 160fbf3c542SHeiko Carstens for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) 161395d31d4SMartin Schwidefsky if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 162395d31d4SMartin Schwidefsky seq_printf(m, "%s ", hwcap_str[i]); 1637f16d7e7SDavid Hildenbrand for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++) 1647f16d7e7SDavid Hildenbrand if (int_hwcap_str[i] && (int_hwcap & (1UL << i))) 1657f16d7e7SDavid Hildenbrand seq_printf(m, "%s ", int_hwcap_str[i]); 166395d31d4SMartin Schwidefsky seq_puts(m, "\n"); 167157467baSHeiko Carstens show_facilities(m); 1686668022cSHeiko Carstens show_cacheinfo(m); 169219a21b3SHeiko Carstens for_each_online_cpu(cpu) { 170097a116cSHeiko Carstens struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu); 171219a21b3SHeiko Carstens 172219a21b3SHeiko Carstens seq_printf(m, "processor %d: " 173395d31d4SMartin Schwidefsky "version = %02X, " 174395d31d4SMartin Schwidefsky "identification = %06X, " 175395d31d4SMartin Schwidefsky "machine = %04X\n", 176219a21b3SHeiko Carstens cpu, id->version, id->ident, id->machine); 177395d31d4SMartin Schwidefsky } 178219a21b3SHeiko Carstens } 179219a21b3SHeiko Carstens 180f17a6d5dSHeiko Carstens /* 181f17a6d5dSHeiko Carstens * Setup hardware capabilities. 182f17a6d5dSHeiko Carstens */ 183f17a6d5dSHeiko Carstens static int __init setup_hwcaps(void) 184f17a6d5dSHeiko Carstens { 185f17a6d5dSHeiko Carstens static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; 186f17a6d5dSHeiko Carstens int i; 187f17a6d5dSHeiko Carstens 188f17a6d5dSHeiko Carstens /* 189f17a6d5dSHeiko Carstens * The store facility list bits numbers as found in the principles 190f17a6d5dSHeiko Carstens * of operation are numbered with bit 1UL<<31 as number 0 to 191f17a6d5dSHeiko Carstens * bit 1UL<<0 as number 31. 192f17a6d5dSHeiko Carstens * Bit 0: instructions named N3, "backported" to esa-mode 193f17a6d5dSHeiko Carstens * Bit 2: z/Architecture mode is active 194f17a6d5dSHeiko Carstens * Bit 7: the store-facility-list-extended facility is installed 195f17a6d5dSHeiko Carstens * Bit 17: the message-security assist is installed 196f17a6d5dSHeiko Carstens * Bit 19: the long-displacement facility is installed 197f17a6d5dSHeiko Carstens * Bit 21: the extended-immediate facility is installed 198f17a6d5dSHeiko Carstens * Bit 22: extended-translation facility 3 is installed 199f17a6d5dSHeiko Carstens * Bit 30: extended-translation facility 3 enhancement facility 200f17a6d5dSHeiko Carstens * These get translated to: 201f17a6d5dSHeiko Carstens * HWCAP_ESAN3 bit 0, HWCAP_ZARCH bit 1, 202f17a6d5dSHeiko Carstens * HWCAP_STFLE bit 2, HWCAP_MSA bit 3, 203f17a6d5dSHeiko Carstens * HWCAP_LDISP bit 4, HWCAP_EIMM bit 5 and 204f17a6d5dSHeiko Carstens * HWCAP_ETF3EH bit 8 (22 && 30). 205f17a6d5dSHeiko Carstens */ 206f17a6d5dSHeiko Carstens for (i = 0; i < 6; i++) 207f17a6d5dSHeiko Carstens if (test_facility(stfl_bits[i])) 208f17a6d5dSHeiko Carstens elf_hwcap |= 1UL << i; 209f17a6d5dSHeiko Carstens 210f17a6d5dSHeiko Carstens if (test_facility(22) && test_facility(30)) 211f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_ETF3EH; 212f17a6d5dSHeiko Carstens 213f17a6d5dSHeiko Carstens /* 214f17a6d5dSHeiko Carstens * Check for additional facilities with store-facility-list-extended. 215f17a6d5dSHeiko Carstens * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 216f17a6d5dSHeiko Carstens * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information 217f17a6d5dSHeiko Carstens * as stored by stfl, bits 32-xxx contain additional facilities. 218f17a6d5dSHeiko Carstens * How many facility words are stored depends on the number of 219f17a6d5dSHeiko Carstens * doublewords passed to the instruction. The additional facilities 220f17a6d5dSHeiko Carstens * are: 221f17a6d5dSHeiko Carstens * Bit 42: decimal floating point facility is installed 222f17a6d5dSHeiko Carstens * Bit 44: perform floating point operation facility is installed 223f17a6d5dSHeiko Carstens * translated to: 224f17a6d5dSHeiko Carstens * HWCAP_DFP bit 6 (42 && 44). 225f17a6d5dSHeiko Carstens */ 226f17a6d5dSHeiko Carstens if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) 227f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_DFP; 228f17a6d5dSHeiko Carstens 229f17a6d5dSHeiko Carstens /* 230f17a6d5dSHeiko Carstens * Huge page support HWCAP_HPAGE is bit 7. 231f17a6d5dSHeiko Carstens */ 232f17a6d5dSHeiko Carstens if (MACHINE_HAS_EDAT1) 233f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_HPAGE; 234f17a6d5dSHeiko Carstens 235f17a6d5dSHeiko Carstens /* 236f17a6d5dSHeiko Carstens * 64-bit register support for 31-bit processes 237f17a6d5dSHeiko Carstens * HWCAP_HIGH_GPRS is bit 9. 238f17a6d5dSHeiko Carstens */ 239f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_HIGH_GPRS; 240f17a6d5dSHeiko Carstens 241f17a6d5dSHeiko Carstens /* 242f17a6d5dSHeiko Carstens * Transactional execution support HWCAP_TE is bit 10. 243f17a6d5dSHeiko Carstens */ 244f17a6d5dSHeiko Carstens if (MACHINE_HAS_TE) 245f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_TE; 246f17a6d5dSHeiko Carstens 247f17a6d5dSHeiko Carstens /* 248f17a6d5dSHeiko Carstens * Vector extension HWCAP_VXRS is bit 11. The Vector extension 249f17a6d5dSHeiko Carstens * can be disabled with the "novx" parameter. Use MACHINE_HAS_VX 250f17a6d5dSHeiko Carstens * instead of facility bit 129. 251f17a6d5dSHeiko Carstens */ 252f17a6d5dSHeiko Carstens if (MACHINE_HAS_VX) { 253f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS; 254f17a6d5dSHeiko Carstens if (test_facility(134)) 255f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS_BCD; 256f17a6d5dSHeiko Carstens if (test_facility(135)) 257f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS_EXT; 258f17a6d5dSHeiko Carstens if (test_facility(148)) 259f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS_EXT2; 260f17a6d5dSHeiko Carstens if (test_facility(152)) 261f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS_PDE; 262f17a6d5dSHeiko Carstens if (test_facility(192)) 263f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_VXRS_PDE2; 264f17a6d5dSHeiko Carstens } 265f17a6d5dSHeiko Carstens if (test_facility(150)) 266f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_SORT; 267f17a6d5dSHeiko Carstens if (test_facility(151)) 268f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_DFLT; 269f17a6d5dSHeiko Carstens if (test_facility(165)) 270f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_NNPA; 271f17a6d5dSHeiko Carstens 272f17a6d5dSHeiko Carstens /* 273f17a6d5dSHeiko Carstens * Guarded storage support HWCAP_GS is bit 12. 274f17a6d5dSHeiko Carstens */ 275f17a6d5dSHeiko Carstens if (MACHINE_HAS_GS) 276f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_GS; 277f17a6d5dSHeiko Carstens if (MACHINE_HAS_PCI_MIO) 278f17a6d5dSHeiko Carstens elf_hwcap |= HWCAP_PCI_MIO; 279f17a6d5dSHeiko Carstens 280*873129caSHeiko Carstens /* 281*873129caSHeiko Carstens * Virtualization support HWCAP_INT_SIE is bit 0. 282*873129caSHeiko Carstens */ 283*873129caSHeiko Carstens if (sclp.has_sief2) 284*873129caSHeiko Carstens int_hwcap |= HWCAP_INT_SIE; 285*873129caSHeiko Carstens 286*873129caSHeiko Carstens return 0; 287*873129caSHeiko Carstens } 288*873129caSHeiko Carstens arch_initcall(setup_hwcaps); 289*873129caSHeiko Carstens 290*873129caSHeiko Carstens static int __init setup_elf_platform(void) 291*873129caSHeiko Carstens { 292*873129caSHeiko Carstens struct cpuid cpu_id; 293*873129caSHeiko Carstens 294f17a6d5dSHeiko Carstens get_cpu_id(&cpu_id); 295f17a6d5dSHeiko Carstens add_device_randomness(&cpu_id, sizeof(cpu_id)); 296f17a6d5dSHeiko Carstens switch (cpu_id.machine) { 297f17a6d5dSHeiko Carstens case 0x2064: 298f17a6d5dSHeiko Carstens case 0x2066: 299f17a6d5dSHeiko Carstens default: /* Use "z900" as default for 64 bit kernels. */ 300f17a6d5dSHeiko Carstens strcpy(elf_platform, "z900"); 301f17a6d5dSHeiko Carstens break; 302f17a6d5dSHeiko Carstens case 0x2084: 303f17a6d5dSHeiko Carstens case 0x2086: 304f17a6d5dSHeiko Carstens strcpy(elf_platform, "z990"); 305f17a6d5dSHeiko Carstens break; 306f17a6d5dSHeiko Carstens case 0x2094: 307f17a6d5dSHeiko Carstens case 0x2096: 308f17a6d5dSHeiko Carstens strcpy(elf_platform, "z9-109"); 309f17a6d5dSHeiko Carstens break; 310f17a6d5dSHeiko Carstens case 0x2097: 311f17a6d5dSHeiko Carstens case 0x2098: 312f17a6d5dSHeiko Carstens strcpy(elf_platform, "z10"); 313f17a6d5dSHeiko Carstens break; 314f17a6d5dSHeiko Carstens case 0x2817: 315f17a6d5dSHeiko Carstens case 0x2818: 316f17a6d5dSHeiko Carstens strcpy(elf_platform, "z196"); 317f17a6d5dSHeiko Carstens break; 318f17a6d5dSHeiko Carstens case 0x2827: 319f17a6d5dSHeiko Carstens case 0x2828: 320f17a6d5dSHeiko Carstens strcpy(elf_platform, "zEC12"); 321f17a6d5dSHeiko Carstens break; 322f17a6d5dSHeiko Carstens case 0x2964: 323f17a6d5dSHeiko Carstens case 0x2965: 324f17a6d5dSHeiko Carstens strcpy(elf_platform, "z13"); 325f17a6d5dSHeiko Carstens break; 326f17a6d5dSHeiko Carstens case 0x3906: 327f17a6d5dSHeiko Carstens case 0x3907: 328f17a6d5dSHeiko Carstens strcpy(elf_platform, "z14"); 329f17a6d5dSHeiko Carstens break; 330f17a6d5dSHeiko Carstens case 0x8561: 331f17a6d5dSHeiko Carstens case 0x8562: 332f17a6d5dSHeiko Carstens strcpy(elf_platform, "z15"); 333f17a6d5dSHeiko Carstens break; 334f17a6d5dSHeiko Carstens } 335f17a6d5dSHeiko Carstens return 0; 336f17a6d5dSHeiko Carstens } 337*873129caSHeiko Carstens arch_initcall(setup_elf_platform); 338f17a6d5dSHeiko Carstens 339fb835102SAlexander Gordeev static void show_cpu_topology(struct seq_file *m, unsigned long n) 340fb835102SAlexander Gordeev { 341fb835102SAlexander Gordeev #ifdef CONFIG_SCHED_TOPOLOGY 342fb835102SAlexander Gordeev seq_printf(m, "physical id : %d\n", topology_physical_package_id(n)); 343fb835102SAlexander Gordeev seq_printf(m, "core id : %d\n", topology_core_id(n)); 344fb835102SAlexander Gordeev seq_printf(m, "book id : %d\n", topology_book_id(n)); 345fb835102SAlexander Gordeev seq_printf(m, "drawer id : %d\n", topology_drawer_id(n)); 346fb835102SAlexander Gordeev seq_printf(m, "dedicated : %d\n", topology_cpu_dedicated(n)); 34742d211a1SAlexander Gordeev seq_printf(m, "address : %d\n", smp_cpu_get_cpu_address(n)); 3482db52dc3SAlexander Gordeev seq_printf(m, "siblings : %d\n", cpumask_weight(topology_core_cpumask(n))); 34995968497SAlexander Gordeev seq_printf(m, "cpu cores : %d\n", topology_booted_cores(n)); 350fb835102SAlexander Gordeev #endif /* CONFIG_SCHED_TOPOLOGY */ 351fb835102SAlexander Gordeev } 352fb835102SAlexander Gordeev 353fb835102SAlexander Gordeev static void show_cpu_ids(struct seq_file *m, unsigned long n) 354fb835102SAlexander Gordeev { 355fb835102SAlexander Gordeev struct cpuid *id = &per_cpu(cpu_info.cpu_id, n); 356fb835102SAlexander Gordeev 357fb835102SAlexander Gordeev seq_printf(m, "version : %02X\n", id->version); 358fb835102SAlexander Gordeev seq_printf(m, "identification : %06X\n", id->ident); 359fb835102SAlexander Gordeev seq_printf(m, "machine : %04X\n", id->machine); 360fb835102SAlexander Gordeev } 361fb835102SAlexander Gordeev 362097a116cSHeiko Carstens static void show_cpu_mhz(struct seq_file *m, unsigned long n) 363097a116cSHeiko Carstens { 364097a116cSHeiko Carstens struct cpu_info *c = per_cpu_ptr(&cpu_info, n); 365097a116cSHeiko Carstens 3661b648dfdSAlexander Gordeev if (!machine_has_cpu_mhz) 3671b648dfdSAlexander Gordeev return; 368097a116cSHeiko Carstens seq_printf(m, "cpu MHz dynamic : %d\n", c->cpu_mhz_dynamic); 369097a116cSHeiko Carstens seq_printf(m, "cpu MHz static : %d\n", c->cpu_mhz_static); 370097a116cSHeiko Carstens } 371097a116cSHeiko Carstens 372219a21b3SHeiko Carstens /* 373219a21b3SHeiko Carstens * show_cpuinfo - Get information on one CPU for use by procfs. 374219a21b3SHeiko Carstens */ 375219a21b3SHeiko Carstens static int show_cpuinfo(struct seq_file *m, void *v) 376219a21b3SHeiko Carstens { 377219a21b3SHeiko Carstens unsigned long n = (unsigned long) v - 1; 378872f2710SAlexander Gordeev unsigned long first = cpumask_first(cpu_online_mask); 379219a21b3SHeiko Carstens 380872f2710SAlexander Gordeev if (n == first) 381219a21b3SHeiko Carstens show_cpu_summary(m, v); 382109ab954SHeiko Carstens seq_printf(m, "\ncpu number : %ld\n", n); 383fb835102SAlexander Gordeev show_cpu_topology(m, n); 384fb835102SAlexander Gordeev show_cpu_ids(m, n); 385097a116cSHeiko Carstens show_cpu_mhz(m, n); 386395d31d4SMartin Schwidefsky return 0; 387395d31d4SMartin Schwidefsky } 388395d31d4SMartin Schwidefsky 389281eaa8cSHeiko Carstens static inline void *c_update(loff_t *pos) 390281eaa8cSHeiko Carstens { 391281eaa8cSHeiko Carstens if (*pos) 392281eaa8cSHeiko Carstens *pos = cpumask_next(*pos - 1, cpu_online_mask); 393872f2710SAlexander Gordeev else 394872f2710SAlexander Gordeev *pos = cpumask_first(cpu_online_mask); 395281eaa8cSHeiko Carstens return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL; 396281eaa8cSHeiko Carstens } 397281eaa8cSHeiko Carstens 398395d31d4SMartin Schwidefsky static void *c_start(struct seq_file *m, loff_t *pos) 399395d31d4SMartin Schwidefsky { 400281eaa8cSHeiko Carstens get_online_cpus(); 401281eaa8cSHeiko Carstens return c_update(pos); 402395d31d4SMartin Schwidefsky } 403395d31d4SMartin Schwidefsky 404395d31d4SMartin Schwidefsky static void *c_next(struct seq_file *m, void *v, loff_t *pos) 405395d31d4SMartin Schwidefsky { 406395d31d4SMartin Schwidefsky ++*pos; 407281eaa8cSHeiko Carstens return c_update(pos); 408395d31d4SMartin Schwidefsky } 409395d31d4SMartin Schwidefsky 410395d31d4SMartin Schwidefsky static void c_stop(struct seq_file *m, void *v) 411395d31d4SMartin Schwidefsky { 412281eaa8cSHeiko Carstens put_online_cpus(); 413395d31d4SMartin Schwidefsky } 414395d31d4SMartin Schwidefsky 415395d31d4SMartin Schwidefsky const struct seq_operations cpuinfo_op = { 416395d31d4SMartin Schwidefsky .start = c_start, 417395d31d4SMartin Schwidefsky .next = c_next, 418395d31d4SMartin Schwidefsky .stop = c_stop, 419395d31d4SMartin Schwidefsky .show = show_cpuinfo, 420395d31d4SMartin Schwidefsky }; 4216b73044bSMartin Schwidefsky 4226b73044bSMartin Schwidefsky int s390_isolate_bp(void) 4236b73044bSMartin Schwidefsky { 4246b73044bSMartin Schwidefsky if (!test_facility(82)) 4256b73044bSMartin Schwidefsky return -EOPNOTSUPP; 4266b73044bSMartin Schwidefsky set_thread_flag(TIF_ISOLATE_BP); 4276b73044bSMartin Schwidefsky return 0; 4286b73044bSMartin Schwidefsky } 4296b73044bSMartin Schwidefsky EXPORT_SYMBOL(s390_isolate_bp); 4306b73044bSMartin Schwidefsky 4316b73044bSMartin Schwidefsky int s390_isolate_bp_guest(void) 4326b73044bSMartin Schwidefsky { 4336b73044bSMartin Schwidefsky if (!test_facility(82)) 4346b73044bSMartin Schwidefsky return -EOPNOTSUPP; 4356b73044bSMartin Schwidefsky set_thread_flag(TIF_ISOLATE_BP_GUEST); 4366b73044bSMartin Schwidefsky return 0; 4376b73044bSMartin Schwidefsky } 4386b73044bSMartin Schwidefsky EXPORT_SYMBOL(s390_isolate_bp_guest); 439