Loading arch/s390/crypto/crypt_s390.h +1 −1 Original line number Diff line number Diff line Loading @@ -297,7 +297,7 @@ static inline int crypt_s390_func_available(int func) int ret; /* check if CPACF facility (bit 17) is available */ if (!(stfl() & 1ULL << (31 - 17))) if (!test_facility(17)) return 0; switch (func & CRYPT_S390_OP_MASK) { Loading arch/s390/include/asm/lowcore.h +8 −3 Original line number Diff line number Diff line Loading @@ -150,9 +150,10 @@ struct _lowcore { */ __u32 ipib; /* 0x0e00 */ __u32 ipib_checksum; /* 0x0e04 */ __u8 pad_0x0e08[0x0f00-0x0e08]; /* 0x0e08 */ /* Align to the top 1k of prefix area */ __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ /* Extended facility list */ __u64 stfle_fac_list[32]; /* 0x0f00 */ } __packed; #else /* CONFIG_32BIT */ Loading Loading @@ -285,7 +286,11 @@ struct _lowcore { */ __u64 ipib; /* 0x0e00 */ __u32 ipib_checksum; /* 0x0e08 */ __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ /* Extended facility list */ __u64 stfle_fac_list[32]; /* 0x0f00 */ __u8 pad_0x1000[0x11b8-0x1000]; /* 0x1000 */ /* 64 bit extparam used for pfault/diag 250: defined by architecture */ __u64 ext_params2; /* 0x11B8 */ Loading arch/s390/include/asm/system.h +12 −21 Original line number Diff line number Diff line Loading @@ -420,30 +420,21 @@ extern void smp_ctl_clear_bit(int cr, int bit); #endif /* CONFIG_SMP */ static inline unsigned int stfl(void) { asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b,0b)); return S390_lowcore.stfl_fac_list; } #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ static inline int __stfle(unsigned long long *list, int doublewords) /* * The test_facility function uses the bit odering where the MSB is bit 0. * That makes it easier to query facility bits with the bit number as * documented in the Principles of Operation. */ static inline int test_facility(unsigned long nr) { typedef struct { unsigned long long _[doublewords]; } addrtype; register unsigned long __nr asm("0") = doublewords - 1; asm volatile(".insn s,0xb2b00000,%0" /* stfle */ : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); return __nr + 1; } unsigned char *ptr; static inline int stfle(unsigned long long *list, int doublewords) { if (!(stfl() & (1UL << 24))) return -EOPNOTSUPP; return __stfle(list, doublewords); if (nr >= MAX_FACILITY_BIT) return 0; ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); return (*ptr & (0x80 >> (nr & 7))) != 0; } static inline unsigned short stap(void) Loading arch/s390/kernel/early.c +29 −11 Original line number Diff line number Diff line Loading @@ -256,13 +256,35 @@ static noinline __init void setup_lowcore_early(void) s390_base_pgm_handler_fn = early_pgm_check_handler; } static noinline __init void setup_facility_list(void) { unsigned long nr; S390_lowcore.stfl_fac_list = 0; asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list)); memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); nr = 4; /* # bytes stored by stfl */ if (test_facility(7)) { /* More facility bits available with stfle */ register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1; asm volatile(".insn s,0xb2b00000,%0" /* stfle */ : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0) : : "cc"); nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ } memset((char *) S390_lowcore.stfle_fac_list + nr, 0, MAX_FACILITY_BIT/8 - nr); } static noinline __init void setup_hpage(void) { #ifndef CONFIG_DEBUG_PAGEALLOC unsigned int facilities; facilities = stfl(); if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) if (!test_facility(2) || !test_facility(8)) return; S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; __ctl_set_bit(0, 23); Loading Loading @@ -356,18 +378,13 @@ static __init void detect_diag44(void) static __init void detect_machine_facilities(void) { #ifdef CONFIG_64BIT unsigned int facilities; unsigned long long facility_bits; facilities = stfl(); if (facilities & (1 << 28)) if (test_facility(3)) S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; if (facilities & (1 << 23)) if (test_facility(8)) S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; if (facilities & (1 << 4)) if (test_facility(27)) S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; if ((stfle(&facility_bits, 1) > 0) && (facility_bits & (1ULL << (63 - 40)))) if (test_facility(40)) S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; #endif } Loading Loading @@ -448,6 +465,7 @@ void __init startup_init(void) lockdep_off(); sort_main_extable(); setup_lowcore_early(); setup_facility_list(); detect_machine_type(); ipl_update_parameters(); setup_boot_command_line(); Loading arch/s390/kernel/setup.c +7 −12 Original line number Diff line number Diff line Loading @@ -409,6 +409,9 @@ setup_lowcore(void) lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union; lc->machine_flags = S390_lowcore.machine_flags; lc->stfl_fac_list = S390_lowcore.stfl_fac_list; memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, MAX_FACILITY_BIT/8); #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lc->extended_save_area_addr = (__u32) Loading Loading @@ -675,12 +678,9 @@ setup_memory(void) static void __init setup_hwcaps(void) { static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; unsigned long long facility_list_extended; unsigned int facility_list; struct cpuid cpu_id; int i; facility_list = stfl(); /* * The store facility list bits numbers as found in the principles * of operation are numbered with bit 1UL<<31 as number 0 to Loading @@ -700,11 +700,10 @@ static void __init setup_hwcaps(void) * HWCAP_S390_ETF3EH bit 8 (22 && 30). */ for (i = 0; i < 6; i++) if (facility_list & (1UL << (31 - stfl_bits[i]))) if (test_facility(stfl_bits[i])) elf_hwcap |= 1UL << i; if ((facility_list & (1UL << (31 - 22))) && (facility_list & (1UL << (31 - 30)))) if (test_facility(22) && test_facility(30)) elf_hwcap |= HWCAP_S390_ETF3EH; /* Loading @@ -720,12 +719,8 @@ static void __init setup_hwcaps(void) * translated to: * HWCAP_S390_DFP bit 6 (42 && 44). */ if ((elf_hwcap & (1UL << 2)) && __stfle(&facility_list_extended, 1) > 0) { if ((facility_list_extended & (1ULL << (63 - 42))) && (facility_list_extended & (1ULL << (63 - 44)))) if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) elf_hwcap |= HWCAP_S390_DFP; } /* * Huge page support HWCAP_S390_HPAGE is bit 7. Loading Loading
arch/s390/crypto/crypt_s390.h +1 −1 Original line number Diff line number Diff line Loading @@ -297,7 +297,7 @@ static inline int crypt_s390_func_available(int func) int ret; /* check if CPACF facility (bit 17) is available */ if (!(stfl() & 1ULL << (31 - 17))) if (!test_facility(17)) return 0; switch (func & CRYPT_S390_OP_MASK) { Loading
arch/s390/include/asm/lowcore.h +8 −3 Original line number Diff line number Diff line Loading @@ -150,9 +150,10 @@ struct _lowcore { */ __u32 ipib; /* 0x0e00 */ __u32 ipib_checksum; /* 0x0e04 */ __u8 pad_0x0e08[0x0f00-0x0e08]; /* 0x0e08 */ /* Align to the top 1k of prefix area */ __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ /* Extended facility list */ __u64 stfle_fac_list[32]; /* 0x0f00 */ } __packed; #else /* CONFIG_32BIT */ Loading Loading @@ -285,7 +286,11 @@ struct _lowcore { */ __u64 ipib; /* 0x0e00 */ __u32 ipib_checksum; /* 0x0e08 */ __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ /* Extended facility list */ __u64 stfle_fac_list[32]; /* 0x0f00 */ __u8 pad_0x1000[0x11b8-0x1000]; /* 0x1000 */ /* 64 bit extparam used for pfault/diag 250: defined by architecture */ __u64 ext_params2; /* 0x11B8 */ Loading
arch/s390/include/asm/system.h +12 −21 Original line number Diff line number Diff line Loading @@ -420,30 +420,21 @@ extern void smp_ctl_clear_bit(int cr, int bit); #endif /* CONFIG_SMP */ static inline unsigned int stfl(void) { asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b,0b)); return S390_lowcore.stfl_fac_list; } #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ static inline int __stfle(unsigned long long *list, int doublewords) /* * The test_facility function uses the bit odering where the MSB is bit 0. * That makes it easier to query facility bits with the bit number as * documented in the Principles of Operation. */ static inline int test_facility(unsigned long nr) { typedef struct { unsigned long long _[doublewords]; } addrtype; register unsigned long __nr asm("0") = doublewords - 1; asm volatile(".insn s,0xb2b00000,%0" /* stfle */ : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); return __nr + 1; } unsigned char *ptr; static inline int stfle(unsigned long long *list, int doublewords) { if (!(stfl() & (1UL << 24))) return -EOPNOTSUPP; return __stfle(list, doublewords); if (nr >= MAX_FACILITY_BIT) return 0; ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); return (*ptr & (0x80 >> (nr & 7))) != 0; } static inline unsigned short stap(void) Loading
arch/s390/kernel/early.c +29 −11 Original line number Diff line number Diff line Loading @@ -256,13 +256,35 @@ static noinline __init void setup_lowcore_early(void) s390_base_pgm_handler_fn = early_pgm_check_handler; } static noinline __init void setup_facility_list(void) { unsigned long nr; S390_lowcore.stfl_fac_list = 0; asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list)); memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); nr = 4; /* # bytes stored by stfl */ if (test_facility(7)) { /* More facility bits available with stfle */ register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1; asm volatile(".insn s,0xb2b00000,%0" /* stfle */ : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0) : : "cc"); nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ } memset((char *) S390_lowcore.stfle_fac_list + nr, 0, MAX_FACILITY_BIT/8 - nr); } static noinline __init void setup_hpage(void) { #ifndef CONFIG_DEBUG_PAGEALLOC unsigned int facilities; facilities = stfl(); if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) if (!test_facility(2) || !test_facility(8)) return; S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; __ctl_set_bit(0, 23); Loading Loading @@ -356,18 +378,13 @@ static __init void detect_diag44(void) static __init void detect_machine_facilities(void) { #ifdef CONFIG_64BIT unsigned int facilities; unsigned long long facility_bits; facilities = stfl(); if (facilities & (1 << 28)) if (test_facility(3)) S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; if (facilities & (1 << 23)) if (test_facility(8)) S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; if (facilities & (1 << 4)) if (test_facility(27)) S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; if ((stfle(&facility_bits, 1) > 0) && (facility_bits & (1ULL << (63 - 40)))) if (test_facility(40)) S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; #endif } Loading Loading @@ -448,6 +465,7 @@ void __init startup_init(void) lockdep_off(); sort_main_extable(); setup_lowcore_early(); setup_facility_list(); detect_machine_type(); ipl_update_parameters(); setup_boot_command_line(); Loading
arch/s390/kernel/setup.c +7 −12 Original line number Diff line number Diff line Loading @@ -409,6 +409,9 @@ setup_lowcore(void) lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union; lc->machine_flags = S390_lowcore.machine_flags; lc->stfl_fac_list = S390_lowcore.stfl_fac_list; memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, MAX_FACILITY_BIT/8); #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) { lc->extended_save_area_addr = (__u32) Loading Loading @@ -675,12 +678,9 @@ setup_memory(void) static void __init setup_hwcaps(void) { static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; unsigned long long facility_list_extended; unsigned int facility_list; struct cpuid cpu_id; int i; facility_list = stfl(); /* * The store facility list bits numbers as found in the principles * of operation are numbered with bit 1UL<<31 as number 0 to Loading @@ -700,11 +700,10 @@ static void __init setup_hwcaps(void) * HWCAP_S390_ETF3EH bit 8 (22 && 30). */ for (i = 0; i < 6; i++) if (facility_list & (1UL << (31 - stfl_bits[i]))) if (test_facility(stfl_bits[i])) elf_hwcap |= 1UL << i; if ((facility_list & (1UL << (31 - 22))) && (facility_list & (1UL << (31 - 30)))) if (test_facility(22) && test_facility(30)) elf_hwcap |= HWCAP_S390_ETF3EH; /* Loading @@ -720,12 +719,8 @@ static void __init setup_hwcaps(void) * translated to: * HWCAP_S390_DFP bit 6 (42 && 44). */ if ((elf_hwcap & (1UL << 2)) && __stfle(&facility_list_extended, 1) > 0) { if ((facility_list_extended & (1ULL << (63 - 42))) && (facility_list_extended & (1ULL << (63 - 44)))) if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) elf_hwcap |= HWCAP_S390_DFP; } /* * Huge page support HWCAP_S390_HPAGE is bit 7. Loading