uaccess.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _PPC64_UACCESS_H
  2. #define _PPC64_UACCESS_H
  3. /* 
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version
  7.  * 2 of the License, or (at your option) any later version.
  8.  */
  9. #ifndef __ASSEMBLY__
  10. #include <linux/sched.h>
  11. #include <linux/errno.h>
  12. #include <asm/processor.h>
  13. #define VERIFY_READ 0
  14. #define VERIFY_WRITE 1
  15. /*
  16.  * The fs value determines whether argument validity checking should be
  17.  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  18.  * get_fs() == KERNEL_DS, checking is bypassed.
  19.  *
  20.  * For historical reasons, these macros are grossly misnamed.
  21.  */
  22. #define KERNEL_DS ((mm_segment_t) { 0 })
  23. #define USER_DS ((mm_segment_t) { 1 })
  24. #define get_ds() (KERNEL_DS)
  25. #define get_fs() (current->thread.fs)
  26. #define set_fs(val) (current->thread.fs = (val))
  27. #define segment_eq(a,b) ((a).seg == (b).seg)
  28. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  29. #define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
  30. #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
  31. #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
  32. static inline int verify_area(int type, const void * addr, unsigned long size)
  33. {
  34. return access_ok(type,addr,size) ? 0 : -EFAULT;
  35. }
  36. /*
  37.  * The exception table consists of pairs of addresses: the first is the
  38.  * address of an instruction that is allowed to fault, and the second is
  39.  * the address at which the program should continue.  No registers are
  40.  * modified, so it is entirely up to the continuation code to figure out
  41.  * what to do.
  42.  *
  43.  * All the routines below use bits of fixup code that are out of line
  44.  * with the main instruction path.  This means when everything is well,
  45.  * we don't even have to jump over them.  Further, they do not intrude
  46.  * on our cache or tlb entries.
  47.  */
  48. struct exception_table_entry
  49. {
  50. unsigned long insn, fixup;
  51. };
  52. /* Returns 0 if exception not found and fixup otherwise.  */
  53. extern unsigned long search_exception_table(unsigned long);
  54. extern void sort_exception_table(void);
  55. /*
  56.  * These are the main single-value transfer routines.  They automatically
  57.  * use the right size if we just have the right pointer type.
  58.  *
  59.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  60.  * and yet we don't want to do any pointers, because that is too much
  61.  * of a performance impact. Thus we have a few rather ugly macros here,
  62.  * and hide all the uglyness from the user.
  63.  *
  64.  * The "__xxx" versions of the user access functions are versions that
  65.  * do not verify the address space, that must have been done previously
  66.  * with a separate "access_ok()" call (this is used when we do multiple
  67.  * accesses to the same area of user memory).
  68.  *
  69.  * As we use the same address space for kernel and user data on the
  70.  * PowerPC, we can just do these as direct assignments.  (Of course, the
  71.  * exception handling means that it's no longer "just"...)
  72.  */
  73. #define get_user(x,ptr) 
  74.   __get_user_check((x),(ptr),sizeof(*(ptr)))
  75. #define put_user(x,ptr) 
  76.   __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  77. #define __get_user(x,ptr) 
  78.   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
  79. #define __put_user(x,ptr) 
  80.   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  81. extern long __put_user_bad(void);
  82. #define __put_user_nocheck(x,ptr,size)
  83. ({
  84. long __pu_err;
  85. __put_user_size((x),(ptr),(size),__pu_err);
  86. __pu_err;
  87. })
  88. #define __put_user_check(x,ptr,size)
  89. ({
  90. long __pu_err = -EFAULT;
  91. __typeof__(*(ptr)) *__pu_addr = (ptr);
  92. if (access_ok(VERIFY_WRITE,__pu_addr,size))
  93. __put_user_size((x),__pu_addr,(size),__pu_err);
  94. __pu_err;
  95. })
  96. #define __put_user_size(x,ptr,size,retval)
  97. do {
  98. retval = 0;
  99. switch (size) {
  100.   case 1: __put_user_asm(x,ptr,retval,"stb"); break;
  101.   case 2: __put_user_asm(x,ptr,retval,"sth"); break;
  102.   case 4: __put_user_asm(x,ptr,retval,"stw"); break;
  103.   case 8: __put_user_asm(x,ptr,retval,"std"); break; 
  104.   default: __put_user_bad();
  105. }
  106. } while (0)
  107. /*
  108.  * We don't tell gcc that we are accessing memory, but this is OK
  109.  * because we do not write to any memory gcc knows about, so there
  110.  * are no aliasing issues.
  111.  */
  112. #define __put_user_asm(x, addr, err, op)
  113. __asm__ __volatile__(
  114. "1: "op" %1,0(%2)n"
  115. "2:n"
  116. ".section .fixup,"ax"n"
  117. "3: li %0,%3n"
  118. " b 2bn"
  119. ".previousn"
  120. ".section __ex_table,"a"n"
  121. " .align 3n"
  122. " .llong 1b,3bn"
  123. ".previous"
  124. : "=r"(err)
  125. : "r"(x), "b"(addr), "i"(-EFAULT), "0"(err))
  126. #define __get_user_nocheck(x,ptr,size)
  127. ({
  128. long __gu_err, __gu_val;
  129. __get_user_size(__gu_val,(ptr),(size),__gu_err);
  130. (x) = (__typeof__(*(ptr)))__gu_val;
  131. __gu_err;
  132. })
  133. #define __get_user_check(x,ptr,size)
  134. ({
  135. long __gu_err = -EFAULT, __gu_val = 0;
  136. const __typeof__(*(ptr)) *__gu_addr = (ptr);
  137. if (access_ok(VERIFY_READ,__gu_addr,size))
  138. __get_user_size(__gu_val,__gu_addr,(size),__gu_err);
  139. (x) = (__typeof__(*(ptr)))__gu_val;
  140. __gu_err;
  141. })
  142. extern long __get_user_bad(void);
  143. #define __get_user_size(x,ptr,size,retval)
  144. do {
  145. retval = 0;
  146. switch (size) {
  147.   case 1: __get_user_asm(x,ptr,retval,"lbz"); break;
  148.   case 2: __get_user_asm(x,ptr,retval,"lhz"); break;
  149.   case 4: __get_user_asm(x,ptr,retval,"lwz"); break;
  150.   case 8: __get_user_asm(x,ptr,retval,"ld");  break;    
  151.   default: (x) = __get_user_bad();
  152. }
  153. } while (0)
  154. #define __get_user_asm(x, addr, err, op)
  155. __asm__ __volatile__(
  156. "1: "op" %1,0(%2)n"
  157. "2:n"
  158. ".section .fixup,"ax"n"
  159. "3: li %0,%3n"
  160. " li %1,0n"
  161. " b 2bn"
  162. ".previousn"
  163. ".section __ex_table,"a"n"
  164. " .align 3n"
  165. " .llong 1b,3bn"
  166. ".previous"
  167. : "=r"(err), "=r"(x)
  168. : "b"(addr), "i"(-EFAULT), "0"(err))
  169. /* more complex routines */
  170. extern unsigned long __copy_tofrom_user(void *to, const void *from, unsigned long size);
  171. static inline unsigned long
  172. copy_from_user(void *to, const void *from, unsigned long n)
  173. {
  174. unsigned long over;
  175. if (access_ok(VERIFY_READ, from, n))
  176. return __copy_tofrom_user(to, from, n);
  177. if ((unsigned long)from < TASK_SIZE) {
  178. over = (unsigned long)from + n - TASK_SIZE;
  179. return __copy_tofrom_user(to, from, n - over) + over;
  180. }
  181. return n;
  182. }
  183. static inline unsigned long
  184. copy_to_user(void *to, const void *from, unsigned long n)
  185. {
  186. unsigned long over;
  187. if (access_ok(VERIFY_WRITE, to, n))
  188. return __copy_tofrom_user(to, from, n);
  189. if ((unsigned long)to < TASK_SIZE) {
  190. over = (unsigned long)to + n - TASK_SIZE;
  191. return __copy_tofrom_user(to, from, n - over) + over;
  192. }
  193. return n;
  194. }
  195. #define __copy_from_user(to, from, size) 
  196. __copy_tofrom_user((to), (from), (size))
  197. #define __copy_to_user(to, from, size) 
  198. __copy_tofrom_user((to), (from), (size))
  199. extern unsigned long __clear_user(void *addr, unsigned long size);
  200. static inline unsigned long
  201. clear_user(void *addr, unsigned long size)
  202. {
  203. if (access_ok(VERIFY_WRITE, addr, size))
  204. return __clear_user(addr, size);
  205. if ((unsigned long)addr < TASK_SIZE) {
  206. unsigned long over = (unsigned long)addr + size - TASK_SIZE;
  207. return __clear_user(addr, size - over) + over;
  208. }
  209. return size;
  210. }
  211. extern int __strncpy_from_user(char *dst, const char *src, long count);
  212. static inline long
  213. strncpy_from_user(char *dst, const char *src, long count)
  214. {
  215. if (access_ok(VERIFY_READ, src, 1))
  216. return __strncpy_from_user(dst, src, count);
  217. return -EFAULT;
  218. }
  219. /*
  220.  * Return the size of a string (including the ending 0)
  221.  *
  222.  * Return 0 for error
  223.  */
  224. extern int __strnlen_user(const char *str, long len, unsigned long top);
  225. /*
  226.  * Returns the length of the string at str (including the null byte),
  227.  * or 0 if we hit a page we can't access,
  228.  * or something > len if we didn't find a null byte.
  229.  *
  230.  * The `top' parameter to __strnlen_user is to make sure that
  231.  * we can never overflow from the user area into kernel space.
  232.  */
  233. static inline int strnlen_user(const char *str, long len)
  234. {
  235. unsigned long top = __kernel_ok? ~0UL: TASK_SIZE - 1;
  236. if ((unsigned long)str > top)
  237. return 0;
  238. return __strnlen_user(str, len, top);
  239. }
  240. #define strlen_user(str) strnlen_user((str), 0x7ffffffe)
  241. #endif  /* __ASSEMBLY__ */
  242. #endif /* _PPC64_UACCESS_H */