linux/arch/mn10300/lib/usercopy.c
<<
>>
Prefs
   1/* MN10300 Userspace accessor functions
   2 *
   3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public Licence
   9 * as published by the Free Software Foundation; either version
  10 * 2 of the Licence, or (at your option) any later version.
  11 */
  12#include <asm/uaccess.h>
  13
  14unsigned long
  15__generic_copy_to_user(void *to, const void *from, unsigned long n)
  16{
  17        if (access_ok(VERIFY_WRITE, to, n))
  18                __copy_user(to, from, n);
  19        return n;
  20}
  21
  22unsigned long
  23__generic_copy_from_user(void *to, const void *from, unsigned long n)
  24{
  25        if (access_ok(VERIFY_READ, from, n))
  26                __copy_user_zeroing(to, from, n);
  27        return n;
  28}
  29
  30/*
  31 * Copy a null terminated string from userspace.
  32 */
  33#define __do_strncpy_from_user(dst, src, count, res)            \
  34do {                                                            \
  35        int w;                                                  \
  36        asm volatile(                                           \
  37                "       mov     %1,%0\n"                        \
  38                "       cmp     0,%1\n"                         \
  39                "       beq     2f\n"                           \
  40                "0:\n"                                          \
  41                "       movbu   (%5),%2\n"                      \
  42                "1:\n"                                          \
  43                "       movbu   %2,(%6)\n"                      \
  44                "       inc     %5\n"                           \
  45                "       inc     %6\n"                           \
  46                "       cmp     0,%2\n"                         \
  47                "       beq     2f\n"                           \
  48                "       add     -1,%1\n"                        \
  49                "       bne     0b\n"                           \
  50                "2:\n"                                          \
  51                "       sub     %1,%0\n"                        \
  52                "3:\n"                                          \
  53                "       .section .fixup,\"ax\"\n"               \
  54                "4:\n"                                          \
  55                "       mov     %3,%0\n"                        \
  56                "       jmp     3b\n"                           \
  57                "       .previous\n"                            \
  58                "       .section __ex_table,\"a\"\n"            \
  59                "       .balign 4\n"                            \
  60                "       .long 0b,4b\n"                          \
  61                "       .long 1b,4b\n"                          \
  62                "       .previous"                              \
  63                :"=&r"(res), "=r"(count), "=&r"(w)              \
  64                :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst)   \
  65                : "memory", "cc");                                      \
  66} while (0)
  67
  68long
  69__strncpy_from_user(char *dst, const char *src, long count)
  70{
  71        long res;
  72        __do_strncpy_from_user(dst, src, count, res);
  73        return res;
  74}
  75
  76long
  77strncpy_from_user(char *dst, const char *src, long count)
  78{
  79        long res = -EFAULT;
  80        if (access_ok(VERIFY_READ, src, 1))
  81                __do_strncpy_from_user(dst, src, count, res);
  82        return res;
  83}
  84
  85
  86/*
  87 * Clear a userspace memory
  88 */
  89#define __do_clear_user(addr, size)             \
  90do {                                            \
  91        int w;                                  \
  92        asm volatile(                           \
  93                "       cmp 0,%0\n"             \
  94                "       beq 1f\n"               \
  95                "       clr %1\n"               \
  96                "0:     movbu %1,(%3,%2)\n"     \
  97                "       inc %3\n"               \
  98                "       cmp %0,%3\n"            \
  99                "       bne 0b\n"               \
 100                "1:\n"                          \
 101                "       sub %3,%0\n"            \
 102                "2:\n"                          \
 103                ".section .fixup,\"ax\"\n"      \
 104                "3:     jmp 2b\n"               \
 105                ".previous\n"                   \
 106                ".section __ex_table,\"a\"\n"   \
 107                "       .balign 4\n"            \
 108                "       .long 0b,3b\n"          \
 109                ".previous\n"                   \
 110                : "+r"(size), "=&r"(w)          \
 111                : "a"(addr), "d"(0)             \
 112                : "memory", "cc");              \
 113} while (0)
 114
 115unsigned long
 116__clear_user(void *to, unsigned long n)
 117{
 118        __do_clear_user(to, n);
 119        return n;
 120}
 121
 122unsigned long
 123clear_user(void *to, unsigned long n)
 124{
 125        if (access_ok(VERIFY_WRITE, to, n))
 126                __do_clear_user(to, n);
 127        return n;
 128}
 129
 130/*
 131 * Return the size of a string (including the ending 0)
 132 *
 133 * Return 0 on exception, a value greater than N if too long
 134 */
 135long strnlen_user(const char *s, long n)
 136{
 137        unsigned long res, w;
 138
 139        if (!__addr_ok(s))
 140                return 0;
 141
 142        if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
 143                n = current_thread_info()->addr_limit.seg - (u_long)s;
 144
 145        asm volatile(
 146                "0:     cmp %4,%0\n"
 147                "       beq 2f\n"
 148                "1:     movbu (%0,%3),%1\n"
 149                "       inc %0\n"
 150                "       cmp 0,%1\n"
 151                "       beq 3f\n"
 152                "       bra 0b\n"
 153                "2:     clr %0\n"
 154                "3:\n"
 155                ".section .fixup,\"ax\"\n"
 156                "4:     jmp 2b\n"
 157                ".previous\n"
 158                ".section __ex_table,\"a\"\n"
 159                "       .balign 4\n"
 160                "       .long 1b,4b\n"
 161                ".previous\n"
 162                :"=d"(res), "=&r"(w)
 163                :"0"(0), "a"(s), "r"(n)
 164                : "memory", "cc");
 165        return res;
 166}
 167