From f17a6d5d83bc05908e5c3fc1c24787aa354653df Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 21 Jul 2021 13:23:07 +0200 Subject: s390/hwcaps: move setup_hwcaps() Move setup_hwcaps() to processor.c for two reasons: - make setup.c a bit smaller - have allmost all of the hwcap code in one file Signed-off-by: Heiko Carstens --- arch/s390/kernel/processor.c | 160 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) (limited to 'arch/s390/kernel/processor.c') diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index e0efe946d8f0..b5569a67ee1d 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -23,8 +24,14 @@ #include #include #include +#include #include +unsigned long __read_mostly elf_hwcap; +char elf_platform[ELF_PLATFORM_SIZE]; + +unsigned long int_hwcap; + struct cpu_info { unsigned int cpu_mhz_dynamic; unsigned int cpu_mhz_static; @@ -170,6 +177,159 @@ static void show_cpu_summary(struct seq_file *m, void *v) } } +/* + * Setup hardware capabilities. + */ +static int __init setup_hwcaps(void) +{ + static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; + struct cpuid cpu_id; + int i; + + /* + * The store facility list bits numbers as found in the principles + * of operation are numbered with bit 1UL<<31 as number 0 to + * bit 1UL<<0 as number 31. + * Bit 0: instructions named N3, "backported" to esa-mode + * Bit 2: z/Architecture mode is active + * Bit 7: the store-facility-list-extended facility is installed + * Bit 17: the message-security assist is installed + * Bit 19: the long-displacement facility is installed + * Bit 21: the extended-immediate facility is installed + * Bit 22: extended-translation facility 3 is installed + * Bit 30: extended-translation facility 3 enhancement facility + * These get translated to: + * HWCAP_ESAN3 bit 0, HWCAP_ZARCH bit 1, + * HWCAP_STFLE bit 2, HWCAP_MSA bit 3, + * HWCAP_LDISP bit 4, HWCAP_EIMM bit 5 and + * HWCAP_ETF3EH bit 8 (22 && 30). + */ + for (i = 0; i < 6; i++) + if (test_facility(stfl_bits[i])) + elf_hwcap |= 1UL << i; + + if (test_facility(22) && test_facility(30)) + elf_hwcap |= HWCAP_ETF3EH; + + /* + * Check for additional facilities with store-facility-list-extended. + * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 + * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information + * as stored by stfl, bits 32-xxx contain additional facilities. + * How many facility words are stored depends on the number of + * doublewords passed to the instruction. The additional facilities + * are: + * Bit 42: decimal floating point facility is installed + * Bit 44: perform floating point operation facility is installed + * translated to: + * HWCAP_DFP bit 6 (42 && 44). + */ + if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) + elf_hwcap |= HWCAP_DFP; + + /* + * Huge page support HWCAP_HPAGE is bit 7. + */ + if (MACHINE_HAS_EDAT1) + elf_hwcap |= HWCAP_HPAGE; + + /* + * 64-bit register support for 31-bit processes + * HWCAP_HIGH_GPRS is bit 9. + */ + elf_hwcap |= HWCAP_HIGH_GPRS; + + /* + * Transactional execution support HWCAP_TE is bit 10. + */ + if (MACHINE_HAS_TE) + elf_hwcap |= HWCAP_TE; + + /* + * Vector extension HWCAP_VXRS is bit 11. The 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 support HWCAP_GS is bit 12. + */ + if (MACHINE_HAS_GS) + elf_hwcap |= HWCAP_GS; + if (MACHINE_HAS_PCI_MIO) + elf_hwcap |= HWCAP_PCI_MIO; + + 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; + } + + /* + * Virtualization support HWCAP_INT_SIE is bit 0. + */ + if (sclp.has_sief2) + int_hwcap |= HWCAP_INT_SIE; + + return 0; +} +arch_initcall(setup_hwcaps); + static void show_cpu_topology(struct seq_file *m, unsigned long n) { #ifdef CONFIG_SCHED_TOPOLOGY -- cgit v1.2.3-59-g8ed1b