linux/arch/frv/include/asm/uaccess.h
<<
>>
Prefs
   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 __force *)(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 */
  35static 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((void __user *)(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 */
  82struct exception_table_entry
  83{
  84        unsigned long insn, fixup;
  85};
  86
  87/* Returns 0 if exception not found and fixup otherwise.  */
  88extern 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        __chk_user_ptr(ptr);                                            \
 101                                                                        \
 102        switch (sizeof (*(ptr))) {                                      \
 103        case 1:                                                         \
 104                __put_user_asm(__pu_err, __pu_val, ptr, "b", "r");      \
 105                break;                                                  \
 106        case 2:                                                         \
 107                __put_user_asm(__pu_err, __pu_val, ptr, "h", "r");      \
 108                break;                                                  \
 109        case 4:                                                         \
 110                __put_user_asm(__pu_err, __pu_val, ptr, "",  "r");      \
 111                break;                                                  \
 112        case 8:                                                         \
 113                __put_user_asm(__pu_err, __pu_val, ptr, "d", "e");      \
 114                break;                                                  \
 115        default:                                                        \
 116                __pu_err = __put_user_bad();                            \
 117                break;                                                  \
 118        }                                                               \
 119        __pu_err;                                                       \
 120})
 121
 122#define put_user(x, ptr)                        \
 123({                                              \
 124        typeof(*(ptr)) __user *_p = (ptr);      \
 125        int _e;                                 \
 126                                                \
 127        _e = __range_ok(_p, sizeof(*_p));       \
 128        if (_e == 0)                            \
 129                _e = __put_user((x), _p);       \
 130        _e;                                     \
 131})
 132
 133extern int __put_user_bad(void);
 134
 135/*
 136 * Tell gcc we read from memory instead of writing: this is because
 137 * we do not write to any memory gcc knows about, so there are no
 138 * aliasing issues.
 139 */
 140
 141#ifdef CONFIG_MMU
 142
 143#define __put_user_asm(err,x,ptr,dsize,constraint)                                      \
 144do {                                                                                    \
 145        asm volatile("1:        st"dsize"%I1    %2,%M1  \n"                             \
 146                     "2:                                \n"                             \
 147                     ".subsection 2                     \n"                             \
 148                     "3:        setlos          %3,%0   \n"                             \
 149                     "          bra             2b      \n"                             \
 150                     ".previous                         \n"                             \
 151                     ".section __ex_table,\"a\"         \n"                             \
 152                     "          .balign         8       \n"                             \
 153                     "          .long           1b,3b   \n"                             \
 154                     ".previous"                                                        \
 155                     : "=r" (err)                                                       \
 156                     : "m" (*__ptr(ptr)), constraint (x), "i"(-EFAULT), "0"(err)        \
 157                     : "memory");                                                       \
 158} while (0)
 159
 160#else
 161
 162#define __put_user_asm(err,x,ptr,bwl,con)       \
 163do {                                            \
 164        asm("   st"bwl"%I0      %1,%M0  \n"     \
 165            "   membar                  \n"     \
 166            :                                   \
 167            : "m" (*__ptr(ptr)), con (x)        \
 168            : "memory");                        \
 169} while (0)
 170
 171#endif
 172
 173/*****************************************************************************/
 174/*
 175 *
 176 */
 177#define __get_user(x, ptr)                                              \
 178({                                                                      \
 179        int __gu_err = 0;                                               \
 180        __chk_user_ptr(ptr);                                            \
 181                                                                        \
 182        switch (sizeof(*(ptr))) {                                       \
 183        case 1: {                                                       \
 184                unsigned char __gu_val;                                 \
 185                __get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r");    \
 186                (x) = *(__force __typeof__(*(ptr)) *) &__gu_val;        \
 187                break;                                                  \
 188        }                                                               \
 189        case 2: {                                                       \
 190                unsigned short __gu_val;                                \
 191                __get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r");    \
 192                (x) = *(__force __typeof__(*(ptr)) *) &__gu_val;        \
 193                break;                                                  \
 194        }                                                               \
 195        case 4: {                                                       \
 196                unsigned int __gu_val;                                  \
 197                __get_user_asm(__gu_err, __gu_val, ptr, "", "=r");      \
 198                (x) = *(__force __typeof__(*(ptr)) *) &__gu_val;        \
 199                break;                                                  \
 200        }                                                               \
 201        case 8: {                                                       \
 202                unsigned long long __gu_val;                            \
 203                __get_user_asm(__gu_err, __gu_val, ptr, "d", "=e");     \
 204                (x) = *(__force __typeof__(*(ptr)) *) &__gu_val;        \
 205                break;                                                  \
 206        }                                                               \
 207        default:                                                        \
 208                __gu_err = __get_user_bad();                            \
 209                break;                                                  \
 210        }                                                               \
 211        __gu_err;                                                       \
 212})
 213
 214#define get_user(x, ptr)                        \
 215({                                              \
 216        const typeof(*(ptr)) __user *_p = (ptr);\
 217        int _e;                                 \
 218                                                \
 219        _e = __range_ok(_p, sizeof(*_p));       \
 220        if (likely(_e == 0))                    \
 221                _e = __get_user((x), _p);       \
 222        else                                    \
 223                (x) = (typeof(x)) 0;            \
 224        _e;                                     \
 225})
 226
 227extern int __get_user_bad(void);
 228
 229#ifdef CONFIG_MMU
 230
 231#define __get_user_asm(err,x,ptr,dtype,constraint)      \
 232do {                                                    \
 233        asm("1:         ld"dtype"%I2    %M2,%1  \n"     \
 234            "2:                                 \n"     \
 235            ".subsection 2                      \n"     \
 236            "3:         setlos          %3,%0   \n"     \
 237            "           setlos          #0,%1   \n"     \
 238            "           bra             2b      \n"     \
 239            ".previous                          \n"     \
 240            ".section __ex_table,\"a\"          \n"     \
 241            "           .balign         8       \n"     \
 242            "           .long           1b,3b   \n"     \
 243            ".previous"                                 \
 244            : "=r" (err), constraint (x)                \
 245            : "m" (*__ptr(ptr)), "i"(-EFAULT), "0"(err) \
 246            );                                          \
 247} while(0)
 248
 249#else
 250
 251#define __get_user_asm(err,x,ptr,bwl,con)       \
 252        asm("   ld"bwl"%I1      %M1,%0  \n"     \
 253            "   membar                  \n"     \
 254            : con(x)                            \
 255            : "m" (*__ptr(ptr)))
 256
 257#endif
 258
 259/*****************************************************************************/
 260/*
 261 *
 262 */
 263#define ____force(x) (__force void *)(void __user *)(x)
 264#ifdef CONFIG_MMU
 265extern long __memset_user(void *dst, unsigned long count);
 266extern long __memcpy_user(void *dst, const void *src, unsigned long count);
 267
 268#define clear_user(dst,count)                   __memset_user(____force(dst), (count))
 269#define __copy_from_user_inatomic(to, from, n)  __memcpy_user((to), ____force(from), (n))
 270#define __copy_to_user_inatomic(to, from, n)    __memcpy_user(____force(to), (from), (n))
 271
 272#else
 273
 274#define clear_user(dst,count)                   (memset(____force(dst), 0, (count)), 0)
 275#define __copy_from_user_inatomic(to, from, n)  (memcpy((to), ____force(from), (n)), 0)
 276#define __copy_to_user_inatomic(to, from, n)    (memcpy(____force(to), (from), (n)), 0)
 277
 278#endif
 279
 280#define __clear_user clear_user
 281
 282static inline unsigned long __must_check
 283__copy_to_user(void __user *to, const void *from, unsigned long n)
 284{
 285       might_sleep();
 286       return __copy_to_user_inatomic(to, from, n);
 287}
 288
 289static inline unsigned long
 290__copy_from_user(void *to, const void __user *from, unsigned long n)
 291{
 292       might_sleep();
 293       return __copy_from_user_inatomic(to, from, n);
 294}
 295
 296static inline long copy_from_user(void *to, const void __user *from, unsigned long n)
 297{
 298        unsigned long ret = n;
 299
 300        if (likely(__access_ok(from, n)))
 301                ret = __copy_from_user(to, from, n);
 302
 303        if (unlikely(ret != 0))
 304                memset(to + (n - ret), 0, ret);
 305
 306        return ret;
 307}
 308
 309static inline long copy_to_user(void __user *to, const void *from, unsigned long n)
 310{
 311        return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n;
 312}
 313
 314extern long strncpy_from_user(char *dst, const char __user *src, long count);
 315extern long strnlen_user(const char __user *src, long count);
 316
 317#define strlen_user(str) strnlen_user(str, 32767)
 318
 319extern unsigned long search_exception_table(unsigned long addr);
 320
 321#endif /* _ASM_UACCESS_H */
 322