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