Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16-rc5 464 lines 13 kB view raw
1#ifndef _ARCH_POWERPC_UACCESS_H 2#define _ARCH_POWERPC_UACCESS_H 3 4#ifdef __KERNEL__ 5#ifndef __ASSEMBLY__ 6 7#include <linux/sched.h> 8#include <linux/errno.h> 9#include <asm/processor.h> 10 11#define VERIFY_READ 0 12#define VERIFY_WRITE 1 13 14/* 15 * The fs value determines whether argument validity checking should be 16 * performed or not. If get_fs() == USER_DS, checking is performed, with 17 * get_fs() == KERNEL_DS, checking is bypassed. 18 * 19 * For historical reasons, these macros are grossly misnamed. 20 * 21 * The fs/ds values are now the highest legal address in the "segment". 22 * This simplifies the checking in the routines below. 23 */ 24 25#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 26 27#define KERNEL_DS MAKE_MM_SEG(~0UL) 28#ifdef __powerpc64__ 29/* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */ 30#define USER_DS MAKE_MM_SEG(TASK_SIZE_USER64 - 1) 31#else 32#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) 33#endif 34 35#define get_ds() (KERNEL_DS) 36#define get_fs() (current->thread.fs) 37#define set_fs(val) (current->thread.fs = (val)) 38 39#define segment_eq(a, b) ((a).seg == (b).seg) 40 41#ifdef __powerpc64__ 42/* 43 * This check is sufficient because there is a large enough 44 * gap between user addresses and the kernel addresses 45 */ 46#define __access_ok(addr, size, segment) \ 47 (((addr) <= (segment).seg) && ((size) <= (segment).seg)) 48 49#else 50 51#define __access_ok(addr, size, segment) \ 52 (((addr) <= (segment).seg) && \ 53 (((size) == 0) || (((size) - 1) <= ((segment).seg - (addr))))) 54 55#endif 56 57#define access_ok(type, addr, size) \ 58 (__chk_user_ptr(addr), \ 59 __access_ok((__force unsigned long)(addr), (size), get_fs())) 60 61/* 62 * The exception table consists of pairs of addresses: the first is the 63 * address of an instruction that is allowed to fault, and the second is 64 * the address at which the program should continue. No registers are 65 * modified, so it is entirely up to the continuation code to figure out 66 * what to do. 67 * 68 * All the routines below use bits of fixup code that are out of line 69 * with the main instruction path. This means when everything is well, 70 * we don't even have to jump over them. Further, they do not intrude 71 * on our cache or tlb entries. 72 */ 73 74struct exception_table_entry { 75 unsigned long insn; 76 unsigned long fixup; 77}; 78 79/* 80 * These are the main single-value transfer routines. They automatically 81 * use the right size if we just have the right pointer type. 82 * 83 * This gets kind of ugly. We want to return _two_ values in "get_user()" 84 * and yet we don't want to do any pointers, because that is too much 85 * of a performance impact. Thus we have a few rather ugly macros here, 86 * and hide all the ugliness from the user. 87 * 88 * The "__xxx" versions of the user access functions are versions that 89 * do not verify the address space, that must have been done previously 90 * with a separate "access_ok()" call (this is used when we do multiple 91 * accesses to the same area of user memory). 92 * 93 * As we use the same address space for kernel and user data on the 94 * PowerPC, we can just do these as direct assignments. (Of course, the 95 * exception handling means that it's no longer "just"...) 96 * 97 * The "user64" versions of the user access functions are versions that 98 * allow access of 64-bit data. The "get_user" functions do not 99 * properly handle 64-bit data because the value gets down cast to a long. 100 * The "put_user" functions already handle 64-bit data properly but we add 101 * "user64" versions for completeness 102 */ 103#define get_user(x, ptr) \ 104 __get_user_check((x), (ptr), sizeof(*(ptr))) 105#define put_user(x, ptr) \ 106 __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) 107 108#define __get_user(x, ptr) \ 109 __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 110#define __put_user(x, ptr) \ 111 __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) 112#ifndef __powerpc64__ 113#define __get_user64(x, ptr) \ 114 __get_user64_nocheck((x), (ptr), sizeof(*(ptr))) 115#define __put_user64(x, ptr) __put_user(x, ptr) 116#endif 117 118#define __get_user_unaligned __get_user 119#define __put_user_unaligned __put_user 120 121extern long __put_user_bad(void); 122 123/* 124 * We don't tell gcc that we are accessing memory, but this is OK 125 * because we do not write to any memory gcc knows about, so there 126 * are no aliasing issues. 127 */ 128#define __put_user_asm(x, addr, err, op) \ 129 __asm__ __volatile__( \ 130 "1: " op " %1,0(%2) # put_user\n" \ 131 "2:\n" \ 132 ".section .fixup,\"ax\"\n" \ 133 "3: li %0,%3\n" \ 134 " b 2b\n" \ 135 ".previous\n" \ 136 ".section __ex_table,\"a\"\n" \ 137 " .balign %5\n" \ 138 PPC_LONG "1b,3b\n" \ 139 ".previous" \ 140 : "=r" (err) \ 141 : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\ 142 "i"(sizeof(unsigned long))) 143 144#ifdef __powerpc64__ 145#define __put_user_asm2(x, ptr, retval) \ 146 __put_user_asm(x, ptr, retval, "std") 147#else /* __powerpc64__ */ 148#define __put_user_asm2(x, addr, err) \ 149 __asm__ __volatile__( \ 150 "1: stw %1,0(%2)\n" \ 151 "2: stw %1+1,4(%2)\n" \ 152 "3:\n" \ 153 ".section .fixup,\"ax\"\n" \ 154 "4: li %0,%3\n" \ 155 " b 3b\n" \ 156 ".previous\n" \ 157 ".section __ex_table,\"a\"\n" \ 158 " .balign %5\n" \ 159 PPC_LONG "1b,4b\n" \ 160 PPC_LONG "2b,4b\n" \ 161 ".previous" \ 162 : "=r" (err) \ 163 : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\ 164 "i"(sizeof(unsigned long))) 165#endif /* __powerpc64__ */ 166 167#define __put_user_size(x, ptr, size, retval) \ 168do { \ 169 retval = 0; \ 170 switch (size) { \ 171 case 1: __put_user_asm(x, ptr, retval, "stb"); break; \ 172 case 2: __put_user_asm(x, ptr, retval, "sth"); break; \ 173 case 4: __put_user_asm(x, ptr, retval, "stw"); break; \ 174 case 8: __put_user_asm2(x, ptr, retval); break; \ 175 default: __put_user_bad(); \ 176 } \ 177} while (0) 178 179#define __put_user_nocheck(x, ptr, size) \ 180({ \ 181 long __pu_err; \ 182 might_sleep(); \ 183 __chk_user_ptr(ptr); \ 184 __put_user_size((x), (ptr), (size), __pu_err); \ 185 __pu_err; \ 186}) 187 188#define __put_user_check(x, ptr, size) \ 189({ \ 190 long __pu_err = -EFAULT; \ 191 __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ 192 might_sleep(); \ 193 if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ 194 __put_user_size((x), __pu_addr, (size), __pu_err); \ 195 __pu_err; \ 196}) 197 198extern long __get_user_bad(void); 199 200#define __get_user_asm(x, addr, err, op) \ 201 __asm__ __volatile__( \ 202 "1: "op" %1,0(%2) # get_user\n" \ 203 "2:\n" \ 204 ".section .fixup,\"ax\"\n" \ 205 "3: li %0,%3\n" \ 206 " li %1,0\n" \ 207 " b 2b\n" \ 208 ".previous\n" \ 209 ".section __ex_table,\"a\"\n" \ 210 " .balign %5\n" \ 211 PPC_LONG "1b,3b\n" \ 212 ".previous" \ 213 : "=r" (err), "=r" (x) \ 214 : "b" (addr), "i" (-EFAULT), "0" (err), \ 215 "i"(sizeof(unsigned long))) 216 217#ifdef __powerpc64__ 218#define __get_user_asm2(x, addr, err) \ 219 __get_user_asm(x, addr, err, "ld") 220#else /* __powerpc64__ */ 221#define __get_user_asm2(x, addr, err) \ 222 __asm__ __volatile__( \ 223 "1: lwz %1,0(%2)\n" \ 224 "2: lwz %1+1,4(%2)\n" \ 225 "3:\n" \ 226 ".section .fixup,\"ax\"\n" \ 227 "4: li %0,%3\n" \ 228 " li %1,0\n" \ 229 " li %1+1,0\n" \ 230 " b 3b\n" \ 231 ".previous\n" \ 232 ".section __ex_table,\"a\"\n" \ 233 " .balign %5\n" \ 234 PPC_LONG "1b,4b\n" \ 235 PPC_LONG "2b,4b\n" \ 236 ".previous" \ 237 : "=r" (err), "=&r" (x) \ 238 : "b" (addr), "i" (-EFAULT), "0" (err), \ 239 "i"(sizeof(unsigned long))) 240#endif /* __powerpc64__ */ 241 242#define __get_user_size(x, ptr, size, retval) \ 243do { \ 244 retval = 0; \ 245 __chk_user_ptr(ptr); \ 246 if (size > sizeof(x)) \ 247 (x) = __get_user_bad(); \ 248 switch (size) { \ 249 case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \ 250 case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \ 251 case 4: __get_user_asm(x, ptr, retval, "lwz"); break; \ 252 case 8: __get_user_asm2(x, ptr, retval); break; \ 253 default: (x) = __get_user_bad(); \ 254 } \ 255} while (0) 256 257#define __get_user_nocheck(x, ptr, size) \ 258({ \ 259 long __gu_err; \ 260 unsigned long __gu_val; \ 261 __chk_user_ptr(ptr); \ 262 might_sleep(); \ 263 __get_user_size(__gu_val, (ptr), (size), __gu_err); \ 264 (x) = (__typeof__(*(ptr)))__gu_val; \ 265 __gu_err; \ 266}) 267 268#ifndef __powerpc64__ 269#define __get_user64_nocheck(x, ptr, size) \ 270({ \ 271 long __gu_err; \ 272 long long __gu_val; \ 273 __chk_user_ptr(ptr); \ 274 might_sleep(); \ 275 __get_user_size(__gu_val, (ptr), (size), __gu_err); \ 276 (x) = (__typeof__(*(ptr)))__gu_val; \ 277 __gu_err; \ 278}) 279#endif /* __powerpc64__ */ 280 281#define __get_user_check(x, ptr, size) \ 282({ \ 283 long __gu_err = -EFAULT; \ 284 unsigned long __gu_val = 0; \ 285 const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ 286 might_sleep(); \ 287 if (access_ok(VERIFY_READ, __gu_addr, (size))) \ 288 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ 289 (x) = (__typeof__(*(ptr)))__gu_val; \ 290 __gu_err; \ 291}) 292 293/* more complex routines */ 294 295extern unsigned long __copy_tofrom_user(void __user *to, 296 const void __user *from, unsigned long size); 297 298#ifndef __powerpc64__ 299 300extern inline unsigned long copy_from_user(void *to, 301 const void __user *from, unsigned long n) 302{ 303 unsigned long over; 304 305 if (access_ok(VERIFY_READ, from, n)) 306 return __copy_tofrom_user((__force void __user *)to, from, n); 307 if ((unsigned long)from < TASK_SIZE) { 308 over = (unsigned long)from + n - TASK_SIZE; 309 return __copy_tofrom_user((__force void __user *)to, from, 310 n - over) + over; 311 } 312 return n; 313} 314 315extern inline unsigned long copy_to_user(void __user *to, 316 const void *from, unsigned long n) 317{ 318 unsigned long over; 319 320 if (access_ok(VERIFY_WRITE, to, n)) 321 return __copy_tofrom_user(to, (__force void __user *)from, n); 322 if ((unsigned long)to < TASK_SIZE) { 323 over = (unsigned long)to + n - TASK_SIZE; 324 return __copy_tofrom_user(to, (__force void __user *)from, 325 n - over) + over; 326 } 327 return n; 328} 329 330#else /* __powerpc64__ */ 331 332#define __copy_in_user(to, from, size) \ 333 __copy_tofrom_user((to), (from), (size)) 334 335extern unsigned long copy_from_user(void *to, const void __user *from, 336 unsigned long n); 337extern unsigned long copy_to_user(void __user *to, const void *from, 338 unsigned long n); 339extern unsigned long copy_in_user(void __user *to, const void __user *from, 340 unsigned long n); 341 342#endif /* __powerpc64__ */ 343 344static inline unsigned long __copy_from_user_inatomic(void *to, 345 const void __user *from, unsigned long n) 346{ 347 if (__builtin_constant_p(n) && (n <= 8)) { 348 unsigned long ret; 349 350 switch (n) { 351 case 1: 352 __get_user_size(*(u8 *)to, from, 1, ret); 353 break; 354 case 2: 355 __get_user_size(*(u16 *)to, from, 2, ret); 356 break; 357 case 4: 358 __get_user_size(*(u32 *)to, from, 4, ret); 359 break; 360 case 8: 361 __get_user_size(*(u64 *)to, from, 8, ret); 362 break; 363 } 364 if (ret == 0) 365 return 0; 366 } 367 return __copy_tofrom_user((__force void __user *)to, from, n); 368} 369 370static inline unsigned long __copy_to_user_inatomic(void __user *to, 371 const void *from, unsigned long n) 372{ 373 if (__builtin_constant_p(n) && (n <= 8)) { 374 unsigned long ret; 375 376 switch (n) { 377 case 1: 378 __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret); 379 break; 380 case 2: 381 __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret); 382 break; 383 case 4: 384 __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret); 385 break; 386 case 8: 387 __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret); 388 break; 389 } 390 if (ret == 0) 391 return 0; 392 } 393 return __copy_tofrom_user(to, (__force const void __user *)from, n); 394} 395 396static inline unsigned long __copy_from_user(void *to, 397 const void __user *from, unsigned long size) 398{ 399 might_sleep(); 400 return __copy_from_user_inatomic(to, from, size); 401} 402 403static inline unsigned long __copy_to_user(void __user *to, 404 const void *from, unsigned long size) 405{ 406 might_sleep(); 407 return __copy_to_user_inatomic(to, from, size); 408} 409 410extern unsigned long __clear_user(void __user *addr, unsigned long size); 411 412static inline unsigned long clear_user(void __user *addr, unsigned long size) 413{ 414 might_sleep(); 415 if (likely(access_ok(VERIFY_WRITE, addr, size))) 416 return __clear_user(addr, size); 417 if ((unsigned long)addr < TASK_SIZE) { 418 unsigned long over = (unsigned long)addr + size - TASK_SIZE; 419 return __clear_user(addr, size - over) + over; 420 } 421 return size; 422} 423 424extern int __strncpy_from_user(char *dst, const char __user *src, long count); 425 426static inline long strncpy_from_user(char *dst, const char __user *src, 427 long count) 428{ 429 might_sleep(); 430 if (likely(access_ok(VERIFY_READ, src, 1))) 431 return __strncpy_from_user(dst, src, count); 432 return -EFAULT; 433} 434 435/* 436 * Return the size of a string (including the ending 0) 437 * 438 * Return 0 for error 439 */ 440extern int __strnlen_user(const char __user *str, long len, unsigned long top); 441 442/* 443 * Returns the length of the string at str (including the null byte), 444 * or 0 if we hit a page we can't access, 445 * or something > len if we didn't find a null byte. 446 * 447 * The `top' parameter to __strnlen_user is to make sure that 448 * we can never overflow from the user area into kernel space. 449 */ 450static inline int strnlen_user(const char __user *str, long len) 451{ 452 unsigned long top = current->thread.fs.seg; 453 454 if ((unsigned long)str > top) 455 return 0; 456 return __strnlen_user(str, len, top); 457} 458 459#define strlen_user(str) strnlen_user((str), 0x7ffffffe) 460 461#endif /* __ASSEMBLY__ */ 462#endif /* __KERNEL__ */ 463 464#endif /* _ARCH_POWERPC_UACCESS_H */