18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * S390 version 48c2ecf20Sopenharmony_ci * Copyright IBM Corp. 1999, 2000 58c2ecf20Sopenharmony_ci * Author(s): Hartmut Penner (hp@de.ibm.com), 68c2ecf20Sopenharmony_ci * Martin Schwidefsky (schwidefsky@de.ibm.com) 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Derived from "include/asm-i386/uaccess.h" 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#ifndef __S390_UACCESS_H 118c2ecf20Sopenharmony_ci#define __S390_UACCESS_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * User space memory access functions 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#include <asm/processor.h> 178c2ecf20Sopenharmony_ci#include <asm/ctl_reg.h> 188c2ecf20Sopenharmony_ci#include <asm/extable.h> 198c2ecf20Sopenharmony_ci#include <asm/facility.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * The fs value determines whether argument validity checking should be 238c2ecf20Sopenharmony_ci * performed or not. If get_fs() == USER_DS, checking is performed, with 248c2ecf20Sopenharmony_ci * get_fs() == KERNEL_DS, checking is bypassed. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * For historical reasons, these macros are grossly misnamed. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define KERNEL_DS (0) 308c2ecf20Sopenharmony_ci#define KERNEL_DS_SACF (1) 318c2ecf20Sopenharmony_ci#define USER_DS (2) 328c2ecf20Sopenharmony_ci#define USER_DS_SACF (3) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define get_fs() (current->thread.mm_segment) 358c2ecf20Sopenharmony_ci#define uaccess_kernel() ((get_fs() & 2) == KERNEL_DS) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_civoid set_fs(mm_segment_t fs); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic inline int __range_ok(unsigned long addr, unsigned long size) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci return 1; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define __access_ok(addr, size) \ 458c2ecf20Sopenharmony_ci({ \ 468c2ecf20Sopenharmony_ci __chk_user_ptr(addr); \ 478c2ecf20Sopenharmony_ci __range_ok((unsigned long)(addr), (size)); \ 488c2ecf20Sopenharmony_ci}) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define access_ok(addr, size) __access_ok(addr, size) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciunsigned long __must_check 538c2ecf20Sopenharmony_ciraw_copy_from_user(void *to, const void __user *from, unsigned long n); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ciunsigned long __must_check 568c2ecf20Sopenharmony_ciraw_copy_to_user(void __user *to, const void *from, unsigned long n); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#ifndef CONFIG_KASAN 598c2ecf20Sopenharmony_ci#define INLINE_COPY_FROM_USER 608c2ecf20Sopenharmony_ci#define INLINE_COPY_TO_USER 618c2ecf20Sopenharmony_ci#endif 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciint __put_user_bad(void) __attribute__((noreturn)); 648c2ecf20Sopenharmony_ciint __get_user_bad(void) __attribute__((noreturn)); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define __put_get_user_asm(to, from, size, spec) \ 698c2ecf20Sopenharmony_ci({ \ 708c2ecf20Sopenharmony_ci register unsigned long __reg0 asm("0") = spec; \ 718c2ecf20Sopenharmony_ci int __rc; \ 728c2ecf20Sopenharmony_ci \ 738c2ecf20Sopenharmony_ci asm volatile( \ 748c2ecf20Sopenharmony_ci "0: mvcos %1,%3,%2\n" \ 758c2ecf20Sopenharmony_ci "1: xr %0,%0\n" \ 768c2ecf20Sopenharmony_ci "2:\n" \ 778c2ecf20Sopenharmony_ci ".pushsection .fixup, \"ax\"\n" \ 788c2ecf20Sopenharmony_ci "3: lhi %0,%5\n" \ 798c2ecf20Sopenharmony_ci " jg 2b\n" \ 808c2ecf20Sopenharmony_ci ".popsection\n" \ 818c2ecf20Sopenharmony_ci EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 828c2ecf20Sopenharmony_ci : "=d" (__rc), "+Q" (*(to)) \ 838c2ecf20Sopenharmony_ci : "d" (size), "Q" (*(from)), \ 848c2ecf20Sopenharmony_ci "d" (__reg0), "K" (-EFAULT) \ 858c2ecf20Sopenharmony_ci : "cc"); \ 868c2ecf20Sopenharmony_ci __rc; \ 878c2ecf20Sopenharmony_ci}) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci unsigned long spec = 0x010000UL; 928c2ecf20Sopenharmony_ci int rc; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci switch (size) { 958c2ecf20Sopenharmony_ci case 1: 968c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned char __user *)ptr, 978c2ecf20Sopenharmony_ci (unsigned char *)x, 988c2ecf20Sopenharmony_ci size, spec); 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case 2: 1018c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned short __user *)ptr, 1028c2ecf20Sopenharmony_ci (unsigned short *)x, 1038c2ecf20Sopenharmony_ci size, spec); 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci case 4: 1068c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned int __user *)ptr, 1078c2ecf20Sopenharmony_ci (unsigned int *)x, 1088c2ecf20Sopenharmony_ci size, spec); 1098c2ecf20Sopenharmony_ci break; 1108c2ecf20Sopenharmony_ci case 8: 1118c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned long __user *)ptr, 1128c2ecf20Sopenharmony_ci (unsigned long *)x, 1138c2ecf20Sopenharmony_ci size, spec); 1148c2ecf20Sopenharmony_ci break; 1158c2ecf20Sopenharmony_ci default: 1168c2ecf20Sopenharmony_ci __put_user_bad(); 1178c2ecf20Sopenharmony_ci break; 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci return rc; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci unsigned long spec = 0x01UL; 1258c2ecf20Sopenharmony_ci int rc; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci switch (size) { 1288c2ecf20Sopenharmony_ci case 1: 1298c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned char *)x, 1308c2ecf20Sopenharmony_ci (unsigned char __user *)ptr, 1318c2ecf20Sopenharmony_ci size, spec); 1328c2ecf20Sopenharmony_ci break; 1338c2ecf20Sopenharmony_ci case 2: 1348c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned short *)x, 1358c2ecf20Sopenharmony_ci (unsigned short __user *)ptr, 1368c2ecf20Sopenharmony_ci size, spec); 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci case 4: 1398c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned int *)x, 1408c2ecf20Sopenharmony_ci (unsigned int __user *)ptr, 1418c2ecf20Sopenharmony_ci size, spec); 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case 8: 1448c2ecf20Sopenharmony_ci rc = __put_get_user_asm((unsigned long *)x, 1458c2ecf20Sopenharmony_ci (unsigned long __user *)ptr, 1468c2ecf20Sopenharmony_ci size, spec); 1478c2ecf20Sopenharmony_ci break; 1488c2ecf20Sopenharmony_ci default: 1498c2ecf20Sopenharmony_ci __get_user_bad(); 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci return rc; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci size = raw_copy_to_user(ptr, x, size); 1608c2ecf20Sopenharmony_ci return size ? -EFAULT : 0; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci size = raw_copy_from_user(x, ptr, size); 1668c2ecf20Sopenharmony_ci return size ? -EFAULT : 0; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/* 1728c2ecf20Sopenharmony_ci * These are the main single-value transfer routines. They automatically 1738c2ecf20Sopenharmony_ci * use the right size if we just have the right pointer type. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci#define __put_user(x, ptr) \ 1768c2ecf20Sopenharmony_ci({ \ 1778c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __x = (x); \ 1788c2ecf20Sopenharmony_ci int __pu_err = -EFAULT; \ 1798c2ecf20Sopenharmony_ci __chk_user_ptr(ptr); \ 1808c2ecf20Sopenharmony_ci switch (sizeof (*(ptr))) { \ 1818c2ecf20Sopenharmony_ci case 1: \ 1828c2ecf20Sopenharmony_ci case 2: \ 1838c2ecf20Sopenharmony_ci case 4: \ 1848c2ecf20Sopenharmony_ci case 8: \ 1858c2ecf20Sopenharmony_ci __pu_err = __put_user_fn(&__x, ptr, \ 1868c2ecf20Sopenharmony_ci sizeof(*(ptr))); \ 1878c2ecf20Sopenharmony_ci break; \ 1888c2ecf20Sopenharmony_ci default: \ 1898c2ecf20Sopenharmony_ci __put_user_bad(); \ 1908c2ecf20Sopenharmony_ci break; \ 1918c2ecf20Sopenharmony_ci } \ 1928c2ecf20Sopenharmony_ci __builtin_expect(__pu_err, 0); \ 1938c2ecf20Sopenharmony_ci}) 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#define put_user(x, ptr) \ 1968c2ecf20Sopenharmony_ci({ \ 1978c2ecf20Sopenharmony_ci might_fault(); \ 1988c2ecf20Sopenharmony_ci __put_user(x, ptr); \ 1998c2ecf20Sopenharmony_ci}) 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#define __get_user(x, ptr) \ 2038c2ecf20Sopenharmony_ci({ \ 2048c2ecf20Sopenharmony_ci int __gu_err = -EFAULT; \ 2058c2ecf20Sopenharmony_ci __chk_user_ptr(ptr); \ 2068c2ecf20Sopenharmony_ci switch (sizeof(*(ptr))) { \ 2078c2ecf20Sopenharmony_ci case 1: { \ 2088c2ecf20Sopenharmony_ci unsigned char __x = 0; \ 2098c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(&__x, ptr, \ 2108c2ecf20Sopenharmony_ci sizeof(*(ptr))); \ 2118c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2128c2ecf20Sopenharmony_ci break; \ 2138c2ecf20Sopenharmony_ci }; \ 2148c2ecf20Sopenharmony_ci case 2: { \ 2158c2ecf20Sopenharmony_ci unsigned short __x = 0; \ 2168c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(&__x, ptr, \ 2178c2ecf20Sopenharmony_ci sizeof(*(ptr))); \ 2188c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2198c2ecf20Sopenharmony_ci break; \ 2208c2ecf20Sopenharmony_ci }; \ 2218c2ecf20Sopenharmony_ci case 4: { \ 2228c2ecf20Sopenharmony_ci unsigned int __x = 0; \ 2238c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(&__x, ptr, \ 2248c2ecf20Sopenharmony_ci sizeof(*(ptr))); \ 2258c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2268c2ecf20Sopenharmony_ci break; \ 2278c2ecf20Sopenharmony_ci }; \ 2288c2ecf20Sopenharmony_ci case 8: { \ 2298c2ecf20Sopenharmony_ci unsigned long long __x = 0; \ 2308c2ecf20Sopenharmony_ci __gu_err = __get_user_fn(&__x, ptr, \ 2318c2ecf20Sopenharmony_ci sizeof(*(ptr))); \ 2328c2ecf20Sopenharmony_ci (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 2338c2ecf20Sopenharmony_ci break; \ 2348c2ecf20Sopenharmony_ci }; \ 2358c2ecf20Sopenharmony_ci default: \ 2368c2ecf20Sopenharmony_ci __get_user_bad(); \ 2378c2ecf20Sopenharmony_ci break; \ 2388c2ecf20Sopenharmony_ci } \ 2398c2ecf20Sopenharmony_ci __builtin_expect(__gu_err, 0); \ 2408c2ecf20Sopenharmony_ci}) 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci#define get_user(x, ptr) \ 2438c2ecf20Sopenharmony_ci({ \ 2448c2ecf20Sopenharmony_ci might_fault(); \ 2458c2ecf20Sopenharmony_ci __get_user(x, ptr); \ 2468c2ecf20Sopenharmony_ci}) 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciunsigned long __must_check 2498c2ecf20Sopenharmony_ciraw_copy_in_user(void __user *to, const void __user *from, unsigned long n); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* 2528c2ecf20Sopenharmony_ci * Copy a null terminated string from userspace. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cilong __strncpy_from_user(char *dst, const char __user *src, long count); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic inline long __must_check 2588c2ecf20Sopenharmony_cistrncpy_from_user(char *dst, const char __user *src, long count) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci might_fault(); 2618c2ecf20Sopenharmony_ci return __strncpy_from_user(dst, src, count); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ciunsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic inline unsigned long strnlen_user(const char __user *src, unsigned long n) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci might_fault(); 2698c2ecf20Sopenharmony_ci return __strnlen_user(src, n); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci/* 2738c2ecf20Sopenharmony_ci * Zero Userspace 2748c2ecf20Sopenharmony_ci */ 2758c2ecf20Sopenharmony_ciunsigned long __must_check __clear_user(void __user *to, unsigned long size); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic inline unsigned long __must_check clear_user(void __user *to, unsigned long n) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci might_fault(); 2808c2ecf20Sopenharmony_ci return __clear_user(to, n); 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ciint copy_to_user_real(void __user *dest, void *src, unsigned long count); 2848c2ecf20Sopenharmony_civoid *s390_kernel_write(void *dst, const void *src, size_t size); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#define HAVE_GET_KERNEL_NOFAULT 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ciint __noreturn __put_kernel_bad(void); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci#define __put_kernel_asm(val, to, insn) \ 2918c2ecf20Sopenharmony_ci({ \ 2928c2ecf20Sopenharmony_ci int __rc; \ 2938c2ecf20Sopenharmony_ci \ 2948c2ecf20Sopenharmony_ci asm volatile( \ 2958c2ecf20Sopenharmony_ci "0: " insn " %2,%1\n" \ 2968c2ecf20Sopenharmony_ci "1: xr %0,%0\n" \ 2978c2ecf20Sopenharmony_ci "2:\n" \ 2988c2ecf20Sopenharmony_ci ".pushsection .fixup, \"ax\"\n" \ 2998c2ecf20Sopenharmony_ci "3: lhi %0,%3\n" \ 3008c2ecf20Sopenharmony_ci " jg 2b\n" \ 3018c2ecf20Sopenharmony_ci ".popsection\n" \ 3028c2ecf20Sopenharmony_ci EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 3038c2ecf20Sopenharmony_ci : "=d" (__rc), "+Q" (*(to)) \ 3048c2ecf20Sopenharmony_ci : "d" (val), "K" (-EFAULT) \ 3058c2ecf20Sopenharmony_ci : "cc"); \ 3068c2ecf20Sopenharmony_ci __rc; \ 3078c2ecf20Sopenharmony_ci}) 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci#define __put_kernel_nofault(dst, src, type, err_label) \ 3108c2ecf20Sopenharmony_cido { \ 3118c2ecf20Sopenharmony_ci u64 __x = (u64)(*((type *)(src))); \ 3128c2ecf20Sopenharmony_ci int __pk_err; \ 3138c2ecf20Sopenharmony_ci \ 3148c2ecf20Sopenharmony_ci switch (sizeof(type)) { \ 3158c2ecf20Sopenharmony_ci case 1: \ 3168c2ecf20Sopenharmony_ci __pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \ 3178c2ecf20Sopenharmony_ci break; \ 3188c2ecf20Sopenharmony_ci case 2: \ 3198c2ecf20Sopenharmony_ci __pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \ 3208c2ecf20Sopenharmony_ci break; \ 3218c2ecf20Sopenharmony_ci case 4: \ 3228c2ecf20Sopenharmony_ci __pk_err = __put_kernel_asm(__x, (type *)(dst), "st"); \ 3238c2ecf20Sopenharmony_ci break; \ 3248c2ecf20Sopenharmony_ci case 8: \ 3258c2ecf20Sopenharmony_ci __pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \ 3268c2ecf20Sopenharmony_ci break; \ 3278c2ecf20Sopenharmony_ci default: \ 3288c2ecf20Sopenharmony_ci __pk_err = __put_kernel_bad(); \ 3298c2ecf20Sopenharmony_ci break; \ 3308c2ecf20Sopenharmony_ci } \ 3318c2ecf20Sopenharmony_ci if (unlikely(__pk_err)) \ 3328c2ecf20Sopenharmony_ci goto err_label; \ 3338c2ecf20Sopenharmony_ci} while (0) 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ciint __noreturn __get_kernel_bad(void); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci#define __get_kernel_asm(val, from, insn) \ 3388c2ecf20Sopenharmony_ci({ \ 3398c2ecf20Sopenharmony_ci int __rc; \ 3408c2ecf20Sopenharmony_ci \ 3418c2ecf20Sopenharmony_ci asm volatile( \ 3428c2ecf20Sopenharmony_ci "0: " insn " %1,%2\n" \ 3438c2ecf20Sopenharmony_ci "1: xr %0,%0\n" \ 3448c2ecf20Sopenharmony_ci "2:\n" \ 3458c2ecf20Sopenharmony_ci ".pushsection .fixup, \"ax\"\n" \ 3468c2ecf20Sopenharmony_ci "3: lhi %0,%3\n" \ 3478c2ecf20Sopenharmony_ci " jg 2b\n" \ 3488c2ecf20Sopenharmony_ci ".popsection\n" \ 3498c2ecf20Sopenharmony_ci EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 3508c2ecf20Sopenharmony_ci : "=d" (__rc), "+d" (val) \ 3518c2ecf20Sopenharmony_ci : "Q" (*(from)), "K" (-EFAULT) \ 3528c2ecf20Sopenharmony_ci : "cc"); \ 3538c2ecf20Sopenharmony_ci __rc; \ 3548c2ecf20Sopenharmony_ci}) 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci#define __get_kernel_nofault(dst, src, type, err_label) \ 3578c2ecf20Sopenharmony_cido { \ 3588c2ecf20Sopenharmony_ci int __gk_err; \ 3598c2ecf20Sopenharmony_ci \ 3608c2ecf20Sopenharmony_ci switch (sizeof(type)) { \ 3618c2ecf20Sopenharmony_ci case 1: { \ 3628c2ecf20Sopenharmony_ci u8 __x = 0; \ 3638c2ecf20Sopenharmony_ci \ 3648c2ecf20Sopenharmony_ci __gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \ 3658c2ecf20Sopenharmony_ci *((type *)(dst)) = (type)__x; \ 3668c2ecf20Sopenharmony_ci break; \ 3678c2ecf20Sopenharmony_ci }; \ 3688c2ecf20Sopenharmony_ci case 2: { \ 3698c2ecf20Sopenharmony_ci u16 __x = 0; \ 3708c2ecf20Sopenharmony_ci \ 3718c2ecf20Sopenharmony_ci __gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \ 3728c2ecf20Sopenharmony_ci *((type *)(dst)) = (type)__x; \ 3738c2ecf20Sopenharmony_ci break; \ 3748c2ecf20Sopenharmony_ci }; \ 3758c2ecf20Sopenharmony_ci case 4: { \ 3768c2ecf20Sopenharmony_ci u32 __x = 0; \ 3778c2ecf20Sopenharmony_ci \ 3788c2ecf20Sopenharmony_ci __gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \ 3798c2ecf20Sopenharmony_ci *((type *)(dst)) = (type)__x; \ 3808c2ecf20Sopenharmony_ci break; \ 3818c2ecf20Sopenharmony_ci }; \ 3828c2ecf20Sopenharmony_ci case 8: { \ 3838c2ecf20Sopenharmony_ci u64 __x = 0; \ 3848c2ecf20Sopenharmony_ci \ 3858c2ecf20Sopenharmony_ci __gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \ 3868c2ecf20Sopenharmony_ci *((type *)(dst)) = (type)__x; \ 3878c2ecf20Sopenharmony_ci break; \ 3888c2ecf20Sopenharmony_ci }; \ 3898c2ecf20Sopenharmony_ci default: \ 3908c2ecf20Sopenharmony_ci __gk_err = __get_kernel_bad(); \ 3918c2ecf20Sopenharmony_ci break; \ 3928c2ecf20Sopenharmony_ci } \ 3938c2ecf20Sopenharmony_ci if (unlikely(__gk_err)) \ 3948c2ecf20Sopenharmony_ci goto err_label; \ 3958c2ecf20Sopenharmony_ci} while (0) 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci#endif /* __S390_UACCESS_H */ 398