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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: uaccess.h,v 1.34 2001/09/27 04:36:24 kanoj Exp $ */
  2. #ifndef _ASM_UACCESS_H
  3. #define _ASM_UACCESS_H
  4. /*
  5.  * User space memory access functions
  6.  */
  7. #ifdef __KERNEL__
  8. #include <linux/sched.h>
  9. #include <linux/string.h>
  10. #include <asm/a.out.h>
  11. #include <asm/asi.h>
  12. #include <asm/system.h>
  13. #include <asm/spitfire.h>
  14. #endif
  15. #ifndef __ASSEMBLY__
  16. /*
  17.  * Sparc64 is segmented, though more like the M68K than the I386. 
  18.  * We use the secondary ASI to address user memory, which references a
  19.  * completely different VM map, thus there is zero chance of the user
  20.  * doing something queer and tricking us into poking kernel memory.
  21.  *
  22.  * What is left here is basically what is needed for the other parts of
  23.  * the kernel that expect to be able to manipulate, erum, "segments".
  24.  * Or perhaps more properly, permissions.
  25.  *
  26.  * "For historical reasons, these macros are grossly misnamed." -Linus
  27.  */
  28. #define KERNEL_DS   ((mm_segment_t) { ASI_P })
  29. #define USER_DS     ((mm_segment_t) { ASI_AIUS }) /* har har har */
  30. #define VERIFY_READ 0
  31. #define VERIFY_WRITE 1
  32. #define get_fs() (current->thread.current_ds)
  33. #define get_ds() (KERNEL_DS)
  34. #define segment_eq(a,b)  ((a).seg == (b).seg)
  35. #define set_fs(val)
  36. do {
  37. current->thread.current_ds = (val);
  38. __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));
  39. } while(0)
  40. #define __user_ok(addr,size) 1
  41. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  42. #define __access_ok(addr,size) 1
  43. #define access_ok(type,addr,size) 1
  44. extern inline int verify_area(int type, const void * addr, unsigned long size)
  45. {
  46. return 0;
  47. }
  48. /*
  49.  * The exception table consists of pairs of addresses: the first is the
  50.  * address of an instruction that is allowed to fault, and the second is
  51.  * the address at which the program should continue.  No registers are
  52.  * modified, so it is entirely up to the continuation code to figure out
  53.  * what to do.
  54.  *
  55.  * All the routines below use bits of fixup code that are out of line
  56.  * with the main instruction path.  This means when everything is well,
  57.  * we don't even have to jump over them.  Further, they do not intrude
  58.  * on our cache or tlb entries.
  59.  *
  60.  * There is a special way how to put a range of potentially faulting
  61.  * insns (like twenty ldd/std's with now intervening other instructions)
  62.  * You specify address of first in insn and 0 in fixup and in the next
  63.  * exception_table_entry you specify last potentially faulting insn + 1
  64.  * and in fixup the routine which should handle the fault.
  65.  * That fixup code will get
  66.  * (faulting_insn_address - first_insn_in_the_range_address)/4
  67.  * in %g2 (ie. index of the faulting instruction in the range).
  68.  */
  69. struct exception_table_entry
  70. {
  71.         unsigned insn, fixup;
  72. };
  73. /* Returns 0 if exception not found and fixup otherwise.  */
  74. extern unsigned long search_exception_table(unsigned long, unsigned long *);
  75. extern void __ret_efault(void);
  76. /* Uh, these should become the main single-value transfer routines..
  77.  * They automatically use the right size if we just have the right
  78.  * pointer type..
  79.  *
  80.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  81.  * and yet we don't want to do any pointers, because that is too much
  82.  * of a performance impact. Thus we have a few rather ugly macros here,
  83.  * and hide all the uglyness from the user.
  84.  */
  85. #define put_user(x,ptr) ({ 
  86. unsigned long __pu_addr = (unsigned long)(ptr); 
  87. __put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
  88. #define get_user(x,ptr) ({ 
  89. unsigned long __gu_addr = (unsigned long)(ptr); 
  90. __get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
  91. #define __put_user(x,ptr) put_user(x,ptr)
  92. #define __get_user(x,ptr) get_user(x,ptr)
  93. struct __large_struct { unsigned long buf[100]; };
  94. #define __m(x) ((struct __large_struct *)(x))
  95. #define __put_user_nocheck(data,addr,size) ({ 
  96. register int __pu_ret; 
  97. switch (size) { 
  98. case 1: __put_user_asm(data,b,addr,__pu_ret); break; 
  99. case 2: __put_user_asm(data,h,addr,__pu_ret); break; 
  100. case 4: __put_user_asm(data,w,addr,__pu_ret); break; 
  101. case 8: __put_user_asm(data,x,addr,__pu_ret); break; 
  102. default: __pu_ret = __put_user_bad(); break; 
  103. } __pu_ret; })
  104. #define __put_user_nocheck_ret(data,addr,size,retval) ({ 
  105. register int __foo __asm__ ("l1"); 
  106. switch (size) { 
  107. case 1: __put_user_asm_ret(data,b,addr,retval,__foo); break; 
  108. case 2: __put_user_asm_ret(data,h,addr,retval,__foo); break; 
  109. case 4: __put_user_asm_ret(data,w,addr,retval,__foo); break; 
  110. case 8: __put_user_asm_ret(data,x,addr,retval,__foo); break; 
  111. default: if (__put_user_bad()) return retval; break; 
  112. } })
  113. #define __put_user_asm(x,size,addr,ret)
  114. __asm__ __volatile__(
  115. "/* Put user asm, inline. */n"
  116. "1:t" "st"#size "a %1, [%2] %%asint"
  117. "clr %0n"
  118. "2:nnt"
  119. ".section .fixup,#alloc,#execinstrnt"
  120. ".align 4n"
  121. "3:nt"
  122. "b 2bnt"
  123. " mov %3, %0nnt"
  124. ".previousnt"
  125. ".section __ex_table,#allocnt"
  126. ".align 4nt"
  127. ".word 1b, 3bnt"
  128. ".previousnnt"
  129.        : "=r" (ret) : "r" (x), "r" (__m(addr)),
  130.  "i" (-EFAULT))
  131. #define __put_user_asm_ret(x,size,addr,ret,foo)
  132. if (__builtin_constant_p(ret) && ret == -EFAULT)
  133. __asm__ __volatile__(
  134. "/* Put user asm ret, inline. */n"
  135. "1:t" "st"#size "a %1, [%2] %%asinnt"
  136. ".section __ex_table,#allocnt"
  137. ".align 4nt"
  138. ".word 1b, __ret_efaultnnt"
  139. ".previousnnt"
  140.        : "=r" (foo) : "r" (x), "r" (__m(addr)));
  141. else
  142. __asm__ __volatile(
  143. "/* Put user asm ret, inline. */n"
  144. "1:t" "st"#size "a %1, [%2] %%asinnt"
  145. ".section .fixup,#alloc,#execinstrnt"
  146. ".align 4n"
  147. "3:nt"
  148. "retnt"
  149. " restore %%g0, %3, %%o0nnt"
  150. ".previousnt"
  151. ".section __ex_table,#allocnt"
  152. ".align 4nt"
  153. ".word 1b, 3bnnt"
  154. ".previousnnt"
  155.        : "=r" (foo) : "r" (x), "r" (__m(addr)),
  156.          "i" (ret))
  157. extern int __put_user_bad(void);
  158. #define __get_user_nocheck(data,addr,size,type) ({ 
  159. register int __gu_ret; 
  160. register unsigned long __gu_val; 
  161. switch (size) { 
  162. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; 
  163. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; 
  164. case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; 
  165. case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; 
  166. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; 
  167. } data = (type) __gu_val; __gu_ret; })
  168. #define __get_user_nocheck_ret(data,addr,size,type,retval) ({ 
  169. register unsigned long __gu_val __asm__ ("l1"); 
  170. switch (size) { 
  171. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; 
  172. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; 
  173. case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; 
  174. case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; 
  175. default: if (__get_user_bad()) return retval; 
  176. } data = (type) __gu_val; })
  177. #define __get_user_asm(x,size,addr,ret)
  178. __asm__ __volatile__(
  179. "/* Get user asm, inline. */n"
  180. "1:t" "ld"#size "a [%2] %%asi, %1nt"
  181. "clr %0n"
  182. "2:nnt"
  183. ".section .fixup,#alloc,#execinstrnt"
  184. ".align 4n"
  185. "3:nt"
  186. "clr %1nt"
  187. "b 2bnt"
  188. " mov %3, %0nnt"
  189. ".previousnt"
  190. ".section __ex_table,#allocnt"
  191. ".align 4nt"
  192. ".word 1b, 3bnnt"
  193. ".previousnt"
  194.        : "=r" (ret), "=r" (x) : "r" (__m(addr)),
  195.  "i" (-EFAULT))
  196. #define __get_user_asm_ret(x,size,addr,retval)
  197. if (__builtin_constant_p(retval) && retval == -EFAULT)
  198. __asm__ __volatile__(
  199. "/* Get user asm ret, inline. */n"
  200. "1:t" "ld"#size "a [%1] %%asi, %0nnt"
  201. ".section __ex_table,#allocnt"
  202. ".align 4nt"
  203. ".word 1b,__ret_efaultnnt"
  204. ".previousnt"
  205.        : "=r" (x) : "r" (__m(addr)));
  206. else
  207. __asm__ __volatile__(
  208. "/* Get user asm ret, inline. */n"
  209. "1:t" "ld"#size "a [%1] %%asi, %0nnt"
  210. ".section .fixup,#alloc,#execinstrnt"
  211. ".align 4n"
  212. "3:nt"
  213. "retnt"
  214. " restore %%g0, %2, %%o0nnt"
  215. ".previousnt"
  216. ".section __ex_table,#allocnt"
  217. ".align 4nt"
  218. ".word 1b, 3bnnt"
  219. ".previousnt"
  220.        : "=r" (x) : "r" (__m(addr)), "i" (retval))
  221. extern int __get_user_bad(void);
  222. extern __kernel_size_t __copy_from_user(void *to, const void *from,
  223. __kernel_size_t size);
  224. extern __kernel_size_t __copy_to_user(void *to, const void *from,
  225.       __kernel_size_t size);
  226. extern __kernel_size_t __copy_in_user(void *to, const void *from,
  227.       __kernel_size_t size);
  228. #define copy_from_user(to,from,n)
  229. __copy_from_user((void *)(to),
  230.     (void *)(from), (__kernel_size_t)(n))
  231. #define copy_to_user(to,from,n) 
  232. __copy_to_user((void *)(to), 
  233. (void *) (from), (__kernel_size_t)(n))
  234. #define copy_in_user(to,from,n) 
  235. __copy_in_user((void *)(to), 
  236. (void *) (from), (__kernel_size_t)(n))
  237. extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
  238. {
  239. extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
  240. return __bzero_noasi(addr, size);
  241. }
  242. #define clear_user(addr,n) 
  243. __clear_user((void *)(addr), (__kernel_size_t)(n))
  244. extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
  245. #define strncpy_from_user(dest,src,count) 
  246. __strncpy_from_user((unsigned long)(dest), (unsigned long)(src), (int)(count))
  247. extern int __strlen_user(const char *);
  248. extern int __strnlen_user(const char *, long len);
  249. #define strlen_user __strlen_user
  250. #define strnlen_user __strnlen_user
  251. #endif  /* __ASSEMBLY__ */
  252. #endif /* _ASM_UACCESS_H */