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