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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* 
  2.  * Authors:    Bjorn Wesen (bjornw@axis.com)
  3.  *        Hans-Peter Nilsson (hp@axis.com)
  4.  *
  5.  * $Log: uaccess.h,v $
  6.  * Revision 1.8  2001/10/29 13:01:48  bjornw
  7.  * Removed unused variable tmp2 in strnlen_user
  8.  *
  9.  * Revision 1.7  2001/10/02 12:44:52  hp
  10.  * Add support for 64-bit put_user/get_user
  11.  *
  12.  * Revision 1.6  2001/10/01 14:51:17  bjornw
  13.  * Added register prefixes and removed underscores
  14.  *
  15.  * Revision 1.5  2000/10/25 03:33:21  hp
  16.  * - Provide implementation for everything else but get_user and put_user;
  17.  *   copying inline to/from user for constant length 0..16, 20, 24, and
  18.  *   clearing for 0..4, 8, 12, 16, 20, 24, strncpy_from_user and strnlen_user
  19.  *   always inline.
  20.  * - Constraints for destination addr in get_user cannot be memory, only reg.
  21.  * - Correct labels for PC at expected fault points.
  22.  * - Nits with assembly code.
  23.  * - Don't use statement expressions without value; use "do {} while (0)".
  24.  * - Return correct values from __generic_... functions.
  25.  *
  26.  * Revision 1.4  2000/09/12 16:28:25  bjornw
  27.  * * Removed comments from the get/put user asm code
  28.  * * Constrains for destination addr in put_user cannot be memory, only reg
  29.  *
  30.  * Revision 1.3  2000/09/12 14:30:20  bjornw
  31.  * MAX_ADDR_USER does not exist anymore
  32.  *
  33.  * Revision 1.2  2000/07/13 15:52:48  bjornw
  34.  * New user-access functions
  35.  *
  36.  * Revision 1.1.1.1  2000/07/10 16:32:31  bjornw
  37.  * CRIS architecture, working draft
  38.  *
  39.  *
  40.  *
  41.  */
  42. /* Asm:s have been tweaked (within the domain of correctness) to give
  43.    satisfactory results for "gcc version 2.96 20000427 (experimental)".
  44.    Check regularly...
  45.    Register $r9 is chosen for temporaries, being a call-clobbered register
  46.    first in line to be used (notably for local blocks), not colliding with
  47.    parameter registers.  */
  48. #ifndef _CRIS_UACCESS_H
  49. #define _CRIS_UACCESS_H
  50. #ifndef __ASSEMBLY__
  51. #include <linux/sched.h>
  52. #include <linux/errno.h>
  53. #include <asm/processor.h>
  54. #include <asm/page.h>
  55. #define VERIFY_READ 0
  56. #define VERIFY_WRITE 1
  57. /*
  58.  * The fs value determines whether argument validity checking should be
  59.  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  60.  * get_fs() == KERNEL_DS, checking is bypassed.
  61.  *
  62.  * For historical reasons, these macros are grossly misnamed.
  63.  */
  64. #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
  65. /* addr_limit is the maximum accessible address for the task. we misuse
  66.  * the KERNEL_DS and USER_DS values to both assign and compare the 
  67.  * addr_limit values through the equally misnamed get/set_fs macros.
  68.  * (see above)
  69.  */
  70. #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
  71. #define USER_DS MAKE_MM_SEG(TASK_SIZE)
  72. #define get_ds() (KERNEL_DS)
  73. #define get_fs() (current->addr_limit)
  74. #define set_fs(x) (current->addr_limit = (x))
  75. #define segment_eq(a,b) ((a).seg == (b).seg)
  76. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  77. #define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
  78. #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
  79. #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
  80. extern inline int verify_area(int type, const void * addr, unsigned long size)
  81. {
  82. return access_ok(type,addr,size) ? 0 : -EFAULT;
  83. }
  84. /*
  85.  * The exception table consists of pairs of addresses: the first is the
  86.  * address of an instruction that is allowed to fault, and the second is
  87.  * the address at which the program should continue.  No registers are
  88.  * modified, so it is entirely up to the continuation code to figure out
  89.  * what to do.
  90.  *
  91.  * All the routines below use bits of fixup code that are out of line
  92.  * with the main instruction path.  This means when everything is well,
  93.  * we don't even have to jump over them.  Further, they do not intrude
  94.  * on our cache or tlb entries.
  95.  */
  96. struct exception_table_entry
  97. {
  98. unsigned long insn, fixup;
  99. };
  100. /* Returns 0 if exception not found and fixup otherwise.  */
  101. extern unsigned long search_exception_table(unsigned long);
  102. /*
  103.  * These are the main single-value transfer routines.  They automatically
  104.  * use the right size if we just have the right pointer type.
  105.  *
  106.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  107.  * and yet we don't want to do any pointers, because that is too much
  108.  * of a performance impact. Thus we have a few rather ugly macros here,
  109.  * and hide all the uglyness from the user.
  110.  *
  111.  * The "__xxx" versions of the user access functions are versions that
  112.  * do not verify the address space, that must have been done previously
  113.  * with a separate "access_ok()" call (this is used when we do multiple
  114.  * accesses to the same area of user memory).
  115.  *
  116.  * As we use the same address space for kernel and user data on
  117.  * CRIS, we can just do these as direct assignments.  (Of course, the
  118.  * exception handling means that it's no longer "just"...)
  119.  */
  120. #define get_user(x,ptr) 
  121.   __get_user_check((x),(ptr),sizeof(*(ptr)))
  122. #define put_user(x,ptr) 
  123.   __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  124. #define __get_user(x,ptr) 
  125.   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
  126. #define __put_user(x,ptr) 
  127.   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  128. /*
  129.  * The "xxx_ret" versions return constant specified in third argument, if
  130.  * something bad happens. These macros can be optimized for the
  131.  * case of just returning from the function xxx_ret is used.
  132.  */
  133. #define put_user_ret(x,ptr,ret) 
  134. do { if (put_user(x,ptr)) return ret; } while (0)
  135. #define get_user_ret(x,ptr,ret) 
  136. do { if (get_user(x,ptr)) return ret; } while (0)
  137. #define __put_user_ret(x,ptr,ret) 
  138. do { if (__put_user(x,ptr)) return ret; } while (0)
  139. #define __get_user_ret(x,ptr,ret) 
  140. do { if (__get_user(x,ptr)) return ret; } while (0)
  141. extern long __put_user_bad(void);
  142. #define __put_user_nocheck(x,ptr,size)
  143. ({
  144. long __pu_err;
  145. __put_user_size((x),(ptr),(size),__pu_err);
  146. __pu_err;
  147. })
  148. #define __put_user_check(x,ptr,size)
  149. ({
  150. long __pu_err = -EFAULT;
  151. __typeof__(*(ptr)) *__pu_addr = (ptr);
  152. if (access_ok(VERIFY_WRITE,__pu_addr,size))
  153. __put_user_size((x),__pu_addr,(size),__pu_err);
  154. __pu_err;
  155. })
  156. #define __put_user_size(x,ptr,size,retval)
  157. do {
  158. retval = 0;
  159. switch (size) {
  160.   case 1: __put_user_asm(x,ptr,retval,"move.b"); break;
  161.   case 2: __put_user_asm(x,ptr,retval,"move.w"); break;
  162.   case 4: __put_user_asm(x,ptr,retval,"move.d"); break;
  163.   case 8: __put_user_asm_64(x,ptr,retval); break;
  164.   default: __put_user_bad();
  165. }
  166. } while (0)
  167. struct __large_struct { unsigned long buf[100]; };
  168. #define __m(x) (*(struct __large_struct *)(x))
  169. /*
  170.  * We don't tell gcc that we are accessing memory, but this is OK
  171.  * because we do not write to any memory gcc knows about, so there
  172.  * are no aliasing issues.
  173.  *
  174.  * Note that PC at a fault is the address *after* the faulting
  175.  * instruction.
  176.  */
  177. #define __put_user_asm(x, addr, err, op)
  178. __asm__ __volatile__(
  179. " "op" %1,[%2]n"
  180. "2:n"
  181. " .section .fixup,"ax"n"
  182. "3: move.d %3,%0n"
  183. " jump 2bn"
  184. " .previousn"
  185. " .section __ex_table,"a"n"
  186. " .dword 2b,3bn"
  187. " .previousn"
  188. : "=r" (err)
  189. : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  190. #define __put_user_asm_64(x, addr, err)
  191. __asm__ __volatile__(
  192. " move.d %M1,[%2]n"
  193. "2: move.d %H1,[%2+4]n"
  194. "4:n"
  195. " .section .fixup,"ax"n"
  196. "3: move.d %3,%0n"
  197. " jump 4bn"
  198. " .previousn"
  199. " .section __ex_table,"a"n"
  200. " .dword 2b,3bn"
  201. " .dword 4b,3bn"
  202. " .previousn"
  203. : "=r" (err)
  204. : "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
  205. #define __get_user_nocheck(x,ptr,size)
  206. ({
  207. long __gu_err, __gu_val;
  208. __get_user_size(__gu_val,(ptr),(size),__gu_err);
  209. (x) = (__typeof__(*(ptr)))__gu_val;
  210. __gu_err;
  211. })
  212. #define __get_user_check(x,ptr,size)
  213. ({
  214. long __gu_err = -EFAULT, __gu_val = 0;
  215. const __typeof__(*(ptr)) *__gu_addr = (ptr);
  216. if (access_ok(VERIFY_READ,__gu_addr,size))
  217. __get_user_size(__gu_val,__gu_addr,(size),__gu_err);
  218. (x) = (__typeof__(*(ptr)))__gu_val;
  219. __gu_err;
  220. })
  221. extern long __get_user_bad(void);
  222. #define __get_user_size(x,ptr,size,retval)
  223. do {
  224. retval = 0;
  225. switch (size) {
  226.   case 1: __get_user_asm(x,ptr,retval,"move.b"); break;
  227.   case 2: __get_user_asm(x,ptr,retval,"move.w"); break;
  228.   case 4: __get_user_asm(x,ptr,retval,"move.d"); break;
  229.   case 8: __get_user_asm_64(x,ptr,retval); break;
  230.   default: (x) = __get_user_bad();
  231. }
  232. } while (0)
  233. /* See comment before __put_user_asm.  */
  234. #define __get_user_asm(x, addr, err, op)
  235. __asm__ __volatile__(
  236. " "op" [%2],%1n"
  237. "2:n"
  238. " .section .fixup,"ax"n"
  239. "3: move.d %3,%0n"
  240. " moveq 0,%1n"
  241. " jump 2bn"
  242. " .previousn"
  243. " .section __ex_table,"a"n"
  244. " .dword 2b,3bn"
  245. " .previousn"
  246. : "=r" (err), "=r" (x)
  247. : "r" (addr), "g" (-EFAULT), "0" (err))
  248. #define __get_user_asm_64(x, addr, err)
  249. __asm__ __volatile__(
  250. " move.d [%2],%M1n"
  251. "2: move.d [%2+4],%H1n"
  252. "4:n"
  253. " .section .fixup,"ax"n"
  254. "3: move.d %3,%0n"
  255. " moveq 0,%1n"
  256. " jump 4bn"
  257. " .previousn"
  258. " .section __ex_table,"a"n"
  259. " .dword 2b,3bn"
  260. " .dword 4b,3bn"
  261. " .previousn"
  262. : "=r" (err), "=r" (x)
  263. : "r" (addr), "g" (-EFAULT), "0" (err))
  264. /* More complex functions.  Most are inline, but some call functions that
  265.    live in lib/usercopy.c  */
  266. extern unsigned long __copy_user(void *to, const void *from, unsigned long n);
  267. extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n);
  268. extern unsigned long __do_clear_user(void *to, unsigned long n);
  269. /*
  270.  * Copy a null terminated string from userspace.
  271.  *
  272.  * Must return:
  273.  * -EFAULT for an exception
  274.  * count if we hit the buffer limit
  275.  * bytes copied if we hit a null byte
  276.  * (without the null byte)
  277.  */
  278. static inline long         
  279. __do_strncpy_from_user(char *dst, const char *src, long count)
  280. {
  281. long res;
  282. if (count == 0)
  283. return 0;
  284. /*
  285.  * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
  286.  *  So do we.
  287.  *
  288.  *  This code is deduced from:
  289.  *
  290.  * char tmp2;
  291.  * long tmp1, tmp3
  292.  * tmp1 = count;
  293.  * while ((*dst++ = (tmp2 = *src++)) != 0
  294.  *        && --tmp1)
  295.  *   ;
  296.  *
  297.  * res = count - tmp1;
  298.  *
  299.  *  with tweaks.
  300.  */
  301. __asm__ __volatile__ (
  302. " move.d %3,%0n"
  303. " move.b [%2+],$r9n"
  304. "1: beq 2fn"
  305. " move.b $r9,[%1+]n"
  306. " subq 1,%0n"
  307. " bne 1bn"
  308. " move.b [%2+],$r9n"
  309. "2: sub.d %3,%0n"
  310. " neg.d %0,%0n"
  311. "3:n"
  312. " .section .fixup,"ax"n"
  313. "4: move.d %7,%0n"
  314. " jump 3bn"
  315. /* There's one address for a fault at the first move, and
  316.    two possible PC values for a fault at the second move,
  317.    being a delay-slot filler.  However, the branch-target
  318.    for the second move is the same as the first address.
  319.    Just so you don't get confused...  */
  320. " .previousn"
  321. " .section __ex_table,"a"n"
  322. " .dword 1b,4bn"
  323. " .dword 2b,4bn"
  324. " .previous"
  325. : "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
  326. : "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
  327. : "r9");
  328. return res;
  329. }
  330. static inline unsigned long
  331. __generic_copy_to_user(void *to, const void *from, unsigned long n)
  332. {
  333. if (access_ok(VERIFY_WRITE, to, n))
  334. return __copy_user(to,from,n);
  335. return n;
  336. }
  337. static inline unsigned long
  338. __generic_copy_from_user(void *to, const void *from, unsigned long n)
  339. {
  340. if (access_ok(VERIFY_READ, from, n))
  341. return __copy_user_zeroing(to,from,n);
  342. return n;
  343. }
  344. static inline unsigned long
  345. __generic_clear_user(void *to, unsigned long n)
  346. {
  347. if (access_ok(VERIFY_WRITE, to, n))
  348. return __do_clear_user(to,n);
  349. return n;
  350. }
  351. static inline long
  352. __strncpy_from_user(char *dst, const char *src, long count)
  353. {
  354. return __do_strncpy_from_user(dst, src, count);
  355. }
  356. static inline long
  357. strncpy_from_user(char *dst, const char *src, long count)
  358. {
  359. long res = -EFAULT;
  360. if (access_ok(VERIFY_READ, src, 1))
  361. res = __do_strncpy_from_user(dst, src, count);
  362. return res;
  363. }
  364. /* A few copy asms to build up the more complex ones from.
  365.    Note again, a post-increment is performed regardless of whether a bus
  366.    fault occurred in that instruction, and PC for a faulted insn is the
  367.    address *after* the insn.  */
  368. #define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  369. __asm__ __volatile__ (
  370. COPY
  371. "1:n"
  372. " .section .fixup,"ax"n"
  373. FIXUP
  374. " jump 1bn"
  375. " .previousn"
  376. " .section __ex_table,"a"n"
  377. TENTRY
  378. " .previousn"
  379. : "=r" (to), "=r" (from), "=r" (ret)
  380. : "0" (to), "1" (from), "2" (ret)
  381. : "r9", "memory")
  382. #define __asm_copy_from_user_1(to, from, ret) 
  383. __asm_copy_user_cont(to, from, ret,
  384. " move.b [%1+],$r9n"
  385. "2: move.b $r9,[%0+]n",
  386. "3: addq 1,%2n"
  387. " clear.b [%0+]n",
  388. " .dword 2b,3bn")
  389. #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  390. __asm_copy_user_cont(to, from, ret,
  391. " move.w [%1+],$r9n"
  392. "2: move.w $r9,[%0+]n" COPY,
  393. "3: addq 2,%2n"
  394. " clear.w [%0+]n" FIXUP,
  395. " .dword 2b,3bn" TENTRY)
  396. #define __asm_copy_from_user_2(to, from, ret) 
  397. __asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
  398. #define __asm_copy_from_user_3(to, from, ret)
  399. __asm_copy_from_user_2x_cont(to, from, ret,
  400. " move.b [%1+],$r9n"
  401. "4: move.b $r9,[%0+]n",
  402. "5: addq 1,%2n"
  403. " clear.b [%0+]n",
  404. " .dword 4b,5bn")
  405. #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  406. __asm_copy_user_cont(to, from, ret,
  407. " move.d [%1+],$r9n"
  408. "2: move.d $r9,[%0+]n" COPY,
  409. "3: addq 4,%2n"
  410. " clear.d [%0+]n" FIXUP,
  411. " .dword 2b,3bn" TENTRY)
  412. #define __asm_copy_from_user_4(to, from, ret) 
  413. __asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
  414. #define __asm_copy_from_user_5(to, from, ret) 
  415. __asm_copy_from_user_4x_cont(to, from, ret,
  416. " move.b [%1+],$r9n"
  417. "4: move.b $r9,[%0+]n",
  418. "5: addq 1,%2n"
  419. " clear.b [%0+]n",
  420. " .dword 4b,5bn")
  421. #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  422. __asm_copy_from_user_4x_cont(to, from, ret,
  423. " move.w [%1+],$r9n"
  424. "4: move.w $r9,[%0+]n" COPY,
  425. "5: addq 2,%2n"
  426. " clear.w [%0+]n" FIXUP,
  427. " .dword 4b,5bn" TENTRY)
  428. #define __asm_copy_from_user_6(to, from, ret) 
  429. __asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
  430. #define __asm_copy_from_user_7(to, from, ret) 
  431. __asm_copy_from_user_6x_cont(to, from, ret,
  432. " move.b [%1+],$r9n"
  433. "6: move.b $r9,[%0+]n",
  434. "7: addq 1,%2n"
  435. " clear.b [%0+]n",
  436. " .dword 6b,7bn")
  437. #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  438. __asm_copy_from_user_4x_cont(to, from, ret,
  439. " move.d [%1+],$r9n"
  440. "4: move.d $r9,[%0+]n" COPY,
  441. "5: addq 4,%2n"
  442. " clear.d [%0+]n" FIXUP,
  443. " .dword 4b,5bn" TENTRY)
  444. #define __asm_copy_from_user_8(to, from, ret) 
  445. __asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
  446. #define __asm_copy_from_user_9(to, from, ret) 
  447. __asm_copy_from_user_8x_cont(to, from, ret,
  448. " move.b [%1+],$r9n"
  449. "6: move.b $r9,[%0+]n",
  450. "7: addq 1,%2n"
  451. " clear.b [%0+]n",
  452. " .dword 6b,7bn")
  453. #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  454. __asm_copy_from_user_8x_cont(to, from, ret,
  455. " move.w [%1+],$r9n"
  456. "6: move.w $r9,[%0+]n" COPY,
  457. "7: addq 2,%2n"
  458. " clear.w [%0+]n" FIXUP,
  459. " .dword 6b,7bn" TENTRY)
  460. #define __asm_copy_from_user_10(to, from, ret) 
  461. __asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
  462. #define __asm_copy_from_user_11(to, from, ret)
  463. __asm_copy_from_user_10x_cont(to, from, ret,
  464. " move.b [%1+],$r9n"
  465. "8: move.b $r9,[%0+]n",
  466. "9: addq 1,%2n"
  467. " clear.b [%0+]n",
  468. " .dword 8b,9bn")
  469. #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  470. __asm_copy_from_user_8x_cont(to, from, ret,
  471. " move.d [%1+],$r9n"
  472. "6: move.d $r9,[%0+]n" COPY,
  473. "7: addq 4,%2n"
  474. " clear.d [%0+]n" FIXUP,
  475. " .dword 6b,7bn" TENTRY)
  476. #define __asm_copy_from_user_12(to, from, ret) 
  477. __asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
  478. #define __asm_copy_from_user_13(to, from, ret) 
  479. __asm_copy_from_user_12x_cont(to, from, ret,
  480. " move.b [%1+],$r9n"
  481. "8: move.b $r9,[%0+]n",
  482. "9: addq 1,%2n"
  483. " clear.b [%0+]n",
  484. " .dword 8b,9bn")
  485. #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  486. __asm_copy_from_user_12x_cont(to, from, ret,
  487. " move.w [%1+],$r9n"
  488. "8: move.w $r9,[%0+]n" COPY,
  489. "9: addq 2,%2n"
  490. " clear.w [%0+]n" FIXUP,
  491. " .dword 8b,9bn" TENTRY)
  492. #define __asm_copy_from_user_14(to, from, ret) 
  493. __asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
  494. #define __asm_copy_from_user_15(to, from, ret) 
  495. __asm_copy_from_user_14x_cont(to, from, ret,
  496. " move.b [%1+],$r9n"
  497. "10: move.b $r9,[%0+]n",
  498. "11: addq 1,%2n"
  499. " clear.b [%0+]n",
  500. " .dword 10b,11bn")
  501. #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  502. __asm_copy_from_user_12x_cont(to, from, ret,
  503. " move.d [%1+],$r9n"
  504. "8: move.d $r9,[%0+]n" COPY,
  505. "9: addq 4,%2n"
  506. " clear.d [%0+]n" FIXUP,
  507. " .dword 8b,9bn" TENTRY)
  508. #define __asm_copy_from_user_16(to, from, ret) 
  509. __asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
  510. #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  511. __asm_copy_from_user_16x_cont(to, from, ret,
  512. " move.d [%1+],$r9n"
  513. "10: move.d $r9,[%0+]n" COPY,
  514. "11: addq 4,%2n"
  515. " clear.d [%0+]n" FIXUP,
  516. " .dword 10b,11bn" TENTRY)
  517. #define __asm_copy_from_user_20(to, from, ret) 
  518. __asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
  519. #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  520. __asm_copy_from_user_20x_cont(to, from, ret,
  521. " move.d [%1+],$r9n"
  522. "12: move.d $r9,[%0+]n" COPY,
  523. "13: addq 4,%2n"
  524. " clear.d [%0+]n" FIXUP,
  525. " .dword 12b,13bn" TENTRY)
  526. #define __asm_copy_from_user_24(to, from, ret) 
  527. __asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
  528. /* And now, the to-user ones.  */
  529. #define __asm_copy_to_user_1(to, from, ret)
  530. __asm_copy_user_cont(to, from, ret,
  531. " move.b [%1+],$r9n"
  532. " move.b $r9,[%0+]n2:n",
  533. "3: addq 1,%2n",
  534. " .dword 2b,3bn")
  535. #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  536. __asm_copy_user_cont(to, from, ret,
  537. " move.w [%1+],$r9n"
  538. " move.w $r9,[%0+]n2:n" COPY,
  539. "3: addq 2,%2n" FIXUP,
  540. " .dword 2b,3bn" TENTRY)
  541. #define __asm_copy_to_user_2(to, from, ret) 
  542. __asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
  543. #define __asm_copy_to_user_3(to, from, ret) 
  544. __asm_copy_to_user_2x_cont(to, from, ret,
  545. " move.b [%1+],$r9n"
  546. " move.b $r9,[%0+]n4:n",
  547. "5: addq 1,%2n",
  548. " .dword 4b,5bn")
  549. #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  550. __asm_copy_user_cont(to, from, ret,
  551. " move.d [%1+],$r9n"
  552. " move.d $r9,[%0+]n2:n" COPY,
  553. "3: addq 4,%2n" FIXUP,
  554. " .dword 2b,3bn" TENTRY)
  555. #define __asm_copy_to_user_4(to, from, ret) 
  556. __asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
  557. #define __asm_copy_to_user_5(to, from, ret) 
  558. __asm_copy_to_user_4x_cont(to, from, ret,
  559. " move.b [%1+],$r9n"
  560. " move.b $r9,[%0+]n4:n",
  561. "5: addq 1,%2n",
  562. " .dword 4b,5bn")
  563. #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  564. __asm_copy_to_user_4x_cont(to, from, ret,
  565. " move.w [%1+],$r9n"
  566. " move.w $r9,[%0+]n4:n" COPY,
  567. "5: addq 2,%2n" FIXUP,
  568. " .dword 4b,5bn" TENTRY)
  569. #define __asm_copy_to_user_6(to, from, ret) 
  570. __asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
  571. #define __asm_copy_to_user_7(to, from, ret) 
  572. __asm_copy_to_user_6x_cont(to, from, ret,
  573. " move.b [%1+],$r9n"
  574. " move.b $r9,[%0+]n6:n",
  575. "7: addq 1,%2n",
  576. " .dword 6b,7bn")
  577. #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  578. __asm_copy_to_user_4x_cont(to, from, ret,
  579. " move.d [%1+],$r9n"
  580. " move.d $r9,[%0+]n4:n" COPY,
  581. "5: addq 4,%2n"  FIXUP,
  582. " .dword 4b,5bn" TENTRY)
  583. #define __asm_copy_to_user_8(to, from, ret) 
  584. __asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
  585. #define __asm_copy_to_user_9(to, from, ret) 
  586. __asm_copy_to_user_8x_cont(to, from, ret,
  587. " move.b [%1+],$r9n"
  588. " move.b $r9,[%0+]n6:n",
  589. "7: addq 1,%2n",
  590. " .dword 6b,7bn")
  591. #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  592. __asm_copy_to_user_8x_cont(to, from, ret,
  593. " move.w [%1+],$r9n"
  594. " move.w $r9,[%0+]n6:n" COPY,
  595. "7: addq 2,%2n" FIXUP,
  596. " .dword 6b,7bn" TENTRY)
  597. #define __asm_copy_to_user_10(to, from, ret) 
  598. __asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
  599. #define __asm_copy_to_user_11(to, from, ret) 
  600. __asm_copy_to_user_10x_cont(to, from, ret,
  601. " move.b [%1+],$r9n"
  602. " move.b $r9,[%0+]n8:n",
  603. "9: addq 1,%2n",
  604. " .dword 8b,9bn")
  605. #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  606. __asm_copy_to_user_8x_cont(to, from, ret,
  607. " move.d [%1+],$r9n"
  608. " move.d $r9,[%0+]n6:n" COPY,
  609. "7: addq 4,%2n" FIXUP,
  610. " .dword 6b,7bn" TENTRY)
  611. #define __asm_copy_to_user_12(to, from, ret) 
  612. __asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
  613. #define __asm_copy_to_user_13(to, from, ret) 
  614. __asm_copy_to_user_12x_cont(to, from, ret,
  615. " move.b [%1+],$r9n"
  616. " move.b $r9,[%0+]n8:n",
  617. "9: addq 1,%2n",
  618. " .dword 8b,9bn")
  619. #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  620. __asm_copy_to_user_12x_cont(to, from, ret,
  621. " move.w [%1+],$r9n"
  622. " move.w $r9,[%0+]n8:n" COPY,
  623. "9: addq 2,%2n" FIXUP,
  624. " .dword 8b,9bn" TENTRY)
  625. #define __asm_copy_to_user_14(to, from, ret)
  626. __asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
  627. #define __asm_copy_to_user_15(to, from, ret) 
  628. __asm_copy_to_user_14x_cont(to, from, ret,
  629. " move.b [%1+],$r9n"
  630. " move.b $r9,[%0+]n10:n",
  631. "11: addq 1,%2n",
  632. " .dword 10b,11bn")
  633. #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  634. __asm_copy_to_user_12x_cont(to, from, ret,
  635. " move.d [%1+],$r9n"
  636. " move.d $r9,[%0+]n8:n" COPY,
  637. "9: addq 4,%2n" FIXUP,
  638. " .dword 8b,9bn" TENTRY)
  639. #define __asm_copy_to_user_16(to, from, ret) 
  640. __asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
  641. #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) 
  642. __asm_copy_to_user_16x_cont(to, from, ret,
  643. " move.d [%1+],$r9n"
  644. " move.d $r9,[%0+]n10:n" COPY,
  645. "11: addq 4,%2n" FIXUP,
  646. " .dword 10b,11bn" TENTRY)
  647. #define __asm_copy_to_user_20(to, from, ret) 
  648. __asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
  649. #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)
  650. __asm_copy_to_user_20x_cont(to, from, ret,
  651. " move.d [%1+],$r9n"
  652. " move.d $r9,[%0+]n12:n" COPY,
  653. "13: addq 4,%2n" FIXUP,
  654. " .dword 12b,13bn" TENTRY)
  655. #define __asm_copy_to_user_24(to, from, ret)
  656. __asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
  657. /* Define a few clearing asms with exception handlers.  */
  658. /* This frame-asm is like the __asm_copy_user_cont one, but has one less
  659.    input.  */
  660. #define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) 
  661. __asm__ __volatile__ (
  662. CLEAR
  663. "1:n"
  664. " .section .fixup,"ax"n"
  665. FIXUP
  666. " jump 1bn"
  667. " .previousn"
  668. " .section __ex_table,"a"n"
  669. TENTRY
  670. " .previous"
  671. : "=r" (to), "=r" (ret)
  672. : "0" (to), "1" (ret)
  673. : "r9", "memory")
  674. #define __asm_clear_1(to, ret) 
  675. __asm_clear(to, ret,
  676. " clear.b [%0+]n2:n",
  677. "3: addq 1,%1n",
  678. " .dword 2b,3bn")
  679. #define __asm_clear_2(to, ret) 
  680. __asm_clear(to, ret,
  681. " clear.w [%0+]n2:n",
  682. "3: addq 2,%1n",
  683. " .dword 2b,3bn")
  684. #define __asm_clear_3(to, ret) 
  685.      __asm_clear(to, ret,
  686.  " clear.w [%0+]n"
  687.  "2: clear.b [%0+]n3:n",
  688.  "4: addq 2,%1n"
  689.  "5: addq 1,%1n",
  690.  " .dword 2b,4bn"
  691.  " .dword 3b,5bn")
  692. #define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  693. __asm_clear(to, ret,
  694. " clear.d [%0+]n2:n" CLEAR,
  695. "3: addq 4,%1n" FIXUP,
  696. " .dword 2b,3bn" TENTRY)
  697. #define __asm_clear_4(to, ret) 
  698. __asm_clear_4x_cont(to, ret, "", "", "")
  699. #define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  700. __asm_clear_4x_cont(to, ret,
  701. " clear.d [%0+]n4:n" CLEAR,
  702. "5: addq 4,%1n" FIXUP,
  703. " .dword 4b,5bn" TENTRY)
  704. #define __asm_clear_8(to, ret) 
  705. __asm_clear_8x_cont(to, ret, "", "", "")
  706. #define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  707. __asm_clear_8x_cont(to, ret,
  708. " clear.d [%0+]n6:n" CLEAR,
  709. "7: addq 4,%1n" FIXUP,
  710. " .dword 6b,7bn" TENTRY)
  711. #define __asm_clear_12(to, ret) 
  712. __asm_clear_12x_cont(to, ret, "", "", "")
  713. #define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  714. __asm_clear_12x_cont(to, ret,
  715. " clear.d [%0+]n8:n" CLEAR,
  716. "9: addq 4,%1n" FIXUP,
  717. " .dword 8b,9bn" TENTRY)
  718. #define __asm_clear_16(to, ret) 
  719. __asm_clear_16x_cont(to, ret, "", "", "")
  720. #define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  721. __asm_clear_16x_cont(to, ret,
  722. " clear.d [%0+]n10:n" CLEAR,
  723. "11: addq 4,%1n" FIXUP,
  724. " .dword 10b,11bn" TENTRY)
  725. #define __asm_clear_20(to, ret) 
  726. __asm_clear_20x_cont(to, ret, "", "", "")
  727. #define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) 
  728. __asm_clear_20x_cont(to, ret,
  729. " clear.d [%0+]n12:n" CLEAR,
  730. "13: addq 4,%1n" FIXUP,
  731. " .dword 12b,13bn" TENTRY)
  732. #define __asm_clear_24(to, ret) 
  733. __asm_clear_24x_cont(to, ret, "", "", "")
  734. /* Note that if these expand awfully if made into switch constructs, so
  735.    don't do that.  */
  736. static inline unsigned long
  737. __constant_copy_from_user(void *to, const void *from, unsigned long n)
  738. {
  739. unsigned long ret = 0;
  740. if (n == 0)
  741. ;
  742. else if (n == 1)
  743. __asm_copy_from_user_1(to, from, ret);
  744. else if (n == 2)
  745. __asm_copy_from_user_2(to, from, ret);
  746. else if (n == 3)
  747. __asm_copy_from_user_3(to, from, ret);
  748. else if (n == 4)
  749. __asm_copy_from_user_4(to, from, ret);
  750. else if (n == 5)
  751. __asm_copy_from_user_5(to, from, ret);
  752. else if (n == 6)
  753. __asm_copy_from_user_6(to, from, ret);
  754. else if (n == 7)
  755. __asm_copy_from_user_7(to, from, ret);
  756. else if (n == 8)
  757. __asm_copy_from_user_8(to, from, ret);
  758. else if (n == 9)
  759. __asm_copy_from_user_9(to, from, ret);
  760. else if (n == 10)
  761. __asm_copy_from_user_10(to, from, ret);
  762. else if (n == 11)
  763. __asm_copy_from_user_11(to, from, ret);
  764. else if (n == 12)
  765. __asm_copy_from_user_12(to, from, ret);
  766. else if (n == 13)
  767. __asm_copy_from_user_13(to, from, ret);
  768. else if (n == 14)
  769. __asm_copy_from_user_14(to, from, ret);
  770. else if (n == 15)
  771. __asm_copy_from_user_15(to, from, ret);
  772. else if (n == 16)
  773. __asm_copy_from_user_16(to, from, ret);
  774. else if (n == 20)
  775. __asm_copy_from_user_20(to, from, ret);
  776. else if (n == 24)
  777. __asm_copy_from_user_24(to, from, ret);
  778. else
  779. ret = __generic_copy_from_user(to, from, n);
  780. return ret;
  781. }
  782. /* Ditto, don't make a switch out of this.  */
  783. static inline unsigned long
  784. __constant_copy_to_user(void *to, const void *from, unsigned long n)
  785. {
  786. unsigned long ret = 0;
  787. if (n == 0)
  788. ;
  789. else if (n == 1)
  790. __asm_copy_to_user_1(to, from, ret);
  791. else if (n == 2)
  792. __asm_copy_to_user_2(to, from, ret);
  793. else if (n == 3)
  794. __asm_copy_to_user_3(to, from, ret);
  795. else if (n == 4)
  796. __asm_copy_to_user_4(to, from, ret);
  797. else if (n == 5)
  798. __asm_copy_to_user_5(to, from, ret);
  799. else if (n == 6)
  800. __asm_copy_to_user_6(to, from, ret);
  801. else if (n == 7)
  802. __asm_copy_to_user_7(to, from, ret);
  803. else if (n == 8)
  804. __asm_copy_to_user_8(to, from, ret);
  805. else if (n == 9)
  806. __asm_copy_to_user_9(to, from, ret);
  807. else if (n == 10)
  808. __asm_copy_to_user_10(to, from, ret);
  809. else if (n == 11)
  810. __asm_copy_to_user_11(to, from, ret);
  811. else if (n == 12)
  812. __asm_copy_to_user_12(to, from, ret);
  813. else if (n == 13)
  814. __asm_copy_to_user_13(to, from, ret);
  815. else if (n == 14)
  816. __asm_copy_to_user_14(to, from, ret);
  817. else if (n == 15)
  818. __asm_copy_to_user_15(to, from, ret);
  819. else if (n == 16)
  820. __asm_copy_to_user_16(to, from, ret);
  821. else if (n == 20)
  822. __asm_copy_to_user_20(to, from, ret);
  823. else if (n == 24)
  824. __asm_copy_to_user_24(to, from, ret);
  825. else
  826. ret = __generic_copy_to_user(to, from, n);
  827. return ret;
  828. }
  829. /* No switch, please.  */
  830. static inline unsigned long
  831. __constant_clear_user(void *to, unsigned long n)
  832. {
  833. unsigned long ret = 0;
  834. if (n == 0)
  835. ;
  836. else if (n == 1)
  837. __asm_clear_1(to, ret);
  838. else if (n == 2)
  839. __asm_clear_2(to, ret);
  840. else if (n == 3)
  841. __asm_clear_3(to, ret);
  842. else if (n == 4)
  843. __asm_clear_4(to, ret);
  844. else if (n == 8)
  845. __asm_clear_8(to, ret);
  846. else if (n == 12)
  847. __asm_clear_12(to, ret);
  848. else if (n == 16)
  849. __asm_clear_16(to, ret);
  850. else if (n == 20)
  851. __asm_clear_20(to, ret);
  852. else if (n == 24)
  853. __asm_clear_24(to, ret);
  854. else
  855. ret = __generic_clear_user(to, n);
  856. return ret;
  857. }
  858. #define clear_user(to, n)
  859. (__builtin_constant_p(n) ?
  860.  __constant_clear_user(to, n) :
  861.  __generic_clear_user(to, n))
  862. #define copy_from_user(to, from, n)
  863. (__builtin_constant_p(n) ?
  864.  __constant_copy_from_user(to, from, n) :
  865.  __generic_copy_from_user(to, from, n))
  866. #define copy_to_user(to, from, n)
  867. (__builtin_constant_p(n) ?
  868.  __constant_copy_to_user(to, from, n) :
  869.  __generic_copy_to_user(to, from, n))
  870. #define copy_to_user_ret(to,from,n,retval) 
  871. do { if (copy_to_user(to,from,n)) return retval; } while (0)
  872. #define copy_from_user_ret(to,from,n,retval) 
  873. do { if (copy_from_user(to,from,n)) return retval; } while (0)
  874. /* We let the __ versions of copy_from/to_user inline, because they're often
  875.  * used in fast paths and have only a small space overhead.
  876.  */
  877. static inline unsigned long
  878. __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
  879. {
  880. return __copy_user_zeroing(to,from,n);
  881. }
  882. static inline unsigned long
  883. __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
  884. {
  885. return __copy_user(to,from,n);
  886. }
  887. static inline unsigned long
  888. __generic_clear_user_nocheck(void *to, unsigned long n)
  889. {
  890. return __do_clear_user(to,n);
  891. }
  892. /* without checking */
  893. #define __copy_to_user(to,from,n)   __generic_copy_to_user_nocheck((to),(from),(n))
  894. #define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
  895. #define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
  896. /*
  897.  * Return the size of a string (including the ending 0)
  898.  *
  899.  * Return length of string in userspace including terminating 0
  900.  * or 0 for error.  Return a value greater than N if too long.
  901.  */
  902. static inline long
  903. strnlen_user(const char *s, long n)
  904. {
  905. long res, tmp1;
  906. if (!access_ok(VERIFY_READ, s, 0))
  907. return 0;
  908. /*
  909.  * This code is deduced from:
  910.  *
  911.  * tmp1 = n;
  912.  * while (tmp1-- > 0 && *s++)
  913.  *   ;
  914.  *
  915.  * res = n - tmp1;
  916.  *
  917.  *  (with tweaks).
  918.  */
  919. __asm__ __volatile__ (
  920. " move.d %1,$r9n"
  921. "0:n"
  922. " ble 1fn"
  923. " subq 1,$r9n"
  924. " test.b [%0+]n"
  925. " bne 0bn"
  926. " test.d $r9n"
  927. "1:n"
  928. " move.d %1,%0n"
  929. " sub.d $r9,%0n"
  930. "2:n"
  931. " .section .fixup,"ax"n"
  932. "3: clear.d %0n"
  933. " jump 2bn"
  934. /* There's one address for a fault at the first move, and
  935.    two possible PC values for a fault at the second move,
  936.    being a delay-slot filler.  However, the branch-target
  937.    for the second move is the same as the first address.
  938.    Just so you don't get confused...  */
  939. " .previousn"
  940. " .section __ex_table,"a"n"
  941. " .dword 0b,3bn"
  942. " .dword 1b,3bn"
  943. " .previousn"
  944. : "=r" (res), "=r" (tmp1)
  945. : "0" (s), "1" (n)
  946. : "r9");
  947. return res;
  948. }
  949. #define strlen_user(str) strnlen_user((str), 0x7ffffffe)
  950. #endif  /* __ASSEMBLY__ */
  951. #endif /* _CRIS_UACCESS_H */