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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: uaccess.h,v 1.13 2001/10/01 02:22:01 gniibe Exp $
  2.  *
  3.  * User space memory access functions
  4.  *
  5.  * Copyright (C) 1999  Niibe Yutaka
  6.  *
  7.  *  Based on:
  8.  *     MIPS implementation version 1.15 by
  9.  *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  10.  *     and i386 version.
  11.  */
  12. #ifndef __ASM_SH_UACCESS_H
  13. #define __ASM_SH_UACCESS_H
  14. #include <linux/errno.h>
  15. #include <linux/sched.h>
  16. #define VERIFY_READ    0
  17. #define VERIFY_WRITE   1
  18. /*
  19.  * The fs value determines whether argument validity checking should be
  20.  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  21.  * get_fs() == KERNEL_DS, checking is bypassed.
  22.  *
  23.  * For historical reasons (Data Segment Register?), these macros are misnamed.
  24.  */
  25. #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
  26. #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
  27. #define USER_DS MAKE_MM_SEG(0x80000000)
  28. #define get_ds() (KERNEL_DS)
  29. #define get_fs()        (current->addr_limit)
  30. #define set_fs(x)       (current->addr_limit=(x))
  31. #define segment_eq(a,b) ((a).seg == (b).seg)
  32. #define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
  33. /*
  34.  * Uhhuh, this needs 33-bit arithmetic. We have a carry..
  35.  *
  36.  * sum := addr + size;  carry? --> flag = true;
  37.  * if (sum >= addr_limit) flag = true;
  38.  */
  39. #define __range_ok(addr,size) ({       
  40. unsigned long flag,sum;        
  41. __asm__("clrt; addc %3, %1; movt %0; cmp/hi %4, %1; rotcl %0"       
  42. :"=&r" (flag), "=r" (sum)        
  43. :"1" (addr), "r" ((int)(size)), "r" (current->addr_limit.seg) 
  44. :"t");        
  45. flag; })
  46. #define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
  47. #define __access_ok(addr,size) (__range_ok(addr,size) == 0)
  48. static inline int verify_area(int type, const void * addr, unsigned long size)
  49. {
  50. return access_ok(type,addr,size) ? 0 : -EFAULT;
  51. }
  52. /*
  53.  * Uh, these should become the main single-value transfer routines ...
  54.  * They automatically use the right size if we just have the right
  55.  * pointer type ...
  56.  *
  57.  * As SuperH uses the same address space for kernel and user data, we
  58.  * can just do these as direct assignments.
  59.  *
  60.  * Careful to not
  61.  * (a) re-use the arguments for side effects (sizeof is ok)
  62.  * (b) require any knowledge of processes at this stage
  63.  */
  64. #define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)))
  65. #define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
  66. /*
  67.  * The "__xxx" versions do not do address space checking, useful when
  68.  * doing multiple accesses to the same area (the user has to do the
  69.  * checks by hand with "access_ok()")
  70.  */
  71. #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
  72. #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
  73. struct __large_struct { unsigned long buf[100]; };
  74. #define __m(x) (*(struct __large_struct *)(x))
  75. #define __get_user_nocheck(x,ptr,size) ({ 
  76. long __gu_err; 
  77. __typeof(*(ptr)) __gu_val; 
  78. long __gu_addr; 
  79. __asm__("":"=r" (__gu_val)); 
  80. __gu_addr = (long) (ptr); 
  81. __asm__("":"=r" (__gu_err)); 
  82. switch (size) { 
  83. case 1: __get_user_asm("b"); break; 
  84. case 2: __get_user_asm("w"); break; 
  85. case 4: __get_user_asm("l"); break; 
  86. default: __get_user_unknown(); break; 
  87. } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
  88. #define __get_user_check(x,ptr,size) ({ 
  89. long __gu_err; 
  90. __typeof__(*(ptr)) __gu_val; 
  91. long __gu_addr; 
  92. __asm__("":"=r" (__gu_val)); 
  93. __gu_addr = (long) (ptr); 
  94. __asm__("":"=r" (__gu_err)); 
  95. if (__access_ok(__gu_addr,size)) { 
  96. switch (size) { 
  97. case 1: __get_user_asm("b"); break; 
  98. case 2: __get_user_asm("w"); break; 
  99. case 4: __get_user_asm("l"); break; 
  100. default: __get_user_unknown(); break; 
  101. } } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
  102. #define __get_user_asm(insn) 
  103. ({ 
  104. __asm__ __volatile__( 
  105. "1:nt" 
  106. "mov." insn " %2, %1nt" 
  107. "mov #0, %0n" 
  108. "2:n" 
  109. ".section .fixup,"ax"n" 
  110. "3:nt" 
  111. "mov #0, %1nt" 
  112. "mov.l 4f, %0nt" 
  113. "jmp @%0nt" 
  114. " mov %3, %0n" 
  115. "4: .long 2bnt" 
  116. ".previousn" 
  117. ".section __ex_table,"a"nt" 
  118. ".long 1b, 3bnt" 
  119. ".previous" 
  120. :"=&r" (__gu_err), "=&r" (__gu_val) 
  121. :"m" (__m(__gu_addr)), "i" (-EFAULT)); })
  122. extern void __get_user_unknown(void);
  123. #define __put_user_nocheck(x,ptr,size) ({ 
  124. long __pu_err; 
  125. __typeof__(*(ptr)) __pu_val; 
  126. long __pu_addr; 
  127. __pu_val = (x); 
  128. __pu_addr = (long) (ptr); 
  129. __asm__("":"=r" (__pu_err)); 
  130. switch (size) { 
  131. case 1: __put_user_asm("b"); break; 
  132. case 2: __put_user_asm("w"); break; 
  133. case 4: __put_user_asm("l"); break; 
  134. case 8: __put_user_u64(__pu_val,__pu_addr,__pu_err); break; 
  135. default: __put_user_unknown(); break; 
  136. } __pu_err; })
  137. #define __put_user_check(x,ptr,size) ({ 
  138. long __pu_err; 
  139. __typeof__(*(ptr)) __pu_val; 
  140. long __pu_addr; 
  141. __pu_val = (x); 
  142. __pu_addr = (long) (ptr); 
  143. __asm__("":"=r" (__pu_err)); 
  144. if (__access_ok(__pu_addr,size)) { 
  145. switch (size) { 
  146. case 1: __put_user_asm("b"); break; 
  147. case 2: __put_user_asm("w"); break; 
  148. case 4: __put_user_asm("l"); break; 
  149. case 8: __put_user_u64(__pu_val,__pu_addr,__pu_err); break; 
  150. default: __put_user_unknown(); break; 
  151. } } __pu_err; })
  152. #define __put_user_asm(insn) 
  153. ({ 
  154. __asm__ __volatile__( 
  155. "1:nt" 
  156. "mov." insn " %1, %2nt" 
  157. "mov #0, %0n" 
  158. "2:n" 
  159. ".section .fixup,"ax"n" 
  160. "3:nt" 
  161. "nopnt" 
  162. "mov.l 4f, %0nt" 
  163. "jmp @%0nt" 
  164. "mov %3, %0n" 
  165. "4: .long 2bnt" 
  166. ".previousn" 
  167. ".section __ex_table,"a"nt" 
  168. ".long 1b, 3bnt" 
  169. ".previous" 
  170. :"=&r" (__pu_err) 
  171. :"r" (__pu_val), "m" (__m(__pu_addr)), "i" (-EFAULT) 
  172.         :"memory"); })
  173. #if defined(__LITTLE_ENDIAN__)
  174. #define __put_user_u64(val,addr,retval) 
  175. ({ 
  176. __asm__ __volatile__( 
  177. "1:nt" 
  178. "mov.l %R1,%2nt" 
  179. "mov.l %S1,%T2nt" 
  180. "mov #0,%0n" 
  181. "2:n" 
  182. ".section .fixup,"ax"n" 
  183. "3:nt" 
  184. "nopnt" 
  185. "mov.l 4f,%0nt" 
  186. "jmp @%0nt" 
  187. " mov %3,%0n" 
  188. "4: .long 2bnt" 
  189. ".previousn" 
  190. ".section __ex_table,"a"nt" 
  191. ".long 1b, 3bnt" 
  192. ".previous" 
  193. : "=r" (retval) 
  194. : "r" (val), "m" (__m(addr)), "i" (-EFAULT) 
  195.         : "memory"); })
  196. #else
  197. #define __put_user_u64(val,addr,retval) 
  198. ({ 
  199. __asm__ __volatile__( 
  200. "1:nt" 
  201. "mov.l %S1,%2nt" 
  202. "mov.l %R1,%T2nt" 
  203. "mov #0,%0n" 
  204. "2:n" 
  205. ".section .fixup,"ax"n" 
  206. "3:nt" 
  207. "nopnt" 
  208. "mov.l 4f,%0nt" 
  209. "jmp @%0nt" 
  210. " mov %3,%0n" 
  211. "4: .long 2bnt" 
  212. ".previousn" 
  213. ".section __ex_table,"a"nt" 
  214. ".long 1b, 3bnt" 
  215. ".previous" 
  216. : "=r" (retval) 
  217. : "r" (val), "m" (__m(addr)), "i" (-EFAULT) 
  218.         : "memory"); })
  219. #endif
  220. extern void __put_user_unknown(void);
  221. /* Generic arbitrary sized copy.  */
  222. /* Return the number of bytes NOT copied */
  223. /* XXX: should be such that: 4byte and the rest. */
  224. static __inline__ __kernel_size_t
  225. __copy_user(void *__to, const void *__from, __kernel_size_t __n)
  226. {
  227. unsigned long __dummy, _f, _t;
  228. __kernel_size_t res;
  229. if ((res = __n))
  230. __asm__ __volatile__(
  231. "9:nt"
  232. "mov.b @%2+, %1nt"
  233. "dt %0n"
  234. "1:nt"
  235. "mov.b %1, @%3nt"
  236. "bf/s 9bnt"
  237. " add #1, %3n"
  238. "2:n"
  239. ".section .fixup,"ax"n"
  240. "3:nt"
  241. "mov.l 5f, %1nt"
  242. "jmp @%1nt"
  243. " add #1, %0nt"
  244. ".balign 4n"
  245. "5: .long 2bn"
  246. ".previousn"
  247. ".section __ex_table,"a"n"
  248. " .balign 4n"
  249. " .long 9b,2bn"
  250. " .long 1b,3bn"
  251. ".previous"
  252. : "=r" (res), "=&z" (__dummy), "=r" (_f), "=r" (_t)
  253. : "2" (__from), "3" (__to), "0" (res)
  254. : "memory", "t");
  255. return res;
  256. }
  257. #define copy_to_user(to,from,n) ({ 
  258. void *__copy_to = (void *) (to); 
  259. __kernel_size_t __copy_size = (__kernel_size_t) (n); 
  260. __kernel_size_t __copy_res; 
  261. if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { 
  262. __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); 
  263. } else __copy_res = __copy_size; 
  264. __copy_res; })
  265. #define __copy_to_user(to,from,n)
  266. __copy_user((void *)(to),
  267.     (void *)(from), n)
  268. #define copy_from_user(to,from,n) ({ 
  269. void *__copy_to = (void *) (to); 
  270. void *__copy_from = (void *) (from); 
  271. __kernel_size_t __copy_size = (__kernel_size_t) (n); 
  272. __kernel_size_t __copy_res; 
  273. if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { 
  274. __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); 
  275. } else __copy_res = __copy_size; 
  276. __copy_res; })
  277. #define __copy_from_user(to,from,n)
  278. __copy_user((void *)(to),
  279.     (void *)(from), n)
  280. /* XXX: Not sure it works well..
  281.    should be such that: 4byte clear and the rest. */
  282. static __inline__ __kernel_size_t
  283. __clear_user(void *addr, __kernel_size_t size)
  284. {
  285. unsigned long __a;
  286. __asm__ __volatile__(
  287. "9:nt"
  288. "dt %0n"
  289. "1:nt"
  290. "mov.b %4, @%1nt"
  291. "bf/s 9bnt"
  292. " add #1, %1n"
  293. "2:n"
  294. ".section .fixup,"ax"n"
  295. "3:nt"
  296. "mov.l 4f, %1nt"
  297. "jmp @%1nt"
  298. " nopn"
  299. ".balign 4n"
  300. "4: .long 2bn"
  301. ".previousn"
  302. ".section __ex_table,"a"n"
  303. " .balign 4n"
  304. " .long 1b,3bn"
  305. ".previous"
  306. : "=r" (size), "=r" (__a)
  307. : "0" (size), "1" (addr), "r" (0)
  308. : "memory", "t");
  309. return size;
  310. }
  311. #define clear_user(addr,n) ({ 
  312. void * __cl_addr = (addr); 
  313. unsigned long __cl_size = (n); 
  314. if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) 
  315. __cl_size = __clear_user(__cl_addr, __cl_size); 
  316. __cl_size; })
  317. static __inline__ int
  318. __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count)
  319. {
  320. __kernel_size_t res;
  321. unsigned long __dummy, _d, _s;
  322. __asm__ __volatile__(
  323. "9:n"
  324. "mov.b @%2+, %1nt"
  325. "cmp/eq #0, %1nt"
  326. "bt/s 2fn"
  327. "1:n"
  328. "mov.b %1, @%3nt"
  329. "dt %7nt"
  330. "bf/s 9bnt"
  331. " add #1, %3nt"
  332. "2:nt"
  333. "sub %7, %0n"
  334. "3:n"
  335. ".section .fixup,"ax"n"
  336. "4:nt"
  337. "mov.l 5f, %1nt"
  338. "jmp @%1nt"
  339. " mov %8, %0nt"
  340. ".balign 4n"
  341. "5: .long 3bn"
  342. ".previousn"
  343. ".section __ex_table,"a"n"
  344. " .balign 4n"
  345. " .long 9b,4bn"
  346. ".previous"
  347. : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d)
  348. : "0" (__count), "2" (__src), "3" (__dest), "r" (__count),
  349.   "i" (-EFAULT)
  350. : "memory", "t");
  351. return res;
  352. }
  353. #define strncpy_from_user(dest,src,count) ({ 
  354. unsigned long __sfu_src = (unsigned long) (src); 
  355. int __sfu_count = (int) (count); 
  356. long __sfu_res = -EFAULT; 
  357. if(__access_ok(__sfu_src, __sfu_count)) { 
  358. __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); 
  359. } __sfu_res; })
  360. #define strlen_user(str) strnlen_user(str, ~0UL >> 1)
  361. /*
  362.  * Return the size of a string (including the ending 0!)
  363.  */
  364. static __inline__ long __strnlen_user(const char *__s, long __n)
  365. {
  366. unsigned long res;
  367. unsigned long __dummy;
  368. __asm__ __volatile__(
  369. "9:n"
  370. "cmp/eq %4, %0nt"
  371. "bt 2fn"
  372. "1:t"
  373. "mov.b @(%0,%3), %1nt"
  374. "tst %1, %1nt"
  375. "bf/s 9bnt"
  376. " add #1, %0n"
  377. "2:n"
  378. ".section .fixup,"ax"n"
  379. "3:nt"
  380. "mov.l 4f, %1nt"
  381. "jmp @%1nt"
  382. " mov %5, %0n"
  383. ".balign 4n"
  384. "4: .long 2bn"
  385. ".previousn"
  386. ".section __ex_table,"a"n"
  387. " .balign 4n"
  388. " .long 1b,3bn"
  389. ".previous"
  390. : "=z" (res), "=&r" (__dummy)
  391. : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT)
  392. : "t");
  393. return res;
  394. }
  395. static __inline__ long strnlen_user(const char *s, long n)
  396. {
  397. if (!__addr_ok(s))
  398. return 0;
  399. else
  400. return __strnlen_user(s, n);
  401. }
  402. struct exception_table_entry
  403. {
  404. unsigned long insn, fixup;
  405. };
  406. /* Returns 0 if exception not found and fixup.unit otherwise.  */
  407. extern unsigned long search_exception_table(unsigned long addr);
  408. /* Returns the new pc */
  409. #define fixup_exception(map_reg, fixup_unit, pc)                
  410. ({                                                              
  411. fixup_unit;                                             
  412. })
  413. #endif /* __ASM_SH_UACCESS_H */