Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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
  7unsigned long raw_copy_from_user(void *to, const void *from,
  8			unsigned long n)
  9{
 10	if (access_ok(from, n))
 11		__copy_user_zeroing(to, from, n);
 12	else
 13		memset(to, 0, n);
 14	return n;
 15}
 16EXPORT_SYMBOL(raw_copy_from_user);
 17
 18unsigned long raw_copy_to_user(void *to, const void *from,
 19			unsigned long n)
 20{
 21	if (access_ok(to, n))
 22		__copy_user(to, from, n);
 23	return n;
 24}
 25EXPORT_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)	\
 32do {							\
 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 */
 85long __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}
 92EXPORT_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 */
112long strncpy_from_user(char *dst, const char *src, long count)
113{
114	long res = -EFAULT;
115
116	if (access_ok(src, 1))
117		__do_strncpy_from_user(dst, src, count, res);
118	return res;
119}
120EXPORT_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 */
133long 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}
167EXPORT_SYMBOL(strnlen_user);
168
169#define __do_clear_user(addr, size)			\
170do {							\
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 */
236unsigned long
237clear_user(void __user *to, unsigned long n)
238{
239	if (access_ok(to, n))
240		__do_clear_user(to, n);
241	return n;
242}
243EXPORT_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 */
256unsigned long
257__clear_user(void __user *to, unsigned long n)
258{
259	__do_clear_user(to, n);
260	return n;
261}
262EXPORT_SYMBOL(__clear_user);