aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2007-08-16 04:47:25 -0400
committerDavid S. Miller <davem@davemloft.net>2007-08-16 04:47:25 -0400
commitcf5adce11743e98739fcb97e76d688f0b0bc2199 (patch)
tree3cea4d74363a6570bbe5aaf4e723e3c256ffb591 /arch
parent0fdb7f96d8c27e37ed2ca1ae5a763baf14b8fe0c (diff)
[SPARC64]: Niagara-2 optimized copies.
The bzero/memset implementation stays the same as Niagara-1. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/head.S11
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/NG2copy_from_user.S40
-rw-r--r--arch/sparc64/lib/NG2copy_to_user.S49
-rw-r--r--arch/sparc64/lib/NG2memcpy.S520
-rw-r--r--arch/sparc64/lib/NG2page.S61
-rw-r--r--arch/sparc64/lib/NG2patch.S33
-rw-r--r--arch/sparc64/lib/NGpage.S1
8 files changed, 716 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index ac18bd8e273f..a2652bcfeb15 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -501,7 +501,7 @@ niagara_tlb_fixup:
501 cmp %g1, SUN4V_CHIP_NIAGARA1 501 cmp %g1, SUN4V_CHIP_NIAGARA1
502 be,pt %xcc, niagara_patch 502 be,pt %xcc, niagara_patch
503 cmp %g1, SUN4V_CHIP_NIAGARA2 503 cmp %g1, SUN4V_CHIP_NIAGARA2
504 be,pt %xcc, niagara_patch 504 be,pt %xcc, niagara2_patch
505 nop 505 nop
506 506
507 call generic_patch_copyops 507 call generic_patch_copyops
@@ -512,6 +512,15 @@ niagara_tlb_fixup:
512 nop 512 nop
513 513
514 ba,a,pt %xcc, 80f 514 ba,a,pt %xcc, 80f
515niagara2_patch:
516 call niagara2_patch_copyops
517 nop
518 call niagara_patch_bzero
519 nop
520 call niagara2_patch_pageops
521 nop
522
523 ba,a,pt %xcc, 80f
515 524
516niagara_patch: 525niagara_patch:
517 call niagara_patch_copyops 526 call niagara_patch_copyops
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index f95fbfa3eeb8..f095e13910bc 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -13,6 +13,8 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ 13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
14 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \ 14 NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
15 NGpage.o NGbzero.o \ 15 NGpage.o NGbzero.o \
16 NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o NG2patch.o \
17 NG2page.o \
16 GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \ 18 GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \
17 GENpage.o GENbzero.o \ 19 GENpage.o GENbzero.o \
18 copy_in_user.o user_fixup.o memmove.o \ 20 copy_in_user.o user_fixup.o memmove.o \
diff --git a/arch/sparc64/lib/NG2copy_from_user.S b/arch/sparc64/lib/NG2copy_from_user.S
new file mode 100644
index 000000000000..c77ef5f22102
--- /dev/null
+++ b/arch/sparc64/lib/NG2copy_from_user.S
@@ -0,0 +1,40 @@
1/* NG2copy_from_user.S: Niagara-2 optimized copy from userspace.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#define EX_LD(x) \
798: x; \
8 .section .fixup; \
9 .align 4; \
1099: wr %g0, ASI_AIUS, %asi;\
11 retl; \
12 mov 1, %o0; \
13 .section __ex_table,"a";\
14 .align 4; \
15 .word 98b, 99b; \
16 .text; \
17 .align 4;
18
19#ifndef ASI_AIUS
20#define ASI_AIUS 0x11
21#endif
22
23#ifndef ASI_BLK_AIUS_4V
24#define ASI_BLK_AIUS_4V 0x17
25#endif
26
27#define FUNC_NAME NG2copy_from_user
28#define LOAD(type,addr,dest) type##a [addr] %asi, dest
29#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS_4V, dest
30#define EX_RETVAL(x) 0
31
32#ifdef __KERNEL__
33#define PREAMBLE \
34 rd %asi, %g1; \
35 cmp %g1, ASI_AIUS; \
36 bne,pn %icc, memcpy_user_stub; \
37 nop
38#endif
39
40#include "NG2memcpy.S"
diff --git a/arch/sparc64/lib/NG2copy_to_user.S b/arch/sparc64/lib/NG2copy_to_user.S
new file mode 100644
index 000000000000..4bd4093acbbd
--- /dev/null
+++ b/arch/sparc64/lib/NG2copy_to_user.S
@@ -0,0 +1,49 @@
1/* NG2copy_to_user.S: Niagara-2 optimized copy to userspace.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#define EX_ST(x) \
798: x; \
8 .section .fixup; \
9 .align 4; \
1099: wr %g0, ASI_AIUS, %asi;\
11 retl; \
12 mov 1, %o0; \
13 .section __ex_table,"a";\
14 .align 4; \
15 .word 98b, 99b; \
16 .text; \
17 .align 4;
18
19#ifndef ASI_AIUS
20#define ASI_AIUS 0x11
21#endif
22
23#ifndef ASI_BLK_AIUS_4V
24#define ASI_BLK_AIUS_4V 0x17
25#endif
26
27#ifndef ASI_BLK_INIT_QUAD_LDD_AIUS
28#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23
29#endif
30
31#define FUNC_NAME NG2copy_to_user
32#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS
33#define STORE_ASI ASI_BLK_INIT_QUAD_LDD_AIUS
34#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS_4V
35#define EX_RETVAL(x) 0
36
37#ifdef __KERNEL__
38 /* Writing to %asi is _expensive_ so we hardcode it.
39 * Reading %asi to check for KERNEL_DS is comparatively
40 * cheap.
41 */
42#define PREAMBLE \
43 rd %asi, %g1; \
44 cmp %g1, ASI_AIUS; \
45 bne,pn %icc, memcpy_user_stub; \
46 nop
47#endif
48
49#include "NG2memcpy.S"
diff --git a/arch/sparc64/lib/NG2memcpy.S b/arch/sparc64/lib/NG2memcpy.S
new file mode 100644
index 000000000000..0aed75653b50
--- /dev/null
+++ b/arch/sparc64/lib/NG2memcpy.S
@@ -0,0 +1,520 @@
1/* NG2memcpy.S: Niagara-2 optimized memcpy.
2 *
3 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
4 */
5
6#ifdef __KERNEL__
7#include <asm/visasm.h>
8#include <asm/asi.h>
9#define GLOBAL_SPARE %g7
10#else
11#define ASI_PNF 0x82
12#define ASI_BLK_P 0xf0
13#define ASI_BLK_INIT_QUAD_LDD_P 0xe2
14#define FPRS_FEF 0x04
15#ifdef MEMCPY_DEBUG
16#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
17 clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
18#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
19#else
20#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
21#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
22#endif
23#define GLOBAL_SPARE %g5
24#endif
25
26#ifndef STORE_ASI
27#ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA
28#define STORE_ASI ASI_BLK_INIT_QUAD_LDD_P
29#else
30#define STORE_ASI 0x80 /* ASI_P */
31#endif
32#endif
33
34#ifndef EX_LD
35#define EX_LD(x) x
36#endif
37
38#ifndef EX_ST
39#define EX_ST(x) x
40#endif
41
42#ifndef EX_RETVAL
43#define EX_RETVAL(x) x
44#endif
45
46#ifndef LOAD
47#define LOAD(type,addr,dest) type [addr], dest
48#endif
49
50#ifndef LOAD_BLK
51#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_P, dest
52#endif
53
54#ifndef STORE
55#ifndef MEMCPY_DEBUG
56#define STORE(type,src,addr) type src, [addr]
57#else
58#define STORE(type,src,addr) type##a src, [addr] 0x80
59#endif
60#endif
61
62#ifndef STORE_BLK
63#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P
64#endif
65
66#ifndef STORE_INIT
67#define STORE_INIT(src,addr) stxa src, [addr] STORE_ASI
68#endif
69
70#ifndef FUNC_NAME
71#define FUNC_NAME NG2memcpy
72#endif
73
74#ifndef PREAMBLE
75#define PREAMBLE
76#endif
77
78#ifndef XCC
79#define XCC xcc
80#endif
81
82#define FREG_FROB(x0, x1, x2, x3, x4, x5, x6, x7, x8) \
83 faligndata %x0, %x1, %f0; \
84 faligndata %x1, %x2, %f2; \
85 faligndata %x2, %x3, %f4; \
86 faligndata %x3, %x4, %f6; \
87 faligndata %x4, %x5, %f8; \
88 faligndata %x5, %x6, %f10; \
89 faligndata %x6, %x7, %f12; \
90 faligndata %x7, %x8, %f14;
91
92#define FREG_MOVE_1(x0) \
93 fmovd %x0, %f0;
94#define FREG_MOVE_2(x0, x1) \
95 fmovd %x0, %f0; \
96 fmovd %x1, %f2;
97#define FREG_MOVE_3(x0, x1, x2) \
98 fmovd %x0, %f0; \
99 fmovd %x1, %f2; \
100 fmovd %x2, %f4;
101#define FREG_MOVE_4(x0, x1, x2, x3) \
102 fmovd %x0, %f0; \
103 fmovd %x1, %f2; \
104 fmovd %x2, %f4; \
105 fmovd %x3, %f6;
106#define FREG_MOVE_5(x0, x1, x2, x3, x4) \
107 fmovd %x0, %f0; \
108 fmovd %x1, %f2; \
109 fmovd %x2, %f4; \
110 fmovd %x3, %f6; \
111 fmovd %x4, %f8;
112#define FREG_MOVE_6(x0, x1, x2, x3, x4, x5) \
113 fmovd %x0, %f0; \
114 fmovd %x1, %f2; \
115 fmovd %x2, %f4; \
116 fmovd %x3, %f6; \
117 fmovd %x4, %f8; \
118 fmovd %x5, %f10;
119#define FREG_MOVE_7(x0, x1, x2, x3, x4, x5, x6) \
120 fmovd %x0, %f0; \
121 fmovd %x1, %f2; \
122 fmovd %x2, %f4; \
123 fmovd %x3, %f6; \
124 fmovd %x4, %f8; \
125 fmovd %x5, %f10; \
126 fmovd %x6, %f12;
127#define FREG_MOVE_8(x0, x1, x2, x3, x4, x5, x6, x7) \
128 fmovd %x0, %f0; \
129 fmovd %x1, %f2; \
130 fmovd %x2, %f4; \
131 fmovd %x3, %f6; \
132 fmovd %x4, %f8; \
133 fmovd %x5, %f10; \
134 fmovd %x6, %f12; \
135 fmovd %x7, %f14;
136#define FREG_LOAD_1(base, x0) \
137 EX_LD(LOAD(ldd, base + 0x00, %x0))
138#define FREG_LOAD_2(base, x0, x1) \
139 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
140 EX_LD(LOAD(ldd, base + 0x08, %x1));
141#define FREG_LOAD_3(base, x0, x1, x2) \
142 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
143 EX_LD(LOAD(ldd, base + 0x08, %x1)); \
144 EX_LD(LOAD(ldd, base + 0x10, %x2));
145#define FREG_LOAD_4(base, x0, x1, x2, x3) \
146 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
147 EX_LD(LOAD(ldd, base + 0x08, %x1)); \
148 EX_LD(LOAD(ldd, base + 0x10, %x2)); \
149 EX_LD(LOAD(ldd, base + 0x18, %x3));
150#define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
151 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
152 EX_LD(LOAD(ldd, base + 0x08, %x1)); \
153 EX_LD(LOAD(ldd, base + 0x10, %x2)); \
154 EX_LD(LOAD(ldd, base + 0x18, %x3)); \
155 EX_LD(LOAD(ldd, base + 0x20, %x4));
156#define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
157 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
158 EX_LD(LOAD(ldd, base + 0x08, %x1)); \
159 EX_LD(LOAD(ldd, base + 0x10, %x2)); \
160 EX_LD(LOAD(ldd, base + 0x18, %x3)); \
161 EX_LD(LOAD(ldd, base + 0x20, %x4)); \
162 EX_LD(LOAD(ldd, base + 0x28, %x5));
163#define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
164 EX_LD(LOAD(ldd, base + 0x00, %x0)); \
165 EX_LD(LOAD(ldd, base + 0x08, %x1)); \
166 EX_LD(LOAD(ldd, base + 0x10, %x2)); \
167 EX_LD(LOAD(ldd, base + 0x18, %x3)); \
168 EX_LD(LOAD(ldd, base + 0x20, %x4)); \
169 EX_LD(LOAD(ldd, base + 0x28, %x5)); \
170 EX_LD(LOAD(ldd, base + 0x30, %x6));
171
172 .register %g2,#scratch
173 .register %g3,#scratch
174
175 .text
176 .align 64
177
178 .globl FUNC_NAME
179 .type FUNC_NAME,#function
180FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */
181 srlx %o2, 31, %g2
182 cmp %g2, 0
183 tne %xcc, 5
184 PREAMBLE
185 mov %o0, GLOBAL_SPARE
186 cmp %o2, 0
187 be,pn %XCC, 85f
188 or %o0, %o1, %o3
189 cmp %o2, 16
190 blu,a,pn %XCC, 80f
191 or %o3, %o2, %o3
192
193 /* 2 blocks (128 bytes) is the minimum we can do the block
194 * copy with. We need to ensure that we'll iterate at least
195 * once in the block copy loop. At worst we'll need to align
196 * the destination to a 64-byte boundary which can chew up
197 * to (64 - 1) bytes from the length before we perform the
198 * block copy loop.
199 *
200 * However, the cut-off point, performance wise, is around
201 * 4 64-byte blocks.
202 */
203 cmp %o2, (4 * 64)
204 blu,pt %XCC, 75f
205 andcc %o3, 0x7, %g0
206
207 /* %o0: dst
208 * %o1: src
209 * %o2: len (known to be >= 128)
210 *
211 * The block copy loops can use %o4, %g2, %g3 as
212 * temporaries while copying the data. %o5 must
213 * be preserved between VISEntryHalf and VISExitHalf
214 */
215
216 LOAD(prefetch, %o1 + 0x000, #one_read)
217 LOAD(prefetch, %o1 + 0x040, #one_read)
218 LOAD(prefetch, %o1 + 0x080, #one_read)
219
220 /* Align destination on 64-byte boundary. */
221 andcc %o0, (64 - 1), %o4
222 be,pt %XCC, 2f
223 sub %o4, 64, %o4
224 sub %g0, %o4, %o4 ! bytes to align dst
225 sub %o2, %o4, %o2
2261: subcc %o4, 1, %o4
227 EX_LD(LOAD(ldub, %o1, %g1))
228 EX_ST(STORE(stb, %g1, %o0))
229 add %o1, 1, %o1
230 bne,pt %XCC, 1b
231 add %o0, 1, %o0
232
2332:
234 /* Clobbers o5/g1/g2/g3/g7/icc/xcc. We must preserve
235 * o5 from here until we hit VISExitHalf.
236 */
237 VISEntryHalf
238
239 alignaddr %o1, %g0, %g0
240
241 add %o1, (64 - 1), %o4
242 andn %o4, (64 - 1), %o4
243 andn %o2, (64 - 1), %g1
244 sub %o2, %g1, %o2
245
246 and %o1, (64 - 1), %g2
247 add %o1, %g1, %o1
248 sub %o0, %o4, %g3
249 brz,pt %g2, 190f
250 cmp %g2, 32
251 blu,a 5f
252 cmp %g2, 16
253 cmp %g2, 48
254 blu,a 4f
255 cmp %g2, 40
256 cmp %g2, 56
257 blu 170f
258 nop
259 ba,a,pt %xcc, 180f
260
2614: /* 32 <= low bits < 48 */
262 blu 150f
263 nop
264 ba,a,pt %xcc, 160f
2655: /* 0 < low bits < 32 */
266 blu,a 6f
267 cmp %g2, 8
268 cmp %g2, 24
269 blu 130f
270 nop
271 ba,a,pt %xcc, 140f
2726: /* 0 < low bits < 16 */
273 bgeu 120f
274 nop
275 /* fall through for 0 < low bits < 8 */
276110: sub %o4, 64, %g2
277 EX_LD(LOAD_BLK(%g2, %f0))
2781: EX_ST(STORE_INIT(%g0, %o4 + %g3))
279 EX_LD(LOAD_BLK(%o4, %f16))
280 FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
281 EX_ST(STORE_BLK(%f0, %o4 + %g3))
282 FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
283 subcc %g1, 64, %g1
284 add %o4, 64, %o4
285 bne,pt %xcc, 1b
286 LOAD(prefetch, %o4 + 64, #one_read)
287 ba,pt %xcc, 195f
288 nop
289
290120: sub %o4, 56, %g2
291 FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
2921: EX_ST(STORE_INIT(%g0, %o4 + %g3))
293 EX_LD(LOAD_BLK(%o4, %f16))
294 FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
295 EX_ST(STORE_BLK(%f0, %o4 + %g3))
296 FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
297 subcc %g1, 64, %g1
298 add %o4, 64, %o4
299 bne,pt %xcc, 1b
300 LOAD(prefetch, %o4 + 64, #one_read)
301 ba,pt %xcc, 195f
302 nop
303
304130: sub %o4, 48, %g2
305 FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
3061: EX_ST(STORE_INIT(%g0, %o4 + %g3))
307 EX_LD(LOAD_BLK(%o4, %f16))
308 FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
309 EX_ST(STORE_BLK(%f0, %o4 + %g3))
310 FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
311 subcc %g1, 64, %g1
312 add %o4, 64, %o4
313 bne,pt %xcc, 1b
314 LOAD(prefetch, %o4 + 64, #one_read)
315 ba,pt %xcc, 195f
316 nop
317
318140: sub %o4, 40, %g2
319 FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
3201: EX_ST(STORE_INIT(%g0, %o4 + %g3))
321 EX_LD(LOAD_BLK(%o4, %f16))
322 FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
323 EX_ST(STORE_BLK(%f0, %o4 + %g3))
324 FREG_MOVE_5(f22, f24, f26, f28, f30)
325 subcc %g1, 64, %g1
326 add %o4, 64, %o4
327 bne,pt %xcc, 1b
328 LOAD(prefetch, %o4 + 64, #one_read)
329 ba,pt %xcc, 195f
330 nop
331
332150: sub %o4, 32, %g2
333 FREG_LOAD_4(%g2, f0, f2, f4, f6)
3341: EX_ST(STORE_INIT(%g0, %o4 + %g3))
335 EX_LD(LOAD_BLK(%o4, %f16))
336 FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
337 EX_ST(STORE_BLK(%f0, %o4 + %g3))
338 FREG_MOVE_4(f24, f26, f28, f30)
339 subcc %g1, 64, %g1
340 add %o4, 64, %o4
341 bne,pt %xcc, 1b
342 LOAD(prefetch, %o4 + 64, #one_read)
343 ba,pt %xcc, 195f
344 nop
345
346160: sub %o4, 24, %g2
347 FREG_LOAD_3(%g2, f0, f2, f4)
3481: EX_ST(STORE_INIT(%g0, %o4 + %g3))
349 EX_LD(LOAD_BLK(%o4, %f16))
350 FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
351 EX_ST(STORE_BLK(%f0, %o4 + %g3))
352 FREG_MOVE_3(f26, f28, f30)
353 subcc %g1, 64, %g1
354 add %o4, 64, %o4
355 bne,pt %xcc, 1b
356 LOAD(prefetch, %o4 + 64, #one_read)
357 ba,pt %xcc, 195f
358 nop
359
360170: sub %o4, 16, %g2
361 FREG_LOAD_2(%g2, f0, f2)
3621: EX_ST(STORE_INIT(%g0, %o4 + %g3))
363 EX_LD(LOAD_BLK(%o4, %f16))
364 FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
365 EX_ST(STORE_BLK(%f0, %o4 + %g3))
366 FREG_MOVE_2(f28, f30)
367 subcc %g1, 64, %g1
368 add %o4, 64, %o4
369 bne,pt %xcc, 1b
370 LOAD(prefetch, %o4 + 64, #one_read)
371 ba,pt %xcc, 195f
372 nop
373
374180: sub %o4, 8, %g2
375 FREG_LOAD_1(%g2, f0)
3761: EX_ST(STORE_INIT(%g0, %o4 + %g3))
377 EX_LD(LOAD_BLK(%o4, %f16))
378 FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
379 EX_ST(STORE_BLK(%f0, %o4 + %g3))
380 FREG_MOVE_1(f30)
381 subcc %g1, 64, %g1
382 add %o4, 64, %o4
383 bne,pt %xcc, 1b
384 LOAD(prefetch, %o4 + 64, #one_read)
385 ba,pt %xcc, 195f
386 nop
387
388190:
3891: EX_ST(STORE_INIT(%g0, %o4 + %g3))
390 subcc %g1, 64, %g1
391 EX_LD(LOAD_BLK(%o4, %f0))
392 EX_ST(STORE_BLK(%f0, %o4 + %g3))
393 add %o4, 64, %o4
394 bne,pt %xcc, 1b
395 LOAD(prefetch, %o4 + 64, #one_read)
396
397195:
398 add %o4, %g3, %o0
399 membar #Sync
400
401 VISExitHalf
402
403 /* %o2 contains any final bytes still needed to be copied
404 * over. If anything is left, we copy it one byte at a time.
405 */
406 brz,pt %o2, 85f
407 sub %o0, %o1, %o3
408 ba,a,pt %XCC, 90f
409
410 .align 64
41175: /* 16 < len <= 64 */
412 bne,pn %XCC, 75f
413 sub %o0, %o1, %o3
414
41572:
416 andn %o2, 0xf, %o4
417 and %o2, 0xf, %o2
4181: subcc %o4, 0x10, %o4
419 EX_LD(LOAD(ldx, %o1, %o5))
420 add %o1, 0x08, %o1
421 EX_LD(LOAD(ldx, %o1, %g1))
422 sub %o1, 0x08, %o1
423 EX_ST(STORE(stx, %o5, %o1 + %o3))
424 add %o1, 0x8, %o1
425 EX_ST(STORE(stx, %g1, %o1 + %o3))
426 bgu,pt %XCC, 1b
427 add %o1, 0x8, %o1
42873: andcc %o2, 0x8, %g0
429 be,pt %XCC, 1f
430 nop
431 sub %o2, 0x8, %o2
432 EX_LD(LOAD(ldx, %o1, %o5))
433 EX_ST(STORE(stx, %o5, %o1 + %o3))
434 add %o1, 0x8, %o1
4351: andcc %o2, 0x4, %g0
436 be,pt %XCC, 1f
437 nop
438 sub %o2, 0x4, %o2
439 EX_LD(LOAD(lduw, %o1, %o5))
440 EX_ST(STORE(stw, %o5, %o1 + %o3))
441 add %o1, 0x4, %o1
4421: cmp %o2, 0
443 be,pt %XCC, 85f
444 nop
445 ba,pt %xcc, 90f
446 nop
447
44875:
449 andcc %o0, 0x7, %g1
450 sub %g1, 0x8, %g1
451 be,pn %icc, 2f
452 sub %g0, %g1, %g1
453 sub %o2, %g1, %o2
454
4551: subcc %g1, 1, %g1
456 EX_LD(LOAD(ldub, %o1, %o5))
457 EX_ST(STORE(stb, %o5, %o1 + %o3))
458 bgu,pt %icc, 1b
459 add %o1, 1, %o1
460
4612: add %o1, %o3, %o0
462 andcc %o1, 0x7, %g1
463 bne,pt %icc, 8f
464 sll %g1, 3, %g1
465
466 cmp %o2, 16
467 bgeu,pt %icc, 72b
468 nop
469 ba,a,pt %xcc, 73b
470
4718: mov 64, %o3
472 andn %o1, 0x7, %o1
473 EX_LD(LOAD(ldx, %o1, %g2))
474 sub %o3, %g1, %o3
475 andn %o2, 0x7, %o4
476 sllx %g2, %g1, %g2
4771: add %o1, 0x8, %o1
478 EX_LD(LOAD(ldx, %o1, %g3))
479 subcc %o4, 0x8, %o4
480 srlx %g3, %o3, %o5
481 or %o5, %g2, %o5
482 EX_ST(STORE(stx, %o5, %o0))
483 add %o0, 0x8, %o0
484 bgu,pt %icc, 1b
485 sllx %g3, %g1, %g2
486
487 srl %g1, 3, %g1
488 andcc %o2, 0x7, %o2
489 be,pn %icc, 85f
490 add %o1, %g1, %o1
491 ba,pt %xcc, 90f
492 sub %o0, %o1, %o3
493
494 .align 64
49580: /* 0 < len <= 16 */
496 andcc %o3, 0x3, %g0
497 bne,pn %XCC, 90f
498 sub %o0, %o1, %o3
499
5001:
501 subcc %o2, 4, %o2
502 EX_LD(LOAD(lduw, %o1, %g1))
503 EX_ST(STORE(stw, %g1, %o1 + %o3))
504 bgu,pt %XCC, 1b
505 add %o1, 4, %o1
506
50785: retl
508 mov EX_RETVAL(GLOBAL_SPARE), %o0
509
510 .align 32
51190:
512 subcc %o2, 1, %o2
513 EX_LD(LOAD(ldub, %o1, %g1))
514 EX_ST(STORE(stb, %g1, %o1 + %o3))
515 bgu,pt %XCC, 90b
516 add %o1, 1, %o1
517 retl
518 mov EX_RETVAL(GLOBAL_SPARE), %o0
519
520 .size FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/NG2page.S b/arch/sparc64/lib/NG2page.S
new file mode 100644
index 000000000000..73b6b7c72cbf
--- /dev/null
+++ b/arch/sparc64/lib/NG2page.S
@@ -0,0 +1,61 @@
1/* NG2page.S: Niagara-2 optimized clear and copy page.
2 *
3 * Copyright (C) 2007 (davem@davemloft.net)
4 */
5
6#include <asm/asi.h>
7#include <asm/page.h>
8#include <asm/visasm.h>
9
10 .text
11 .align 32
12
13 /* This is heavily simplified from the sun4u variants
14 * because Niagara-2 does not have any D-cache aliasing issues.
15 */
16NG2copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
17 prefetch [%o1 + 0x00], #one_read
18 prefetch [%o1 + 0x40], #one_read
19 VISEntryHalf
20 set PAGE_SIZE, %g7
21 sub %o0, %o1, %g3
221: stxa %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
23 subcc %g7, 64, %g7
24 ldda [%o1] ASI_BLK_P, %f0
25 stda %f0, [%o1 + %g3] ASI_BLK_P
26 add %o1, 64, %o1
27 bne,pt %xcc, 1b
28 prefetch [%o1 + 0x40], #one_read
29 membar #Sync
30 VISExitHalf
31 retl
32 nop
33
34#define BRANCH_ALWAYS 0x10680000
35#define NOP 0x01000000
36#define NG_DO_PATCH(OLD, NEW) \
37 sethi %hi(NEW), %g1; \
38 or %g1, %lo(NEW), %g1; \
39 sethi %hi(OLD), %g2; \
40 or %g2, %lo(OLD), %g2; \
41 sub %g1, %g2, %g1; \
42 sethi %hi(BRANCH_ALWAYS), %g3; \
43 sll %g1, 11, %g1; \
44 srl %g1, 11 + 2, %g1; \
45 or %g3, %lo(BRANCH_ALWAYS), %g3; \
46 or %g3, %g1, %g3; \
47 stw %g3, [%g2]; \
48 sethi %hi(NOP), %g3; \
49 or %g3, %lo(NOP), %g3; \
50 stw %g3, [%g2 + 0x4]; \
51 flush %g2;
52
53 .globl niagara2_patch_pageops
54 .type niagara2_patch_pageops,#function
55niagara2_patch_pageops:
56 NG_DO_PATCH(copy_user_page, NG2copy_user_page)
57 NG_DO_PATCH(_clear_page, NGclear_page)
58 NG_DO_PATCH(clear_user_page, NGclear_user_page)
59 retl
60 nop
61 .size niagara2_patch_pageops,.-niagara2_patch_pageops
diff --git a/arch/sparc64/lib/NG2patch.S b/arch/sparc64/lib/NG2patch.S
new file mode 100644
index 000000000000..28c36f06a6d1
--- /dev/null
+++ b/arch/sparc64/lib/NG2patch.S
@@ -0,0 +1,33 @@
1/* NG2patch.S: Patch Ultra-I routines with Niagara-2 variant.
2 *
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4 */
5
6#define BRANCH_ALWAYS 0x10680000
7#define NOP 0x01000000
8#define NG_DO_PATCH(OLD, NEW) \
9 sethi %hi(NEW), %g1; \
10 or %g1, %lo(NEW), %g1; \
11 sethi %hi(OLD), %g2; \
12 or %g2, %lo(OLD), %g2; \
13 sub %g1, %g2, %g1; \
14 sethi %hi(BRANCH_ALWAYS), %g3; \
15 sll %g1, 11, %g1; \
16 srl %g1, 11 + 2, %g1; \
17 or %g3, %lo(BRANCH_ALWAYS), %g3; \
18 or %g3, %g1, %g3; \
19 stw %g3, [%g2]; \
20 sethi %hi(NOP), %g3; \
21 or %g3, %lo(NOP), %g3; \
22 stw %g3, [%g2 + 0x4]; \
23 flush %g2;
24
25 .globl niagara2_patch_copyops
26 .type niagara2_patch_copyops,#function
27niagara2_patch_copyops:
28 NG_DO_PATCH(memcpy, NG2memcpy)
29 NG_DO_PATCH(___copy_from_user, NG2copy_from_user)
30 NG_DO_PATCH(___copy_to_user, NG2copy_to_user)
31 retl
32 nop
33 .size niagara2_patch_copyops,.-niagara2_patch_copyops
diff --git a/arch/sparc64/lib/NGpage.S b/arch/sparc64/lib/NGpage.S
index 8ce3a0c9c537..428920de05ba 100644
--- a/arch/sparc64/lib/NGpage.S
+++ b/arch/sparc64/lib/NGpage.S
@@ -45,6 +45,7 @@ NGcopy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
45 retl 45 retl
46 nop 46 nop
47 47
48 .globl NGclear_page, NGclear_user_page
48NGclear_page: /* %o0=dest */ 49NGclear_page: /* %o0=dest */
49NGclear_user_page: /* %o0=dest, %o1=vaddr */ 50NGclear_user_page: /* %o0=dest, %o1=vaddr */
50 mov 8, %g1 51 mov 8, %g1