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

嵌入式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. /*
  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 __copy_to_user(to,from,n) ({ 
  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. __asm__ __volatile__( 
  250. "movet$4, %1nt" 
  251. "movet$5, %2nt" 
  252. "movet$6, %3nt" 
  253. __MODULE_JAL(__copy_user) 
  254. "movet%0, $6" 
  255. : "=r" (__cu_len) 
  256. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  257. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", 
  258.   "$24", "$31","memory"); 
  259. __cu_len; 
  260. })
  261. #define __copy_from_user(to,from,n) ({ 
  262. void *__cu_to; 
  263. const void *__cu_from; 
  264. long __cu_len; 
  265. __cu_to = (to); 
  266. __cu_from = (from); 
  267. __cu_len = (n); 
  268. __asm__ __volatile__( 
  269. "movet$4, %1nt" 
  270. "movet$5, %2nt" 
  271. "movet$6, %3nt" 
  272. ".settnoreordernt" 
  273. __MODULE_JAL(__copy_user) 
  274. ".settnoatnt" 
  275. "addut$1, %2, %3nt" 
  276. ".settatnt" 
  277. ".settreordernt" 
  278. "movet%0, $6" 
  279. : "=r" (__cu_len) 
  280. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  281. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", 
  282.   "$24", "$31","memory"); 
  283. __cu_len; 
  284. })
  285. #define copy_to_user(to,from,n) ({ 
  286. void *__cu_to; 
  287. const void *__cu_from; 
  288. long __cu_len; 
  289. __cu_to = (to); 
  290. __cu_from = (from); 
  291. __cu_len = (n); 
  292. if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) 
  293. __asm__ __volatile__( 
  294. "movet$4, %1nt" 
  295. "movet$5, %2nt" 
  296. "movet$6, %3nt" 
  297. __MODULE_JAL(__copy_user) 
  298. "movet%0, $6" 
  299. : "=r" (__cu_len) 
  300. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  301. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", 
  302.   "$15", "$24", "$31","memory"); 
  303. __cu_len; 
  304. })
  305. #define copy_from_user(to,from,n) ({ 
  306. void *__cu_to; 
  307. const void *__cu_from; 
  308. long __cu_len; 
  309. __cu_to = (to); 
  310. __cu_from = (from); 
  311. __cu_len = (n); 
  312. if (access_ok(VERIFY_READ, __cu_from, __cu_len)) 
  313. __asm__ __volatile__( 
  314. "movet$4, %1nt" 
  315. "movet$5, %2nt" 
  316. "movet$6, %3nt" 
  317. ".settnoreordernt" 
  318. __MODULE_JAL(__copy_user) 
  319. ".settnoatnt" 
  320. "addut$1, %2, %3nt" 
  321. ".settatnt" 
  322. ".settreordernt" 
  323. "movet%0, $6" 
  324. : "=r" (__cu_len) 
  325. : "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) 
  326. : "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", 
  327.   "$15", "$24", "$31","memory"); 
  328. __cu_len; 
  329. })
  330. extern inline __kernel_size_t
  331. __clear_user(void *addr, __kernel_size_t size)
  332. {
  333. __kernel_size_t res;
  334. __asm__ __volatile__(
  335. "movet$4, %1nt"
  336. "movet$5, $0nt"
  337. "movet$6, %2nt"
  338. __MODULE_JAL(__bzero)
  339. "movet%0, $6"
  340. : "=r" (res)
  341. : "r" (addr), "r" (size)
  342. : "$4", "$5", "$6", "$8", "$9", "$31");
  343. return res;
  344. }
  345. #define clear_user(addr,n) ({ 
  346. void * __cl_addr = (addr); 
  347. unsigned long __cl_size = (n); 
  348. if (__cl_size && access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) 
  349. __cl_size = __clear_user(__cl_addr, __cl_size); 
  350. __cl_size; })
  351. /*
  352.  * Returns: -EFAULT if exception before terminator, N if the entire
  353.  * buffer filled, else strlen.
  354.  */
  355. extern inline long
  356. __strncpy_from_user(char *__to, const char *__from, long __len)
  357. {
  358. long res;
  359. __asm__ __volatile__(
  360. "movet$4, %1nt"
  361. "movet$5, %2nt"
  362. "movet$6, %3nt"
  363. __MODULE_JAL(__strncpy_from_user_nocheck_asm)
  364. "movet%0, $2"
  365. : "=r" (res)
  366. : "r" (__to), "r" (__from), "r" (__len)
  367. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  368. return res;
  369. }
  370. extern inline long
  371. strncpy_from_user(char *__to, const char *__from, long __len)
  372. {
  373. long res;
  374. __asm__ __volatile__(
  375. "movet$4, %1nt"
  376. "movet$5, %2nt"
  377. "movet$6, %3nt"
  378. __MODULE_JAL(__strncpy_from_user_asm)
  379. "movet%0, $2"
  380. : "=r" (res)
  381. : "r" (__to), "r" (__from), "r" (__len)
  382. : "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
  383. return res;
  384. }
  385. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  386. extern inline long __strlen_user(const char *s)
  387. {
  388. long res;
  389. __asm__ __volatile__(
  390. "movet$4, %1nt"
  391. __MODULE_JAL(__strlen_user_nocheck_asm)
  392. "movet%0, $2"
  393. : "=r" (res)
  394. : "r" (s)
  395. : "$2", "$4", "$8", "$31");
  396. return res;
  397. }
  398. extern inline long strlen_user(const char *s)
  399. {
  400. long res;
  401. __asm__ __volatile__(
  402. "movet$4, %1nt"
  403. __MODULE_JAL(__strlen_user_asm)
  404. "movet%0, $2"
  405. : "=r" (res)
  406. : "r" (s)
  407. : "$2", "$4", "$8", "$31");
  408. return res;
  409. }
  410. /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
  411. extern inline long __strnlen_user(const char *s, long n)
  412. {
  413. long res;
  414. __asm__ __volatile__(
  415. "movet$4, %1nt"
  416. "movet$5, %2nt"
  417. __MODULE_JAL(__strnlen_user_nocheck_asm)
  418. "movet%0, $2"
  419. : "=r" (res)
  420. : "r" (s), "r" (n)
  421. : "$2", "$4", "$5", "$8", "$31");
  422. return res;
  423. }
  424. extern inline long strnlen_user(const char *s, long n)
  425. {
  426. long res;
  427. __asm__ __volatile__(
  428. "movet$4, %1nt"
  429. "movet$5, %2nt"
  430. __MODULE_JAL(__strnlen_user_asm)
  431. "movet%0, $2"
  432. : "=r" (res)
  433. : "r" (s), "r" (n)
  434. : "$2", "$4", "$5", "$8", "$31");
  435. return res;
  436. }
  437. struct exception_table_entry
  438. {
  439. unsigned long insn;
  440. unsigned long nextinsn;
  441. };
  442. /* Returns 0 if exception not found and fixup.unit otherwise.  */
  443. extern unsigned long search_exception_table(unsigned long addr);
  444. /* Returns the new pc */
  445. #define fixup_exception(map_reg, fixup_unit, pc)                
  446. ({                                                              
  447. fixup_unit;                                             
  448. })
  449. #endif /* _ASM_UACCESS_H */