1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * S390 version 4 * Copyright IBM Corp. 1999, 2000 5 * Author(s): Hartmut Penner (hp@de.ibm.com), 6 * Martin Schwidefsky (schwidefsky@de.ibm.com) 7 * 8 * Derived from "include/asm-i386/uaccess.h" 9 */ 10 #ifndef __S390_UACCESS_H 11 #define __S390_UACCESS_H 12 13 /* 14 * User space memory access functions 15 */ 16 #include <asm/processor.h> 17 #include <asm/ctl_reg.h> 18 #include <asm/extable.h> 19 #include <asm/facility.h> 20 21 /* 22 * The fs value determines whether argument validity checking should be 23 * performed or not. If get_fs() == USER_DS, checking is performed, with 24 * get_fs() == KERNEL_DS, checking is bypassed. 25 * 26 * For historical reasons, these macros are grossly misnamed. 27 */ 28 29 #define KERNEL_DS (0) 30 #define KERNEL_DS_SACF (1) 31 #define USER_DS (2) 32 #define USER_DS_SACF (3) 33 34 #define get_fs() (current->thread.mm_segment) 35 #define uaccess_kernel() ((get_fs() & 2) == KERNEL_DS) 36 37 void set_fs(mm_segment_t fs); 38 39 static inline int __range_ok(unsigned long addr, unsigned long size) 40 { 41 return 1; 42 } 43 44 #define __access_ok(addr, size) \ 45 ({ \ 46 __chk_user_ptr(addr); \ 47 __range_ok((unsigned long)(addr), (size)); \ 48 }) 49 50 #define access_ok(addr, size) __access_ok(addr, size) 51 52 unsigned long __must_check 53 raw_copy_from_user(void *to, const void __user *from, unsigned long n); 54 55 unsigned long __must_check 56 raw_copy_to_user(void __user *to, const void *from, unsigned long n); 57 58 #ifndef CONFIG_KASAN 59 #define INLINE_COPY_FROM_USER 60 #define INLINE_COPY_TO_USER 61 #endif 62 63 #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES 64 65 #define __put_get_user_asm(to, from, size, spec) \ 66 ({ \ 67 register unsigned long __reg0 asm("0") = spec; \ 68 int __rc; \ 69 \ 70 asm volatile( \ 71 "0: mvcos %1,%3,%2\n" \ 72 "1: xr %0,%0\n" \ 73 "2:\n" \ 74 ".pushsection .fixup, \"ax\"\n" \ 75 "3: lhi %0,%5\n" \ 76 " jg 2b\n" \ 77 ".popsection\n" \ 78 EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 79 : "=d" (__rc), "+Q" (*(to)) \ 80 : "d" (size), "Q" (*(from)), \ 81 "d" (__reg0), "K" (-EFAULT) \ 82 : "cc"); \ 83 __rc; \ 84 }) 85 86 static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 87 { 88 unsigned long spec = 0x010000UL; 89 int rc; 90 91 switch (size) { 92 case 1: 93 rc = __put_get_user_asm((unsigned char __user *)ptr, 94 (unsigned char *)x, 95 size, spec); 96 break; 97 case 2: 98 rc = __put_get_user_asm((unsigned short __user *)ptr, 99 (unsigned short *)x, 100 size, spec); 101 break; 102 case 4: 103 rc = __put_get_user_asm((unsigned int __user *)ptr, 104 (unsigned int *)x, 105 size, spec); 106 break; 107 case 8: 108 rc = __put_get_user_asm((unsigned long __user *)ptr, 109 (unsigned long *)x, 110 size, spec); 111 break; 112 } 113 return rc; 114 } 115 116 static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 117 { 118 unsigned long spec = 0x01UL; 119 int rc; 120 121 switch (size) { 122 case 1: 123 rc = __put_get_user_asm((unsigned char *)x, 124 (unsigned char __user *)ptr, 125 size, spec); 126 break; 127 case 2: 128 rc = __put_get_user_asm((unsigned short *)x, 129 (unsigned short __user *)ptr, 130 size, spec); 131 break; 132 case 4: 133 rc = __put_get_user_asm((unsigned int *)x, 134 (unsigned int __user *)ptr, 135 size, spec); 136 break; 137 case 8: 138 rc = __put_get_user_asm((unsigned long *)x, 139 (unsigned long __user *)ptr, 140 size, spec); 141 break; 142 } 143 return rc; 144 } 145 146 #else /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 147 148 static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 149 { 150 size = raw_copy_to_user(ptr, x, size); 151 return size ? -EFAULT : 0; 152 } 153 154 static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 155 { 156 size = raw_copy_from_user(x, ptr, size); 157 return size ? -EFAULT : 0; 158 } 159 160 #endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 161 162 /* 163 * These are the main single-value transfer routines. They automatically 164 * use the right size if we just have the right pointer type. 165 */ 166 #define __put_user(x, ptr) \ 167 ({ \ 168 __typeof__(*(ptr)) __x = (x); \ 169 int __pu_err = -EFAULT; \ 170 __chk_user_ptr(ptr); \ 171 switch (sizeof (*(ptr))) { \ 172 case 1: \ 173 case 2: \ 174 case 4: \ 175 case 8: \ 176 __pu_err = __put_user_fn(&__x, ptr, \ 177 sizeof(*(ptr))); \ 178 break; \ 179 default: \ 180 __put_user_bad(); \ 181 break; \ 182 } \ 183 __builtin_expect(__pu_err, 0); \ 184 }) 185 186 #define put_user(x, ptr) \ 187 ({ \ 188 might_fault(); \ 189 __put_user(x, ptr); \ 190 }) 191 192 193 int __put_user_bad(void) __attribute__((noreturn)); 194 195 #define __get_user(x, ptr) \ 196 ({ \ 197 int __gu_err = -EFAULT; \ 198 __chk_user_ptr(ptr); \ 199 switch (sizeof(*(ptr))) { \ 200 case 1: { \ 201 unsigned char __x = 0; \ 202 __gu_err = __get_user_fn(&__x, ptr, \ 203 sizeof(*(ptr))); \ 204 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 205 break; \ 206 }; \ 207 case 2: { \ 208 unsigned short __x = 0; \ 209 __gu_err = __get_user_fn(&__x, ptr, \ 210 sizeof(*(ptr))); \ 211 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 212 break; \ 213 }; \ 214 case 4: { \ 215 unsigned int __x = 0; \ 216 __gu_err = __get_user_fn(&__x, ptr, \ 217 sizeof(*(ptr))); \ 218 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 219 break; \ 220 }; \ 221 case 8: { \ 222 unsigned long long __x = 0; \ 223 __gu_err = __get_user_fn(&__x, ptr, \ 224 sizeof(*(ptr))); \ 225 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 226 break; \ 227 }; \ 228 default: \ 229 __get_user_bad(); \ 230 break; \ 231 } \ 232 __builtin_expect(__gu_err, 0); \ 233 }) 234 235 #define get_user(x, ptr) \ 236 ({ \ 237 might_fault(); \ 238 __get_user(x, ptr); \ 239 }) 240 241 int __get_user_bad(void) __attribute__((noreturn)); 242 243 unsigned long __must_check 244 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); 245 246 /* 247 * Copy a null terminated string from userspace. 248 */ 249 250 long __strncpy_from_user(char *dst, const char __user *src, long count); 251 252 static inline long __must_check 253 strncpy_from_user(char *dst, const char __user *src, long count) 254 { 255 might_fault(); 256 return __strncpy_from_user(dst, src, count); 257 } 258 259 unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); 260 261 static inline unsigned long strnlen_user(const char __user *src, unsigned long n) 262 { 263 might_fault(); 264 return __strnlen_user(src, n); 265 } 266 267 /* 268 * Zero Userspace 269 */ 270 unsigned long __must_check __clear_user(void __user *to, unsigned long size); 271 272 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) 273 { 274 might_fault(); 275 return __clear_user(to, n); 276 } 277 278 int copy_to_user_real(void __user *dest, void *src, unsigned long count); 279 void *s390_kernel_write(void *dst, const void *src, size_t size); 280 281 #endif /* __S390_UACCESS_H */ 282