home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-frv / uaccess.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  7.9 KB  |  310 lines

  1. /* uaccess.h: userspace accessor functions
  2.  *
  3.  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4.  * Written by David Howells (dhowells@redhat.com)
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version
  9.  * 2 of the License, or (at your option) any later version.
  10.  */
  11.  
  12. #ifndef _ASM_UACCESS_H
  13. #define _ASM_UACCESS_H
  14.  
  15. /*
  16.  * User space memory access functions
  17.  */
  18. #include <linux/sched.h>
  19. #include <linux/mm.h>
  20. #include <asm/segment.h>
  21. #include <asm/sections.h>
  22.  
  23. #define HAVE_ARCH_UNMAPPED_AREA    /* we decide where to put mmaps */
  24.  
  25. #define __ptr(x) ((unsigned long *)(x))
  26.  
  27. #define VERIFY_READ    0
  28. #define VERIFY_WRITE    1
  29.  
  30. #define __addr_ok(addr) ((unsigned long)(addr) < get_addr_limit())
  31.  
  32. /*
  33.  * check that a range of addresses falls within the current address limit
  34.  */
  35. static inline int ___range_ok(unsigned long addr, unsigned long size)
  36. {
  37. #ifdef CONFIG_MMU
  38.     int flag = -EFAULT, tmp;
  39.  
  40.     asm volatile (
  41.         "    addcc    %3,%2,%1,icc0    \n"    /* set C-flag if addr+size>4GB */
  42.         "    subcc.p    %1,%4,gr0,icc1    \n"    /* jump if addr+size>limit */
  43.         "    bc    icc0,#0,0f    \n"
  44.         "    bhi    icc1,#0,0f    \n"
  45.         "    setlos    #0,%0        \n"    /* mark okay */
  46.         "0:                \n"
  47.         : "=r"(flag), "=&r"(tmp)
  48.         : "r"(addr), "r"(size), "r"(get_addr_limit()), "0"(flag)
  49.         );
  50.  
  51.     return flag;
  52.  
  53. #else
  54.  
  55.     if (addr < memory_start ||
  56.         addr > memory_end ||
  57.         size > memory_end - memory_start ||
  58.         addr + size > memory_end)
  59.         return -EFAULT;
  60.  
  61.     return 0;
  62. #endif
  63. }
  64.  
  65. #define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size))
  66.  
  67. #define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
  68. #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
  69.  
  70. /*
  71.  * The exception table consists of pairs of addresses: the first is the
  72.  * address of an instruction that is allowed to fault, and the second is
  73.  * the address at which the program should continue.  No registers are
  74.  * modified, so it is entirely up to the continuation code to figure out
  75.  * what to do.
  76.  *
  77.  * All the routines below use bits of fixup code that are out of line
  78.  * with the main instruction path.  This means when everything is well,
  79.  * we don't even have to jump over them.  Further, they do not intrude
  80.  * on our cache or tlb entries.
  81.  */
  82. struct exception_table_entry
  83. {
  84.     unsigned long insn, fixup;
  85. };
  86.  
  87. /* Returns 0 if exception not found and fixup otherwise.  */
  88. extern unsigned long search_exception_table(unsigned long);
  89.  
  90.  
  91. /*
  92.  * These are the main single-value transfer routines.  They automatically
  93.  * use the right size if we just have the right pointer type.
  94.  */
  95. #define __put_user(x, ptr)                        \
  96. ({                                    \
  97.     int __pu_err = 0;                        \
  98.                                     \
  99.     typeof(*(ptr)) __pu_val = (x);                    \
  100.                                     \
  101.     switch (sizeof (*(ptr))) {                    \
  102.     case 1:                                \
  103.         __put_user_asm(__pu_err, __pu_val, ptr, "b", "r");    \
  104.         break;                            \
  105.     case 2:                                \
  106.         __put_user_asm(__pu_err, __pu_val, ptr, "h", "r");    \
  107.         break;                            \
  108.     case 4:                                \
  109.         __put_user_asm(__pu_err, __pu_val, ptr, "",  "r");    \
  110.         break;                            \
  111.     case 8:                                \
  112.         __put_user_asm(__pu_err, __pu_val, ptr, "d", "e");    \
  113.         break;                            \
  114.     default:                            \
  115.         __pu_err = __put_user_bad();                \
  116.         break;                            \
  117.     }                                \
  118.     __pu_err;                            \
  119. })
  120.  
  121. #define put_user(x, ptr)            \
  122. ({                        \
  123.     typeof(&*ptr) _p = (ptr);        \
  124.     int _e;                    \
  125.                         \
  126.     _e = __range_ok(_p, sizeof(*_p));    \
  127.     if (_e == 0)                \
  128.         _e = __put_user((x), _p);    \
  129.     _e;                    \
  130. })
  131.  
  132. extern int __put_user_bad(void);
  133.  
  134. /*
  135.  * Tell gcc we read from memory instead of writing: this is because
  136.  * we do not write to any memory gcc knows about, so there are no
  137.  * aliasing issues.
  138.  */
  139.  
  140. #ifdef CONFIG_MMU
  141.  
  142. #define __put_user_asm(err,x,ptr,dsize,constraint)                    \
  143. do {                                            \
  144.     asm volatile("1:    st"dsize"%I1    %2,%M1    \n"                \
  145.              "2:                \n"                \
  146.              ".subsection 2            \n"                \
  147.              "3:    setlos        %3,%0    \n"                \
  148.              "        bra        2b    \n"                \
  149.              ".previous                \n"                \
  150.              ".section __ex_table,\"a\"        \n"                \
  151.              "        .balign        8    \n"                \
  152.              "        .long        1b,3b    \n"                \
  153.              ".previous"                            \
  154.              : "=r" (err)                            \
  155.              : "m" (*__ptr(ptr)), constraint (x), "i"(-EFAULT), "0"(err)    \
  156.              : "memory");                            \
  157. } while (0)
  158.  
  159. #else
  160.  
  161. #define __put_user_asm(err,x,ptr,bwl,con)    \
  162. do {                        \
  163.     asm("    st"bwl"%I0    %1,%M0    \n"    \
  164.         "    membar            \n"    \
  165.         :                    \
  166.         : "m" (*__ptr(ptr)), con (x)    \
  167.         : "memory");            \
  168. } while (0)
  169.  
  170. #endif
  171.  
  172. /*****************************************************************************/
  173. /*
  174.  *
  175.  */
  176. #define __get_user(x, ptr)                        \
  177. ({                                    \
  178.     typeof(*(ptr)) __gu_val = 0;                    \
  179.     int __gu_err = 0;                        \
  180.                                     \
  181.     switch (sizeof(*(ptr))) {                    \
  182.     case 1:                                \
  183.         __get_user_asm(__gu_err, *(u8*)&__gu_val, ptr, "ub", "=r"); \
  184.         break;                            \
  185.     case 2:                                \
  186.         __get_user_asm(__gu_err, *(u16*)&__gu_val, ptr, "uh", "=r"); \
  187.         break;                            \
  188.     case 4:                                \
  189.         __get_user_asm(__gu_err, *(u32*)&__gu_val, ptr, "", "=r"); \
  190.         break;                            \
  191.     case 8:                                \
  192.         __get_user_asm(__gu_err, *(u64*)&__gu_val, ptr, "d", "=e"); \
  193.         break;                            \
  194.     default:                            \
  195.         __gu_err = __get_user_bad();                \
  196.         break;                            \
  197.     }                                \
  198.     (x) = __gu_val;                            \
  199.     __gu_err;                            \
  200. })
  201.  
  202. #define get_user(x, ptr)            \
  203. ({                        \
  204.     typeof(&*ptr) _p = (ptr);        \
  205.     int _e;                    \
  206.                         \
  207.     _e = __range_ok(_p, sizeof(*_p));    \
  208.     if (likely(_e == 0))            \
  209.         _e = __get_user((x), _p);    \
  210.     else                    \
  211.         (x) = (typeof(x)) 0;        \
  212.     _e;                    \
  213. })
  214.  
  215. extern int __get_user_bad(void);
  216.  
  217. #ifdef CONFIG_MMU
  218.  
  219. #define __get_user_asm(err,x,ptr,dtype,constraint)    \
  220. do {                            \
  221.     asm("1:        ld"dtype"%I2    %M2,%1    \n"    \
  222.         "2:                    \n"    \
  223.         ".subsection 2            \n"    \
  224.         "3:        setlos        %3,%0    \n"    \
  225.         "        setlos        #0,%1    \n"    \
  226.         "        bra        2b    \n"    \
  227.         ".previous                \n"    \
  228.         ".section __ex_table,\"a\"        \n"    \
  229.         "        .balign        8    \n"    \
  230.         "        .long        1b,3b    \n"    \
  231.         ".previous"                    \
  232.         : "=r" (err), constraint (x)        \
  233.         : "m" (*__ptr(ptr)), "i"(-EFAULT), "0"(err)    \
  234.         );                        \
  235. } while(0)
  236.  
  237. #else
  238.  
  239. #define __get_user_asm(err,x,ptr,bwl,con)    \
  240.     asm("    ld"bwl"%I1    %M1,%0    \n"    \
  241.         "    membar            \n"    \
  242.         : con(x)                \
  243.         : "m" (*__ptr(ptr)))
  244.  
  245. #endif
  246.  
  247. /*****************************************************************************/
  248. /*
  249.  *
  250.  */
  251. #ifdef CONFIG_MMU
  252. extern long __memset_user(void *dst, unsigned long count);
  253. extern long __memcpy_user(void *dst, const void *src, unsigned long count);
  254.  
  255. #define clear_user(dst,count)            __memset_user((dst), (count))
  256. #define __copy_from_user_inatomic(to, from, n)    __memcpy_user((to), (from), (n))
  257. #define __copy_to_user_inatomic(to, from, n)    __memcpy_user((to), (from), (n))
  258.  
  259. #else
  260.  
  261. #define clear_user(dst,count)            (memset((dst), 0, (count)), 0)
  262. #define __copy_from_user_inatomic(to, from, n)    (memcpy((to), (from), (n)), 0)
  263. #define __copy_to_user_inatomic(to, from, n)    (memcpy((to), (from), (n)), 0)
  264.  
  265. #endif
  266.  
  267. static inline unsigned long __must_check
  268. __copy_to_user(void __user *to, const void *from, unsigned long n)
  269. {
  270.        might_sleep();
  271.        return __copy_to_user_inatomic(to, from, n);
  272. }
  273.  
  274. static inline unsigned long
  275. __copy_from_user(void *to, const void __user *from, unsigned long n)
  276. {
  277.        might_sleep();
  278.        return __copy_from_user_inatomic(to, from, n);
  279. }
  280.  
  281. static inline long copy_from_user(void *to, const void *from, unsigned long n)
  282. {
  283.     unsigned long ret = n;
  284.  
  285.     if (likely(__access_ok(from, n)))
  286.         ret = __copy_from_user(to, from, n);
  287.  
  288.     if (unlikely(ret != 0))
  289.         memset(to + (n - ret), 0, ret);
  290.  
  291.     return ret;
  292. }
  293.  
  294. static inline long copy_to_user(void *to, const void *from, unsigned long n)
  295. {
  296.     return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n;
  297. }
  298.  
  299. #define copy_to_user_ret(to,from,n,retval)    ({ if (copy_to_user(to,from,n)) return retval; })
  300. #define copy_from_user_ret(to,from,n,retval)    ({ if (copy_from_user(to,from,n)) return retval; })
  301.  
  302. extern long strncpy_from_user(char *dst, const char *src, long count);
  303. extern long strnlen_user(const char *src, long count);
  304.  
  305. #define strlen_user(str) strnlen_user(str, 32767)
  306.  
  307. extern unsigned long search_exception_table(unsigned long addr);
  308.  
  309. #endif /* _ASM_UACCESS_H */
  310.