1/* 2 * include/asm-s390/uaccess.h 3 * 4 * S390 version 5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Hartmut Penner (hp@de.ibm.com), 7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 8 * 9 * Derived from "include/asm-i386/uaccess.h" 10 */ 11#ifndef __S390_UACCESS_H 12#define __S390_UACCESS_H 13 14/* 15 * User space memory access functions 16 */ 17#include <linux/sched.h> 18 19#define VERIFY_READ 0 20#define VERIFY_WRITE 1 21 22 23/* 24 * The fs value determines whether argument validity checking should be 25 * performed or not. If get_fs() == USER_DS, checking is performed, with 26 * get_fs() == KERNEL_DS, checking is bypassed. 27 * 28 * For historical reasons, these macros are grossly misnamed. 29 */ 30 31#define MAKE_MM_SEG(a) ((mm_segment_t) { (a) }) 32 33 34#define KERNEL_DS MAKE_MM_SEG(0) 35#define USER_DS MAKE_MM_SEG(1) 36 37#define get_ds() (KERNEL_DS) 38#define get_fs() (current->addr_limit) 39#define set_fs(x) ({asm volatile("sar 4,%0"::"a" ((x).ar4)); \ 40 current->addr_limit = (x);}) 41 42#define segment_eq(a,b) ((a).ar4 == (b).ar4) 43 44 45#define __access_ok(addr,size) (1) 46 47#define access_ok(type,addr,size) __access_ok(addr,size) 48 49extern inline int verify_area(int type, const void * addr, unsigned long size) 50{ 51 return access_ok(type,addr,size)?0:-EFAULT; 52} 53 54/* 55 * The exception table consists of pairs of addresses: the first is the 56 * address of an instruction that is allowed to fault, and the second is 57 * the address at which the program should continue. No registers are 58 * modified, so it is entirely up to the continuation code to figure out 59 * what to do. 60 * 61 * All the routines below use bits of fixup code that are out of line 62 * with the main instruction path. This means when everything is well, 63 * we don't even have to jump over them. Further, they do not intrude 64 * on our cache or tlb entries. 65 */ 66 67struct exception_table_entry 68{ 69 unsigned long insn, fixup; 70}; 71 72/* Returns 0 if exception not found and fixup otherwise. */ 73extern unsigned long search_exception_table(unsigned long); 74 75 76/* 77 * These are the main single-value transfer routines. They automatically 78 * use the right size if we just have the right pointer type. 79 */ 80 81extern inline int __put_user_asm_8(__u64 x, void *ptr) 82{ 83 int err; 84 85 __asm__ __volatile__ ( " sr %1,%1\n" 86 " la 2,%2\n" 87 " la 4,%0\n" 88 " sacf 512\n" 89 "0: mvc 0(8,4),0(2)\n" 90 " sacf 0\n" 91 "1:\n" 92 ".section .fixup,\"ax\"\n" 93 "2: sacf 0\n" 94 " lhi %1,%h3\n" 95 " bras 4,3f\n" 96 " .long 1b\n" 97 "3: l 4,0(4)\n" 98 " br 4\n" 99 ".previous\n" 100 ".section __ex_table,\"a\"\n" 101 " .align 4\n" 102 " .long 0b,2b\n" 103 ".previous" 104 : "=m" (*((__u32*) ptr)), "=&d" (err) 105 : "m" (x), "K" (-EFAULT) 106 : "cc", "2", "4" ); 107 return err; 108} 109 110extern inline int __put_user_asm_4(__u32 x, void *ptr) 111{ 112 int err; 113 114 __asm__ __volatile__ ( " sr %1,%1\n" 115 " la 4,%0\n" 116 " sacf 512\n" 117 "0: st %2,0(4)\n" 118 " sacf 0\n" 119 "1:\n" 120 ".section .fixup,\"ax\"\n" 121 "2: sacf 0\n" 122 " lhi %1,%h3\n" 123 " bras 4,3f\n" 124 " .long 1b\n" 125 "3: l 4,0(4)\n" 126 " br 4\n" 127 ".previous\n" 128 ".section __ex_table,\"a\"\n" 129 " .align 4\n" 130 " .long 0b,2b\n" 131 ".previous" 132 : "=m" (*((__u32*) ptr)) , "=&d" (err) 133 : "d" (x), "K" (-EFAULT) 134 : "cc", "4" ); 135 return err; 136} 137 138extern inline int __put_user_asm_2(__u16 x, void *ptr) 139{ 140 int err; 141 142 __asm__ __volatile__ ( " sr %1,%1\n" 143 " la 4,%0\n" 144 " sacf 512\n" 145 "0: sth %2,0(4)\n" 146 " sacf 0\n" 147 "1:\n" 148 ".section .fixup,\"ax\"\n" 149 "2: sacf 0\n" 150 " lhi %1,%h3\n" 151 " bras 4,3f\n" 152 " .long 1b\n" 153 "3: l 4,0(4)\n" 154 " br 4\n" 155 ".previous\n" 156 ".section __ex_table,\"a\"\n" 157 " .align 4\n" 158 " .long 0b,2b\n" 159 ".previous" 160 : "=m" (*((__u16*) ptr)) , "=&d" (err) 161 : "d" (x), "K" (-EFAULT) 162 : "cc", "4" ); 163 return err; 164} 165 166extern inline int __put_user_asm_1(__u8 x, void *ptr) 167{ 168 int err; 169 170 __asm__ __volatile__ ( " sr %1,%1\n" 171 " la 4,%0\n" 172 " sacf 512\n" 173 "0: stc %2,0(4)\n" 174 " sacf 0\n" 175 "1:\n" 176 ".section .fixup,\"ax\"\n" 177 "2: sacf 0\n" 178 " lhi %1,%h3\n" 179 " bras 4,3f\n" 180 " .long 1b\n" 181 "3: l 4,0(4)\n" 182 " br 4\n" 183 ".previous\n" 184 ".section __ex_table,\"a\"\n" 185 " .align 4\n" 186 " .long 0b,2b\n" 187 ".previous" 188 : "=m" (*((__u8*) ptr)) , "=&d" (err) 189 : "d" (x), "K" (-EFAULT) 190 : "cc", "4" ); 191 return err; 192} 193 194/* 195 * (u8)(u32) ... autsch, but that the only way we can suppress the 196 * warnings when compiling binfmt_elf.c 197 */ 198#define __put_user(x, ptr) \ 199({ \ 200 __typeof__(*(ptr)) *__pu_addr = (ptr); \ 201 __typeof__(*(ptr)) __x = (x); \ 202 int __pu_err; \ 203 switch (sizeof (*(ptr))) { \ 204 case 1: \ 205 __pu_err = __put_user_asm_1((__u8)(__u32) __x, \ 206 __pu_addr); \ 207 break; \ 208 case 2: \ 209 __pu_err = __put_user_asm_2((__u16)(__u32) __x, \ 210 __pu_addr); \ 211 break; \ 212 case 4: \ 213 __pu_err = __put_user_asm_4((__u32) __x, \ 214 __pu_addr); \ 215 break; \ 216 case 8: \ 217 __pu_err = __put_user_asm_8((__u64) __x, \ 218 __pu_addr); \ 219 break; \ 220 default: \ 221 __pu_err = __put_user_bad(); \ 222 break; \ 223 } \ 224 __pu_err; \ 225}) 226 227#define put_user(x, ptr) __put_user(x, ptr) 228 229extern int __put_user_bad(void); 230 231#define __get_user_asm_8(x, ptr, err) \ 232({ \ 233 __asm__ __volatile__ ( " sr %1,%1\n" \ 234 " la 2,%0\n" \ 235 " la 4,%2\n" \ 236 " sacf 512\n" \ 237 "0: mvc 0(8,2),0(4)\n" \ 238 " sacf 0\n" \ 239 "1:\n" \ 240 ".section .fixup,\"ax\"\n" \ 241 "2: sacf 0\n" \ 242 " lhi %1,%h3\n" \ 243 " bras 4,3f\n" \ 244 " .long 1b\n" \ 245 "3: l 4,0(4)\n" \ 246 " br 4\n" \ 247 ".previous\n" \ 248 ".section __ex_table,\"a\"\n" \ 249 " .align 4\n" \ 250 " .long 0b,2b\n" \ 251 ".previous" \ 252 : "=m" (x) , "=&d" (err) \ 253 : "m" (*(const __u64*)(ptr)),"K" (-EFAULT) \ 254 : "cc", "2", "4" ); \ 255}) 256 257#define __get_user_asm_4(x, ptr, err) \ 258({ \ 259 __asm__ __volatile__ ( " sr %1,%1\n" \ 260 " la 4,%2\n" \ 261 " sacf 512\n" \ 262 "0: l %0,0(4)\n" \ 263 " sacf 0\n" \ 264 "1:\n" \ 265 ".section .fixup,\"ax\"\n" \ 266 "2: sacf 0\n" \ 267 " lhi %1,%h3\n" \ 268 " bras 4,3f\n" \ 269 " .long 1b\n" \ 270 "3: l 4,0(4)\n" \ 271 " br 4\n" \ 272 ".previous\n" \ 273 ".section __ex_table,\"a\"\n" \ 274 " .align 4\n" \ 275 " .long 0b,2b\n" \ 276 ".previous" \ 277 : "=d" (x) , "=&d" (err) \ 278 : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \ 279 : "cc", "4" ); \ 280}) 281 282#define __get_user_asm_2(x, ptr, err) \ 283({ \ 284 __asm__ __volatile__ ( " sr %1,%1\n" \ 285 " la 4,%2\n" \ 286 " sacf 512\n" \ 287 "0: lh %0,0(4)\n" \ 288 " sacf 0\n" \ 289 "1:\n" \ 290 ".section .fixup,\"ax\"\n" \ 291 "2: sacf 0\n" \ 292 " lhi %1,%h3\n" \ 293 " bras 4,3f\n" \ 294 " .long 1b\n" \ 295 "3: l 4,0(4)\n" \ 296 " br 4\n" \ 297 ".previous\n" \ 298 ".section __ex_table,\"a\"\n" \ 299 " .align 4\n" \ 300 " .long 0b,2b\n" \ 301 ".previous" \ 302 : "=d" (x) , "=&d" (err) \ 303 : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \ 304 : "cc", "4" ); \ 305}) 306 307#define __get_user_asm_1(x, ptr, err) \ 308({ \ 309 __asm__ __volatile__ ( " sr %1,%1\n" \ 310 " la 4,%2\n" \ 311 " sr %0,%0\n" \ 312 " sacf 512\n" \ 313 "0: ic %0,0(4)\n" \ 314 " sacf 0\n" \ 315 "1:\n" \ 316 ".section .fixup,\"ax\"\n" \ 317 "2: sacf 0\n" \ 318 " lhi %1,%h3\n" \ 319 " bras 4,3f\n" \ 320 " .long 1b\n" \ 321 "3: l 4,0(4)\n" \ 322 " br 4\n" \ 323 ".previous\n" \ 324 ".section __ex_table,\"a\"\n" \ 325 " .align 4\n" \ 326 " .long 0b,2b\n" \ 327 ".previous" \ 328 : "=d" (x) , "=&d" (err) \ 329 : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \ 330 : "cc", "4" ); \ 331}) 332 333#define __get_user(x, ptr) \ 334({ \ 335 __typeof__(ptr) __gu_addr = (ptr); \ 336 __typeof__(*(ptr)) __x; \ 337 int __gu_err; \ 338 switch (sizeof(*(__gu_addr))) { \ 339 case 1: \ 340 __get_user_asm_1(__x, __gu_addr, __gu_err); \ 341 break; \ 342 case 2: \ 343 __get_user_asm_2(__x, __gu_addr, __gu_err); \ 344 break; \ 345 case 4: \ 346 __get_user_asm_4(__x, __gu_addr, __gu_err); \ 347 break; \ 348 case 8: \ 349 __get_user_asm_8(__x, __gu_addr, __gu_err); \ 350 break; \ 351 default: \ 352 __x = 0; \ 353 __gu_err = __get_user_bad(); \ 354 break; \ 355 } \ 356 (x) = __x; \ 357 __gu_err; \ 358}) 359 360#define get_user(x, ptr) __get_user(x, ptr) 361 362extern int __get_user_bad(void); 363 364/* 365 * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel) 366 */ 367 368extern long __copy_to_user_asm(const void *from, long n, const void *to); 369 370#define __copy_to_user(to, from, n) \ 371({ \ 372 __copy_to_user_asm(from, n, to); \ 373}) 374 375#define copy_to_user(to, from, n) \ 376({ \ 377 long err = 0; \ 378 __typeof__(n) __n = (n); \ 379 if (__access_ok(to,__n)) { \ 380 err = __copy_to_user_asm(from, __n, to); \ 381 } \ 382 else \ 383 err = __n; \ 384 err; \ 385}) 386 387extern long __copy_from_user_asm(void *to, long n, const void *from); 388 389#define __copy_from_user(to, from, n) \ 390({ \ 391 __copy_from_user_asm(to, n, from); \ 392}) 393 394#define copy_from_user(to, from, n) \ 395({ \ 396 long err = 0; \ 397 __typeof__(n) __n = (n); \ 398 if (__access_ok(from,__n)) { \ 399 err = __copy_from_user_asm(to, __n, from); \ 400 } \ 401 else \ 402 err = __n; \ 403 err; \ 404}) 405 406/* 407 * Copy a null terminated string from userspace. 408 */ 409 410static inline long 411__strncpy_from_user(char *dst, const char *src, long count) 412{ 413 int len; 414 __asm__ __volatile__ ( " slr %0,%0\n" 415 " lr 2,%1\n" 416 " lr 4,%2\n" 417 " slr 3,3\n" 418 " sacf 512\n" 419 "0: ic 3,0(%0,4)\n" 420 "1: stc 3,0(%0,2)\n" 421 " ltr 3,3\n" 422 " jz 2f\n" 423 " ahi %0,1\n" 424 " clr %0,%3\n" 425 " jl 0b\n" 426 "2: sacf 0\n" 427 ".section .fixup,\"ax\"\n" 428 "3: lhi %0,%h4\n" 429 " basr 3,0\n" 430 " l 3,4f-.(3)\n" 431 " br 3\n" 432 "4: .long 2b\n" 433 ".previous\n" 434 ".section __ex_table,\"a\"\n" 435 " .align 4\n" 436 " .long 0b,3b\n" 437 " .long 1b,3b\n" 438 ".previous" 439 : "=&a" (len) 440 : "a" (dst), "d" (src), "d" (count), 441 "K" (-EFAULT) 442 : "2", "3", "4", "memory", "cc" ); 443 return len; 444} 445 446static inline long 447strncpy_from_user(char *dst, const char *src, long count) 448{ 449 long res = -EFAULT; 450 if (access_ok(VERIFY_READ, src, 1)) 451 res = __strncpy_from_user(dst, src, count); 452 return res; 453} 454 455 456/* 457 * Return the size of a string (including the ending 0) 458 * 459 * Return 0 for error 460 */ 461static inline unsigned long 462strnlen_user(const char * src, unsigned long n) 463{ 464 __asm__ __volatile__ (" alr %0,%1\n" 465 " slr 0,0\n" 466 " lr 4,%1\n" 467 " sacf 512\n" 468 "0: srst %0,4\n" 469 " jo 0b\n" 470 " slr %0,%1\n" 471 " ahi %0,1\n" 472 " sacf 0\n" 473 "1:\n" 474 ".section .fixup,\"ax\"\n" 475 "2: sacf 0\n" 476 " slr %0,%0\n" 477 " bras 4,3f\n" 478 " .long 1b\n" 479 "3: l 4,0(4)\n" 480 " br 4\n" 481 ".previous\n" 482 ".section __ex_table,\"a\"\n" 483 " .align 4\n" 484 " .long 0b,2b\n" 485 ".previous" 486 : "+&a" (n) : "d" (src) 487 : "cc", "0", "4" ); 488 return n; 489} 490#define strlen_user(str) strnlen_user(str, ~0UL) 491 492/* 493 * Zero Userspace 494 */ 495 496extern long __clear_user_asm(void *to, long n); 497 498#define __clear_user(to, n) \ 499({ \ 500 __clear_user_asm(to, n); \ 501}) 502 503static inline unsigned long 504clear_user(void *to, unsigned long n) 505{ 506 if (access_ok(VERIFY_WRITE, to, n)) 507 n = __clear_user(to, n); 508 return n; 509} 510 511 512#endif /* _S390_UACCESS_H */ 513