diff options
Diffstat (limited to 'arch/s390')
76 files changed, 1159 insertions, 754 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index c59d2b54df49..371c2bf88149 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -21,7 +21,7 @@ config ARCH_PROC_KCORE_TEXT def_bool y config GENERIC_HWEIGHT - def_bool y + def_bool !HAVE_MARCH_Z196_FEATURES config GENERIC_BUG def_bool y if BUG @@ -142,6 +142,7 @@ config S390 select FUNCTION_ALIGNMENT_8B if CC_IS_GCC select FUNCTION_ALIGNMENT_16B if !CC_IS_GCC select GENERIC_ALLOCATOR + select GENERIC_CPU_DEVICES select GENERIC_CPU_AUTOPROBE select GENERIC_CPU_VULNERABILITIES select GENERIC_ENTRY diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index b24de9aabf7d..a21f301acd29 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -51,11 +51,11 @@ static inline int __diag308(unsigned long subcode, void *addr) : [r1] "+&d" (r1.pair), [reg1] "=&d" (reg1), [reg2] "=&a" (reg2), - "+Q" (S390_lowcore.program_new_psw), + "+Q" (get_lowcore()->program_new_psw), "=Q" (old) : [subcode] "d" (subcode), [psw_old] "a" (&old), - [psw_pgm] "a" (&S390_lowcore.program_new_psw) + [psw_pgm] "a" (&get_lowcore()->program_new_psw) : "cc", "memory"); return r1.odd; } diff --git a/arch/s390/boot/ipl_report.c b/arch/s390/boot/ipl_report.c index 1803035e68d2..d00898852a88 100644 --- a/arch/s390/boot/ipl_report.c +++ b/arch/s390/boot/ipl_report.c @@ -106,7 +106,7 @@ int read_ipl_report(void) * the IPL parameter list, then align the address to a double * word boundary. */ - tmp = (unsigned long) S390_lowcore.ipl_parmblock_ptr; + tmp = (unsigned long)get_lowcore()->ipl_parmblock_ptr; pl_hdr = (struct ipl_pl_hdr *) tmp; tmp = (tmp + pl_hdr->len + 7) & -8UL; rl_hdr = (struct ipl_rl_hdr *) tmp; diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c index ea96275b0380..5352b3d356da 100644 --- a/arch/s390/boot/pgm_check_info.c +++ b/arch/s390/boot/pgm_check_info.c @@ -145,22 +145,22 @@ void print_stacktrace(unsigned long sp) void print_pgm_check_info(void) { - unsigned long *gpregs = (unsigned long *)S390_lowcore.gpregs_save_area; - struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area); + unsigned long *gpregs = (unsigned long *)get_lowcore()->gpregs_save_area; + struct psw_bits *psw = &psw_bits(get_lowcore()->psw_save_area); decompressor_printk("Linux version %s\n", kernel_version); if (!is_prot_virt_guest() && early_command_line[0]) decompressor_printk("Kernel command line: %s\n", early_command_line); decompressor_printk("Kernel fault: interruption code %04x ilc:%x\n", - S390_lowcore.pgm_code, S390_lowcore.pgm_ilc >> 1); + get_lowcore()->pgm_code, get_lowcore()->pgm_ilc >> 1); if (kaslr_enabled()) { decompressor_printk("Kernel random base: %lx\n", __kaslr_offset); decompressor_printk("Kernel random base phys: %lx\n", __kaslr_offset_phys); } decompressor_printk("PSW : %016lx %016lx (%pS)\n", - S390_lowcore.psw_save_area.mask, - S390_lowcore.psw_save_area.addr, - (void *)S390_lowcore.psw_save_area.addr); + get_lowcore()->psw_save_area.mask, + get_lowcore()->psw_save_area.addr, + (void *)get_lowcore()->psw_save_area.addr); decompressor_printk( " R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n", psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck, @@ -174,8 +174,8 @@ void print_pgm_check_info(void) gpregs[8], gpregs[9], gpregs[10], gpregs[11]); decompressor_printk(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]); - print_stacktrace(S390_lowcore.gpregs_save_area[15]); + print_stacktrace(get_lowcore()->gpregs_save_area[15]); decompressor_printk("Last Breaking-Event-Address:\n"); - decompressor_printk(" [<%016lx>] %pS\n", (unsigned long)S390_lowcore.pgm_last_break, - (void *)S390_lowcore.pgm_last_break); + decompressor_printk(" [<%016lx>] %pS\n", (unsigned long)get_lowcore()->pgm_last_break, + (void *)get_lowcore()->pgm_last_break); } diff --git a/arch/s390/boot/physmem_info.c b/arch/s390/boot/physmem_info.c index 0cf79826eef9..4c9ad8258f7e 100644 --- a/arch/s390/boot/physmem_info.c +++ b/arch/s390/boot/physmem_info.c @@ -81,11 +81,11 @@ static int __diag260(unsigned long rx1, unsigned long rx2) [reg2] "=&a" (reg2), [rc] "+&d" (rc), [ry] "+&d" (ry), - "+Q" (S390_lowcore.program_new_psw), + "+Q" (get_lowcore()->program_new_psw), "=Q" (old) : [rx] "d" (rx.pair), [psw_old] "a" (&old), - [psw_pgm] "a" (&S390_lowcore.program_new_psw) + [psw_pgm] "a" (&get_lowcore()->program_new_psw) : "cc", "memory"); return rc == 0 ? ry : -1; } @@ -129,10 +129,10 @@ static int tprot(unsigned long addr) : [reg1] "=&d" (reg1), [reg2] "=&a" (reg2), [rc] "+&d" (rc), - "=Q" (S390_lowcore.program_new_psw.addr), + "=Q" (get_lowcore()->program_new_psw.addr), "=Q" (old) : [psw_old] "a" (&old), - [psw_pgm] "a" (&S390_lowcore.program_new_psw), + [psw_pgm] "a" (&get_lowcore()->program_new_psw), [addr] "a" (addr) : "cc", "memory"); return rc; diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 5a36d5538dae..320c964cd603 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -78,10 +78,10 @@ static int cmma_test_essa(void) [reg2] "=&a" (reg2), [rc] "+&d" (rc), [tmp] "=&d" (tmp), - "+Q" (S390_lowcore.program_new_psw), + "+Q" (get_lowcore()->program_new_psw), "=Q" (old) : [psw_old] "a" (&old), - [psw_pgm] "a" (&S390_lowcore.program_new_psw), + [psw_pgm] "a" (&get_lowcore()->program_new_psw), [cmd] "i" (ESSA_GET_STATE) : "cc", "memory"); return rc; @@ -101,10 +101,10 @@ static void cmma_init(void) static void setup_lpp(void) { - S390_lowcore.current_pid = 0; - S390_lowcore.lpp = LPP_MAGIC; + get_lowcore()->current_pid = 0; + get_lowcore()->lpp = LPP_MAGIC; if (test_facility(40)) - lpp(&S390_lowcore.lpp); + lpp(&get_lowcore()->lpp); } #ifdef CONFIG_KERNEL_UNCOMPRESSED @@ -501,7 +501,7 @@ void startup_kernel(void) * Save KASLR offset for early dumps, before vmcore_info is set. * Mark as uneven to distinguish from real vmcore_info pointer. */ - S390_lowcore.vmcore_info = __kaslr_offset_phys ? __kaslr_offset_phys | 0x1UL : 0; + get_lowcore()->vmcore_info = __kaslr_offset_phys ? __kaslr_offset_phys | 0x1UL : 0; /* * Jump to the decompressed kernel entry point and switch DAT mode on. diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index 40cfce2687c4..a255ca189aaa 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -476,13 +476,13 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l kasan_populate_shadow(kernel_start, kernel_end); - S390_lowcore.kernel_asce.val = swapper_pg_dir | asce_bits; - S390_lowcore.user_asce = s390_invalid_asce; + get_lowcore()->kernel_asce.val = swapper_pg_dir | asce_bits; + get_lowcore()->user_asce = s390_invalid_asce; - local_ctl_load(1, &S390_lowcore.kernel_asce); - local_ctl_load(7, &S390_lowcore.user_asce); - local_ctl_load(13, &S390_lowcore.kernel_asce); + local_ctl_load(1, &get_lowcore()->kernel_asce); + local_ctl_load(7, &get_lowcore()->user_asce); + local_ctl_load(13, &get_lowcore()->kernel_asce); - init_mm.context.asce = S390_lowcore.kernel_asce.val; + init_mm.context.asce = get_lowcore()->kernel_asce.val; init_mm.pgd = init_mm_pgd; } diff --git a/arch/s390/crypto/crc32-vx.c b/arch/s390/crypto/crc32-vx.c index 74f17c905d12..89a10337e6ea 100644 --- a/arch/s390/crypto/crc32-vx.c +++ b/arch/s390/crypto/crc32-vx.c @@ -297,6 +297,7 @@ module_cpu_feature_match(S390_CPU_FEATURE_VXRS, crc_vx_mod_init); module_exit(crc_vx_mod_exit); MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>"); +MODULE_DESCRIPTION("CRC-32 algorithms using z/Architecture Vector Extension Facility"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CRYPTO("crc32"); diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index 4024599eb448..0e855c5e91c5 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c @@ -39,7 +39,9 @@ static ssize_t dbfs_read(struct file *file, char __user *buf, return 0; df = file_inode(file)->i_private; - mutex_lock(&df->lock); + if (mutex_lock_interruptible(&df->lock)) + return -ERESTARTSYS; + data = hypfs_dbfs_data_alloc(df); if (!data) { mutex_unlock(&df->lock); diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 279b7bba4d43..26a009f9c49e 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -140,11 +140,22 @@ fail_alloc: int diag204_store(void *buf, int pages) { + unsigned long subcode; int rc; - rc = diag204((unsigned long)diag204_store_sc | - (unsigned long)diag204_get_info_type(), pages, buf); - return rc < 0 ? -EOPNOTSUPP : 0; + subcode = diag204_get_info_type(); + subcode |= diag204_store_sc; + if (diag204_has_bif()) + subcode |= DIAG204_BIF_BIT; + while (1) { + rc = diag204(subcode, pages, buf); + if (rc != -EBUSY) + break; + if (signal_pending(current)) + return -ERESTARTSYS; + schedule_timeout_interruptible(DIAG204_BUSY_WAIT); + } + return rc < 0 ? rc : 0; } struct dbfs_d204_hdr { diff --git a/arch/s390/include/asm/arch_hweight.h b/arch/s390/include/asm/arch_hweight.h new file mode 100644 index 000000000000..50e23ce854e5 --- /dev/null +++ b/arch/s390/include/asm/arch_hweight.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_S390_ARCH_HWEIGHT_H +#define _ASM_S390_ARCH_HWEIGHT_H + +#include <linux/types.h> + +static __always_inline unsigned long popcnt_z196(unsigned long w) +{ + unsigned long cnt; + + asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],0,0" + : [cnt] "=d" (cnt) + : [w] "d" (w) + : "cc"); + return cnt; +} + +static __always_inline unsigned long popcnt_z15(unsigned long w) +{ + unsigned long cnt; + + asm volatile(".insn rrf,0xb9e10000,%[cnt],%[w],8,0" + : [cnt] "=d" (cnt) + : [w] "d" (w) + : "cc"); + return cnt; +} + +static __always_inline unsigned long __arch_hweight64(__u64 w) +{ + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + return popcnt_z15(w); + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + w = popcnt_z196(w); + w += w >> 32; + w += w >> 16; + w += w >> 8; + return w & 0xff; + } + return __sw_hweight64(w); +} + +static __always_inline unsigned int __arch_hweight32(unsigned int w) +{ + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + return popcnt_z15(w); + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + w = popcnt_z196(w); + w += w >> 16; + w += w >> 8; + return w & 0xff; + } + return __sw_hweight32(w); +} + +static __always_inline unsigned int __arch_hweight16(unsigned int w) +{ + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z15_FEATURES)) + return popcnt_z15((unsigned short)w); + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) { + w = popcnt_z196(w); + w += w >> 8; + return w & 0xff; + } + return __sw_hweight16(w); +} + +static __always_inline unsigned int __arch_hweight8(unsigned int w) +{ + if (IS_ENABLED(CONFIG_HAVE_MARCH_Z196_FEATURES)) + return popcnt_z196((unsigned char)w); + return __sw_hweight8(w); +} + +#endif /* _ASM_S390_ARCH_HWEIGHT_H */ diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index 7fa5f96a553a..2b379d1d9046 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -8,21 +8,29 @@ #ifndef __ARCH_S390_ATOMIC_OPS__ #define __ARCH_S390_ATOMIC_OPS__ +#include <linux/limits.h> + static __always_inline int __atomic_read(const atomic_t *v) { int c; asm volatile( - " l %0,%1\n" - : "=d" (c) : "R" (v->counter)); + " l %[c],%[counter]\n" + : [c] "=d" (c) : [counter] "R" (v->counter)); return c; } static __always_inline void __atomic_set(atomic_t *v, int i) { - asm volatile( - " st %1,%0\n" - : "=R" (v->counter) : "d" (i)); + if (__builtin_constant_p(i) && i >= S16_MIN && i <= S16_MAX) { + asm volatile( + " mvhi %[counter], %[i]\n" + : [counter] "=Q" (v->counter) : [i] "K" (i)); + } else { + asm volatile( + " st %[i],%[counter]\n" + : [counter] "=R" (v->counter) : [i] "d" (i)); + } } static __always_inline s64 __atomic64_read(const atomic64_t *v) @@ -30,16 +38,22 @@ static __always_inline s64 __atomic64_read(const atomic64_t *v) s64 c; asm volatile( - " lg %0,%1\n" - : "=d" (c) : "RT" (v->counter)); + " lg %[c],%[counter]\n" + : [c] "=d" (c) : [counter] "RT" (v->counter)); return c; } static __always_inline void __atomic64_set(atomic64_t *v, s64 i) { - asm volatile( - " stg %1,%0\n" - : "=RT" (v->counter) : "d" (i)); + if (__builtin_constant_p(i) && i >= S16_MIN && i <= S16_MAX) { + asm volatile( + " mvghi %[counter], %[i]\n" + : [counter] "=Q" (v->counter) : [i] "K" (i)); + } else { + asm volatile( + " stg %[i],%[counter]\n" + : [counter] "=RT" (v->counter) : [i] "d" (i)); + } } #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES @@ -164,26 +178,54 @@ static __always_inline int __atomic_cmpxchg(int *ptr, int old, int new) return old; } +static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) +{ + asm volatile( + " csg %[old],%[new],%[ptr]" + : [old] "+d" (old), [ptr] "+QS" (*ptr) + : [new] "d" (new) + : "cc", "memory"); + return old; +} + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) { - int old_expected = old; + int cc; asm volatile( " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) + : [old] "+d" (old), [ptr] "+Q" (*ptr), "=@cc" (cc) : [new] "d" (new) - : "cc", "memory"); - return old == old_expected; + : "memory"); + return cc == 0; } -static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) +static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) { + int cc; + asm volatile( " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+QS" (*ptr) + : [old] "+d" (old), [ptr] "+QS" (*ptr), "=@cc" (cc) + : [new] "d" (new) + : "memory"); + return cc == 0; +} + +#else /* __GCC_ASM_FLAG_OUTPUTS__ */ + +static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) +{ + int old_expected = old; + + asm volatile( + " cs %[old],%[new],%[ptr]" + : [old] "+d" (old), [ptr] "+Q" (*ptr) : [new] "d" (new) : "cc", "memory"); - return old; + return old == old_expected; } static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) @@ -198,4 +240,6 @@ static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long ne return old == old_expected; } +#endif /* __GCC_ASM_FLAG_OUTPUTS__ */ + #endif /* __ARCH_S390_ATOMIC_OPS__ */ diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index c467dffa8c12..54a079cd39ed 100644 --- a/arch/s390/include/asm/bitops.h +++ b/ |
