blob: f085995ee8482da474be869148b581543cbf786f [file] [log] [blame]
Michal Simek0d6de952009-05-26 16:30:23 +02001/*
2 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2009 PetaLogix
4 * Copyright (C) 2007 LynuxWorks, Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/errno.h>
12#include <linux/linkage.h>
Michal Simekebe21122011-06-10 10:49:08 +020013#include <asm/page.h>
Michal Simek0d6de952009-05-26 16:30:23 +020014
15/*
16 * int __strncpy_user(char *to, char *from, int len);
17 *
18 * Returns:
19 * -EFAULT for an exception
20 * len if we hit the buffer limit
21 * bytes copied
22 */
23
24 .text
25.globl __strncpy_user;
Michal Simek13851962010-03-23 08:09:32 +010026.type __strncpy_user, @function
Michal Simek0d6de952009-05-26 16:30:23 +020027.align 4;
28__strncpy_user:
29
30 /*
31 * r5 - to
32 * r6 - from
33 * r7 - len
34 * r3 - temp count
35 * r4 - temp val
36 */
Michal Simekcb5edfe2011-10-02 13:07:02 +020037 beqid r7,3f
Michal Simek0d6de952009-05-26 16:30:23 +020038 addik r3,r7,0 /* temp_count = len */
Michal Simek0d6de952009-05-26 16:30:23 +0200391:
40 lbu r4,r6,r0
41 sb r4,r5,r0
42
43 addik r3,r3,-1
44 beqi r3,2f /* break on len */
45
46 addik r5,r5,1
47 bneid r4,1b
48 addik r6,r6,1 /* delay slot */
49 addik r3,r3,1 /* undo "temp_count--" */
502:
51 rsubk r3,r3,r7 /* temp_count = len - temp_count */
523:
53 rtsd r15,8
54 nop
Michal Simek13851962010-03-23 08:09:32 +010055 .size __strncpy_user, . - __strncpy_user
Michal Simek0d6de952009-05-26 16:30:23 +020056
Michal Simek0d6de952009-05-26 16:30:23 +020057 .section .fixup, "ax"
58 .align 2
594:
60 brid 3b
61 addik r3,r0, -EFAULT
62
63 .section __ex_table, "a"
64 .word 1b,4b
65
66/*
67 * int __strnlen_user(char __user *str, int maxlen);
68 *
69 * Returns:
70 * 0 on error
71 * maxlen + 1 if no NUL byte found within maxlen bytes
72 * size of the string (including NUL byte)
73 */
74
75 .text
76.globl __strnlen_user;
Michal Simek13851962010-03-23 08:09:32 +010077.type __strnlen_user, @function
Michal Simek0d6de952009-05-26 16:30:23 +020078.align 4;
79__strnlen_user:
Michal Simekcb5edfe2011-10-02 13:07:02 +020080 beqid r6,3f
Michal Simek0d6de952009-05-26 16:30:23 +020081 addik r3,r6,0
Michal Simek0d6de952009-05-26 16:30:23 +0200821:
83 lbu r4,r5,r0
84 beqid r4,2f /* break on NUL */
85 addik r3,r3,-1 /* delay slot */
86
87 bneid r3,1b
88 addik r5,r5,1 /* delay slot */
89
90 addik r3,r3,-1 /* for break on len */
912:
92 rsubk r3,r3,r6
933:
94 rtsd r15,8
95 nop
Michal Simek13851962010-03-23 08:09:32 +010096 .size __strnlen_user, . - __strnlen_user
Michal Simek0d6de952009-05-26 16:30:23 +020097
Michal Simek0d6de952009-05-26 16:30:23 +020098 .section .fixup,"ax"
994:
100 brid 3b
101 addk r3,r0,r0
102
103 .section __ex_table,"a"
104 .word 1b,4b
105
Michal Simekebe21122011-06-10 10:49:08 +0200106/* Loop unrolling for __copy_tofrom_user */
107#define COPY(offset) \
1081: lwi r4 , r6, 0x0000 + offset; \
1092: lwi r19, r6, 0x0004 + offset; \
1103: lwi r20, r6, 0x0008 + offset; \
1114: lwi r21, r6, 0x000C + offset; \
1125: lwi r22, r6, 0x0010 + offset; \
1136: lwi r23, r6, 0x0014 + offset; \
1147: lwi r24, r6, 0x0018 + offset; \
1158: lwi r25, r6, 0x001C + offset; \
1169: swi r4 , r5, 0x0000 + offset; \
11710: swi r19, r5, 0x0004 + offset; \
11811: swi r20, r5, 0x0008 + offset; \
11912: swi r21, r5, 0x000C + offset; \
12013: swi r22, r5, 0x0010 + offset; \
12114: swi r23, r5, 0x0014 + offset; \
12215: swi r24, r5, 0x0018 + offset; \
12316: swi r25, r5, 0x001C + offset; \
124 .section __ex_table,"a"; \
Michal Simekac64a9c2012-03-30 08:21:38 +0200125 .word 1b, 33f; \
126 .word 2b, 33f; \
127 .word 3b, 33f; \
128 .word 4b, 33f; \
129 .word 5b, 33f; \
130 .word 6b, 33f; \
131 .word 7b, 33f; \
132 .word 8b, 33f; \
133 .word 9b, 33f; \
134 .word 10b, 33f; \
135 .word 11b, 33f; \
136 .word 12b, 33f; \
137 .word 13b, 33f; \
138 .word 14b, 33f; \
139 .word 15b, 33f; \
140 .word 16b, 33f; \
Michal Simekebe21122011-06-10 10:49:08 +0200141 .text
142
143#define COPY_80(offset) \
144 COPY(0x00 + offset);\
145 COPY(0x20 + offset);\
146 COPY(0x40 + offset);\
147 COPY(0x60 + offset);
148
Michal Simek0d6de952009-05-26 16:30:23 +0200149/*
150 * int __copy_tofrom_user(char *to, char *from, int len)
151 * Return:
152 * 0 on success
153 * number of not copied bytes on error
154 */
155 .text
156.globl __copy_tofrom_user;
Michal Simek13851962010-03-23 08:09:32 +0100157.type __copy_tofrom_user, @function
Michal Simek0d6de952009-05-26 16:30:23 +0200158.align 4;
159__copy_tofrom_user:
160 /*
161 * r5 - to
162 * r6 - from
163 * r7, r3 - count
164 * r4 - tempval
165 */
Michal Simek9b133f82011-06-10 11:03:44 +0200166 beqid r7, 0f /* zero size is not likely */
Michal Simekca3865b2010-03-22 20:31:26 +0100167 or r3, r5, r6 /* find if is any to/from unaligned */
Michal Simek782d4912011-06-10 11:08:57 +0200168 or r3, r3, r7 /* find if count is unaligned */
169 andi r3, r3, 0x3 /* mask last 3 bits */
170 bneid r3, bu1 /* if r3 is not zero then byte copying */
Michal Simekca3865b2010-03-22 20:31:26 +0100171 or r3, r0, r0
172
Michal Simekebe21122011-06-10 10:49:08 +0200173 rsubi r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
174 beqid r3, page;
175 or r3, r0, r0
176
Michal Simekc83858b2011-06-10 11:07:55 +0200177w1: lw r4, r6, r3 /* at least one 4 byte copy */
178w2: sw r4, r5, r3
Michal Simekca3865b2010-03-22 20:31:26 +0100179 addik r7, r7, -4
Michal Simekc83858b2011-06-10 11:07:55 +0200180 bneid r7, w1
Michal Simekca3865b2010-03-22 20:31:26 +0100181 addik r3, r3, 4
182 addik r3, r7, 0
183 rtsd r15, 8
184 nop
Michal Simekeedac792011-06-10 11:05:45 +0200185
186 .section __ex_table,"a"
Michal Simekc83858b2011-06-10 11:07:55 +0200187 .word w1, 0f;
188 .word w2, 0f;
Michal Simekeedac792011-06-10 11:05:45 +0200189 .text
190
Michal Simekebe21122011-06-10 10:49:08 +0200191.align 4 /* Alignment is important to keep icache happy */
192page: /* Create room on stack and save registers for storign values */
Michal Simekac64a9c2012-03-30 08:21:38 +0200193 addik r1, r1, -40
194 swi r5, r1, 0
195 swi r6, r1, 4
196 swi r7, r1, 8
197 swi r19, r1, 12
198 swi r20, r1, 16
199 swi r21, r1, 20
200 swi r22, r1, 24
201 swi r23, r1, 28
202 swi r24, r1, 32
203 swi r25, r1, 36
Michal Simekebe21122011-06-10 10:49:08 +0200204loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
205 /* Loop unrolling to get performance boost */
206 COPY_80(0x000);
207 COPY_80(0x080);
208 COPY_80(0x100);
209 COPY_80(0x180);
210 /* copy loop */
Michal Simekac64a9c2012-03-30 08:21:38 +0200211 addik r6, r6, 0x200
212 addik r7, r7, -0x200
213 bneid r7, loop
214 addik r5, r5, 0x200
215
Michal Simekebe21122011-06-10 10:49:08 +0200216 /* Restore register content */
Michal Simekac64a9c2012-03-30 08:21:38 +0200217 lwi r5, r1, 0
218 lwi r6, r1, 4
219 lwi r7, r1, 8
220 lwi r19, r1, 12
221 lwi r20, r1, 16
222 lwi r21, r1, 20
223 lwi r22, r1, 24
224 lwi r23, r1, 28
225 lwi r24, r1, 32
226 lwi r25, r1, 36
227 addik r1, r1, 40
Michal Simekebe21122011-06-10 10:49:08 +0200228 /* return back */
Michal Simekac64a9c2012-03-30 08:21:38 +0200229 addik r3, r0, 0
230 rtsd r15, 8
231 nop
232
233/* Fault case - return temp count */
23433:
Michal Simekebe21122011-06-10 10:49:08 +0200235 addik r3, r7, 0
Michal Simekac64a9c2012-03-30 08:21:38 +0200236 /* Restore register content */
237 lwi r5, r1, 0
238 lwi r6, r1, 4
239 lwi r7, r1, 8
240 lwi r19, r1, 12
241 lwi r20, r1, 16
242 lwi r21, r1, 20
243 lwi r22, r1, 24
244 lwi r23, r1, 28
245 lwi r24, r1, 32
246 lwi r25, r1, 36
247 addik r1, r1, 40
248 /* return back */
Michal Simekebe21122011-06-10 10:49:08 +0200249 rtsd r15, 8
250 nop
251
252.align 4 /* Alignment is important to keep icache happy */
Michal Simekc83858b2011-06-10 11:07:55 +0200253bu1: lbu r4,r6,r3
254bu2: sb r4,r5,r3
Michal Simekca3865b2010-03-22 20:31:26 +0100255 addik r7,r7,-1
Michal Simekc83858b2011-06-10 11:07:55 +0200256 bneid r7,bu1
Michal Simekca3865b2010-03-22 20:31:26 +0100257 addik r3,r3,1 /* delay slot */
Michal Simek9b133f82011-06-10 11:03:44 +02002580:
Michal Simekca3865b2010-03-22 20:31:26 +0100259 addik r3,r7,0
Michal Simek0d6de952009-05-26 16:30:23 +0200260 rtsd r15,8
261 nop
Michal Simek13851962010-03-23 08:09:32 +0100262 .size __copy_tofrom_user, . - __copy_tofrom_user
Michal Simek0d6de952009-05-26 16:30:23 +0200263
Michal Simek0d6de952009-05-26 16:30:23 +0200264 .section __ex_table,"a"
Michal Simekc83858b2011-06-10 11:07:55 +0200265 .word bu1, 0b;
266 .word bu2, 0b;
Michal Simekeedac792011-06-10 11:05:45 +0200267 .text