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

Linux/Unix编程

开发平台:

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. static 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 __invoke_copy_to_user(to,from,n)
  197. ({
  198. register void *__cu_to_r __asm__ ("$4");
  199. register const void *__cu_from_r __asm__ ("$5");
  200. register long __cu_len_r __asm__ ("$6");
  201. __cu_to_r = (to);
  202. __cu_from_r = (from);
  203. __cu_len_r = (n);
  204. __asm__ __volatile__(
  205. __MODULE_JAL(__copy_user)
  206. : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
  207. :
  208. : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",
  209.   "memory");
  210. __cu_len_r;
  211. })
  212. #define __copy_to_user(to,from,n)
  213. ({
  214. void *__cu_to;
  215. const void *__cu_from;
  216. long __cu_len;
  217. __cu_to = (to);
  218. __cu_from = (from);
  219. __cu_len = (n);
  220. __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len);
  221. __cu_len;
  222. })
  223. #define copy_to_user(to,from,n)
  224. ({
  225. void *__cu_to;
  226. const void *__cu_from;
  227. long __cu_len;
  228. __cu_to = (to);
  229. __cu_from = (from);
  230. __cu_len = (n);
  231. if (access_ok(VERIFY_WRITE, __cu_to, __cu_len))
  232. __cu_len = __invoke_copy_to_user(__cu_to, __cu_from,
  233.                                 __cu_len);
  234. __cu_len;
  235. })
  236. #define __invoke_copy_from_user(to,from,n)
  237. ({
  238. register void *__cu_to_r __asm__ ("$4");
  239. register const void *__cu_from_r __asm__ ("$5");
  240. register long __cu_len_r __asm__ ("$6");
  241. __cu_to_r = (to);
  242. __cu_from_r = (from);
  243. __cu_len_r = (n);
  244. __asm__ __volatile__(
  245. ".settnoreordernt"
  246. __MODULE_JAL(__copy_user)
  247. ".settnoatnt"
  248. "daddut$1, %1, %2nt"
  249. ".settatnt"
  250. ".settreordernt"
  251. "movet%0, $6"
  252. : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
  253. :
  254. : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",
  255.   "memory");
  256. __cu_len_r;
  257. })
  258. #define __copy_from_user(to,from,n)
  259. ({
  260. void *__cu_to;
  261. const void *__cu_from;
  262. long __cu_len;
  263. __cu_to = (to);
  264. __cu_from = (from);
  265. __cu_len = (n);
  266. __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,
  267.                                    __cu_len);
  268. __cu_len;
  269. })
  270. #define copy_from_user(to,from,n)
  271. ({
  272. void *__cu_to;
  273. const void *__cu_from;
  274. long __cu_len;
  275. __cu_to = (to);
  276. __cu_from = (from);
  277. __cu_len = (n);
  278. if (access_ok(VERIFY_READ, __cu_from, __cu_len))
  279. __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,
  280.                                    __cu_len);
  281. __cu_len;
  282. })
  283. static inline __kernel_size_t
  284. __clear_user(void *addr, __kernel_size_t size)
  285. {
  286. __kernel_size_t res;
  287. __asm__ __volatile__(
  288. "movet$4, %1nt"
  289. "movet$5, $0nt"
  290. "movet$6, %2nt"
  291. __MODULE_JAL(__bzero)
  292. "movet%0, $6"
  293. : "=r" (res)
  294. : "r" (addr), "r" (size)
  295. : "$4", "$5", "$6", "$8", "$9", "$31");
  296. return res;
  297. }
  298. #define clear_user(addr,n)
  299. ({
  300. void * __cl_addr = (addr);
  301. unsigned long __cl_size = (n);
  302. if (__cl_size && __access_ok(VERIFY_WRITE,
  303.        ((unsigned long)(__cl_addr)), __cl_size))
  304. __cl_size = __clear_user(__cl_addr, __cl_size);
  305. __cl_size;
  306. })
  307. /*
  308.  * Returns: -EFAULT if exception before terminator, N if the entire
  309.  * buffer filled, else strlen.
  310.  */
  311. static inline long
  312. __strncpy_from_user(char *__to, const char *__from, long __len)
  313. {
  314. long res;
  315. __asm__ __volatile__(
  316. "movet$4, %1nt"
  317. "movet$5, %2nt"
  318. "movet$6, %3nt"
  319. __MODULE_JAL(__strncpy_from_user_nocheck_asm)
  320. "movet%0, $2"
  321. : "=r" (res)
  322. : "r" (__to), "r" (__from), "r" (__len)
  323. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  324. return res;
  325. }
  326. static inline long
  327. strncpy_from_user(char *__to, const char *__from, long __len)
  328. {
  329. long res;
  330. __asm__ __volatile__(
  331. "movet$4, %1nt"
  332. "movet$5, %2nt"
  333. "movet$6, %3nt"
  334. __MODULE_JAL(__strncpy_from_user_asm)
  335. "movet%0, $2"
  336. : "=r" (res)
  337. : "r" (__to), "r" (__from), "r" (__len)
  338. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  339. return res;
  340. }
  341. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  342. static inline long __strlen_user(const char *s)
  343. {
  344. long res;
  345. __asm__ __volatile__(
  346. "movet$4, %1nt"
  347. __MODULE_JAL(__strlen_user_nocheck_asm)
  348. "movet%0, $2"
  349. : "=r" (res)
  350. : "r" (s)
  351. : "$2", "$4", "$8", "$31");
  352. return res;
  353. }
  354. static inline long strlen_user(const char *s)
  355. {
  356. long res;
  357. __asm__ __volatile__(
  358. "movet$4, %1nt"
  359. __MODULE_JAL(__strlen_user_asm)
  360. "movet%0, $2"
  361. : "=r" (res)
  362. : "r" (s)
  363. : "$2", "$4", "$8", "$31");
  364. return res;
  365. }
  366. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  367. static inline long __strnlen_user(const char *s, long n)
  368. {
  369. long res;
  370. __asm__ __volatile__(
  371. "movet$4, %1nt"
  372. "movet$5, %2nt"
  373. __MODULE_JAL(__strnlen_user_nocheck_asm)
  374. "movet%0, $2"
  375. : "=r" (res)
  376. : "r" (s), "r" (n)
  377. : "$2", "$4", "$5", "$8", "$31");
  378. return res;
  379. }
  380. static inline long strnlen_user(const char *s, long n)
  381. {
  382. long res;
  383. __asm__ __volatile__(
  384. "movet$4, %1nt"
  385. "movet$5, %2nt"
  386. __MODULE_JAL(__strnlen_user_asm)
  387. "movet%0, $2"
  388. : "=r" (res)
  389. : "r" (s), "r" (n)
  390. : "$2", "$4", "$5", "$8", "$31");
  391. return res;
  392. }
  393. struct exception_table_entry
  394. {
  395. unsigned long insn;
  396. unsigned long nextinsn;
  397. };
  398. /* Returns 0 if exception not found and fixup.unit otherwise.  */
  399. extern unsigned long search_exception_table(unsigned long addr);
  400. /* Returns the new pc */
  401. #define fixup_exception(map_reg, fixup_unit, pc)                
  402. ({                                                              
  403. fixup_unit;                                             
  404. })
  405. #endif /* _ASM_UACCESS_H */