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

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. /*
  79.  * Yuck.  We need two variants, one for 64bit operation and one
  80.  * for 32 bit mode and old iron.
  81.  */
  82. #ifdef __mips64
  83. #define __GET_USER_DW __get_user_asm("ld")
  84. #else
  85. #define __GET_USER_DW __get_user_asm_ll32
  86. #endif
  87. #define __get_user_nocheck(x,ptr,size) ({ 
  88. long __gu_err; 
  89. __typeof(*(ptr)) __gu_val; 
  90. long __gu_addr; 
  91. __asm__("":"=r" (__gu_val)); 
  92. __gu_addr = (long) (ptr); 
  93. __asm__("":"=r" (__gu_err)); 
  94. switch (size) { 
  95. case 1: __get_user_asm("lb"); break; 
  96. case 2: __get_user_asm("lh"); break; 
  97. case 4: __get_user_asm("lw"); break; 
  98. case 8: __GET_USER_DW; break; 
  99. default: __get_user_unknown(); break; 
  100. } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
  101. #define __get_user_check(x,ptr,size) ({ 
  102. long __gu_err; 
  103. __typeof__(*(ptr)) __gu_val; 
  104. long __gu_addr; 
  105. __asm__("":"=r" (__gu_val)); 
  106. __gu_addr = (long) (ptr); 
  107. __asm__("":"=r" (__gu_err)); 
  108. if (__access_ok(__gu_addr,size,__access_mask)) { 
  109. switch (size) { 
  110. case 1: __get_user_asm("lb"); break; 
  111. case 2: __get_user_asm("lh"); break; 
  112. case 4: __get_user_asm("lw"); break; 
  113. case 8: __GET_USER_DW; break; 
  114. default: __get_user_unknown(); break; 
  115. } } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
  116. #define __get_user_asm(insn) 
  117. ({ 
  118. __asm__ __volatile__( 
  119. "1:t" insn "t%1,%2nt" 
  120. "movet%0,$0n" 
  121. "2:nt" 
  122. ".sectiont.fixup,"ax"n" 
  123. "3:tlit%0,%3nt" 
  124. "movet%1,$0nt" 
  125. "jt2bnt" 
  126. ".previousnt" 
  127. ".sectiont__ex_table,"a"nt" 
  128. ".wordt1b,3bnt" 
  129. ".previous" 
  130. :"=r" (__gu_err), "=r" (__gu_val) 
  131. :"o" (__m(__gu_addr)), "i" (-EFAULT)); })
  132. /*
  133.  * Get a long long 64 using 32 bit registers.
  134.  */
  135. #define __get_user_asm_ll32 
  136. ({ 
  137. __asm__ __volatile__( 
  138. "1:tlwt%1,%2n" 
  139. "2:tlwt%D1,%3nt" 
  140. "movet%0,$0n" 
  141. "3:t.sectiont.fixup,"ax"n" 
  142. "4:tlit%0,%4nt" 
  143. "movet%1,$0nt" 
  144. "movet%D1,$0nt" 
  145. "jt3bnt" 
  146. ".previousnt" 
  147. ".sectiont__ex_table,"a"nt" 
  148. ".wordt1b,4bnt" 
  149. ".wordt2b,4bnt" 
  150. ".previous" 
  151. :"=r" (__gu_err), "=&r" (__gu_val) 
  152. :"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)), 
  153.  "i" (-EFAULT)); })
  154. extern void __get_user_unknown(void);
  155. /*
  156.  * Yuck.  We need two variants, one for 64bit operation and one
  157.  * for 32 bit mode and old iron.
  158.  */
  159. #ifdef __mips64
  160. #define __PUT_USER_DW __put_user_asm("sd")
  161. #else
  162. #define __PUT_USER_DW __put_user_asm_ll32
  163. #endif
  164. #define __put_user_nocheck(x,ptr,size) ({ 
  165. long __pu_err; 
  166. __typeof__(*(ptr)) __pu_val; 
  167. long __pu_addr; 
  168. __pu_val = (x); 
  169. __pu_addr = (long) (ptr); 
  170. __asm__("":"=r" (__pu_err)); 
  171. switch (size) { 
  172. case 1: __put_user_asm("sb"); break; 
  173. case 2: __put_user_asm("sh"); break; 
  174. case 4: __put_user_asm("sw"); break; 
  175. case 8: __PUT_USER_DW; break; 
  176. default: __put_user_unknown(); break; 
  177. } __pu_err; })
  178. #define __put_user_check(x,ptr,size) ({ 
  179. long __pu_err; 
  180. __typeof__(*(ptr)) __pu_val; 
  181. long __pu_addr; 
  182. __pu_val = (x); 
  183. __pu_addr = (long) (ptr); 
  184. __asm__("":"=r" (__pu_err)); 
  185. if (__access_ok(__pu_addr,size,__access_mask)) { 
  186. switch (size) { 
  187. case 1: __put_user_asm("sb"); break; 
  188. case 2: __put_user_asm("sh"); break; 
  189. case 4: __put_user_asm("sw"); break; 
  190. case 8: __PUT_USER_DW; break; 
  191. default: __put_user_unknown(); break; 
  192. } } __pu_err; })
  193. #define __put_user_asm(insn) 
  194. ({ 
  195. __asm__ __volatile__( 
  196. "1:t" insn "t%z1, %2ttt# __put_user_asmnt" 
  197. "movet%0, $0n" 
  198. "2:nt" 
  199. ".sectiont.fixup,"ax"n" 
  200. "3:tlit%0,%3nt" 
  201. "jt2bnt" 
  202. ".previousnt" 
  203. ".sectiont__ex_table,"a"nt" 
  204. ".wordt1b,3bnt" 
  205. ".previous" 
  206. :"=r" (__pu_err) 
  207. :"Jr" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); })
  208. #define __put_user_asm_ll32 
  209. ({ 
  210. __asm__ __volatile__( 
  211. "1:tswt%1, %2ttt# __put_user_asm_ll32nt" 
  212. "2:tswt%D1, %3n" 
  213. "movet%0, $0n" 
  214. "3:nt" 
  215. ".sectiont.fixup,"ax"n" 
  216. "4:tlit%0,%4nt" 
  217. "jt3bnt" 
  218. ".previousnt" 
  219. ".sectiont__ex_table,"a"nt" 
  220. ".wordt1b,4bnt" 
  221. ".wordt2b,4bnt" 
  222. ".previous" 
  223. :"=r" (__pu_err) 
  224. :"r" (__pu_val), "o" (__m(__pu_addr)), "o" (__m(__pu_addr + 4)), 
  225.  "i" (-EFAULT)); })
  226. extern void __put_user_unknown(void);
  227. /*
  228.  * We're generating jump to subroutines which will be outside the range of
  229.  * jump instructions
  230.  */
  231. #ifdef MODULE
  232. #define __MODULE_JAL(destination) 
  233. ".settnoatnt" 
  234. "lat$1, " #destination "nt" 
  235. "jalrt$1nt" 
  236. ".settatnt"
  237. #else
  238. #define __MODULE_JAL(destination) 
  239. "jalt" #destination "nt"
  240. #endif
  241. extern size_t __copy_user(void *__to, const void *__from, size_t __n);
  242. #define __invoke_copy_to_user(to,from,n) ({
  243. register void *__cu_to_r __asm__ ("$4");
  244. register const void *__cu_from_r __asm__ ("$5");
  245. register long __cu_len_r __asm__ ("$6");
  246. __cu_to_r = (to);
  247. __cu_from_r = (from);
  248. __cu_len_r = (n);
  249. __asm__ __volatile__(
  250. __MODULE_JAL(__copy_user)
  251. : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
  252. :
  253. : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",
  254.   "memory");
  255. __cu_len_r;
  256. })
  257. #define __copy_to_user(to,from,n) ({
  258. void *__cu_to;
  259. const void *__cu_from;
  260. long __cu_len;
  261. __cu_to = (to);
  262. __cu_from = (from);
  263. __cu_len = (n);
  264. __cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len);
  265. __cu_len;
  266. })
  267. #define copy_to_user(to,from,n) ({
  268. void *__cu_to;
  269. const void *__cu_from;
  270. long __cu_len;
  271. __cu_to = (to);
  272. __cu_from = (from);
  273. __cu_len = (n);
  274. if (access_ok(VERIFY_WRITE, __cu_to, __cu_len))
  275. __cu_len = __invoke_copy_to_user(__cu_to, __cu_from,
  276.                                  __cu_len);
  277. __cu_len;
  278. })
  279. #define __invoke_copy_from_user(to,from,n) ({
  280. register void *__cu_to_r __asm__ ("$4");
  281. register const void *__cu_from_r __asm__ ("$5");
  282. register long __cu_len_r __asm__ ("$6");
  283. __cu_to_r = (to);
  284. __cu_from_r = (from);
  285. __cu_len_r = (n);
  286. __asm__ __volatile__(
  287. ".settnoreordernt"
  288. __MODULE_JAL(__copy_user)
  289. ".settnoatnt"
  290. "addut$1, %1, %2nt"
  291. ".settatnt"
  292. ".settreordernt"
  293. : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
  294. :
  295. : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31",
  296.   "memory");
  297. __cu_len_r;
  298. })
  299. #define __copy_from_user(to,from,n) ({
  300. void *__cu_to;
  301. const void *__cu_from;
  302. long __cu_len;
  303. __cu_to = (to);
  304. __cu_from = (from);
  305. __cu_len = (n);
  306. __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,
  307.                                    __cu_len);
  308. __cu_len;
  309. })
  310. #define copy_from_user(to,from,n) ({
  311. void *__cu_to;
  312. const void *__cu_from;
  313. long __cu_len;
  314. __cu_to = (to);
  315. __cu_from = (from);
  316. __cu_len = (n);
  317. if (access_ok(VERIFY_READ, __cu_from, __cu_len))
  318. __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,
  319.                                    __cu_len);
  320. __cu_len;
  321. })
  322. static inline __kernel_size_t
  323. __clear_user(void *addr, __kernel_size_t size)
  324. {
  325. __kernel_size_t res;
  326. __asm__ __volatile__(
  327. "movet$4, %1nt"
  328. "movet$5, $0nt"
  329. "movet$6, %2nt"
  330. __MODULE_JAL(__bzero)
  331. "movet%0, $6"
  332. : "=r" (res)
  333. : "r" (addr), "r" (size)
  334. : "$4", "$5", "$6", "$8", "$9", "$31");
  335. return res;
  336. }
  337. #define clear_user(addr,n) ({ 
  338. void * __cl_addr = (addr); 
  339. unsigned long __cl_size = (n); 
  340. if (__cl_size && access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) 
  341. __cl_size = __clear_user(__cl_addr, __cl_size); 
  342. __cl_size; })
  343. /*
  344.  * Returns: -EFAULT if exception before terminator, N if the entire
  345.  * buffer filled, else strlen.
  346.  */
  347. static inline long
  348. __strncpy_from_user(char *__to, const char *__from, long __len)
  349. {
  350. long res;
  351. __asm__ __volatile__(
  352. "movet$4, %1nt"
  353. "movet$5, %2nt"
  354. "movet$6, %3nt"
  355. __MODULE_JAL(__strncpy_from_user_nocheck_asm)
  356. "movet%0, $2"
  357. : "=r" (res)
  358. : "r" (__to), "r" (__from), "r" (__len)
  359. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  360. return res;
  361. }
  362. static inline long
  363. strncpy_from_user(char *__to, const char *__from, long __len)
  364. {
  365. long res;
  366. __asm__ __volatile__(
  367. "movet$4, %1nt"
  368. "movet$5, %2nt"
  369. "movet$6, %3nt"
  370. __MODULE_JAL(__strncpy_from_user_asm)
  371. "movet%0, $2"
  372. : "=r" (res)
  373. : "r" (__to), "r" (__from), "r" (__len)
  374. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  375. return res;
  376. }
  377. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  378. static inline long __strlen_user(const char *s)
  379. {
  380. long res;
  381. __asm__ __volatile__(
  382. "movet$4, %1nt"
  383. __MODULE_JAL(__strlen_user_nocheck_asm)
  384. "movet%0, $2"
  385. : "=r" (res)
  386. : "r" (s)
  387. : "$2", "$4", "$8", "$31");
  388. return res;
  389. }
  390. static inline long strlen_user(const char *s)
  391. {
  392. long res;
  393. __asm__ __volatile__(
  394. "movet$4, %1nt"
  395. __MODULE_JAL(__strlen_user_asm)
  396. "movet%0, $2"
  397. : "=r" (res)
  398. : "r" (s)
  399. : "$2", "$4", "$8", "$31");
  400. return res;
  401. }
  402. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  403. static inline long __strnlen_user(const char *s, long n)
  404. {
  405. long res;
  406. __asm__ __volatile__(
  407. "movet$4, %1nt"
  408. "movet$5, %2nt"
  409. __MODULE_JAL(__strnlen_user_nocheck_asm)
  410. "movet%0, $2"
  411. : "=r" (res)
  412. : "r" (s), "r" (n)
  413. : "$2", "$4", "$5", "$8", "$31");
  414. return res;
  415. }
  416. static inline long strnlen_user(const char *s, long n)
  417. {
  418. long res;
  419. __asm__ __volatile__(
  420. "movet$4, %1nt"
  421. "movet$5, %2nt"
  422. __MODULE_JAL(__strnlen_user_asm)
  423. "movet%0, $2"
  424. : "=r" (res)
  425. : "r" (s), "r" (n)
  426. : "$2", "$4", "$5", "$8", "$31");
  427. return res;
  428. }
  429. struct exception_table_entry
  430. {
  431. unsigned long insn;
  432. unsigned long nextinsn;
  433. };
  434. /* Returns 0 if exception not found and fixup.unit otherwise.  */
  435. extern unsigned long search_exception_table(unsigned long addr);
  436. /* Returns the new pc */
  437. #define fixup_exception(map_reg, fixup_unit, pc)                
  438. ({                                                              
  439. fixup_unit;                                             
  440. })
  441. #endif /* _ASM_UACCESS_H */