Linux Audio

Check our new training course

Loading...
v5.9
  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	___copy_from_user(to, from, n);
 
 
 
 11	return n;
 12}
 13EXPORT_SYMBOL(raw_copy_from_user);
 14
 15unsigned 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}
 21EXPORT_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)	\
 28do {							\
 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 */
 81long __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}
 88EXPORT_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 */
108long 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}
116EXPORT_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 */
129long 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}
163EXPORT_SYMBOL(strnlen_user);
164
165#define __do_clear_user(addr, size)			\
166do {							\
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 */
232unsigned long
233clear_user(void __user *to, unsigned long n)
234{
235	if (access_ok(to, n))
236		__do_clear_user(to, n);
237	return n;
238}
239EXPORT_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 */
252unsigned long
253__clear_user(void __user *to, unsigned long n)
254{
255	__do_clear_user(to, n);
256	return n;
257}
258EXPORT_SYMBOL(__clear_user);
v5.4
  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);