diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-06-03 22:57:50 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-06-03 22:57:50 +0200 |
commit | 4ab6cfc4ad9f867a107b0ef029088dd4c0a8f83c (patch) | |
tree | 3f30f7307c893160c3a00662f63c1a92285838bf /arch/s390/include/asm/uaccess.h | |
parent | Merge tag 'efi-next-for-v5.19-2' of git://git.kernel.org/pub/scm/linux/kernel... (diff) | |
parent | s390/stack: add union to reflect kvm stack slot usages (diff) | |
download | linux-4ab6cfc4ad9f867a107b0ef029088dd4c0a8f83c.tar.xz linux-4ab6cfc4ad9f867a107b0ef029088dd4c0a8f83c.zip |
Merge tag 's390-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull more s390 updates from Heiko Carstens:
"Just a couple of small improvements, bug fixes and cleanups:
- Add Eric Farman as maintainer for s390 virtio drivers.
- Improve machine check handling, and avoid incorrectly injecting a
machine check into a kvm guest.
- Add cond_resched() call to gmap page table walker in order to avoid
possible huge latencies. Also use non-quiesing sske instruction to
speed up storage key handling.
- Add __GFP_NORETRY to KEXEC_CONTROL_MEMORY_GFP so s390 behaves
similar like common code.
- Get sie control block address from correct stack slot in perf event
code. This fixes potential random memory accesses.
- Change uaccess code so that the exception handler sets the result
of get_user() and __get_kernel_nofault() to zero in case of a
fault. Until now this was done via input parameters for inline
assemblies. Doing it via fault handling is what most or even all
other architectures are doing.
- Couple of other small cleanups and fixes"
* tag 's390-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/stack: add union to reflect kvm stack slot usages
s390/stack: merge empty stack frame slots
s390/uaccess: whitespace cleanup
s390/uaccess: use __noreturn instead of __attribute__((noreturn))
s390/uaccess: use exception handler to zero result on get_user() failure
s390/uaccess: use symbolic names for inline assembler operands
s390/mcck: isolate SIE instruction when setting CIF_MCCK_GUEST flag
s390/mm: use non-quiescing sske for KVM switch to keyed guest
s390/gmap: voluntarily schedule during key setting
MAINTAINERS: Update s390 virtio-ccw
s390/kexec: add __GFP_NORETRY to KEXEC_CONTROL_MEMORY_GFP
s390/Kconfig.debug: fix indentation
s390/Kconfig: fix indentation
s390/perf: obtain sie_block from the right address
s390: generate register offsets into pt_regs automatically
s390: simplify early program check handler
s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
Diffstat (limited to 'arch/s390/include/asm/uaccess.h')
-rw-r--r-- | arch/s390/include/asm/uaccess.h | 217 |
1 files changed, 118 insertions, 99 deletions
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 1f150a7cfb3d..f4511e21d646 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -3,7 +3,7 @@ * S390 version * Copyright IBM Corp. 1999, 2000 * Author(s): Hartmut Penner (hp@de.ibm.com), - * Martin Schwidefsky (schwidefsky@de.ibm.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Derived from "include/asm-i386/uaccess.h" */ @@ -55,9 +55,6 @@ copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned lo return n; } -int __put_user_bad(void) __attribute__((noreturn)); -int __get_user_bad(void) __attribute__((noreturn)); - union oac { unsigned int val; struct { @@ -80,8 +77,14 @@ union oac { }; }; -#define __put_get_user_asm(to, from, size, oac_spec) \ +int __noreturn __put_user_bad(void); + +#define __put_user_asm(to, from, size) \ ({ \ + union oac __oac_spec = { \ + .oac1.as = PSW_BITS_AS_SECONDARY, \ + .oac1.a = 1, \ + }; \ int __rc; \ \ asm volatile( \ @@ -89,26 +92,15 @@ union oac { "0: mvcos %[_to],%[_from],%[_size]\n" \ "1: xr %[rc],%[rc]\n" \ "2:\n" \ - EX_TABLE_UA(0b,2b,%[rc]) EX_TABLE_UA(1b,2b,%[rc]) \ + EX_TABLE_UA_STORE(0b, 2b, %[rc]) \ + EX_TABLE_UA_STORE(1b, 2b, %[rc]) \ : [rc] "=&d" (__rc), [_to] "+Q" (*(to)) \ : [_size] "d" (size), [_from] "Q" (*(from)), \ - [spec] "d" (oac_spec.val) \ + [spec] "d" (__oac_spec.val) \ : "cc", "0"); \ __rc; \ }) -#define __put_user_asm(to, from, size) \ - __put_get_user_asm(to, from, size, ((union oac) { \ - .oac1.as = PSW_BITS_AS_SECONDARY, \ - .oac1.a = 1 \ - })) - -#define __get_user_asm(to, from, size) \ - __put_get_user_asm(to, from, size, ((union oac) { \ - .oac2.as = PSW_BITS_AS_SECONDARY, \ - .oac2.a = 1 \ - })) \ - static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) { int rc; @@ -141,6 +133,31 @@ static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned lon return rc; } +int __noreturn __get_user_bad(void); + +#define __get_user_asm(to, from, size) \ +({ \ + union oac __oac_spec = { \ + .oac2.as = PSW_BITS_AS_SECONDARY, \ + .oac2.a = 1, \ + }; \ + int __rc; \ + \ + asm volatile( \ + " lr 0,%[spec]\n" \ + "0: mvcos 0(%[_to]),%[_from],%[_size]\n" \ + "1: xr %[rc],%[rc]\n" \ + "2:\n" \ + EX_TABLE_UA_LOAD_MEM(0b, 2b, %[rc], %[_to], %[_ksize]) \ + EX_TABLE_UA_LOAD_MEM(1b, 2b, %[rc], %[_to], %[_ksize]) \ + : [rc] "=&d" (__rc), "=Q" (*(to)) \ + : [_size] "d" (size), [_from] "Q" (*(from)), \ + [spec] "d" (__oac_spec.val), [_to] "a" (to), \ + [_ksize] "K" (size) \ + : "cc", "0"); \ + __rc; \ +}) + static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) { int rc; @@ -177,77 +194,77 @@ static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsign * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. */ -#define __put_user(x, ptr) \ -({ \ - __typeof__(*(ptr)) __x = (x); \ - int __pu_err = -EFAULT; \ - __chk_user_ptr(ptr); \ - switch (sizeof (*(ptr))) { \ - case 1: \ - case 2: \ - case 4: \ - case 8: \ - __pu_err = __put_user_fn(&__x, ptr, \ - sizeof(*(ptr))); \ - break; \ - default: \ - __put_user_bad(); \ - break; \ - } \ - __builtin_expect(__pu_err, 0); \ +#define __put_user(x, ptr) \ +({ \ + __typeof__(*(ptr)) __x = (x); \ + int __pu_err = -EFAULT; \ + \ + __chk_user_ptr(ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: \ + case 2: \ + case 4: \ + case 8: \ + __pu_err = __put_user_fn(&__x, ptr, sizeof(*(ptr))); \ + break; \ + default: \ + __put_user_bad(); \ + break; \ + } \ + __builtin_expect(__pu_err, 0); \ }) -#define put_user(x, ptr) \ -({ \ - might_fault(); \ - __put_user(x, ptr); \ +#define put_user(x, ptr) \ +({ \ + might_fault(); \ + __put_user(x, ptr); \ }) - -#define __get_user(x, ptr) \ -({ \ - int __gu_err = -EFAULT; \ - __chk_user_ptr(ptr); \ - switch (sizeof(*(ptr))) { \ - case 1: { \ - unsigned char __x = 0; \ - __gu_err = __get_user_fn(&__x, ptr, \ - sizeof(*(ptr))); \ - (x) = *(__force __typeof__(*(ptr)) *) &__x; \ - break; \ - }; \ - case 2: { \ - unsigned short __x = 0; \ - __gu_err = __get_user_fn(&__x, ptr, \ - sizeof(*(ptr))); \ - (x) = *(__force __typeof__(*(ptr)) *) &__x; \ - break; \ - }; \ - case 4: { \ - unsigned int __x = 0; \ - __gu_err = __get_user_fn(&__x, ptr, \ - sizeof(*(ptr))); \ - (x) = *(__force __typeof__(*(ptr)) *) &__x; \ - break; \ - }; \ - case 8: { \ - unsigned long long __x = 0; \ - __gu_err = __get_user_fn(&__x, ptr, \ - sizeof(*(ptr))); \ - (x) = *(__force __typeof__(*(ptr)) *) &__x; \ - break; \ - }; \ - default: \ - __get_user_bad(); \ - break; \ - } \ - __builtin_expect(__gu_err, 0); \ +#define __get_user(x, ptr) \ +({ \ + int __gu_err = -EFAULT; \ + \ + __chk_user_ptr(ptr); \ + switch (sizeof(*(ptr))) { \ + case 1: { \ + unsigned char __x; \ + \ + __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr))); \ + (x) = *(__force __typeof__(*(ptr)) *)&__x; \ + break; \ + }; \ + case 2: { \ + unsigned short __x; \ + \ + __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr))); \ + (x) = *(__force __typeof__(*(ptr)) *)&__x; \ + break; \ + }; \ + case 4: { \ + unsigned int __x; \ + \ + __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr))); \ + (x) = *(__force __typeof__(*(ptr)) *)&__x; \ + break; \ + }; \ + case 8: { \ + unsigned long __x; \ + \ + __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr))); \ + (x) = *(__force __typeof__(*(ptr)) *)&__x; \ + break; \ + }; \ + default: \ + __get_user_bad(); \ + break; \ + } \ + __builtin_expect(__gu_err, 0); \ }) -#define get_user(x, ptr) \ -({ \ - might_fault(); \ - __get_user(x, ptr); \ +#define get_user(x, ptr) \ +({ \ + might_fault(); \ + __get_user(x, ptr); \ }) /* @@ -278,19 +295,20 @@ int __noreturn __put_kernel_bad(void); int __rc; \ \ asm volatile( \ - "0: " insn " %2,%1\n" \ - "1: xr %0,%0\n" \ + "0: " insn " %[_val],%[_to]\n" \ + "1: xr %[rc],%[rc]\n" \ "2:\n" \ - EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \ - : "=d" (__rc), "+Q" (*(to)) \ - : "d" (val) \ + EX_TABLE_UA_STORE(0b, 2b, %[rc]) \ + EX_TABLE_UA_STORE(1b, 2b, %[rc]) \ + : [rc] "=d" (__rc), [_to] "+Q" (*(to)) \ + : [_val] "d" (val) \ : "cc"); \ __rc; \ }) #define __put_kernel_nofault(dst, src, type, err_label) \ do { \ - u64 __x = (u64)(*((type *)(src))); \ + unsigned long __x = (unsigned long)(*((type *)(src))); \ int __pk_err; \ \ switch (sizeof(type)) { \ @@ -321,12 +339,13 @@ int __noreturn __get_kernel_bad(void); int __rc; \ \ asm volatile( \ - "0: " insn " %1,%2\n" \ - "1: xr %0,%0\n" \ + "0: " insn " %[_val],%[_from]\n" \ + "1: xr %[rc],%[rc]\n" \ "2:\n" \ - EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \ - : "=d" (__rc), "+d" (val) \ - : "Q" (*(from)) \ + EX_TABLE_UA_LOAD_REG(0b, 2b, %[rc], %[_val]) \ + EX_TABLE_UA_LOAD_REG(1b, 2b, %[rc], %[_val]) \ + : [rc] "=d" (__rc), [_val] "=d" (val) \ + : [_from] "Q" (*(from)) \ : "cc"); \ __rc; \ }) @@ -337,28 +356,28 @@ do { \ \ switch (sizeof(type)) { \ case 1: { \ - u8 __x = 0; \ + unsigned char __x; \ \ __gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \ *((type *)(dst)) = (type)__x; \ break; \ }; \ case 2: { \ - u16 __x = 0; \ + unsigned short __x; \ \ __gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \ *((type *)(dst)) = (type)__x; \ break; \ }; \ case 4: { \ - u32 __x = 0; \ + unsigned int __x; \ \ __gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \ *((type *)(dst)) = (type)__x; \ break; \ }; \ case 8: { \ - u64 __x = 0; \ + unsigned long __x; \ \ __gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \ *((type *)(dst)) = (type)__x; \ |