uaccess.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: uaccess.h,v 1.24 2001/10/30 04:32:24 davem Exp $
  2.  * uaccess.h: User space memore access functions.
  3.  *
  4.  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  6.  */
  7. #ifndef _ASM_UACCESS_H
  8. #define _ASM_UACCESS_H
  9. #ifdef __KERNEL__
  10. #include <linux/sched.h>
  11. #include <linux/string.h>
  12. #include <asm/vac-ops.h>
  13. #include <asm/a.out.h>
  14. #endif
  15. #ifndef __ASSEMBLY__
  16. /* Sparc is not segmented, however we need to be able to fool verify_area()
  17.  * when doing system calls from kernel mode legitimately.
  18.  *
  19.  * "For historical reasons, these macros are grossly misnamed." -Linus
  20.  */
  21. #define KERNEL_DS   ((mm_segment_t) { 0 })
  22. #define USER_DS     ((mm_segment_t) { -1 })
  23. #define VERIFY_READ 0
  24. #define VERIFY_WRITE 1
  25. #define get_ds() (KERNEL_DS)
  26. #define get_fs() (current->thread.current_ds)
  27. #define set_fs(val) ((current->thread.current_ds) = (val))
  28. #define segment_eq(a,b) ((a).seg == (b).seg)
  29. /* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test
  30.  * can be fairly lightweight.
  31.  * No one can read/write anything from userland in the kernel space by setting
  32.  * large size and address near to PAGE_OFFSET - a fault will break his intentions.
  33.  */
  34. #define __user_ok(addr,size) ((addr) < STACK_TOP)
  35. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  36. #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
  37. #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
  38. extern inline int verify_area(int type, const void * addr, unsigned long size)
  39. {
  40. return access_ok(type,addr,size)?0:-EFAULT;
  41. }
  42. /*
  43.  * The exception table consists of pairs of addresses: the first is the
  44.  * address of an instruction that is allowed to fault, and the second is
  45.  * the address at which the program should continue.  No registers are
  46.  * modified, so it is entirely up to the continuation code to figure out
  47.  * what to do.
  48.  *
  49.  * All the routines below use bits of fixup code that are out of line
  50.  * with the main instruction path.  This means when everything is well,
  51.  * we don't even have to jump over them.  Further, they do not intrude
  52.  * on our cache or tlb entries.
  53.  *
  54.  * There is a special way how to put a range of potentially faulting
  55.  * insns (like twenty ldd/std's with now intervening other instructions)
  56.  * You specify address of first in insn and 0 in fixup and in the next
  57.  * exception_table_entry you specify last potentially faulting insn + 1
  58.  * and in fixup the routine which should handle the fault.
  59.  * That fixup code will get
  60.  * (faulting_insn_address - first_insn_in_the_range_address)/4
  61.  * in %g2 (ie. index of the faulting instruction in the range).
  62.  */
  63. struct exception_table_entry
  64. {
  65.         unsigned long insn, fixup;
  66. };
  67. /* Returns 0 if exception not found and fixup otherwise.  */
  68. extern unsigned long search_exception_table(unsigned long, unsigned long *);
  69. extern void __ret_efault(void);
  70. /* Uh, these should become the main single-value transfer routines..
  71.  * They automatically use the right size if we just have the right
  72.  * pointer type..
  73.  *
  74.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  75.  * and yet we don't want to do any pointers, because that is too much
  76.  * of a performance impact. Thus we have a few rather ugly macros here,
  77.  * and hide all the uglyness from the user.
  78.  */
  79. #define put_user(x,ptr) ({ 
  80. unsigned long __pu_addr = (unsigned long)(ptr); 
  81. __put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
  82. #define get_user(x,ptr) ({ 
  83. unsigned long __gu_addr = (unsigned long)(ptr); 
  84. __get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
  85. /*
  86.  * The "__xxx" versions do not do address space checking, useful when
  87.  * doing multiple accesses to the same area (the user has to do the
  88.  * checks by hand with "access_ok()")
  89.  */
  90. #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
  91. #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
  92. struct __large_struct { unsigned long buf[100]; };
  93. #define __m(x) ((struct __large_struct *)(x))
  94. #define __put_user_check(x,addr,size) ({ 
  95. register int __pu_ret; 
  96. if (__access_ok(addr,size)) { 
  97. switch (size) { 
  98. case 1: __put_user_asm(x,b,addr,__pu_ret); break; 
  99. case 2: __put_user_asm(x,h,addr,__pu_ret); break; 
  100. case 4: __put_user_asm(x,,addr,__pu_ret); break; 
  101. case 8: __put_user_asm(x,d,addr,__pu_ret); break; 
  102. default: __pu_ret = __put_user_bad(); break; 
  103. } } else { __pu_ret = -EFAULT; } __pu_ret; })
  104. #define __put_user_check_ret(x,addr,size,retval) ({ 
  105. register int __foo __asm__ ("l1"); 
  106. if (__access_ok(addr,size)) { 
  107. switch (size) { 
  108. case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; 
  109. case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; 
  110. case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; 
  111. case 8: __put_user_asm_ret(x,d,addr,retval,__foo); break; 
  112. default: if (__put_user_bad()) return retval; break; 
  113. } } else return retval; })
  114. #define __put_user_nocheck(x,addr,size) ({ 
  115. register int __pu_ret; 
  116. switch (size) { 
  117. case 1: __put_user_asm(x,b,addr,__pu_ret); break; 
  118. case 2: __put_user_asm(x,h,addr,__pu_ret); break; 
  119. case 4: __put_user_asm(x,,addr,__pu_ret); break; 
  120. case 8: __put_user_asm(x,d,addr,__pu_ret); break; 
  121. default: __pu_ret = __put_user_bad(); break; 
  122. } __pu_ret; })
  123. #define __put_user_nocheck_ret(x,addr,size,retval) ({ 
  124. register int __foo __asm__ ("l1"); 
  125. switch (size) { 
  126. case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; 
  127. case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; 
  128. case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; 
  129. case 8: __put_user_asm_ret(x,d,addr,retval,__foo); break; 
  130. default: if (__put_user_bad()) return retval; break; 
  131. } })
  132. #define __put_user_asm(x,size,addr,ret)
  133. __asm__ __volatile__(
  134. "/* Put user asm, inline. */n"
  135. "1:t" "st"#size " %1, %2nt"
  136. "clr %0n"
  137. "2:nnt"
  138. ".section .fixup,#alloc,#execinstrnt"
  139. ".align 4n"
  140. "3:nt"
  141. "b 2bnt"
  142. " mov %3, %0nt"
  143.         ".previousnnt"
  144. ".section __ex_table,#allocnt"
  145. ".align 4nt"
  146. ".word 1b, 3bnt"
  147. ".previousnnt"
  148.        : "=&r" (ret) : "r" (x), "m" (*__m(addr)),
  149.  "i" (-EFAULT))
  150. #define __put_user_asm_ret(x,size,addr,ret,foo)
  151. if (__builtin_constant_p(ret) && ret == -EFAULT)
  152. __asm__ __volatile__(
  153. "/* Put user asm ret, inline. */n"
  154. "1:t" "st"#size " %1, %2nnt"
  155. ".section __ex_table,#allocnt"
  156. ".align 4nt"
  157. ".word 1b, __ret_efaultnnt"
  158. ".previousnnt"
  159.        : "=r" (foo) : "r" (x), "m" (*__m(addr)));
  160. else
  161. __asm__ __volatile(
  162. "/* Put user asm ret, inline. */n"
  163. "1:t" "st"#size " %1, %2nnt"
  164. ".section .fixup,#alloc,#execinstrnt"
  165. ".align 4n"
  166. "3:nt"
  167. "retnt"
  168. " restore %%g0, %3, %%o0nt"
  169. ".previousnnt"
  170. ".section __ex_table,#allocnt"
  171. ".align 4nt"
  172. ".word 1b, 3bnnt"
  173. ".previousnnt"
  174.        : "=r" (foo) : "r" (x), "m" (*__m(addr)), "i" (ret))
  175. extern int __put_user_bad(void);
  176. #define __get_user_check(x,addr,size,type) ({ 
  177. register int __gu_ret; 
  178. register unsigned long __gu_val; 
  179. if (__access_ok(addr,size)) { 
  180. switch (size) { 
  181. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; 
  182. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; 
  183. case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; 
  184. case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; 
  185. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; 
  186. } } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (type) __gu_val; __gu_ret; })
  187. #define __get_user_check_ret(x,addr,size,type,retval) ({ 
  188. register unsigned long __gu_val __asm__ ("l1"); 
  189. if (__access_ok(addr,size)) { 
  190. switch (size) { 
  191. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; 
  192. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; 
  193. case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; 
  194. case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; 
  195. default: if (__get_user_bad()) return retval; 
  196. } x = (type) __gu_val; } else return retval; })
  197. #define __get_user_nocheck(x,addr,size,type) ({ 
  198. register int __gu_ret; 
  199. register unsigned long __gu_val; 
  200. switch (size) { 
  201. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; 
  202. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; 
  203. case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; 
  204. case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; 
  205. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; 
  206. } x = (type) __gu_val; __gu_ret; })
  207. #define __get_user_nocheck_ret(x,addr,size,type,retval) ({ 
  208. register unsigned long __gu_val __asm__ ("l1"); 
  209. switch (size) { 
  210. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; 
  211. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; 
  212. case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; 
  213. case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; 
  214. default: if (__get_user_bad()) return retval; 
  215. } x = (type) __gu_val; })
  216. #define __get_user_asm(x,size,addr,ret)
  217. __asm__ __volatile__(
  218. "/* Get user asm, inline. */n"
  219. "1:t" "ld"#size " %2, %1nt"
  220. "clr %0n"
  221. "2:nnt"
  222. ".section .fixup,#alloc,#execinstrnt"
  223. ".align 4n"
  224. "3:nt"
  225. "clr %1nt"
  226. "b 2bnt"
  227. " mov %3, %0nnt"
  228. ".previousnt"
  229. ".section __ex_table,#allocnt"
  230. ".align 4nt"
  231. ".word 1b, 3bnnt"
  232. ".previousnt"
  233.        : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)),
  234.  "i" (-EFAULT))
  235. #define __get_user_asm_ret(x,size,addr,retval)
  236. if (__builtin_constant_p(retval) && retval == -EFAULT)
  237. __asm__ __volatile__(
  238. "/* Get user asm ret, inline. */n"
  239. "1:t" "ld"#size " %1, %0nnt"
  240. ".section __ex_table,#allocnt"
  241. ".align 4nt"
  242. ".word 1b,__ret_efaultnnt"
  243. ".previousnt"
  244.        : "=&r" (x) : "m" (*__m(addr)));
  245. else
  246. __asm__ __volatile__(
  247. "/* Get user asm ret, inline. */n"
  248. "1:t" "ld"#size " %1, %0nnt"
  249. ".section .fixup,#alloc,#execinstrnt"
  250. ".align 4n"
  251. "3:nt"
  252. "retnt"
  253. " restore %%g0, %2, %%o0nnt"
  254. ".previousnt"
  255. ".section __ex_table,#allocnt"
  256. ".align 4nt"
  257. ".word 1b, 3bnnt"
  258. ".previousnt"
  259.        : "=&r" (x) : "m" (*__m(addr)), "i" (retval))
  260. extern int __get_user_bad(void);
  261. extern __kernel_size_t __copy_user(void *to, void *from, __kernel_size_t size);
  262. #define copy_to_user(to,from,n) ({ 
  263. void *__copy_to = (void *) (to); 
  264. __kernel_size_t __copy_size = (__kernel_size_t) (n); 
  265. __kernel_size_t __copy_res; 
  266. if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { 
  267. __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); 
  268. } else __copy_res = __copy_size; 
  269. __copy_res; })
  270. #define __copy_to_user(to,from,n)
  271. __copy_user((void *)(to),
  272.     (void *)(from), n)
  273. #define copy_from_user(to,from,n) ({ 
  274. void *__copy_to = (void *) (to); 
  275. void *__copy_from = (void *) (from); 
  276. __kernel_size_t __copy_size = (__kernel_size_t) (n); 
  277. __kernel_size_t __copy_res; 
  278. if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { 
  279. __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); 
  280. } else __copy_res = __copy_size; 
  281. __copy_res; })
  282. #define __copy_from_user(to,from,n)
  283. __copy_user((void *)(to),
  284.     (void *)(from), n)
  285. extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
  286. {
  287.   __kernel_size_t ret;
  288.   __asm__ __volatile__ (
  289. ".section __ex_table,#allocnt"
  290. ".align 4nt"
  291. ".word 1f,3nt"
  292. ".previousnt"
  293. "mov %2, %%o1n"
  294. "1:nt"
  295. "call __bzeront"
  296. " mov %1, %%o0nt"
  297. "mov %%o0, %0n"
  298. : "=r" (ret) : "r" (addr), "r" (size) :
  299. "o0", "o1", "o2", "o3", "o4", "o5", "o7",
  300. "g1", "g2", "g3", "g4", "g5", "g7", "cc");
  301.   return ret;
  302. }
  303. #define clear_user(addr,n) ({ 
  304. void *__clear_addr = (void *) (addr); 
  305. __kernel_size_t __clear_size = (__kernel_size_t) (n); 
  306. __kernel_size_t __clear_res; 
  307. if(__clear_size && __access_ok((unsigned long)__clear_addr, __clear_size)) { 
  308. __clear_res = __clear_user(__clear_addr, __clear_size); 
  309. } else __clear_res = __clear_size; 
  310. __clear_res; })
  311. extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
  312. #define strncpy_from_user(dest,src,count) ({ 
  313. unsigned long __sfu_src = (unsigned long) (src); 
  314. int __sfu_count = (int) (count); 
  315. long __sfu_res = -EFAULT; 
  316. if(__access_ok(__sfu_src, __sfu_count)) { 
  317. __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); 
  318. } __sfu_res; })
  319. extern int __strlen_user(const char *);
  320. extern int __strnlen_user(const char *, long len);
  321. extern __inline__ int strlen_user(const char *str)
  322. {
  323. if(!access_ok(VERIFY_READ, str, 0))
  324. return 0;
  325. else
  326. return __strlen_user(str);
  327. }
  328. extern __inline__ int strnlen_user(const char *str, long len)
  329. {
  330. if(!access_ok(VERIFY_READ, str, 0))
  331. return 0;
  332. else
  333. return __strnlen_user(str, len);
  334. }
  335. #endif  /* __ASSEMBLY__ */
  336. #endif /* _ASM_UACCESS_H */