root/arch/microblaze/include/asm/uaccess.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. ___range_ok
  2. access_ok
  3. __clear_user
  4. clear_user
  5. raw_copy_from_user
  6. raw_copy_to_user
  7. strncpy_from_user
  8. strnlen_user

   1 /*
   2  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
   3  * Copyright (C) 2008-2009 PetaLogix
   4  * Copyright (C) 2006 Atmark Techno, Inc.
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License. See the file "COPYING" in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 #ifndef _ASM_MICROBLAZE_UACCESS_H
  12 #define _ASM_MICROBLAZE_UACCESS_H
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/mm.h>
  16 
  17 #include <asm/mmu.h>
  18 #include <asm/page.h>
  19 #include <asm/pgtable.h>
  20 #include <asm/extable.h>
  21 #include <linux/string.h>
  22 
  23 /*
  24  * On Microblaze the fs value is actually the top of the corresponding
  25  * address space.
  26  *
  27  * The fs value determines whether argument validity checking should be
  28  * performed or not. If get_fs() == USER_DS, checking is performed, with
  29  * get_fs() == KERNEL_DS, checking is bypassed.
  30  *
  31  * For historical reasons, these macros are grossly misnamed.
  32  *
  33  * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
  34  */
  35 # define MAKE_MM_SEG(s)       ((mm_segment_t) { (s) })
  36 
  37 #  ifndef CONFIG_MMU
  38 #  define KERNEL_DS     MAKE_MM_SEG(0)
  39 #  define USER_DS       KERNEL_DS
  40 #  else
  41 #  define KERNEL_DS     MAKE_MM_SEG(0xFFFFFFFF)
  42 #  define USER_DS       MAKE_MM_SEG(TASK_SIZE - 1)
  43 #  endif
  44 
  45 # define get_fs()       (current_thread_info()->addr_limit)
  46 # define set_fs(val)    (current_thread_info()->addr_limit = (val))
  47 
  48 # define segment_eq(a, b)       ((a).seg == (b).seg)
  49 
  50 #ifndef CONFIG_MMU
  51 
  52 /* Check against bounds of physical memory */
  53 static inline int ___range_ok(unsigned long addr, unsigned long size)
  54 {
  55         return ((addr < memory_start) ||
  56                 ((addr + size - 1) > (memory_start + memory_size - 1)));
  57 }
  58 
  59 #define __range_ok(addr, size) \
  60                 ___range_ok((unsigned long)(addr), (unsigned long)(size))
  61 
  62 #define access_ok(addr, size) (__range_ok((addr), (size)) == 0)
  63 
  64 #else
  65 
  66 static inline int access_ok(const void __user *addr, unsigned long size)
  67 {
  68         if (!size)
  69                 goto ok;
  70 
  71         if ((get_fs().seg < ((unsigned long)addr)) ||
  72                         (get_fs().seg < ((unsigned long)addr + size - 1))) {
  73                 pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
  74                         (__force u32)addr, (u32)size,
  75                         (u32)get_fs().seg);
  76                 return 0;
  77         }
  78 ok:
  79         pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
  80                         (__force u32)addr, (u32)size,
  81                         (u32)get_fs().seg);
  82         return 1;
  83 }
  84 #endif
  85 
  86 #ifdef CONFIG_MMU
  87 # define __FIXUP_SECTION        ".section .fixup,\"ax\"\n"
  88 # define __EX_TABLE_SECTION     ".section __ex_table,\"a\"\n"
  89 #else
  90 # define __FIXUP_SECTION        ".section .discard,\"ax\"\n"
  91 # define __EX_TABLE_SECTION     ".section .discard,\"ax\"\n"
  92 #endif
  93 
  94 extern unsigned long __copy_tofrom_user(void __user *to,
  95                 const void __user *from, unsigned long size);
  96 
  97 /* Return: number of not copied bytes, i.e. 0 if OK or non-zero if fail. */
  98 static inline unsigned long __must_check __clear_user(void __user *to,
  99                                                         unsigned long n)
 100 {
 101         /* normal memset with two words to __ex_table */
 102         __asm__ __volatile__ (                          \
 103                         "1:     sb      r0, %1, r0;"    \
 104                         "       addik   %0, %0, -1;"    \
 105                         "       bneid   %0, 1b;"        \
 106                         "       addik   %1, %1, 1;"     \
 107                         "2:                     "       \
 108                         __EX_TABLE_SECTION              \
 109                         ".word  1b,2b;"                 \
 110                         ".previous;"                    \
 111                 : "=r"(n), "=r"(to)                     \
 112                 : "0"(n), "1"(to)
 113         );
 114         return n;
 115 }
 116 
 117 static inline unsigned long __must_check clear_user(void __user *to,
 118                                                         unsigned long n)
 119 {
 120         might_fault();
 121         if (unlikely(!access_ok(to, n)))
 122                 return n;
 123 
 124         return __clear_user(to, n);
 125 }
 126 
 127 /* put_user and get_user macros */
 128 extern long __user_bad(void);
 129 
 130 #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err)      \
 131 ({                                                              \
 132         __asm__ __volatile__ (                                  \
 133                         "1:"    insn    " %1, %2, r0;"          \
 134                         "       addk    %0, r0, r0;"            \
 135                         "2:                     "               \
 136                         __FIXUP_SECTION                         \
 137                         "3:     brid    2b;"                    \
 138                         "       addik   %0, r0, %3;"            \
 139                         ".previous;"                            \
 140                         __EX_TABLE_SECTION                      \
 141                         ".word  1b,3b;"                         \
 142                         ".previous;"                            \
 143                 : "=&r"(__gu_err), "=r"(__gu_val)               \
 144                 : "r"(__gu_ptr), "i"(-EFAULT)                   \
 145         );                                                      \
 146 })
 147 
 148 /**
 149  * get_user: - Get a simple variable from user space.
 150  * @x:   Variable to store result.
 151  * @ptr: Source address, in user space.
 152  *
 153  * Context: User context only. This function may sleep if pagefaults are
 154  *          enabled.
 155  *
 156  * This macro copies a single simple variable from user space to kernel
 157  * space.  It supports simple types like char and int, but not larger
 158  * data types like structures or arrays.
 159  *
 160  * @ptr must have pointer-to-simple-variable type, and the result of
 161  * dereferencing @ptr must be assignable to @x without a cast.
 162  *
 163  * Returns zero on success, or -EFAULT on error.
 164  * On error, the variable @x is set to zero.
 165  */
 166 #define get_user(x, ptr) ({                             \
 167         const typeof(*(ptr)) __user *__gu_ptr = (ptr);  \
 168         access_ok(__gu_ptr, sizeof(*__gu_ptr)) ?        \
 169                 __get_user(x, __gu_ptr) : -EFAULT;      \
 170 })
 171 
 172 #define __get_user(x, ptr)                                              \
 173 ({                                                                      \
 174         unsigned long __gu_val = 0;                                     \
 175         long __gu_err;                                                  \
 176         switch (sizeof(*(ptr))) {                                       \
 177         case 1:                                                         \
 178                 __get_user_asm("lbu", (ptr), __gu_val, __gu_err);       \
 179                 break;                                                  \
 180         case 2:                                                         \
 181                 __get_user_asm("lhu", (ptr), __gu_val, __gu_err);       \
 182                 break;                                                  \
 183         case 4:                                                         \
 184                 __get_user_asm("lw", (ptr), __gu_val, __gu_err);        \
 185                 break;                                                  \
 186         case 8:                                                         \
 187                 __gu_err = __copy_from_user(&__gu_val, ptr, 8);         \
 188                 if (__gu_err)                                           \
 189                         __gu_err = -EFAULT;                             \
 190                 break;                                                  \
 191         default:                                                        \
 192                 /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
 193         }                                                               \
 194         x = (__force __typeof__(*(ptr))) __gu_val;                      \
 195         __gu_err;                                                       \
 196 })
 197 
 198 
 199 #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err)      \
 200 ({                                                              \
 201         __asm__ __volatile__ (                                  \
 202                         "1:"    insn    " %1, %2, r0;"          \
 203                         "       addk    %0, r0, r0;"            \
 204                         "2:                     "               \
 205                         __FIXUP_SECTION                         \
 206                         "3:     brid    2b;"                    \
 207                         "       addik   %0, r0, %3;"            \
 208                         ".previous;"                            \
 209                         __EX_TABLE_SECTION                      \
 210                         ".word  1b,3b;"                         \
 211                         ".previous;"                            \
 212                 : "=&r"(__gu_err)                               \
 213                 : "r"(__gu_val), "r"(__gu_ptr), "i"(-EFAULT)    \
 214         );                                                      \
 215 })
 216 
 217 #define __put_user_asm_8(__gu_ptr, __gu_val, __gu_err)          \
 218 ({                                                              \
 219         __asm__ __volatile__ (" lwi     %0, %1, 0;"             \
 220                         "1:     swi     %0, %2, 0;"             \
 221                         "       lwi     %0, %1, 4;"             \
 222                         "2:     swi     %0, %2, 4;"             \
 223                         "       addk    %0, r0, r0;"            \
 224                         "3:                     "               \
 225                         __FIXUP_SECTION                         \
 226                         "4:     brid    3b;"                    \
 227                         "       addik   %0, r0, %3;"            \
 228                         ".previous;"                            \
 229                         __EX_TABLE_SECTION                      \
 230                         ".word  1b,4b,2b,4b;"                   \
 231                         ".previous;"                            \
 232                 : "=&r"(__gu_err)                               \
 233                 : "r"(&__gu_val), "r"(__gu_ptr), "i"(-EFAULT)   \
 234                 );                                              \
 235 })
 236 
 237 /**
 238  * put_user: - Write a simple value into user space.
 239  * @x:   Value to copy to user space.
 240  * @ptr: Destination address, in user space.
 241  *
 242  * Context: User context only. This function may sleep if pagefaults are
 243  *          enabled.
 244  *
 245  * This macro copies a single simple value from kernel space to user
 246  * space.  It supports simple types like char and int, but not larger
 247  * data types like structures or arrays.
 248  *
 249  * @ptr must have pointer-to-simple-variable type, and @x must be assignable
 250  * to the result of dereferencing @ptr.
 251  *
 252  * Returns zero on success, or -EFAULT on error.
 253  */
 254 #define put_user(x, ptr)                                                \
 255         __put_user_check((x), (ptr), sizeof(*(ptr)))
 256 
 257 #define __put_user_check(x, ptr, size)                                  \
 258 ({                                                                      \
 259         typeof(*(ptr)) volatile __pu_val = x;                           \
 260         typeof(*(ptr)) __user *__pu_addr = (ptr);                       \
 261         int __pu_err = 0;                                               \
 262                                                                         \
 263         if (access_ok(__pu_addr, size)) {                       \
 264                 switch (size) {                                         \
 265                 case 1:                                                 \
 266                         __put_user_asm("sb", __pu_addr, __pu_val,       \
 267                                        __pu_err);                       \
 268                         break;                                          \
 269                 case 2:                                                 \
 270                         __put_user_asm("sh", __pu_addr, __pu_val,       \
 271                                        __pu_err);                       \
 272                         break;                                          \
 273                 case 4:                                                 \
 274                         __put_user_asm("sw", __pu_addr, __pu_val,       \
 275                                        __pu_err);                       \
 276                         break;                                          \
 277                 case 8:                                                 \
 278                         __put_user_asm_8(__pu_addr, __pu_val, __pu_err);\
 279                         break;                                          \
 280                 default:                                                \
 281                         __pu_err = __user_bad();                        \
 282                         break;                                          \
 283                 }                                                       \
 284         } else {                                                        \
 285                 __pu_err = -EFAULT;                                     \
 286         }                                                               \
 287         __pu_err;                                                       \
 288 })
 289 
 290 #define __put_user(x, ptr)                                              \
 291 ({                                                                      \
 292         __typeof__(*(ptr)) volatile __gu_val = (x);                     \
 293         long __gu_err = 0;                                              \
 294         switch (sizeof(__gu_val)) {                                     \
 295         case 1:                                                         \
 296                 __put_user_asm("sb", (ptr), __gu_val, __gu_err);        \
 297                 break;                                                  \
 298         case 2:                                                         \
 299                 __put_user_asm("sh", (ptr), __gu_val, __gu_err);        \
 300                 break;                                                  \
 301         case 4:                                                         \
 302                 __put_user_asm("sw", (ptr), __gu_val, __gu_err);        \
 303                 break;                                                  \
 304         case 8:                                                         \
 305                 __put_user_asm_8((ptr), __gu_val, __gu_err);            \
 306                 break;                                                  \
 307         default:                                                        \
 308                 /*__gu_err = -EINVAL;*/ __gu_err = __user_bad();        \
 309         }                                                               \
 310         __gu_err;                                                       \
 311 })
 312 
 313 static inline unsigned long
 314 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 315 {
 316         return __copy_tofrom_user((__force void __user *)to, from, n);
 317 }
 318 
 319 static inline unsigned long
 320 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 321 {
 322         return __copy_tofrom_user(to, (__force const void __user *)from, n);
 323 }
 324 #define INLINE_COPY_FROM_USER
 325 #define INLINE_COPY_TO_USER
 326 
 327 /*
 328  * Copy a null terminated string from userspace.
 329  */
 330 extern int __strncpy_user(char *to, const char __user *from, int len);
 331 
 332 static inline long
 333 strncpy_from_user(char *dst, const char __user *src, long count)
 334 {
 335         if (!access_ok(src, 1))
 336                 return -EFAULT;
 337         return __strncpy_user(dst, src, count);
 338 }
 339 
 340 /*
 341  * Return the size of a string (including the ending 0)
 342  *
 343  * Return 0 on exception, a value greater than N if too long
 344  */
 345 extern int __strnlen_user(const char __user *sstr, int len);
 346 
 347 static inline long strnlen_user(const char __user *src, long n)
 348 {
 349         if (!access_ok(src, 1))
 350                 return 0;
 351         return __strnlen_user(src, n);
 352 }
 353 
 354 #endif /* _ASM_MICROBLAZE_UACCESS_H */

/* [<][>][^][v][top][bottom][index][help] */