Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12-rc4 600 lines 14 kB view raw
1/* $Id: uaccess.h,v 1.11 2003/10/13 07:21:20 lethal Exp $ 2 * 3 * User space memory access functions 4 * 5 * Copyright (C) 1999, 2002 Niibe Yutaka 6 * Copyright (C) 2003 Paul Mundt 7 * 8 * Based on: 9 * MIPS implementation version 1.15 by 10 * Copyright (C) 1996, 1997, 1998 by Ralf Baechle 11 * and i386 version. 12 */ 13#ifndef __ASM_SH_UACCESS_H 14#define __ASM_SH_UACCESS_H 15 16#include <linux/errno.h> 17#include <linux/sched.h> 18 19/* 20 * NOTE: Macro/functions in this file depends on threads_info.h implementation. 21 * Assumes: 22 * TI_FLAGS == 8 23 * TIF_USERSPACE == 31 24 * USER_ADDR_LIMIT == 0x80000000 25 */ 26 27#define VERIFY_READ 0 28#define VERIFY_WRITE 1 29 30typedef struct { 31 unsigned int is_user_space; 32} mm_segment_t; 33 34/* 35 * The fs value determines whether argument validity checking should be 36 * performed or not. If get_fs() == USER_DS, checking is performed, with 37 * get_fs() == KERNEL_DS, checking is bypassed. 38 * 39 * For historical reasons (Data Segment Register?), these macros are misnamed. 40 */ 41 42#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 43#define segment_eq(a,b) ((a).is_user_space == (b).is_user_space) 44 45#define USER_ADDR_LIMIT 0x80000000 46 47#define KERNEL_DS MAKE_MM_SEG(0) 48#define USER_DS MAKE_MM_SEG(1) 49 50#define get_ds() (KERNEL_DS) 51 52#if !defined(CONFIG_MMU) 53static inline mm_segment_t get_fs(void) 54{ 55 return USER_DS; 56} 57 58static inline void set_fs(mm_segment_t s) 59{ 60} 61 62/* 63 * __access_ok: Check if address with size is OK or not. 64 * 65 * If we don't have an MMU (or if its disabled) the only thing we really have 66 * to look out for is if the address resides somewhere outside of what 67 * available RAM we have. 68 * 69 * TODO: This check could probably also stand to be restricted somewhat more.. 70 * though it still does the Right Thing(tm) for the time being. 71 */ 72static inline int __access_ok(unsigned long addr, unsigned long size) 73{ 74 extern unsigned long memory_start, memory_end; 75 76 return ((addr >= memory_start) && ((addr + size) < memory_end)); 77} 78#else /* CONFIG_MMU */ 79static inline mm_segment_t get_fs(void) 80{ 81 return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE)); 82} 83 84static inline void set_fs(mm_segment_t s) 85{ 86 unsigned long ti, flag; 87 __asm__ __volatile__( 88 "stc r7_bank, %0\n\t" 89 "mov.l @(8,%0), %1\n\t" 90 "shal %1\n\t" 91 "cmp/pl %2\n\t" 92 "rotcr %1\n\t" 93 "mov.l %1, @(8,%0)" 94 : "=&r" (ti), "=&r" (flag) 95 : "r" (s.is_user_space) 96 : "t"); 97/**** 98 if (s.is_user_space) 99 set_thread_flag(TIF_USERSPACE); 100 else 101 clear_thread_flag(TIF_USERSPACE); 102****/ 103} 104 105/* 106 * __access_ok: Check if address with size is OK or not. 107 * 108 * We do three checks: 109 * (1) is it user space? 110 * (2) addr + size --> carry? 111 * (3) addr + size >= 0x80000000 (USER_ADDR_LIMIT) 112 * 113 * (1) (2) (3) | RESULT 114 * 0 0 0 | ok 115 * 0 0 1 | ok 116 * 0 1 0 | bad 117 * 0 1 1 | bad 118 * 1 0 0 | ok 119 * 1 0 1 | bad 120 * 1 1 0 | bad 121 * 1 1 1 | bad 122 */ 123static inline int __access_ok(unsigned long addr, unsigned long size) 124{ 125 unsigned long flag, tmp; 126 127 __asm__("stc r7_bank, %0\n\t" 128 "mov.l @(8,%0), %0\n\t" 129 "clrt\n\t" 130 "addc %2, %1\n\t" 131 "and %1, %0\n\t" 132 "rotcl %0\n\t" 133 "rotcl %0\n\t" 134 "and #3, %0" 135 : "=&z" (flag), "=r" (tmp) 136 : "r" (addr), "1" (size) 137 : "t"); 138 139 return flag == 0; 140} 141#endif /* CONFIG_MMU */ 142 143static inline int access_ok(int type, const void __user *p, unsigned long size) 144{ 145 unsigned long addr = (unsigned long)p; 146 return __access_ok(addr, size); 147} 148 149/* this function will go away soon - use access_ok() instead */ 150static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size) 151{ 152 return access_ok(type,addr,size) ? 0 : -EFAULT; 153} 154 155/* 156 * Uh, these should become the main single-value transfer routines ... 157 * They automatically use the right size if we just have the right 158 * pointer type ... 159 * 160 * As SuperH uses the same address space for kernel and user data, we 161 * can just do these as direct assignments. 162 * 163 * Careful to not 164 * (a) re-use the arguments for side effects (sizeof is ok) 165 * (b) require any knowledge of processes at this stage 166 */ 167#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) 168#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) 169 170/* 171 * The "__xxx" versions do not do address space checking, useful when 172 * doing multiple accesses to the same area (the user has to do the 173 * checks by hand with "access_ok()") 174 */ 175#define __put_user(x,ptr) \ 176 __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) 177#define __get_user(x,ptr) \ 178 __get_user_nocheck((x),(ptr),sizeof(*(ptr))) 179 180struct __large_struct { unsigned long buf[100]; }; 181#define __m(x) (*(struct __large_struct *)(x)) 182 183#define __get_user_size(x,ptr,size,retval) \ 184do { \ 185 retval = 0; \ 186 switch (size) { \ 187 case 1: \ 188 __get_user_asm(x, ptr, retval, "b"); \ 189 break; \ 190 case 2: \ 191 __get_user_asm(x, ptr, retval, "w"); \ 192 break; \ 193 case 4: \ 194 __get_user_asm(x, ptr, retval, "l"); \ 195 break; \ 196 default: \ 197 __get_user_unknown(); \ 198 break; \ 199 } \ 200} while (0) 201 202#define __get_user_nocheck(x,ptr,size) \ 203({ \ 204 long __gu_err, __gu_val; \ 205 __get_user_size(__gu_val, (ptr), (size), __gu_err); \ 206 (x) = (__typeof__(*(ptr)))__gu_val; \ 207 __gu_err; \ 208}) 209 210#define __get_user_check(x,ptr,size) \ 211({ \ 212 long __gu_err, __gu_val; \ 213 switch (size) { \ 214 case 1: \ 215 __get_user_1(__gu_val, (ptr), __gu_err); \ 216 break; \ 217 case 2: \ 218 __get_user_2(__gu_val, (ptr), __gu_err); \ 219 break; \ 220 case 4: \ 221 __get_user_4(__gu_val, (ptr), __gu_err); \ 222 break; \ 223 default: \ 224 __get_user_unknown(); \ 225 break; \ 226 } \ 227 \ 228 (x) = (__typeof__(*(ptr)))__gu_val; \ 229 __gu_err; \ 230}) 231 232#define __get_user_1(x,addr,err) ({ \ 233__asm__("stc r7_bank, %1\n\t" \ 234 "mov.l @(8,%1), %1\n\t" \ 235 "and %2, %1\n\t" \ 236 "cmp/pz %1\n\t" \ 237 "bt/s 1f\n\t" \ 238 " mov #0, %0\n\t" \ 239 "0:\n" \ 240 "mov #-14, %0\n\t" \ 241 "bra 2f\n\t" \ 242 " mov #0, %1\n" \ 243 "1:\n\t" \ 244 "mov.b @%2, %1\n\t" \ 245 "extu.b %1, %1\n" \ 246 "2:\n" \ 247 ".section __ex_table,\"a\"\n\t" \ 248 ".long 1b, 0b\n\t" \ 249 ".previous" \ 250 : "=&r" (err), "=&r" (x) \ 251 : "r" (addr) \ 252 : "t"); \ 253}) 254 255#define __get_user_2(x,addr,err) ({ \ 256__asm__("stc r7_bank, %1\n\t" \ 257 "mov.l @(8,%1), %1\n\t" \ 258 "and %2, %1\n\t" \ 259 "cmp/pz %1\n\t" \ 260 "bt/s 1f\n\t" \ 261 " mov #0, %0\n\t" \ 262 "0:\n" \ 263 "mov #-14, %0\n\t" \ 264 "bra 2f\n\t" \ 265 " mov #0, %1\n" \ 266 "1:\n\t" \ 267 "mov.w @%2, %1\n\t" \ 268 "extu.w %1, %1\n" \ 269 "2:\n" \ 270 ".section __ex_table,\"a\"\n\t" \ 271 ".long 1b, 0b\n\t" \ 272 ".previous" \ 273 : "=&r" (err), "=&r" (x) \ 274 : "r" (addr) \ 275 : "t"); \ 276}) 277 278#define __get_user_4(x,addr,err) ({ \ 279__asm__("stc r7_bank, %1\n\t" \ 280 "mov.l @(8,%1), %1\n\t" \ 281 "and %2, %1\n\t" \ 282 "cmp/pz %1\n\t" \ 283 "bt/s 1f\n\t" \ 284 " mov #0, %0\n\t" \ 285 "0:\n" \ 286 "mov #-14, %0\n\t" \ 287 "bra 2f\n\t" \ 288 " mov #0, %1\n" \ 289 "1:\n\t" \ 290 "mov.l @%2, %1\n\t" \ 291 "2:\n" \ 292 ".section __ex_table,\"a\"\n\t" \ 293 ".long 1b, 0b\n\t" \ 294 ".previous" \ 295 : "=&r" (err), "=&r" (x) \ 296 : "r" (addr) \ 297 : "t"); \ 298}) 299 300#define __get_user_asm(x, addr, err, insn) \ 301({ \ 302__asm__ __volatile__( \ 303 "1:\n\t" \ 304 "mov." insn " %2, %1\n\t" \ 305 "mov #0, %0\n" \ 306 "2:\n" \ 307 ".section .fixup,\"ax\"\n" \ 308 "3:\n\t" \ 309 "mov #0, %1\n\t" \ 310 "mov.l 4f, %0\n\t" \ 311 "jmp @%0\n\t" \ 312 " mov %3, %0\n" \ 313 "4: .long 2b\n\t" \ 314 ".previous\n" \ 315 ".section __ex_table,\"a\"\n\t" \ 316 ".long 1b, 3b\n\t" \ 317 ".previous" \ 318 :"=&r" (err), "=&r" (x) \ 319 :"m" (__m(addr)), "i" (-EFAULT)); }) 320 321extern void __get_user_unknown(void); 322 323#define __put_user_size(x,ptr,size,retval) \ 324do { \ 325 retval = 0; \ 326 switch (size) { \ 327 case 1: \ 328 __put_user_asm(x, ptr, retval, "b"); \ 329 break; \ 330 case 2: \ 331 __put_user_asm(x, ptr, retval, "w"); \ 332 break; \ 333 case 4: \ 334 __put_user_asm(x, ptr, retval, "l"); \ 335 break; \ 336 case 8: \ 337 __put_user_u64(x, ptr, retval); \ 338 break; \ 339 default: \ 340 __put_user_unknown(); \ 341 } \ 342} while (0) 343 344#define __put_user_nocheck(x,ptr,size) \ 345({ \ 346 long __pu_err; \ 347 __put_user_size((x),(ptr),(size),__pu_err); \ 348 __pu_err; \ 349}) 350 351#define __put_user_check(x,ptr,size) \ 352({ \ 353 long __pu_err = -EFAULT; \ 354 __typeof__(*(ptr)) *__pu_addr = (ptr); \ 355 \ 356 if (__access_ok((unsigned long)__pu_addr,size)) \ 357 __put_user_size((x),__pu_addr,(size),__pu_err); \ 358 __pu_err; \ 359}) 360 361#define __put_user_asm(x, addr, err, insn) \ 362({ \ 363__asm__ __volatile__( \ 364 "1:\n\t" \ 365 "mov." insn " %1, %2\n\t" \ 366 "mov #0, %0\n" \ 367 "2:\n" \ 368 ".section .fixup,\"ax\"\n" \ 369 "3:\n\t" \ 370 "nop\n\t" \ 371 "mov.l 4f, %0\n\t" \ 372 "jmp @%0\n\t" \ 373 "mov %3, %0\n" \ 374 "4: .long 2b\n\t" \ 375 ".previous\n" \ 376 ".section __ex_table,\"a\"\n\t" \ 377 ".long 1b, 3b\n\t" \ 378 ".previous" \ 379 :"=&r" (err) \ 380 :"r" (x), "m" (__m(addr)), "i" (-EFAULT) \ 381 :"memory"); }) 382 383#if defined(__LITTLE_ENDIAN__) 384#define __put_user_u64(val,addr,retval) \ 385({ \ 386__asm__ __volatile__( \ 387 "1:\n\t" \ 388 "mov.l %R1,%2\n\t" \ 389 "mov.l %S1,%T2\n\t" \ 390 "mov #0,%0\n" \ 391 "2:\n" \ 392 ".section .fixup,\"ax\"\n" \ 393 "3:\n\t" \ 394 "nop\n\t" \ 395 "mov.l 4f,%0\n\t" \ 396 "jmp @%0\n\t" \ 397 " mov %3,%0\n" \ 398 "4: .long 2b\n\t" \ 399 ".previous\n" \ 400 ".section __ex_table,\"a\"\n\t" \ 401 ".long 1b, 3b\n\t" \ 402 ".previous" \ 403 : "=r" (retval) \ 404 : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \ 405 : "memory"); }) 406#else 407#define __put_user_u64(val,addr,retval) \ 408({ \ 409__asm__ __volatile__( \ 410 "1:\n\t" \ 411 "mov.l %S1,%2\n\t" \ 412 "mov.l %R1,%T2\n\t" \ 413 "mov #0,%0\n" \ 414 "2:\n" \ 415 ".section .fixup,\"ax\"\n" \ 416 "3:\n\t" \ 417 "nop\n\t" \ 418 "mov.l 4f,%0\n\t" \ 419 "jmp @%0\n\t" \ 420 " mov %3,%0\n" \ 421 "4: .long 2b\n\t" \ 422 ".previous\n" \ 423 ".section __ex_table,\"a\"\n\t" \ 424 ".long 1b, 3b\n\t" \ 425 ".previous" \ 426 : "=r" (retval) \ 427 : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \ 428 : "memory"); }) 429#endif 430 431extern void __put_user_unknown(void); 432 433/* Generic arbitrary sized copy. */ 434/* Return the number of bytes NOT copied */ 435extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); 436 437#define copy_to_user(to,from,n) ({ \ 438void *__copy_to = (void *) (to); \ 439__kernel_size_t __copy_size = (__kernel_size_t) (n); \ 440__kernel_size_t __copy_res; \ 441if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ 442__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ 443} else __copy_res = __copy_size; \ 444__copy_res; }) 445 446#define __copy_to_user(to,from,n) \ 447 __copy_user((void *)(to), \ 448 (void *)(from), n) 449 450#define __copy_to_user_inatomic __copy_to_user 451#define __copy_from_user_inatomic __copy_from_user 452 453 454#define copy_from_user(to,from,n) ({ \ 455void *__copy_to = (void *) (to); \ 456void *__copy_from = (void *) (from); \ 457__kernel_size_t __copy_size = (__kernel_size_t) (n); \ 458__kernel_size_t __copy_res; \ 459if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ 460__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ 461} else __copy_res = __copy_size; \ 462__copy_res; }) 463 464#define __copy_from_user(to,from,n) \ 465 __copy_user((void *)(to), \ 466 (void *)(from), n) 467 468/* 469 * Clear the area and return remaining number of bytes 470 * (on failure. Usually it's 0.) 471 */ 472extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size); 473 474#define clear_user(addr,n) ({ \ 475void * __cl_addr = (addr); \ 476unsigned long __cl_size = (n); \ 477if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \ 478__cl_size = __clear_user(__cl_addr, __cl_size); \ 479__cl_size; }) 480 481static __inline__ int 482__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) 483{ 484 __kernel_size_t res; 485 unsigned long __dummy, _d, _s; 486 487 __asm__ __volatile__( 488 "9:\n" 489 "mov.b @%2+, %1\n\t" 490 "cmp/eq #0, %1\n\t" 491 "bt/s 2f\n" 492 "1:\n" 493 "mov.b %1, @%3\n\t" 494 "dt %7\n\t" 495 "bf/s 9b\n\t" 496 " add #1, %3\n\t" 497 "2:\n\t" 498 "sub %7, %0\n" 499 "3:\n" 500 ".section .fixup,\"ax\"\n" 501 "4:\n\t" 502 "mov.l 5f, %1\n\t" 503 "jmp @%1\n\t" 504 " mov %8, %0\n\t" 505 ".balign 4\n" 506 "5: .long 3b\n" 507 ".previous\n" 508 ".section __ex_table,\"a\"\n" 509 " .balign 4\n" 510 " .long 9b,4b\n" 511 ".previous" 512 : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d) 513 : "0" (__count), "2" (__src), "3" (__dest), "r" (__count), 514 "i" (-EFAULT) 515 : "memory", "t"); 516 517 return res; 518} 519 520#define strncpy_from_user(dest,src,count) ({ \ 521unsigned long __sfu_src = (unsigned long) (src); \ 522int __sfu_count = (int) (count); \ 523long __sfu_res = -EFAULT; \ 524if(__access_ok(__sfu_src, __sfu_count)) { \ 525__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ 526} __sfu_res; }) 527 528/* 529 * Return the size of a string (including the ending 0!) 530 */ 531static __inline__ long __strnlen_user(const char __user *__s, long __n) 532{ 533 unsigned long res; 534 unsigned long __dummy; 535 536 __asm__ __volatile__( 537 "9:\n" 538 "cmp/eq %4, %0\n\t" 539 "bt 2f\n" 540 "1:\t" 541 "mov.b @(%0,%3), %1\n\t" 542 "tst %1, %1\n\t" 543 "bf/s 9b\n\t" 544 " add #1, %0\n" 545 "2:\n" 546 ".section .fixup,\"ax\"\n" 547 "3:\n\t" 548 "mov.l 4f, %1\n\t" 549 "jmp @%1\n\t" 550 " mov %5, %0\n" 551 ".balign 4\n" 552 "4: .long 2b\n" 553 ".previous\n" 554 ".section __ex_table,\"a\"\n" 555 " .balign 4\n" 556 " .long 1b,3b\n" 557 ".previous" 558 : "=z" (res), "=&r" (__dummy) 559 : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT) 560 : "t"); 561 return res; 562} 563 564static __inline__ long strnlen_user(const char __user *s, long n) 565{ 566 if (!access_ok(VERIFY_READ, s, n)) 567 return 0; 568 else 569 return __strnlen_user(s, n); 570} 571 572static __inline__ long strlen_user(const char __user *s) 573{ 574 if (!access_ok(VERIFY_READ, s, 0)) 575 return 0; 576 else 577 return __strnlen_user(s, ~0UL >> 1); 578} 579 580/* 581 * The exception table consists of pairs of addresses: the first is the 582 * address of an instruction that is allowed to fault, and the second is 583 * the address at which the program should continue. No registers are 584 * modified, so it is entirely up to the continuation code to figure out 585 * what to do. 586 * 587 * All the routines below use bits of fixup code that are out of line 588 * with the main instruction path. This means when everything is well, 589 * we don't even have to jump over them. Further, they do not intrude 590 * on our cache or tlb entries. 591 */ 592 593struct exception_table_entry 594{ 595 unsigned long insn, fixup; 596}; 597 598extern int fixup_exception(struct pt_regs *regs); 599 600#endif /* __ASM_SH_UACCESS_H */