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 int __put_user_bad(void) __attribute__((noreturn)); 64 int __get_user_bad(void) __attribute__((noreturn)); 65 66 #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES 67 68 #define __put_get_user_asm(to, from, size, spec) \ 69 ({ \ 70 register unsigned long __reg0 asm("0") = spec; \ 71 int __rc; \ 72 \ 73 asm volatile( \ 74 "0: mvcos %1,%3,%2\n" \ 75 "1: xr %0,%0\n" \ 76 "2:\n" \ 77 ".pushsection .fixup, \"ax\"\n" \ 78 "3: lhi %0,%5\n" \ 79 " jg 2b\n" \ 80 ".popsection\n" \ 81 EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 82 : "=d" (__rc), "+Q" (*(to)) \ 83 : "d" (size), "Q" (*(from)), \ 84 "d" (__reg0), "K" (-EFAULT) \ 85 : "cc"); \ 86 __rc; \ 87 }) 88 89 static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 90 { 91 unsigned long spec = 0x010000UL; 92 int rc; 93 94 switch (size) { 95 case 1: 96 rc = __put_get_user_asm((unsigned char __user *)ptr, 97 (unsigned char *)x, 98 size, spec); 99 break; 100 case 2: 101 rc = __put_get_user_asm((unsigned short __user *)ptr, 102 (unsigned short *)x, 103 size, spec); 104 break; 105 case 4: 106 rc = __put_get_user_asm((unsigned int __user *)ptr, 107 (unsigned int *)x, 108 size, spec); 109 break; 110 case 8: 111 rc = __put_get_user_asm((unsigned long __user *)ptr, 112 (unsigned long *)x, 113 size, spec); 114 break; 115 default: 116 __put_user_bad(); 117 break; 118 } 119 return rc; 120 } 121 122 static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 123 { 124 unsigned long spec = 0x01UL; 125 int rc; 126 127 switch (size) { 128 case 1: 129 rc = __put_get_user_asm((unsigned char *)x, 130 (unsigned char __user *)ptr, 131 size, spec); 132 break; 133 case 2: 134 rc = __put_get_user_asm((unsigned short *)x, 135 (unsigned short __user *)ptr, 136 size, spec); 137 break; 138 case 4: 139 rc = __put_get_user_asm((unsigned int *)x, 140 (unsigned int __user *)ptr, 141 size, spec); 142 break; 143 case 8: 144 rc = __put_get_user_asm((unsigned long *)x, 145 (unsigned long __user *)ptr, 146 size, spec); 147 break; 148 default: 149 __get_user_bad(); 150 break; 151 } 152 return rc; 153 } 154 155 #else /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 156 157 static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) 158 { 159 size = raw_copy_to_user(ptr, x, size); 160 return size ? -EFAULT : 0; 161 } 162 163 static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) 164 { 165 size = raw_copy_from_user(x, ptr, size); 166 return size ? -EFAULT : 0; 167 } 168 169 #endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */ 170 171 /* 172 * These are the main single-value transfer routines. They automatically 173 * use the right size if we just have the right pointer type. 174 */ 175 #define __put_user(x, ptr) \ 176 ({ \ 177 __typeof__(*(ptr)) __x = (x); \ 178 int __pu_err = -EFAULT; \ 179 __chk_user_ptr(ptr); \ 180 switch (sizeof (*(ptr))) { \ 181 case 1: \ 182 case 2: \ 183 case 4: \ 184 case 8: \ 185 __pu_err = __put_user_fn(&__x, ptr, \ 186 sizeof(*(ptr))); \ 187 break; \ 188 default: \ 189 __put_user_bad(); \ 190 break; \ 191 } \ 192 __builtin_expect(__pu_err, 0); \ 193 }) 194 195 #define put_user(x, ptr) \ 196 ({ \ 197 might_fault(); \ 198 __put_user(x, ptr); \ 199 }) 200 201 202 #define __get_user(x, ptr) \ 203 ({ \ 204 int __gu_err = -EFAULT; \ 205 __chk_user_ptr(ptr); \ 206 switch (sizeof(*(ptr))) { \ 207 case 1: { \ 208 unsigned char __x = 0; \ 209 __gu_err = __get_user_fn(&__x, ptr, \ 210 sizeof(*(ptr))); \ 211 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 212 break; \ 213 }; \ 214 case 2: { \ 215 unsigned short __x = 0; \ 216 __gu_err = __get_user_fn(&__x, ptr, \ 217 sizeof(*(ptr))); \ 218 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 219 break; \ 220 }; \ 221 case 4: { \ 222 unsigned int __x = 0; \ 223 __gu_err = __get_user_fn(&__x, ptr, \ 224 sizeof(*(ptr))); \ 225 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 226 break; \ 227 }; \ 228 case 8: { \ 229 unsigned long long __x = 0; \ 230 __gu_err = __get_user_fn(&__x, ptr, \ 231 sizeof(*(ptr))); \ 232 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 233 break; \ 234 }; \ 235 default: \ 236 __get_user_bad(); \ 237 break; \ 238 } \ 239 __builtin_expect(__gu_err, 0); \ 240 }) 241 242 #define get_user(x, ptr) \ 243 ({ \ 244 might_fault(); \ 245 __get_user(x, ptr); \ 246 }) 247 248 unsigned long __must_check 249 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); 250 251 /* 252 * Copy a null terminated string from userspace. 253 */ 254 255 long __strncpy_from_user(char *dst, const char __user *src, long count); 256 257 static inline long __must_check 258 strncpy_from_user(char *dst, const char __user *src, long count) 259 { 260 might_fault(); 261 return __strncpy_from_user(dst, src, count); 262 } 263 264 unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); 265 266 static inline unsigned long strnlen_user(const char __user *src, unsigned long n) 267 { 268 might_fault(); 269 return __strnlen_user(src, n); 270 } 271 272 /* 273 * Zero Userspace 274 */ 275 unsigned long __must_check __clear_user(void __user *to, unsigned long size); 276 277 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) 278 { 279 might_fault(); 280 return __clear_user(to, n); 281 } 282 283 int copy_to_user_real(void __user *dest, void *src, unsigned long count); 284 void *s390_kernel_write(void *dst, const void *src, size_t size); 285 286 #define HAVE_GET_KERNEL_NOFAULT 287 288 int __noreturn __put_kernel_bad(void); 289 290 #define __put_kernel_asm(val, to, insn) \ 291 ({ \ 292 int __rc; \ 293 \ 294 asm volatile( \ 295 "0: " insn " %2,%1\n" \ 296 "1: xr %0,%0\n" \ 297 "2:\n" \ 298 ".pushsection .fixup, \"ax\"\n" \ 299 "3: lhi %0,%3\n" \ 300 " jg 2b\n" \ 301 ".popsection\n" \ 302 EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 303 : "=d" (__rc), "+Q" (*(to)) \ 304 : "d" (val), "K" (-EFAULT) \ 305 : "cc"); \ 306 __rc; \ 307 }) 308 309 #define __put_kernel_nofault(dst, src, type, err_label) \ 310 do { \ 311 u64 __x = (u64)(*((type *)(src))); \ 312 int __pk_err; \ 313 \ 314 switch (sizeof(type)) { \ 315 case 1: \ 316 __pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \ 317 break; \ 318 case 2: \ 319 __pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \ 320 break; \ 321 case 4: \ 322 __pk_err = __put_kernel_asm(__x, (type *)(dst), "st"); \ 323 break; \ 324 case 8: \ 325 __pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \ 326 break; \ 327 default: \ 328 __pk_err = __put_kernel_bad(); \ 329 break; \ 330 } \ 331 if (unlikely(__pk_err)) \ 332 goto err_label; \ 333 } while (0) 334 335 int __noreturn __get_kernel_bad(void); 336 337 #define __get_kernel_asm(val, from, insn) \ 338 ({ \ 339 int __rc; \ 340 \ 341 asm volatile( \ 342 "0: " insn " %1,%2\n" \ 343 "1: xr %0,%0\n" \ 344 "2:\n" \ 345 ".pushsection .fixup, \"ax\"\n" \ 346 "3: lhi %0,%3\n" \ 347 " jg 2b\n" \ 348 ".popsection\n" \ 349 EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ 350 : "=d" (__rc), "+d" (val) \ 351 : "Q" (*(from)), "K" (-EFAULT) \ 352 : "cc"); \ 353 __rc; \ 354 }) 355 356 #define __get_kernel_nofault(dst, src, type, err_label) \ 357 do { \ 358 int __gk_err; \ 359 \ 360 switch (sizeof(type)) { \ 361 case 1: { \ 362 u8 __x = 0; \ 363 \ 364 __gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \ 365 *((type *)(dst)) = (type)__x; \ 366 break; \ 367 }; \ 368 case 2: { \ 369 u16 __x = 0; \ 370 \ 371 __gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \ 372 *((type *)(dst)) = (type)__x; \ 373 break; \ 374 }; \ 375 case 4: { \ 376 u32 __x = 0; \ 377 \ 378 __gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \ 379 *((type *)(dst)) = (type)__x; \ 380 break; \ 381 }; \ 382 case 8: { \ 383 u64 __x = 0; \ 384 \ 385 __gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \ 386 *((type *)(dst)) = (type)__x; \ 387 break; \ 388 }; \ 389 default: \ 390 __gk_err = __get_kernel_bad(); \ 391 break; \ 392 } \ 393 if (unlikely(__gk_err)) \ 394 goto err_label; \ 395 } while (0) 396 397 #endif /* __S390_UACCESS_H */ 398