linux/arch/nios2/include/asm/uaccess.h
<<
>>
Prefs
   1/*
   2 * User space memory access functions for Nios II
   3 *
   4 * Copyright (C) 2010-2011, Tobias Klauser <tklauser@distanz.ch>
   5 * Copyright (C) 2009, Wind River Systems Inc
   6 *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12
  13#ifndef _ASM_NIOS2_UACCESS_H
  14#define _ASM_NIOS2_UACCESS_H
  15
  16#include <linux/string.h>
  17
  18#include <asm/page.h>
  19
  20#include <asm/extable.h>
  21
  22/*
  23 * Segment stuff
  24 */
  25#define MAKE_MM_SEG(s)          ((mm_segment_t) { (s) })
  26#define USER_DS                 MAKE_MM_SEG(0x80000000UL)
  27#define KERNEL_DS               MAKE_MM_SEG(0)
  28
  29#define get_ds()                (KERNEL_DS)
  30
  31#define get_fs()                (current_thread_info()->addr_limit)
  32#define set_fs(seg)             (current_thread_info()->addr_limit = (seg))
  33
  34#define segment_eq(a, b)        ((a).seg == (b).seg)
  35
  36#define __access_ok(addr, len)                  \
  37        (((signed long)(((long)get_fs().seg) &  \
  38                ((long)(addr) | (((long)(addr)) + (len)) | (len)))) == 0)
  39
  40#define access_ok(type, addr, len)              \
  41        likely(__access_ok((unsigned long)(addr), (unsigned long)(len)))
  42
  43# define __EX_TABLE_SECTION     ".section __ex_table,\"a\"\n"
  44
  45#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
  46
  47/*
  48 * Zero Userspace
  49 */
  50
  51static inline unsigned long __must_check __clear_user(void __user *to,
  52                                                      unsigned long n)
  53{
  54        __asm__ __volatile__ (
  55                "1:     stb     zero, 0(%1)\n"
  56                "       addi    %0, %0, -1\n"
  57                "       addi    %1, %1, 1\n"
  58                "       bne     %0, zero, 1b\n"
  59                "2:\n"
  60                __EX_TABLE_SECTION
  61                ".word  1b, 2b\n"
  62                ".previous\n"
  63                : "=r" (n), "=r" (to)
  64                : "0" (n), "1" (to)
  65        );
  66
  67        return n;
  68}
  69
  70static inline unsigned long __must_check clear_user(void __user *to,
  71                                                    unsigned long n)
  72{
  73        if (!access_ok(VERIFY_WRITE, to, n))
  74                return n;
  75        return __clear_user(to, n);
  76}
  77
  78extern unsigned long
  79raw_copy_from_user(void *to, const void __user *from, unsigned long n);
  80extern unsigned long
  81raw_copy_to_user(void __user *to, const void *from, unsigned long n);
  82#define INLINE_COPY_FROM_USER
  83#define INLINE_COPY_TO_USER
  84
  85extern long strncpy_from_user(char *__to, const char __user *__from,
  86                              long __len);
  87extern __must_check long strlen_user(const char __user *str);
  88extern __must_check long strnlen_user(const char __user *s, long n);
  89
  90/* Optimized macros */
  91#define __get_user_asm(val, insn, addr, err)                            \
  92{                                                                       \
  93        __asm__ __volatile__(                                           \
  94        "       movi    %0, %3\n"                                       \
  95        "1:   " insn " %1, 0(%2)\n"                                     \
  96        "       movi     %0, 0\n"                                       \
  97        "2:\n"                                                          \
  98        "       .section __ex_table,\"a\"\n"                            \
  99        "       .word 1b, 2b\n"                                         \
 100        "       .previous"                                              \
 101        : "=&r" (err), "=r" (val)                                       \
 102        : "r" (addr), "i" (-EFAULT));                                   \
 103}
 104
 105#define __get_user_unknown(val, size, ptr, err) do {                    \
 106        err = 0;                                                        \
 107        if (__copy_from_user(&(val), ptr, size)) {                      \
 108                err = -EFAULT;                                          \
 109        }                                                               \
 110        } while (0)
 111
 112#define __get_user_common(val, size, ptr, err)                          \
 113do {                                                                    \
 114        switch (size) {                                                 \
 115        case 1:                                                         \
 116                __get_user_asm(val, "ldbu", ptr, err);                  \
 117                break;                                                  \
 118        case 2:                                                         \
 119                __get_user_asm(val, "ldhu", ptr, err);                  \
 120                break;                                                  \
 121        case 4:                                                         \
 122                __get_user_asm(val, "ldw", ptr, err);                   \
 123                break;                                                  \
 124        default:                                                        \
 125                __get_user_unknown(val, size, ptr, err);                \
 126                break;                                                  \
 127        }                                                               \
 128} while (0)
 129
 130#define __get_user(x, ptr)                                              \
 131        ({                                                              \
 132        long __gu_err = -EFAULT;                                        \
 133        const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
 134        unsigned long __gu_val = 0;                                     \
 135        __get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
 136        (x) = (__force __typeof__(x))__gu_val;                          \
 137        __gu_err;                                                       \
 138        })
 139
 140#define get_user(x, ptr)                                                \
 141({                                                                      \
 142        long __gu_err = -EFAULT;                                        \
 143        const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
 144        unsigned long __gu_val = 0;                                     \
 145        if (access_ok(VERIFY_READ,  __gu_ptr, sizeof(*__gu_ptr)))       \
 146                __get_user_common(__gu_val, sizeof(*__gu_ptr),          \
 147                        __gu_ptr, __gu_err);                            \
 148        (x) = (__force __typeof__(x))__gu_val;                          \
 149        __gu_err;                                                       \
 150})
 151
 152#define __put_user_asm(val, insn, ptr, err)                             \
 153{                                                                       \
 154        __asm__ __volatile__(                                           \
 155        "       movi    %0, %3\n"                                       \
 156        "1:   " insn " %1, 0(%2)\n"                                     \
 157        "       movi     %0, 0\n"                                       \
 158        "2:\n"                                                          \
 159        "       .section __ex_table,\"a\"\n"                            \
 160        "       .word 1b, 2b\n"                                         \
 161        "       .previous\n"                                            \
 162        : "=&r" (err)                                                   \
 163        : "r" (val), "r" (ptr), "i" (-EFAULT));                         \
 164}
 165
 166#define put_user(x, ptr)                                                \
 167({                                                                      \
 168        long __pu_err = -EFAULT;                                        \
 169        __typeof__(*(ptr)) __user *__pu_ptr = (ptr);                    \
 170        __typeof__(*(ptr)) __pu_val = (__typeof(*ptr))(x);              \
 171        if (access_ok(VERIFY_WRITE, __pu_ptr, sizeof(*__pu_ptr))) {     \
 172                switch (sizeof(*__pu_ptr)) {                            \
 173                case 1:                                                 \
 174                        __put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \
 175                        break;                                          \
 176                case 2:                                                 \
 177                        __put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \
 178                        break;                                          \
 179                case 4:                                                 \
 180                        __put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \
 181                        break;                                          \
 182                default:                                                \
 183                        /* XXX: This looks wrong... */                  \
 184                        __pu_err = 0;                                   \
 185                        if (copy_to_user(__pu_ptr, &(__pu_val),         \
 186                                sizeof(*__pu_ptr)))                     \
 187                                __pu_err = -EFAULT;                     \
 188                        break;                                          \
 189                }                                                       \
 190        }                                                               \
 191        __pu_err;                                                       \
 192})
 193
 194#define __put_user(x, ptr) put_user(x, ptr)
 195
 196#endif /* _ASM_NIOS2_UACCESS_H */
 197