linux/arch/m68k/include/asm/uaccess_mm.h
<<
>>
Prefs
   1#ifndef __M68K_UACCESS_H
   2#define __M68K_UACCESS_H
   3
   4/*
   5 * User space memory access functions
   6 */
   7#include <linux/compiler.h>
   8#include <linux/errno.h>
   9#include <linux/types.h>
  10#include <linux/sched.h>
  11#include <asm/segment.h>
  12
  13#define VERIFY_READ     0
  14#define VERIFY_WRITE    1
  15
  16/* We let the MMU do all checking */
  17static inline int access_ok(int type, const void __user *addr,
  18                            unsigned long size)
  19{
  20        return 1;
  21}
  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
  36struct exception_table_entry
  37{
  38        unsigned long insn, fixup;
  39};
  40
  41extern int __put_user_bad(void);
  42extern int __get_user_bad(void);
  43
  44#define __put_user_asm(res, x, ptr, bwl, reg, err)      \
  45asm volatile ("\n"                                      \
  46        "1:     moves."#bwl"    %2,%1\n"                \
  47        "2:\n"                                          \
  48        "       .section .fixup,\"ax\"\n"               \
  49        "       .even\n"                                \
  50        "10:    moveq.l %3,%0\n"                        \
  51        "       jra 2b\n"                               \
  52        "       .previous\n"                            \
  53        "\n"                                            \
  54        "       .section __ex_table,\"a\"\n"            \
  55        "       .align  4\n"                            \
  56        "       .long   1b,10b\n"                       \
  57        "       .long   2b,10b\n"                       \
  58        "       .previous"                              \
  59        : "+d" (res), "=m" (*(ptr))                     \
  60        : #reg (x), "i" (err))
  61
  62/*
  63 * These are the main single-value transfer routines.  They automatically
  64 * use the right size if we just have the right pointer type.
  65 */
  66
  67#define __put_user(x, ptr)                                              \
  68({                                                                      \
  69        typeof(*(ptr)) __pu_val = (x);                                  \
  70        int __pu_err = 0;                                               \
  71        __chk_user_ptr(ptr);                                            \
  72        switch (sizeof (*(ptr))) {                                      \
  73        case 1:                                                         \
  74                __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \
  75                break;                                                  \
  76        case 2:                                                         \
  77                __put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT); \
  78                break;                                                  \
  79        case 4:                                                         \
  80                __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \
  81                break;                                                  \
  82        case 8:                                                         \
  83            {                                                           \
  84                const void __user *__pu_ptr = (ptr);                    \
  85                asm volatile ("\n"                                      \
  86                        "1:     moves.l %2,(%1)+\n"                     \
  87                        "2:     moves.l %R2,(%1)\n"                     \
  88                        "3:\n"                                          \
  89                        "       .section .fixup,\"ax\"\n"               \
  90                        "       .even\n"                                \
  91                        "10:    movel %3,%0\n"                          \
  92                        "       jra 3b\n"                               \
  93                        "       .previous\n"                            \
  94                        "\n"                                            \
  95                        "       .section __ex_table,\"a\"\n"            \
  96                        "       .align 4\n"                             \
  97                        "       .long 1b,10b\n"                         \
  98                        "       .long 2b,10b\n"                         \
  99                        "       .long 3b,10b\n"                         \
 100                        "       .previous"                              \
 101                        : "+d" (__pu_err), "+a" (__pu_ptr)              \
 102                        : "r" (__pu_val), "i" (-EFAULT)                 \
 103                        : "memory");                                    \
 104                break;                                                  \
 105            }                                                           \
 106        default:                                                        \
 107                __pu_err = __put_user_bad();                            \
 108                break;                                                  \
 109        }                                                               \
 110        __pu_err;                                                       \
 111})
 112#define put_user(x, ptr)        __put_user(x, ptr)
 113
 114
 115#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({     \
 116        type __gu_val;                                          \
 117        asm volatile ("\n"                                      \
 118                "1:     moves."#bwl"    %2,%1\n"                \
 119                "2:\n"                                          \
 120                "       .section .fixup,\"ax\"\n"               \
 121                "       .even\n"                                \
 122                "10:    move.l  %3,%0\n"                        \
 123                "       sub."#bwl"      %1,%1\n"                \
 124                "       jra     2b\n"                           \
 125                "       .previous\n"                            \
 126                "\n"                                            \
 127                "       .section __ex_table,\"a\"\n"            \
 128                "       .align  4\n"                            \
 129                "       .long   1b,10b\n"                       \
 130                "       .previous"                              \
 131                : "+d" (res), "=&" #reg (__gu_val)              \
 132                : "m" (*(ptr)), "i" (err));                     \
 133        (x) = (typeof(*(ptr)))(unsigned long)__gu_val;          \
 134})
 135
 136#define __get_user(x, ptr)                                              \
 137({                                                                      \
 138        int __gu_err = 0;                                               \
 139        __chk_user_ptr(ptr);                                            \
 140        switch (sizeof(*(ptr))) {                                       \
 141        case 1:                                                         \
 142                __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT);    \
 143                break;                                                  \
 144        case 2:                                                         \
 145                __get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT);   \
 146                break;                                                  \
 147        case 4:                                                         \
 148                __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT);   \
 149                break;                                                  \
 150/*      case 8: disabled because gcc-4.1 has a broken typeof            \
 151            {                                                           \
 152                const void *__gu_ptr = (ptr);                           \
 153                u64 __gu_val;                                           \
 154                asm volatile ("\n"                                      \
 155                        "1:     moves.l (%2)+,%1\n"                     \
 156                        "2:     moves.l (%2),%R1\n"                     \
 157                        "3:\n"                                          \
 158                        "       .section .fixup,\"ax\"\n"               \
 159                        "       .even\n"                                \
 160                        "10:    move.l  %3,%0\n"                        \
 161                        "       sub.l   %1,%1\n"                        \
 162                        "       sub.l   %R1,%R1\n"                      \
 163                        "       jra     3b\n"                           \
 164                        "       .previous\n"                            \
 165                        "\n"                                            \
 166                        "       .section __ex_table,\"a\"\n"            \
 167                        "       .align  4\n"                            \
 168                        "       .long   1b,10b\n"                       \
 169                        "       .long   2b,10b\n"                       \
 170                        "       .previous"                              \
 171                        : "+d" (__gu_err), "=&r" (__gu_val),            \
 172                          "+a" (__gu_ptr)                               \
 173                        : "i" (-EFAULT)                                 \
 174                        : "memory");                                    \
 175                (x) = (typeof(*(ptr)))__gu_val;                         \
 176                break;                                                  \
 177            }   */                                                      \
 178        default:                                                        \
 179                __gu_err = __get_user_bad();                            \
 180                break;                                                  \
 181        }                                                               \
 182        __gu_err;                                                       \
 183})
 184#define get_user(x, ptr) __get_user(x, ptr)
 185
 186unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n);
 187unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n);
 188
 189#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\
 190        asm volatile ("\n"                                              \
 191                "1:     moves."#s1"     (%2)+,%3\n"                     \
 192                "       move."#s1"      %3,(%1)+\n"                     \
 193                "2:     moves."#s2"     (%2)+,%3\n"                     \
 194                "       move."#s2"      %3,(%1)+\n"                     \
 195                "       .ifnc   \""#s3"\",\"\"\n"                       \
 196                "3:     moves."#s3"     (%2)+,%3\n"                     \
 197                "       move."#s3"      %3,(%1)+\n"                     \
 198                "       .endif\n"                                       \
 199                "4:\n"                                                  \
 200                "       .section __ex_table,\"a\"\n"                    \
 201                "       .align  4\n"                                    \
 202                "       .long   1b,10f\n"                               \
 203                "       .long   2b,20f\n"                               \
 204                "       .ifnc   \""#s3"\",\"\"\n"                       \
 205                "       .long   3b,30f\n"                               \
 206                "       .endif\n"                                       \
 207                "       .previous\n"                                    \
 208                "\n"                                                    \
 209                "       .section .fixup,\"ax\"\n"                       \
 210                "       .even\n"                                        \
 211                "10:    clr."#s1"       (%1)+\n"                        \
 212                "20:    clr."#s2"       (%1)+\n"                        \
 213                "       .ifnc   \""#s3"\",\"\"\n"                       \
 214                "30:    clr."#s3"       (%1)+\n"                        \
 215                "       .endif\n"                                       \
 216                "       moveq.l #"#n",%0\n"                             \
 217                "       jra     4b\n"                                   \
 218                "       .previous\n"                                    \
 219                : "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp)      \
 220                : : "memory")
 221
 222static __always_inline unsigned long
 223__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
 224{
 225        unsigned long res = 0, tmp;
 226
 227        switch (n) {
 228        case 1:
 229                __get_user_asm(res, *(u8 *)to, (u8 __user *)from, u8, b, d, 1);
 230                break;
 231        case 2:
 232                __get_user_asm(res, *(u16 *)to, (u16 __user *)from, u16, w, d, 2);
 233                break;
 234        case 3:
 235                __constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,);
 236                break;
 237        case 4:
 238                __get_user_asm(res, *(u32 *)to, (u32 __user *)from, u32, l, r, 4);
 239                break;
 240        case 5:
 241                __constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,);
 242                break;
 243        case 6:
 244                __constant_copy_from_user_asm(res, to, from, tmp, 6, l, w,);
 245                break;
 246        case 7:
 247                __constant_copy_from_user_asm(res, to, from, tmp, 7, l, w, b);
 248                break;
 249        case 8:
 250                __constant_copy_from_user_asm(res, to, from, tmp, 8, l, l,);
 251                break;
 252        case 9:
 253                __constant_copy_from_user_asm(res, to, from, tmp, 9, l, l, b);
 254                break;
 255        case 10:
 256                __constant_copy_from_user_asm(res, to, from, tmp, 10, l, l, w);
 257                break;
 258        case 12:
 259                __constant_copy_from_user_asm(res, to, from, tmp, 12, l, l, l);
 260                break;
 261        default:
 262                /* we limit the inlined version to 3 moves */
 263                return __generic_copy_from_user(to, from, n);
 264        }
 265
 266        return res;
 267}
 268
 269#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3)  \
 270        asm volatile ("\n"                                              \
 271                "       move."#s1"      (%2)+,%3\n"                     \
 272                "11:    moves."#s1"     %3,(%1)+\n"                     \
 273                "12:    move."#s2"      (%2)+,%3\n"                     \
 274                "21:    moves."#s2"     %3,(%1)+\n"                     \
 275                "22:\n"                                                 \
 276                "       .ifnc   \""#s3"\",\"\"\n"                       \
 277                "       move."#s3"      (%2)+,%3\n"                     \
 278                "31:    moves."#s3"     %3,(%1)+\n"                     \
 279                "32:\n"                                                 \
 280                "       .endif\n"                                       \
 281                "4:\n"                                                  \
 282                "\n"                                                    \
 283                "       .section __ex_table,\"a\"\n"                    \
 284                "       .align  4\n"                                    \
 285                "       .long   11b,5f\n"                               \
 286                "       .long   12b,5f\n"                               \
 287                "       .long   21b,5f\n"                               \
 288                "       .long   22b,5f\n"                               \
 289                "       .ifnc   \""#s3"\",\"\"\n"                       \
 290                "       .long   31b,5f\n"                               \
 291                "       .long   32b,5f\n"                               \
 292                "       .endif\n"                                       \
 293                "       .previous\n"                                    \
 294                "\n"                                                    \
 295                "       .section .fixup,\"ax\"\n"                       \
 296                "       .even\n"                                        \
 297                "5:     moveq.l #"#n",%0\n"                             \
 298                "       jra     4b\n"                                   \
 299                "       .previous\n"                                    \
 300                : "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp)       \
 301                : : "memory")
 302
 303static __always_inline unsigned long
 304__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
 305{
 306        unsigned long res = 0, tmp;
 307
 308        switch (n) {
 309        case 1:
 310                __put_user_asm(res, *(u8 *)from, (u8 __user *)to, b, d, 1);
 311                break;
 312        case 2:
 313                __put_user_asm(res, *(u16 *)from, (u16 __user *)to, w, d, 2);
 314                break;
 315        case 3:
 316                __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
 317                break;
 318        case 4:
 319                __put_user_asm(res, *(u32 *)from, (u32 __user *)to, l, r, 4);
 320                break;
 321        case 5:
 322                __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
 323                break;
 324        case 6:
 325                __constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,);
 326                break;
 327        case 7:
 328                __constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b);
 329                break;
 330        case 8:
 331                __constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,);
 332                break;
 333        case 9:
 334                __constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b);
 335                break;
 336        case 10:
 337                __constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w);
 338                break;
 339        case 12:
 340                __constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l);
 341                break;
 342        default:
 343                /* limit the inlined version to 3 moves */
 344                return __generic_copy_to_user(to, from, n);
 345        }
 346
 347        return res;
 348}
 349
 350#define __copy_from_user(to, from, n)           \
 351(__builtin_constant_p(n) ?                      \
 352 __constant_copy_from_user(to, from, n) :       \
 353 __generic_copy_from_user(to, from, n))
 354
 355#define __copy_to_user(to, from, n)             \
 356(__builtin_constant_p(n) ?                      \
 357 __constant_copy_to_user(to, from, n) :         \
 358 __generic_copy_to_user(to, from, n))
 359
 360#define __copy_to_user_inatomic         __copy_to_user
 361#define __copy_from_user_inatomic       __copy_from_user
 362
 363#define copy_from_user(to, from, n)     __copy_from_user(to, from, n)
 364#define copy_to_user(to, from, n)       __copy_to_user(to, from, n)
 365
 366long strncpy_from_user(char *dst, const char __user *src, long count);
 367long strnlen_user(const char __user *src, long n);
 368unsigned long __clear_user(void __user *to, unsigned long n);
 369
 370#define clear_user      __clear_user
 371
 372#define strlen_user(str) strnlen_user(str, 32767)
 373
 374#endif /* _M68K_UACCESS_H */
 375