home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / arm / include / asm / uaccess.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  12.1 KB  |  445 lines

  1. /*
  2.  *  arch/arm/include/asm/uaccess.h
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License version 2 as
  6.  * published by the Free Software Foundation.
  7.  */
  8. #ifndef _ASMARM_UACCESS_H
  9. #define _ASMARM_UACCESS_H
  10.  
  11. /*
  12.  * User space memory access functions
  13.  */
  14. #include <linux/sched.h>
  15. #include <asm/errno.h>
  16. #include <asm/memory.h>
  17. #include <asm/domain.h>
  18. #include <asm/system.h>
  19.  
  20. #define VERIFY_READ 0
  21. #define VERIFY_WRITE 1
  22.  
  23. /*
  24.  * The exception table consists of pairs of addresses: the first is the
  25.  * address of an instruction that is allowed to fault, and the second is
  26.  * the address at which the program should continue.  No registers are
  27.  * modified, so it is entirely up to the continuation code to figure out
  28.  * what to do.
  29.  *
  30.  * All the routines below use bits of fixup code that are out of line
  31.  * with the main instruction path.  This means when everything is well,
  32.  * we don't even have to jump over them.  Further, they do not intrude
  33.  * on our cache or tlb entries.
  34.  */
  35.  
  36. struct exception_table_entry
  37. {
  38.     unsigned long insn, fixup;
  39. };
  40.  
  41. extern int fixup_exception(struct pt_regs *regs);
  42.  
  43. /*
  44.  * These two are intentionally not defined anywhere - if the kernel
  45.  * code generates any references to them, that's a bug.
  46.  */
  47. extern int __get_user_bad(void);
  48. extern int __put_user_bad(void);
  49.  
  50. /*
  51.  * Note that this is actually 0x1,0000,0000
  52.  */
  53. #define KERNEL_DS    0x00000000
  54. #define get_ds()    (KERNEL_DS)
  55.  
  56. #ifdef CONFIG_MMU
  57.  
  58. #define USER_DS        TASK_SIZE
  59. #define get_fs()    (current_thread_info()->addr_limit)
  60.  
  61. static inline void set_fs(mm_segment_t fs)
  62. {
  63.     current_thread_info()->addr_limit = fs;
  64.     modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
  65. }
  66.  
  67. #define segment_eq(a,b)    ((a) == (b))
  68.  
  69. #define __addr_ok(addr) ({ \
  70.     unsigned long flag; \
  71.     __asm__("cmp %2, %0; movlo %0, #0" \
  72.         : "=&r" (flag) \
  73.         : "0" (current_thread_info()->addr_limit), "r" (addr) \
  74.         : "cc"); \
  75.     (flag == 0); })
  76.  
  77. /* We use 33-bit arithmetic here... */
  78. #define __range_ok(addr,size) ({ \
  79.     unsigned long flag, roksum; \
  80.     __chk_user_ptr(addr);    \
  81.     __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
  82.         : "=&r" (flag), "=&r" (roksum) \
  83.         : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
  84.         : "cc"); \
  85.     flag; })
  86.  
  87. /*
  88.  * Single-value transfer routines.  They automatically use the right
  89.  * size if we just have the right pointer type.  Note that the functions
  90.  * which read from user space (*get_*) need to take care not to leak
  91.  * kernel data even if the calling code is buggy and fails to check
  92.  * the return value.  This means zeroing out the destination variable
  93.  * or buffer on error.  Normally this is done out of line by the
  94.  * fixup code, but there are a few places where it intrudes on the
  95.  * main code path.  When we only write to user space, there is no
  96.  * problem.
  97.  */
  98. extern int __get_user_1(void *);
  99. extern int __get_user_2(void *);
  100. extern int __get_user_4(void *);
  101.  
  102. #define __get_user_x(__r2,__p,__e,__s,__i...)                \
  103.        __asm__ __volatile__ (                    \
  104.         __asmeq("%0", "r0") __asmeq("%1", "r2")            \
  105.         "bl    __get_user_" #__s                \
  106.         : "=&r" (__e), "=r" (__r2)                \
  107.         : "0" (__p)                        \
  108.         : __i, "cc")
  109.  
  110. #define get_user(x,p)                            \
  111.     ({                                \
  112.         register const typeof(*(p)) __user *__p asm("r0") = (p);\
  113.         register unsigned long __r2 asm("r2");            \
  114.         register int __e asm("r0");                \
  115.         switch (sizeof(*(__p))) {                \
  116.         case 1:                            \
  117.             __get_user_x(__r2, __p, __e, 1, "lr");        \
  118.                    break;                        \
  119.         case 2:                            \
  120.             __get_user_x(__r2, __p, __e, 2, "r3", "lr");    \
  121.             break;                        \
  122.         case 4:                            \
  123.                    __get_user_x(__r2, __p, __e, 4, "lr");        \
  124.             break;                        \
  125.         default: __e = __get_user_bad(); break;            \
  126.         }                            \
  127.         x = (typeof(*(p))) __r2;                \
  128.         __e;                            \
  129.     })
  130.  
  131. extern int __put_user_1(void *, unsigned int);
  132. extern int __put_user_2(void *, unsigned int);
  133. extern int __put_user_4(void *, unsigned int);
  134. extern int __put_user_8(void *, unsigned long long);
  135.  
  136. #define __put_user_x(__r2,__p,__e,__s)                    \
  137.        __asm__ __volatile__ (                    \
  138.         __asmeq("%0", "r0") __asmeq("%2", "r2")            \
  139.         "bl    __put_user_" #__s                \
  140.         : "=&r" (__e)                        \
  141.         : "0" (__p), "r" (__r2)                    \
  142.         : "ip", "lr", "cc")
  143.  
  144. #define put_user(x,p)                            \
  145.     ({                                \
  146.         register const typeof(*(p)) __r2 asm("r2") = (x);    \
  147.         register const typeof(*(p)) __user *__p asm("r0") = (p);\
  148.         register int __e asm("r0");                \
  149.         switch (sizeof(*(__p))) {                \
  150.         case 1:                            \
  151.             __put_user_x(__r2, __p, __e, 1);        \
  152.             break;                        \
  153.         case 2:                            \
  154.             __put_user_x(__r2, __p, __e, 2);        \
  155.             break;                        \
  156.         case 4:                            \
  157.             __put_user_x(__r2, __p, __e, 4);        \
  158.             break;                        \
  159.         case 8:                            \
  160.             __put_user_x(__r2, __p, __e, 8);        \
  161.             break;                        \
  162.         default: __e = __put_user_bad(); break;            \
  163.         }                            \
  164.         __e;                            \
  165.     })
  166.  
  167. #else /* CONFIG_MMU */
  168.  
  169. /*
  170.  * uClinux has only one addr space, so has simplified address limits.
  171.  */
  172. #define USER_DS            KERNEL_DS
  173.  
  174. #define segment_eq(a,b)        (1)
  175. #define __addr_ok(addr)        (1)
  176. #define __range_ok(addr,size)    (0)
  177. #define get_fs()        (KERNEL_DS)
  178.  
  179. static inline void set_fs(mm_segment_t fs)
  180. {
  181. }
  182.  
  183. #define get_user(x,p)    __get_user(x,p)
  184. #define put_user(x,p)    __put_user(x,p)
  185.  
  186. #endif /* CONFIG_MMU */
  187.  
  188. #define access_ok(type,addr,size)    (__range_ok(addr,size) == 0)
  189.  
  190. /*
  191.  * The "__xxx" versions of the user access functions do not verify the
  192.  * address space - it must have been done previously with a separate
  193.  * "access_ok()" call.
  194.  *
  195.  * The "xxx_error" versions set the third argument to EFAULT if an
  196.  * error occurs, and leave it unchanged on success.  Note that these
  197.  * versions are void (ie, don't return a value as such).
  198.  */
  199. #define __get_user(x,ptr)                        \
  200. ({                                    \
  201.     long __gu_err = 0;                        \
  202.     __get_user_err((x),(ptr),__gu_err);                \
  203.     __gu_err;                            \
  204. })
  205.  
  206. #define __get_user_error(x,ptr,err)                    \
  207. ({                                    \
  208.     __get_user_err((x),(ptr),err);                    \
  209.     (void) 0;                            \
  210. })
  211.  
  212. #define __get_user_err(x,ptr,err)                    \
  213. do {                                    \
  214.     unsigned long __gu_addr = (unsigned long)(ptr);            \
  215.     unsigned long __gu_val;                        \
  216.     __chk_user_ptr(ptr);                        \
  217.     switch (sizeof(*(ptr))) {                    \
  218.     case 1:    __get_user_asm_byte(__gu_val,__gu_addr,err);    break;    \
  219.     case 2:    __get_user_asm_half(__gu_val,__gu_addr,err);    break;    \
  220.     case 4:    __get_user_asm_word(__gu_val,__gu_addr,err);    break;    \
  221.     default: (__gu_val) = __get_user_bad();                \
  222.     }                                \
  223.     (x) = (__typeof__(*(ptr)))__gu_val;                \
  224. } while (0)
  225.  
  226. #define __get_user_asm_byte(x,addr,err)                \
  227.     __asm__ __volatile__(                    \
  228.     "1:    ldrbt    %1,[%2]\n"                \
  229.     "2:\n"                            \
  230.     "    .section .fixup,\"ax\"\n"            \
  231.     "    .align    2\n"                    \
  232.     "3:    mov    %0, %3\n"                \
  233.     "    mov    %1, #0\n"                \
  234.     "    b    2b\n"                    \
  235.     "    .previous\n"                    \
  236.     "    .section __ex_table,\"a\"\n"            \
  237.     "    .align    3\n"                    \
  238.     "    .long    1b, 3b\n"                \
  239.     "    .previous"                    \
  240.     : "+r" (err), "=&r" (x)                    \
  241.     : "r" (addr), "i" (-EFAULT)                \
  242.     : "cc")
  243.  
  244. #ifndef __ARMEB__
  245. #define __get_user_asm_half(x,__gu_addr,err)            \
  246. ({                                \
  247.     unsigned long __b1, __b2;                \
  248.     __get_user_asm_byte(__b1, __gu_addr, err);        \
  249.     __get_user_asm_byte(__b2, __gu_addr + 1, err);        \
  250.     (x) = __b1 | (__b2 << 8);                \
  251. })
  252. #else
  253. #define __get_user_asm_half(x,__gu_addr,err)            \
  254. ({                                \
  255.     unsigned long __b1, __b2;                \
  256.     __get_user_asm_byte(__b1, __gu_addr, err);        \
  257.     __get_user_asm_byte(__b2, __gu_addr + 1, err);        \
  258.     (x) = (__b1 << 8) | __b2;                \
  259. })
  260. #endif
  261.  
  262. #define __get_user_asm_word(x,addr,err)                \
  263.     __asm__ __volatile__(                    \
  264.     "1:    ldrt    %1,[%2]\n"                \
  265.     "2:\n"                            \
  266.     "    .section .fixup,\"ax\"\n"            \
  267.     "    .align    2\n"                    \
  268.     "3:    mov    %0, %3\n"                \
  269.     "    mov    %1, #0\n"                \
  270.     "    b    2b\n"                    \
  271.     "    .previous\n"                    \
  272.     "    .section __ex_table,\"a\"\n"            \
  273.     "    .align    3\n"                    \
  274.     "    .long    1b, 3b\n"                \
  275.     "    .previous"                    \
  276.     : "+r" (err), "=&r" (x)                    \
  277.     : "r" (addr), "i" (-EFAULT)                \
  278.     : "cc")
  279.  
  280. #define __put_user(x,ptr)                        \
  281. ({                                    \
  282.     long __pu_err = 0;                        \
  283.     __put_user_err((x),(ptr),__pu_err);                \
  284.     __pu_err;                            \
  285. })
  286.  
  287. #define __put_user_error(x,ptr,err)                    \
  288. ({                                    \
  289.     __put_user_err((x),(ptr),err);                    \
  290.     (void) 0;                            \
  291. })
  292.  
  293. #define __put_user_err(x,ptr,err)                    \
  294. do {                                    \
  295.     unsigned long __pu_addr = (unsigned long)(ptr);            \
  296.     __typeof__(*(ptr)) __pu_val = (x);                \
  297.     __chk_user_ptr(ptr);                        \
  298.     switch (sizeof(*(ptr))) {                    \
  299.     case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);    break;    \
  300.     case 2: __put_user_asm_half(__pu_val,__pu_addr,err);    break;    \
  301.     case 4: __put_user_asm_word(__pu_val,__pu_addr,err);    break;    \
  302.     case 8:    __put_user_asm_dword(__pu_val,__pu_addr,err);    break;    \
  303.     default: __put_user_bad();                    \
  304.     }                                \
  305. } while (0)
  306.  
  307. #define __put_user_asm_byte(x,__pu_addr,err)            \
  308.     __asm__ __volatile__(                    \
  309.     "1:    strbt    %1,[%2]\n"                \
  310.     "2:\n"                            \
  311.     "    .section .fixup,\"ax\"\n"            \
  312.     "    .align    2\n"                    \
  313.     "3:    mov    %0, %3\n"                \
  314.     "    b    2b\n"                    \
  315.     "    .previous\n"                    \
  316.     "    .section __ex_table,\"a\"\n"            \
  317.     "    .align    3\n"                    \
  318.     "    .long    1b, 3b\n"                \
  319.     "    .previous"                    \
  320.     : "+r" (err)                        \
  321.     : "r" (x), "r" (__pu_addr), "i" (-EFAULT)        \
  322.     : "cc")
  323.  
  324. #ifndef __ARMEB__
  325. #define __put_user_asm_half(x,__pu_addr,err)            \
  326. ({                                \
  327.     unsigned long __temp = (unsigned long)(x);        \
  328.     __put_user_asm_byte(__temp, __pu_addr, err);        \
  329.     __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);    \
  330. })
  331. #else
  332. #define __put_user_asm_half(x,__pu_addr,err)            \
  333. ({                                \
  334.     unsigned long __temp = (unsigned long)(x);        \
  335.     __put_user_asm_byte(__temp >> 8, __pu_addr, err);    \
  336.     __put_user_asm_byte(__temp, __pu_addr + 1, err);    \
  337. })
  338. #endif
  339.  
  340. #define __put_user_asm_word(x,__pu_addr,err)            \
  341.     __asm__ __volatile__(                    \
  342.     "1:    strt    %1,[%2]\n"                \
  343.     "2:\n"                            \
  344.     "    .section .fixup,\"ax\"\n"            \
  345.     "    .align    2\n"                    \
  346.     "3:    mov    %0, %3\n"                \
  347.     "    b    2b\n"                    \
  348.     "    .previous\n"                    \
  349.     "    .section __ex_table,\"a\"\n"            \
  350.     "    .align    3\n"                    \
  351.     "    .long    1b, 3b\n"                \
  352.     "    .previous"                    \
  353.     : "+r" (err)                        \
  354.     : "r" (x), "r" (__pu_addr), "i" (-EFAULT)        \
  355.     : "cc")
  356.  
  357. #ifndef __ARMEB__
  358. #define    __reg_oper0    "%R2"
  359. #define    __reg_oper1    "%Q2"
  360. #else
  361. #define    __reg_oper0    "%Q2"
  362. #define    __reg_oper1    "%R2"
  363. #endif
  364.  
  365. #define __put_user_asm_dword(x,__pu_addr,err)            \
  366.     __asm__ __volatile__(                    \
  367.     "1:    strt    " __reg_oper1 ", [%1], #4\n"        \
  368.     "2:    strt    " __reg_oper0 ", [%1]\n"        \
  369.     "3:\n"                            \
  370.     "    .section .fixup,\"ax\"\n"            \
  371.     "    .align    2\n"                    \
  372.     "4:    mov    %0, %3\n"                \
  373.     "    b    3b\n"                    \
  374.     "    .previous\n"                    \
  375.     "    .section __ex_table,\"a\"\n"            \
  376.     "    .align    3\n"                    \
  377.     "    .long    1b, 4b\n"                \
  378.     "    .long    2b, 4b\n"                \
  379.     "    .previous"                    \
  380.     : "+r" (err), "+r" (__pu_addr)                \
  381.     : "r" (x), "i" (-EFAULT)                \
  382.     : "cc")
  383.  
  384.  
  385. #ifdef CONFIG_MMU
  386. extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
  387. extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
  388. extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
  389. #else
  390. #define __copy_from_user(to,from,n)    (memcpy(to, (void __force *)from, n), 0)
  391. #define __copy_to_user(to,from,n)    (memcpy((void __force *)to, from, n), 0)
  392. #define __clear_user(addr,n)        (memset((void __force *)addr, 0, n), 0)
  393. #endif
  394.  
  395. extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count);
  396. extern unsigned long __must_check __strnlen_user(const char __user *s, long n);
  397.  
  398. static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
  399. {
  400.     if (access_ok(VERIFY_READ, from, n))
  401.         n = __copy_from_user(to, from, n);
  402.     else /* security hole - plug it */
  403.         memzero(to, n);
  404.     return n;
  405. }
  406.  
  407. static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
  408. {
  409.     if (access_ok(VERIFY_WRITE, to, n))
  410.         n = __copy_to_user(to, from, n);
  411.     return n;
  412. }
  413.  
  414. #define __copy_to_user_inatomic __copy_to_user
  415. #define __copy_from_user_inatomic __copy_from_user
  416.  
  417. static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
  418. {
  419.     if (access_ok(VERIFY_WRITE, to, n))
  420.         n = __clear_user(to, n);
  421.     return n;
  422. }
  423.  
  424. static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count)
  425. {
  426.     long res = -EFAULT;
  427.     if (access_ok(VERIFY_READ, src, 1))
  428.         res = __strncpy_from_user(dst, src, count);
  429.     return res;
  430. }
  431.  
  432. #define strlen_user(s)    strnlen_user(s, ~0UL >> 1)
  433.  
  434. static inline long __must_check strnlen_user(const char __user *s, long n)
  435. {
  436.     unsigned long res = 0;
  437.  
  438.     if (__addr_ok(s))
  439.         res = __strnlen_user(s, n);
  440.  
  441.     return res;
  442. }
  443.  
  444. #endif /* _ASMARM_UACCESS_H */
  445.