root/arch/csky/lib/usercopy.c

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

DEFINITIONS

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

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
   3 
   4 #include <linux/uaccess.h>
   5 #include <linux/types.h>
   6 
   7 unsigned long raw_copy_from_user(void *to, const void *from,
   8                         unsigned long n)
   9 {
  10         ___copy_from_user(to, from, n);
  11         return n;
  12 }
  13 EXPORT_SYMBOL(raw_copy_from_user);
  14 
  15 unsigned long raw_copy_to_user(void *to, const void *from,
  16                         unsigned long n)
  17 {
  18         ___copy_to_user(to, from, n);
  19         return n;
  20 }
  21 EXPORT_SYMBOL(raw_copy_to_user);
  22 
  23 
  24 /*
  25  * copy a null terminated string from userspace.
  26  */
  27 #define __do_strncpy_from_user(dst, src, count, res)    \
  28 do {                                                    \
  29         int tmp;                                        \
  30         long faultres;                                  \
  31         asm volatile(                                   \
  32         "       cmpnei  %3, 0           \n"             \
  33         "       bf      4f              \n"             \
  34         "1:     cmpnei  %1, 0           \n"             \
  35         "       bf      5f              \n"             \
  36         "2:     ldb     %4, (%3, 0)     \n"             \
  37         "       stb     %4, (%2, 0)     \n"             \
  38         "       cmpnei  %4, 0           \n"             \
  39         "       bf      3f              \n"             \
  40         "       addi    %3,  1          \n"             \
  41         "       addi    %2,  1          \n"             \
  42         "       subi    %1,  1          \n"             \
  43         "       br      1b              \n"             \
  44         "3:     subu    %0, %1          \n"             \
  45         "       br      5f              \n"             \
  46         "4:     mov     %0, %5          \n"             \
  47         "       br      5f              \n"             \
  48         ".section __ex_table, \"a\"     \n"             \
  49         ".align   2                     \n"             \
  50         ".long    2b, 4b                \n"             \
  51         ".previous                      \n"             \
  52         "5:                             \n"             \
  53         : "=r"(res), "=r"(count), "=r"(dst),            \
  54           "=r"(src), "=r"(tmp),   "=r"(faultres)        \
  55         : "5"(-EFAULT), "0"(count), "1"(count),         \
  56           "2"(dst), "3"(src)                            \
  57         : "memory", "cc");                              \
  58 } while (0)
  59 
  60 /*
  61  * __strncpy_from_user: - Copy a NUL terminated string from userspace,
  62  * with less checking.
  63  * @dst:   Destination address, in kernel space.  This buffer must be at
  64  *         least @count bytes long.
  65  * @src:   Source address, in user space.
  66  * @count: Maximum number of bytes to copy, including the trailing NUL.
  67  *
  68  * Copies a NUL-terminated string from userspace to kernel space.
  69  * Caller must check the specified block with access_ok() before calling
  70  * this function.
  71  *
  72  * On success, returns the length of the string (not including the trailing
  73  * NUL).
  74  *
  75  * If access to userspace fails, returns -EFAULT (some data may have been
  76  * copied).
  77  *
  78  * If @count is smaller than the length of the string, copies @count bytes
  79  * and returns @count.
  80  */
  81 long __strncpy_from_user(char *dst, const char *src, long count)
  82 {
  83         long res;
  84 
  85         __do_strncpy_from_user(dst, src, count, res);
  86         return res;
  87 }
  88 EXPORT_SYMBOL(__strncpy_from_user);
  89 
  90 /*
  91  * strncpy_from_user: - Copy a NUL terminated string from userspace.
  92  * @dst:   Destination address, in kernel space.  This buffer must be at
  93  *         least @count bytes long.
  94  * @src:   Source address, in user space.
  95  * @count: Maximum number of bytes to copy, including the trailing NUL.
  96  *
  97  * Copies a NUL-terminated string from userspace to kernel space.
  98  *
  99  * On success, returns the length of the string (not including the trailing
 100  * NUL).
 101  *
 102  * If access to userspace fails, returns -EFAULT (some data may have been
 103  * copied).
 104  *
 105  * If @count is smaller than the length of the string, copies @count bytes
 106  * and returns @count.
 107  */
 108 long strncpy_from_user(char *dst, const char *src, long count)
 109 {
 110         long res = -EFAULT;
 111 
 112         if (access_ok(src, 1))
 113                 __do_strncpy_from_user(dst, src, count, res);
 114         return res;
 115 }
 116 EXPORT_SYMBOL(strncpy_from_user);
 117 
 118 /*
 119  * strlen_user: - Get the size of a string in user space.
 120  * @str: The string to measure.
 121  * @n:   The maximum valid length
 122  *
 123  * Get the size of a NUL-terminated string in user space.
 124  *
 125  * Returns the size of the string INCLUDING the terminating NUL.
 126  * On exception, returns 0.
 127  * If the string is too long, returns a value greater than @n.
 128  */
 129 long strnlen_user(const char *s, long n)
 130 {
 131         unsigned long res, tmp;
 132 
 133         if (s == NULL)
 134                 return 0;
 135 
 136         asm volatile(
 137         "       cmpnei  %1, 0           \n"
 138         "       bf      3f              \n"
 139         "1:     cmpnei  %0, 0           \n"
 140         "       bf      3f              \n"
 141         "2:     ldb     %3, (%1, 0)     \n"
 142         "       cmpnei  %3, 0           \n"
 143         "       bf      3f              \n"
 144         "       subi    %0,  1          \n"
 145         "       addi    %1,  1          \n"
 146         "       br      1b              \n"
 147         "3:     subu    %2, %0          \n"
 148         "       addi    %2,  1          \n"
 149         "       br      5f              \n"
 150         "4:     movi    %0, 0           \n"
 151         "       br      5f              \n"
 152         ".section __ex_table, \"a\"     \n"
 153         ".align   2                     \n"
 154         ".long    2b, 4b                \n"
 155         ".previous                      \n"
 156         "5:                             \n"
 157         : "=r"(n), "=r"(s), "=r"(res), "=r"(tmp)
 158         : "0"(n), "1"(s), "2"(n)
 159         : "memory", "cc");
 160 
 161         return res;
 162 }
 163 EXPORT_SYMBOL(strnlen_user);
 164 
 165 #define __do_clear_user(addr, size)                     \
 166 do {                                                    \
 167         int __d0, zvalue, tmp;                          \
 168                                                         \
 169         asm volatile(                                   \
 170         "0:     cmpnei  %1, 0           \n"             \
 171         "       bf      7f              \n"             \
 172         "       mov     %3, %1          \n"             \
 173         "       andi    %3, 3           \n"             \
 174         "       cmpnei  %3, 0           \n"             \
 175         "       bf      1f              \n"             \
 176         "       br      5f              \n"             \
 177         "1:     cmplti  %0, 32          \n" /* 4W */    \
 178         "       bt      3f              \n"             \
 179         "8:     stw     %2, (%1, 0)     \n"             \
 180         "10:    stw     %2, (%1, 4)     \n"             \
 181         "11:    stw     %2, (%1, 8)     \n"             \
 182         "12:    stw     %2, (%1, 12)    \n"             \
 183         "13:    stw     %2, (%1, 16)    \n"             \
 184         "14:    stw     %2, (%1, 20)    \n"             \
 185         "15:    stw     %2, (%1, 24)    \n"             \
 186         "16:    stw     %2, (%1, 28)    \n"             \
 187         "       addi    %1, 32          \n"             \
 188         "       subi    %0, 32          \n"             \
 189         "       br      1b              \n"             \
 190         "3:     cmplti  %0, 4           \n" /* 1W */    \
 191         "       bt      5f              \n"             \
 192         "4:     stw     %2, (%1, 0)     \n"             \
 193         "       addi    %1, 4           \n"             \
 194         "       subi    %0, 4           \n"             \
 195         "       br      3b              \n"             \
 196         "5:     cmpnei  %0, 0           \n" /* 1B */    \
 197         "9:     bf      7f              \n"             \
 198         "6:     stb     %2, (%1, 0)     \n"             \
 199         "       addi    %1,  1          \n"             \
 200         "       subi    %0,  1          \n"             \
 201         "       br      5b              \n"             \
 202         ".section __ex_table,\"a\"      \n"             \
 203         ".align   2                     \n"             \
 204         ".long    8b, 9b                \n"             \
 205         ".long    10b, 9b               \n"             \
 206         ".long    11b, 9b               \n"             \
 207         ".long    12b, 9b               \n"             \
 208         ".long    13b, 9b               \n"             \
 209         ".long    14b, 9b               \n"             \
 210         ".long    15b, 9b               \n"             \
 211         ".long    16b, 9b               \n"             \
 212         ".long    4b, 9b                \n"             \
 213         ".long    6b, 9b                \n"             \
 214         ".previous                      \n"             \
 215         "7:                             \n"             \
 216         : "=r"(size), "=r" (__d0),                      \
 217           "=r"(zvalue), "=r"(tmp)                       \
 218         : "0"(size), "1"(addr), "2"(0)                  \
 219         : "memory", "cc");                              \
 220 } while (0)
 221 
 222 /*
 223  * clear_user: - Zero a block of memory in user space.
 224  * @to:   Destination address, in user space.
 225  * @n:    Number of bytes to zero.
 226  *
 227  * Zero a block of memory in user space.
 228  *
 229  * Returns number of bytes that could not be cleared.
 230  * On success, this will be zero.
 231  */
 232 unsigned long
 233 clear_user(void __user *to, unsigned long n)
 234 {
 235         if (access_ok(to, n))
 236                 __do_clear_user(to, n);
 237         return n;
 238 }
 239 EXPORT_SYMBOL(clear_user);
 240 
 241 /*
 242  * __clear_user: - Zero a block of memory in user space, with less checking.
 243  * @to:   Destination address, in user space.
 244  * @n:    Number of bytes to zero.
 245  *
 246  * Zero a block of memory in user space.  Caller must check
 247  * the specified block with access_ok() before calling this function.
 248  *
 249  * Returns number of bytes that could not be cleared.
 250  * On success, this will be zero.
 251  */
 252 unsigned long
 253 __clear_user(void __user *to, unsigned long n)
 254 {
 255         __do_clear_user(to, n);
 256         return n;
 257 }
 258 EXPORT_SYMBOL(__clear_user);

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