1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
4 #include <linux/uaccess.h>
5 #include <linux/types.h>
7 unsigned long raw_copy_from_user(void *to, const void *from,
23 "2: ldw %3, (%2, 0) \n"
24 "10: ldw %4, (%2, 4) \n"
27 "11: ldw %3, (%2, 8) \n"
28 "12: ldw %4, (%2, 12) \n"
30 " stw %4, (%1, 12) \n"
37 "4: ldw %3, (%2, 0) \n"
45 "6: ldb %3, (%2, 0) \n"
51 "8: stw %3, (%1, 0) \n"
56 "13: stw %3, (%1, 8) \n"
59 ".section __ex_table, \"a\" \n"
69 : "=r"(n), "=r"(to), "=r"(from), "=r"(nsave),
71 : "0"(n), "1"(to), "2"(from)
76 EXPORT_SYMBOL(raw_copy_from_user);
78 unsigned long raw_copy_to_user(void *to, const void *from,
92 "1: cmplti %0, 16 \n" /* 4W */
97 " ldw %6, (%2, 12) \n"
98 "2: stw %3, (%1, 0) \n"
99 "9: stw %4, (%1, 4) \n"
100 "10: stw %5, (%1, 8) \n"
101 "11: stw %6, (%1, 12) \n"
106 "3: cmplti %0, 4 \n" /* 1W */
108 " ldw %3, (%2, 0) \n"
109 "4: stw %3, (%1, 0) \n"
114 "5: cmpnei %0, 0 \n" /* 1B */
116 " ldb %3, (%2, 0) \n"
117 "6: stb %3, (%1, 0) \n"
126 ".section __ex_table, \"a\" \n"
136 : "=r"(n), "=r"(to), "=r"(from), "=r"(w0),
137 "=r"(w1), "=r"(w2), "=r"(w3)
138 : "0"(n), "1"(to), "2"(from)
143 EXPORT_SYMBOL(raw_copy_to_user);
146 * __strncpy_from_user: - Copy a NUL terminated string from userspace,
147 * with less checking.
148 * @dst: Destination address, in kernel space. This buffer must be at
149 * least @count bytes long.
150 * @src: Source address, in user space.
151 * @count: Maximum number of bytes to copy, including the trailing NUL.
153 * Copies a NUL-terminated string from userspace to kernel space.
154 * Caller must check the specified block with access_ok() before calling
157 * On success, returns the length of the string (not including the trailing
160 * If access to userspace fails, returns -EFAULT (some data may have been
163 * If @count is smaller than the length of the string, copies @count bytes
164 * and returns @count.
166 long __strncpy_from_user(char *dst, const char *src, long count)
171 __asm__ __volatile__(
176 "2: ldb %4, (%3, 0) \n"
177 " stb %4, (%2, 0) \n"
188 ".section __ex_table, \"a\" \n"
193 : "=r"(res), "=r"(count), "=r"(dst),
194 "=r"(src), "=r"(tmp), "=r"(faultres)
195 : "5"(-EFAULT), "0"(count), "1"(count),
201 EXPORT_SYMBOL(__strncpy_from_user);
204 * strnlen_user: - Get the size of a string in user space.
205 * @str: The string to measure.
206 * @n: The maximum valid length
208 * Get the size of a NUL-terminated string in user space.
210 * Returns the size of the string INCLUDING the terminating NUL.
211 * On exception, returns 0.
212 * If the string is too long, returns a value greater than @n.
214 long __strnlen_user(const char *s, long n)
216 unsigned long res, tmp;
218 __asm__ __volatile__(
223 "2: ldb %3, (%1, 0) \n"
234 ".section __ex_table, \"a\" \n"
239 : "=r"(n), "=r"(s), "=r"(res), "=r"(tmp)
240 : "0"(n), "1"(s), "2"(n)
245 EXPORT_SYMBOL(__strnlen_user);
248 * __clear_user: - Zero a block of memory in user space, with less checking.
249 * @to: Destination address, in user space.
250 * @n: Number of bytes to zero.
252 * Zero a block of memory in user space. Caller must check
253 * the specified block with access_ok() before calling this function.
255 * Returns number of bytes that could not be cleared.
256 * On success, this will be zero.
259 __clear_user(void __user *to, unsigned long n)
261 int data, value, tmp;
263 __asm__ __volatile__(
271 "1: cmplti %0, 32 \n" /* 4W */
273 "8: stw %2, (%1, 0) \n"
274 "10: stw %2, (%1, 4) \n"
275 "11: stw %2, (%1, 8) \n"
276 "12: stw %2, (%1, 12) \n"
277 "13: stw %2, (%1, 16) \n"
278 "14: stw %2, (%1, 20) \n"
279 "15: stw %2, (%1, 24) \n"
280 "16: stw %2, (%1, 28) \n"
284 "3: cmplti %0, 4 \n" /* 1W */
286 "4: stw %2, (%1, 0) \n"
290 "5: cmpnei %0, 0 \n" /* 1B */
292 "6: stb %2, (%1, 0) \n"
296 ".section __ex_table,\"a\" \n"
310 : "=r"(n), "=r" (data), "=r"(value), "=r"(tmp)
311 : "0"(n), "1"(to), "2"(0)
316 EXPORT_SYMBOL(__clear_user);