xref: /openbmc/linux/arch/m68k/lib/uaccess.c (revision 92ed1a76)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file COPYING in the main directory of this archive
4  * for more details.
5  */
6 
7 #include <linux/module.h>
8 #include <asm/uaccess.h>
9 
10 unsigned long __generic_copy_from_user(void *to, const void __user *from,
11 				       unsigned long n)
12 {
13 	unsigned long tmp, res;
14 
15 	asm volatile ("\n"
16 		"	tst.l	%0\n"
17 		"	jeq	2f\n"
18 		"1:	moves.l	(%1)+,%3\n"
19 		"	move.l	%3,(%2)+\n"
20 		"	subq.l	#1,%0\n"
21 		"	jne	1b\n"
22 		"2:	btst	#1,%5\n"
23 		"	jeq	4f\n"
24 		"3:	moves.w	(%1)+,%3\n"
25 		"	move.w	%3,(%2)+\n"
26 		"4:	btst	#0,%5\n"
27 		"	jeq	6f\n"
28 		"5:	moves.b	(%1)+,%3\n"
29 		"	move.b  %3,(%2)+\n"
30 		"6:\n"
31 		"	.section .fixup,\"ax\"\n"
32 		"	.even\n"
33 		"10:	move.l	%0,%3\n"
34 		"7:	clr.l	(%2)+\n"
35 		"	subq.l	#1,%3\n"
36 		"	jne	7b\n"
37 		"	lsl.l	#2,%0\n"
38 		"	btst	#1,%5\n"
39 		"	jeq	8f\n"
40 		"30:	clr.w	(%2)+\n"
41 		"	addq.l	#2,%0\n"
42 		"8:	btst	#0,%5\n"
43 		"	jeq	6b\n"
44 		"50:	clr.b	(%2)+\n"
45 		"	addq.l	#1,%0\n"
46 		"	jra	6b\n"
47 		"	.previous\n"
48 		"\n"
49 		"	.section __ex_table,\"a\"\n"
50 		"	.align	4\n"
51 		"	.long	1b,10b\n"
52 		"	.long	3b,30b\n"
53 		"	.long	5b,50b\n"
54 		"	.previous"
55 		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
56 		: "0" (n / 4), "d" (n & 3));
57 
58 	return res;
59 }
60 EXPORT_SYMBOL(__generic_copy_from_user);
61 
62 unsigned long __generic_copy_to_user(void __user *to, const void *from,
63 				     unsigned long n)
64 {
65 	unsigned long tmp, res;
66 
67 	asm volatile ("\n"
68 		"	tst.l	%0\n"
69 		"	jeq	4f\n"
70 		"1:	move.l	(%1)+,%3\n"
71 		"2:	moves.l	%3,(%2)+\n"
72 		"3:	subq.l	#1,%0\n"
73 		"	jne	1b\n"
74 		"4:	btst	#1,%5\n"
75 		"	jeq	6f\n"
76 		"	move.w	(%1)+,%3\n"
77 		"5:	moves.w	%3,(%2)+\n"
78 		"6:	btst	#0,%5\n"
79 		"	jeq	8f\n"
80 		"	move.b	(%1)+,%3\n"
81 		"7:	moves.b  %3,(%2)+\n"
82 		"8:\n"
83 		"	.section .fixup,\"ax\"\n"
84 		"	.even\n"
85 		"20:	lsl.l	#2,%0\n"
86 		"50:	add.l	%5,%0\n"
87 		"	jra	8b\n"
88 		"	.previous\n"
89 		"\n"
90 		"	.section __ex_table,\"a\"\n"
91 		"	.align	4\n"
92 		"	.long	2b,20b\n"
93 		"	.long	3b,20b\n"
94 		"	.long	5b,50b\n"
95 		"	.long	6b,50b\n"
96 		"	.long	7b,50b\n"
97 		"	.long	8b,50b\n"
98 		"	.previous"
99 		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
100 		: "0" (n / 4), "d" (n & 3));
101 
102 	return res;
103 }
104 EXPORT_SYMBOL(__generic_copy_to_user);
105 
106 /*
107  * Copy a null terminated string from userspace.
108  */
109 long strncpy_from_user(char *dst, const char __user *src, long count)
110 {
111 	long res;
112 	char c;
113 
114 	if (count <= 0)
115 		return count;
116 
117 	asm volatile ("\n"
118 		"1:	moves.b	(%2)+,%4\n"
119 		"	move.b	%4,(%1)+\n"
120 		"	jeq	2f\n"
121 		"	subq.l	#1,%3\n"
122 		"	jne	1b\n"
123 		"2:	sub.l	%3,%0\n"
124 		"3:\n"
125 		"	.section .fixup,\"ax\"\n"
126 		"	.even\n"
127 		"10:	move.l	%5,%0\n"
128 		"	jra	3b\n"
129 		"	.previous\n"
130 		"\n"
131 		"	.section __ex_table,\"a\"\n"
132 		"	.align	4\n"
133 		"	.long	1b,10b\n"
134 		"	.previous"
135 		: "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c)
136 		: "i" (-EFAULT), "0" (count));
137 
138 	return res;
139 }
140 EXPORT_SYMBOL(strncpy_from_user);
141 
142 /*
143  * Return the size of a string (including the ending 0)
144  *
145  * Return 0 on exception, a value greater than N if too long
146  */
147 long strnlen_user(const char __user *src, long n)
148 {
149 	char c;
150 	long res;
151 
152 	asm volatile ("\n"
153 		"1:	subq.l	#1,%1\n"
154 		"	jmi	3f\n"
155 		"2:	moves.b	(%0)+,%2\n"
156 		"	tst.b	%2\n"
157 		"	jne	1b\n"
158 		"	jra	4f\n"
159 		"\n"
160 		"3:	addq.l	#1,%0\n"
161 		"4:	sub.l	%4,%0\n"
162 		"5:\n"
163 		"	.section .fixup,\"ax\"\n"
164 		"	.even\n"
165 		"20:	sub.l	%0,%0\n"
166 		"	jra	5b\n"
167 		"	.previous\n"
168 		"\n"
169 		"	.section __ex_table,\"a\"\n"
170 		"	.align	4\n"
171 		"	.long	2b,20b\n"
172 		"	.previous\n"
173 		: "=&a" (res), "+d" (n), "=&d" (c)
174 		: "0" (src), "r" (src));
175 
176 	return res;
177 }
178 EXPORT_SYMBOL(strnlen_user);
179 
180 /*
181  * Zero Userspace
182  */
183 
184 unsigned long __clear_user(void __user *to, unsigned long n)
185 {
186 	unsigned long res;
187 
188 	asm volatile ("\n"
189 		"	tst.l	%0\n"
190 		"	jeq	3f\n"
191 		"1:	moves.l	%2,(%1)+\n"
192 		"2:	subq.l	#1,%0\n"
193 		"	jne	1b\n"
194 		"3:	btst	#1,%4\n"
195 		"	jeq	5f\n"
196 		"4:	moves.w	%2,(%1)+\n"
197 		"5:	btst	#0,%4\n"
198 		"	jeq	7f\n"
199 		"6:	moves.b	%2,(%1)\n"
200 		"7:\n"
201 		"	.section .fixup,\"ax\"\n"
202 		"	.even\n"
203 		"10:	lsl.l	#2,%0\n"
204 		"40:	add.l	%4,%0\n"
205 		"	jra	7b\n"
206 		"	.previous\n"
207 		"\n"
208 		"	.section __ex_table,\"a\"\n"
209 		"	.align	4\n"
210 		"	.long	1b,10b\n"
211 		"	.long	2b,10b\n"
212 		"	.long	4b,40b\n"
213 		"	.long	5b,40b\n"
214 		"	.long	6b,40b\n"
215 		"	.long	7b,40b\n"
216 		"	.previous"
217 		: "=d" (res), "+a" (to)
218 		: "r" (0), "0" (n / 4), "d" (n & 3));
219 
220     return res;
221 }
222 EXPORT_SYMBOL(__clear_user);
223