blob: dd5f3bfbc2c5c2bb1cc3c08f6f6562f0829989e7 [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
Michal Simekebe21122011-06-10 10:49:08 +020015/* Loop unrolling for __copy_tofrom_user */
16#define COPY(offset) \
171: lwi r4 , r6, 0x0000 + offset; \
182: lwi r19, r6, 0x0004 + offset; \
193: lwi r20, r6, 0x0008 + offset; \
204: lwi r21, r6, 0x000C + offset; \
215: lwi r22, r6, 0x0010 + offset; \
226: lwi r23, r6, 0x0014 + offset; \
237: lwi r24, r6, 0x0018 + offset; \
248: lwi r25, r6, 0x001C + offset; \
259: swi r4 , r5, 0x0000 + offset; \
2610: swi r19, r5, 0x0004 + offset; \
2711: swi r20, r5, 0x0008 + offset; \
2812: swi r21, r5, 0x000C + offset; \
2913: swi r22, r5, 0x0010 + offset; \
3014: swi r23, r5, 0x0014 + offset; \
3115: swi r24, r5, 0x0018 + offset; \
3216: swi r25, r5, 0x001C + offset; \
33 .section __ex_table,"a"; \
Michal Simekac64a9c2012-03-30 08:21:38 +020034 .word 1b, 33f; \
35 .word 2b, 33f; \
36 .word 3b, 33f; \
37 .word 4b, 33f; \
38 .word 5b, 33f; \
39 .word 6b, 33f; \
40 .word 7b, 33f; \
41 .word 8b, 33f; \
42 .word 9b, 33f; \
43 .word 10b, 33f; \
44 .word 11b, 33f; \
45 .word 12b, 33f; \
46 .word 13b, 33f; \
47 .word 14b, 33f; \
48 .word 15b, 33f; \
49 .word 16b, 33f; \
Michal Simekebe21122011-06-10 10:49:08 +020050 .text
51
52#define COPY_80(offset) \
53 COPY(0x00 + offset);\
54 COPY(0x20 + offset);\
55 COPY(0x40 + offset);\
56 COPY(0x60 + offset);
57
Michal Simek0d6de952009-05-26 16:30:23 +020058/*
59 * int __copy_tofrom_user(char *to, char *from, int len)
60 * Return:
61 * 0 on success
62 * number of not copied bytes on error
63 */
64 .text
65.globl __copy_tofrom_user;
Michal Simek13851962010-03-23 08:09:32 +010066.type __copy_tofrom_user, @function
Michal Simek0d6de952009-05-26 16:30:23 +020067.align 4;
68__copy_tofrom_user:
69 /*
70 * r5 - to
71 * r6 - from
72 * r7, r3 - count
73 * r4 - tempval
74 */
Michal Simek9b133f82011-06-10 11:03:44 +020075 beqid r7, 0f /* zero size is not likely */
Michal Simekca3865b2010-03-22 20:31:26 +010076 or r3, r5, r6 /* find if is any to/from unaligned */
Michal Simek782d4912011-06-10 11:08:57 +020077 or r3, r3, r7 /* find if count is unaligned */
78 andi r3, r3, 0x3 /* mask last 3 bits */
79 bneid r3, bu1 /* if r3 is not zero then byte copying */
Michal Simekca3865b2010-03-22 20:31:26 +010080 or r3, r0, r0
81
Michal Simekebe21122011-06-10 10:49:08 +020082 rsubi r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
83 beqid r3, page;
84 or r3, r0, r0
85
Michal Simekc83858b2011-06-10 11:07:55 +020086w1: lw r4, r6, r3 /* at least one 4 byte copy */
87w2: sw r4, r5, r3
Michal Simekca3865b2010-03-22 20:31:26 +010088 addik r7, r7, -4
Michal Simekc83858b2011-06-10 11:07:55 +020089 bneid r7, w1
Michal Simekca3865b2010-03-22 20:31:26 +010090 addik r3, r3, 4
91 addik r3, r7, 0
92 rtsd r15, 8
93 nop
Michal Simekeedac792011-06-10 11:05:45 +020094
95 .section __ex_table,"a"
Michal Simekc83858b2011-06-10 11:07:55 +020096 .word w1, 0f;
97 .word w2, 0f;
Michal Simekeedac792011-06-10 11:05:45 +020098 .text
99
Michal Simekebe21122011-06-10 10:49:08 +0200100.align 4 /* Alignment is important to keep icache happy */
Bhaskar Chowdhurybbcee722021-03-19 10:23:23 +0530101page: /* Create room on stack and save registers for storing values */
Michal Simekac64a9c2012-03-30 08:21:38 +0200102 addik r1, r1, -40
103 swi r5, r1, 0
104 swi r6, r1, 4
105 swi r7, r1, 8
106 swi r19, r1, 12
107 swi r20, r1, 16
108 swi r21, r1, 20
109 swi r22, r1, 24
110 swi r23, r1, 28
111 swi r24, r1, 32
112 swi r25, r1, 36
Michal Simekebe21122011-06-10 10:49:08 +0200113loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
114 /* Loop unrolling to get performance boost */
115 COPY_80(0x000);
116 COPY_80(0x080);
117 COPY_80(0x100);
118 COPY_80(0x180);
119 /* copy loop */
Michal Simekac64a9c2012-03-30 08:21:38 +0200120 addik r6, r6, 0x200
121 addik r7, r7, -0x200
122 bneid r7, loop
123 addik r5, r5, 0x200
124
Michal Simekebe21122011-06-10 10:49:08 +0200125 /* Restore register content */
Michal Simekac64a9c2012-03-30 08:21:38 +0200126 lwi r5, r1, 0
127 lwi r6, r1, 4
128 lwi r7, r1, 8
129 lwi r19, r1, 12
130 lwi r20, r1, 16
131 lwi r21, r1, 20
132 lwi r22, r1, 24
133 lwi r23, r1, 28
134 lwi r24, r1, 32
135 lwi r25, r1, 36
136 addik r1, r1, 40
Michal Simekebe21122011-06-10 10:49:08 +0200137 /* return back */
Michal Simekac64a9c2012-03-30 08:21:38 +0200138 addik r3, r0, 0
139 rtsd r15, 8
140 nop
141
142/* Fault case - return temp count */
14333:
Michal Simekebe21122011-06-10 10:49:08 +0200144 addik r3, r7, 0
Michal Simekac64a9c2012-03-30 08:21:38 +0200145 /* Restore register content */
146 lwi r5, r1, 0
147 lwi r6, r1, 4
148 lwi r7, r1, 8
149 lwi r19, r1, 12
150 lwi r20, r1, 16
151 lwi r21, r1, 20
152 lwi r22, r1, 24
153 lwi r23, r1, 28
154 lwi r24, r1, 32
155 lwi r25, r1, 36
156 addik r1, r1, 40
157 /* return back */
Michal Simekebe21122011-06-10 10:49:08 +0200158 rtsd r15, 8
159 nop
160
161.align 4 /* Alignment is important to keep icache happy */
Michal Simekc83858b2011-06-10 11:07:55 +0200162bu1: lbu r4,r6,r3
163bu2: sb r4,r5,r3
Michal Simekca3865b2010-03-22 20:31:26 +0100164 addik r7,r7,-1
Michal Simekc83858b2011-06-10 11:07:55 +0200165 bneid r7,bu1
Michal Simekca3865b2010-03-22 20:31:26 +0100166 addik r3,r3,1 /* delay slot */
Michal Simek9b133f82011-06-10 11:03:44 +02001670:
Michal Simekca3865b2010-03-22 20:31:26 +0100168 addik r3,r7,0
Michal Simek0d6de952009-05-26 16:30:23 +0200169 rtsd r15,8
170 nop
Michal Simek13851962010-03-23 08:09:32 +0100171 .size __copy_tofrom_user, . - __copy_tofrom_user
Michal Simek0d6de952009-05-26 16:30:23 +0200172
Michal Simek0d6de952009-05-26 16:30:23 +0200173 .section __ex_table,"a"
Michal Simekc83858b2011-06-10 11:07:55 +0200174 .word bu1, 0b;
175 .word bu2, 0b;
Michal Simekeedac792011-06-10 11:05:45 +0200176 .text