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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
  7.  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8.  */
  9. #ifndef _ASM_UACCESS_H
  10. #define _ASM_UACCESS_H
  11. #include <linux/errno.h>
  12. #include <linux/sched.h>
  13. #define STR(x)  __STR(x)
  14. #define __STR(x)  #x
  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) { (unsigned long) 0L })
  23. #define USER_DS ((mm_segment_t) { (unsigned long) -1L })
  24. #define VERIFY_READ    0
  25. #define VERIFY_WRITE   1
  26. #define get_fs()        (current->thread.current_ds)
  27. #define get_ds() (KERNEL_DS)
  28. #define set_fs(x)       (current->thread.current_ds=(x))
  29. #define segment_eq(a,b) ((a).seg == (b).seg)
  30. /*
  31.  * Is a address valid? This does a straighforward calculation rather
  32.  * than tests.
  33.  *
  34.  * Address valid if:
  35.  *  - "addr" doesn't have any high-bits set
  36.  *  - AND "size" doesn't have any high-bits set
  37.  *  - AND "addr+size" doesn't have any high-bits set
  38.  *  - OR we are in kernel mode.
  39.  */
  40. #define __ua_size(size)
  41. (__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size))
  42. #define __access_ok(addr,size,mask)
  43. (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0)
  44. #define __access_mask ((long)(get_fs().seg))
  45. #define access_ok(type,addr,size) 
  46. __access_ok(((unsigned long)(addr)),(size),__access_mask)
  47. extern inline int verify_area(int type, const void * addr, unsigned long size)
  48. {
  49. return access_ok(type,addr,size) ? 0 : -EFAULT;
  50. }
  51. /*
  52.  * Uh, these should become the main single-value transfer routines ...
  53.  * They automatically use the right size if we just have the right
  54.  * pointer type ...
  55.  *
  56.  * As MIPS uses the same address space for kernel and user data, we
  57.  * can just do these as direct assignments.
  58.  *
  59.  * Careful to not
  60.  * (a) re-use the arguments for side effects (sizeof is ok)
  61.  * (b) require any knowledge of processes at this stage
  62.  */
  63. #define put_user(x,ptr)
  64. __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  65. #define get_user(x,ptr) 
  66. __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  67. /*
  68.  * The "__xxx" versions do not do address space checking, useful when
  69.  * doing multiple accesses to the same area (the user has to do the
  70.  * checks by hand with "access_ok()")
  71.  */
  72. #define __put_user(x,ptr) 
  73. __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  74. #define __get_user(x,ptr) 
  75. __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  76. struct __large_struct { unsigned long buf[100]; };
  77. #define __m(x) (*(struct __large_struct *)(x))
  78. #define __get_user_nocheck(x,ptr,size)
  79. ({
  80. long __gu_err;
  81. __typeof(*(ptr)) __gu_val;
  82. long __gu_addr;
  83. __asm__("":"=r" (__gu_val));
  84. __gu_addr = (long) (ptr);
  85. __asm__("":"=r" (__gu_err));
  86. switch (size) {
  87. case 1: __get_user_asm("lb"); break;
  88. case 2: __get_user_asm("lh"); break;
  89. case 4: __get_user_asm("lw"); break;
  90. case 8: __get_user_asm("ld"); break;
  91. default: __get_user_unknown(); break;
  92. } x = (__typeof__(*(ptr))) __gu_val; __gu_err;
  93. })
  94. #define __get_user_check(x,ptr,size)
  95. ({
  96. long __gu_err;
  97. __typeof__(*(ptr)) __gu_val;
  98. long __gu_addr;
  99. __asm__("":"=r" (__gu_val));
  100. __gu_addr = (long) (ptr);
  101. __asm__("":"=r" (__gu_err));
  102. if (__access_ok(__gu_addr,size,__access_mask)) {
  103. switch (size) {
  104. case 1: __get_user_asm("lb"); break;
  105. case 2: __get_user_asm("lh"); break;
  106. case 4: __get_user_asm("lw"); break;
  107. case 8: __get_user_asm("ld"); break;
  108. default: __get_user_unknown(); break;
  109. }
  110. } x = (__typeof__(*(ptr))) __gu_val; __gu_err;
  111. })
  112. #define __get_user_asm(insn)
  113. ({
  114. __asm__ __volatile__(
  115. "1:t" insn "t%1,%2nt"
  116. "movet%0,$0n"
  117. "2:nt"
  118. ".sectiont.fixup,"ax"n"
  119. "3:tlit%0,%3nt"
  120. "movet%1,$0nt"
  121. "jt2bnt"
  122. ".previousnt"
  123. ".sectiont__ex_table,"a"nt"
  124. ".dwordt1b,3bnt"
  125. ".previous"
  126. :"=r" (__gu_err), "=r" (__gu_val)
  127. :"o" (__m(__gu_addr)), "i" (-EFAULT));
  128. })
  129. extern void __get_user_unknown(void);
  130. #define __put_user_nocheck(x,ptr,size)
  131. ({
  132. long __pu_err;
  133. __typeof__(*(ptr)) __pu_val;
  134. long __pu_addr;
  135. __pu_val = (x);
  136. __pu_addr = (long) (ptr);
  137. __asm__("":"=r" (__pu_err));
  138. switch (size) {
  139. case 1: __put_user_asm("sb"); break;
  140. case 2: __put_user_asm("sh"); break;
  141. case 4: __put_user_asm("sw"); break;
  142. case 8: __put_user_asm("sd"); break;
  143. default: __put_user_unknown(); break;
  144. } __pu_err;
  145. })
  146. #define __put_user_check(x,ptr,size)
  147. ({
  148. long __pu_err;
  149. __typeof__(*(ptr)) __pu_val;
  150. long __pu_addr;
  151. __pu_val = (x);
  152. __pu_addr = (long) (ptr);
  153. __asm__("":"=r" (__pu_err));
  154. if (__access_ok(__pu_addr,size,__access_mask)) { 
  155. switch (size) {
  156. case 1: __put_user_asm("sb"); break;
  157. case 2: __put_user_asm("sh"); break;
  158. case 4: __put_user_asm("sw"); break;
  159. case 8: __put_user_asm("sd"); break;
  160. default: __put_user_unknown(); break;
  161. }
  162. } __pu_err;
  163. })
  164. #define __put_user_asm(insn)
  165. ({
  166. __asm__ __volatile__(
  167. "1:t" insn "t%z1, %2ttt# __put_user_asmnt"
  168. "movet%0,$0n"
  169. "2:nt"
  170. ".sectiont.fixup,"ax"n"
  171. "3:tlit%0,%3nt"
  172. "jt2bnt"
  173. ".previousnt"
  174. ".sectiont__ex_table,"a"nt"
  175. ".dwordt1b,3bnt"
  176. ".previous"
  177. :"=r" (__pu_err)
  178. :"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT));
  179. })
  180. extern void __put_user_unknown(void);
  181. /*
  182.  * We're generating jump to subroutines which will be outside the range of
  183.  * jump instructions
  184.  */
  185. #ifdef MODULE
  186. #define __MODULE_JAL(destination)
  187. ".settnoatnt"
  188. "dlat$1, " #destination "nt" 
  189. "jalrt$1nt"
  190. ".settatnt"
  191. #else
  192. #define __MODULE_JAL(destination)
  193. "jalt" #destination "nt"
  194. #endif
  195. extern size_t __copy_user(void *__to, const void *__from, size_t __n);
  196. #define __copy_to_user(to,from,n)
  197. ({
  198. void *__cu_to;
  199. const void *__cu_from;
  200. long __cu_len;
  201. __cu_to = (to);
  202. __cu_from = (from);
  203. __cu_len = (n);
  204. __asm__ __volatile__(
  205. "movet$4, %1nt"
  206. "movet$5, %2nt"
  207. "movet$6, %3nt"
  208. __MODULE_JAL(__copy_user)
  209. "movet%0, $6"
  210. : "=r" (__cu_len)
  211. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len)
  212. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12",
  213.   "$15", "$24", "$31","memory");
  214. __cu_len;
  215. })
  216. #define __copy_from_user(to,from,n)
  217. ({
  218. void *__cu_to;
  219. const void *__cu_from;
  220. long __cu_len;
  221. __cu_to = (to);
  222. __cu_from = (from);
  223. __cu_len = (n);
  224. __asm__ __volatile__(
  225. "movet$4, %1nt"
  226. "movet$5, %2nt"
  227. "movet$6, %3nt"
  228. ".settnoreordernt"
  229. __MODULE_JAL(__copy_user)
  230. ".settnoatnt"
  231. "daddut$1, %2, %3nt"
  232. ".settatnt"
  233. ".settreordernt"
  234. "movet%0, $6"
  235. : "=r" (__cu_len)
  236. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len)
  237. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12",
  238.   "$15", "$24", "$31","memory");
  239. __cu_len;
  240. })
  241. #define copy_to_user(to,from,n)
  242. ({
  243. void *__cu_to;
  244. const void *__cu_from;
  245. long __cu_len;
  246. __cu_to = (to);
  247. __cu_from = (from);
  248. __cu_len = (n);
  249. if (access_ok(VERIFY_WRITE, __cu_to, __cu_len))
  250. __asm__ __volatile__(
  251. "movet$4, %1nt"
  252. "movet$5, %2nt"
  253. "movet$6, %3nt"
  254. __MODULE_JAL(__copy_user)
  255. "movet%0, $6"
  256. : "=r" (__cu_len)
  257. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  258. : "$4", "$5", "$6", "$8", "$9", "$10", "$11",
  259.   "$12", "$15", "$24", "$31","memory");
  260. __cu_len;
  261. })
  262. #define copy_from_user(to,from,n)
  263. ({
  264. void *__cu_to;
  265. const void *__cu_from;
  266. long __cu_len;
  267. __cu_to = (to);
  268. __cu_from = (from);
  269. __cu_len = (n);
  270. if (access_ok(VERIFY_READ, __cu_from, __cu_len))
  271. __asm__ __volatile__(
  272. "movet$4, %1nt"
  273. "movet$5, %2nt"
  274. "movet$6, %3nt"
  275. ".settnoreordernt"
  276. __MODULE_JAL(__copy_user)
  277. ".settnoatnt"
  278. "daddut$1, %2, %3nt"
  279. ".settatnt"
  280. ".settreordernt"
  281. "movet%0, $6"
  282. : "=r" (__cu_len)
  283. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  284. : "$4", "$5", "$6", "$8", "$9", "$10", "$11",
  285.   "$12", "$15", "$24", "$31","memory");
  286. __cu_len;
  287. })
  288. extern inline __kernel_size_t
  289. __clear_user(void *addr, __kernel_size_t size)
  290. {
  291. __kernel_size_t res;
  292. __asm__ __volatile__(
  293. "movet$4, %1nt"
  294. "movet$5, $0nt"
  295. "movet$6, %2nt"
  296. __MODULE_JAL(__bzero)
  297. "movet%0, $6"
  298. : "=r" (res)
  299. : "r" (addr), "r" (size)
  300. : "$4", "$5", "$6", "$8", "$9", "$31");
  301. return res;
  302. }
  303. #define clear_user(addr,n)
  304. ({
  305. void * __cl_addr = (addr);
  306. unsigned long __cl_size = (n);
  307. if (__cl_size && __access_ok(VERIFY_WRITE,
  308.        ((unsigned long)(__cl_addr)), __cl_size))
  309. __cl_size = __clear_user(__cl_addr, __cl_size);
  310. __cl_size;
  311. })
  312. /*
  313.  * Returns: -EFAULT if exception before terminator, N if the entire
  314.  * buffer filled, else strlen.
  315.  */
  316. extern inline long
  317. __strncpy_from_user(char *__to, const char *__from, long __len)
  318. {
  319. long res;
  320. __asm__ __volatile__(
  321. "movet$4, %1nt"
  322. "movet$5, %2nt"
  323. "movet$6, %3nt"
  324. __MODULE_JAL(__strncpy_from_user_nocheck_asm)
  325. "movet%0, $2"
  326. : "=r" (res)
  327. : "r" (__to), "r" (__from), "r" (__len)
  328. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  329. return res;
  330. }
  331. extern inline long
  332. strncpy_from_user(char *__to, const char *__from, long __len)
  333. {
  334. long res;
  335. __asm__ __volatile__(
  336. "movet$4, %1nt"
  337. "movet$5, %2nt"
  338. "movet$6, %3nt"
  339. __MODULE_JAL(__strncpy_from_user_asm)
  340. "movet%0, $2"
  341. : "=r" (res)
  342. : "r" (__to), "r" (__from), "r" (__len)
  343. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  344. return res;
  345. }
  346. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  347. extern inline long __strlen_user(const char *s)
  348. {
  349. long res;
  350. __asm__ __volatile__(
  351. "movet$4, %1nt"
  352. __MODULE_JAL(__strlen_user_nocheck_asm)
  353. "movet%0, $2"
  354. : "=r" (res)
  355. : "r" (s)
  356. : "$2", "$4", "$8", "$31");
  357. return res;
  358. }
  359. extern inline long strlen_user(const char *s)
  360. {
  361. long res;
  362. __asm__ __volatile__(
  363. "movet$4, %1nt"
  364. __MODULE_JAL(__strlen_user_asm)
  365. "movet%0, $2"
  366. : "=r" (res)
  367. : "r" (s)
  368. : "$2", "$4", "$8", "$31");
  369. return res;
  370. }
  371. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  372. extern inline long __strnlen_user(const char *s, long n)
  373. {
  374. long res;
  375. __asm__ __volatile__(
  376. "movet$4, %1nt"
  377. "movet$5, %2nt"
  378. __MODULE_JAL(__strlen_user_nocheck_asm)
  379. "movet%0, $2"
  380. : "=r" (res)
  381. : "r" (s), "r" (n)
  382. : "$2", "$4", "$5", "$8", "$31");
  383. return res;
  384. }
  385. extern inline long strnlen_user(const char *s, long n)
  386. {
  387. long res;
  388. __asm__ __volatile__(
  389. "movet$4, %1nt"
  390. "movet$5, %2nt"
  391. __MODULE_JAL(__strlen_user_asm)
  392. "movet%0, $2"
  393. : "=r" (res)
  394. : "r" (s), "r" (n)
  395. : "$2", "$4", "$5", "$8", "$31");
  396. return res;
  397. }
  398. struct exception_table_entry
  399. {
  400. unsigned long insn;
  401. unsigned long nextinsn;
  402. };
  403. /* Returns 0 if exception not found and fixup.unit otherwise.  */
  404. extern unsigned long search_exception_table(unsigned long addr);
  405. /* Returns the new pc */
  406. #define fixup_exception(map_reg, fixup_unit, pc)                
  407. ({                                                              
  408. fixup_unit;                                             
  409. })
  410. #endif /* _ASM_UACCESS_H */