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 37void set_fs(mm_segment_t fs); 38 39static 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 52unsigned long __must_check 53raw_copy_from_user(void *to, const void __user *from, unsigned long n); 54 55unsigned long __must_check 56raw_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 63int __put_user_bad(void) __attribute__((noreturn)); 64int __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 89static __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 122static __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 157static 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 163static 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 248unsigned long __must_check 249raw_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 255long __strncpy_from_user(char *dst, const char __user *src, long count); 256 257static inline long __must_check 258strncpy_from_user(char *dst, const char __user *src, long count) 259{ 260 might_fault(); 261 return __strncpy_from_user(dst, src, count); 262} 263 264unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); 265 266static 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 */ 275unsigned long __must_check __clear_user(void __user *to, unsigned long size); 276 277static 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 283int copy_to_user_real(void __user *dest, void *src, unsigned long count); 284void *s390_kernel_write(void *dst, const void *src, size_t size); 285 286#define HAVE_GET_KERNEL_NOFAULT 287 288int __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) \ 310do { \ 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 335int __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) \ 357do { \ 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