History

sparc64: fix FP corruption in user copy functions

Short story: Exception handlers used by some copy_to_user() and copy_from_user() functions do not diligently clean up floating point register usage, and this can result in a user process seeing invalid values in floating point registers. This sometimes makes the process fail. Long story: Several cpu-specific (NG4, NG2, U1, U3) memcpy functions use floating point registers and VIS alignaddr/faligndata to accelerate data copying when source and dest addresses don't align well. Linux uses a lazy scheme for saving floating point registers; It is not done upon entering the kernel since it's a very expensive operation. Rather, it is done only when needed. If the kernel ends up not using FP regs during the course of some trap or system call, then it can return to user space without saving or restoring them. The various memcpy functions begin their FP code with VISEntry (or a variation thereof), which saves the FP regs. They conclude their FP code with VISExit (or a variation) which essentially marks the FP regs "clean", ie, they contain no unsaved values. fprs.FPRS_FEF is turned off so that a lazy restore will be triggered when/if the user process accesses floating point regs again. The bug is that the user copy variants of memcpy, copy_from_user() and copy_to_user(), employ an exception handling mechanism to detect faults when accessing user space addresses, and when this handler is invoked, an immediate return from the function is forced, and VISExit is not executed, thus leaving the fprs register in an indeterminate state, but often with fprs.FPRS_FEF set and one or more dirty bits. This results in a return to user space with invalid values in the FP regs, and since fprs.FPRS_FEF is on, no lazy restore occurs. This bug affects copy_to_user() and copy_from_user() for NG4, NG2, U3, and U1. All are fixed by using a new exception handler for those loads and stores that are done during the time between VISEnter and VISExit. n.b. In NG4memcpy, the problematic code can be triggered by a copy size greater than 128 bytes and an unaligned source address. This bug is known to be the cause of random user process memory corruptions while perf is running with the callgraph option (ie, perf record -g). This occurs because perf uses copy_from_user() to read user stacks, and may fault when it follows a stack frame pointer off to an invalid page. Validation checks on the stack address just obscure the underlying problem.

Rob Gardner committed 10 years ago

Commit a7c57241 parent 833526913 files · +235 −134Browse files

Unified · Split

13 files
  1. arch/sparc/kernel/head_64.S +13 −0
  2. arch/sparc/lib/NG2copy_from_user.S +8 −0
  3. arch/sparc/lib/NG2copy_to_user.S +8 −0
  4. arch/sparc/lib/NG2memcpy.S +62 −56
  5. arch/sparc/lib/NG4copy_from_user.S +8 −0
  6. arch/sparc/lib/NG4copy_to_user.S +8 −0
  7. arch/sparc/lib/NG4memcpy.S +23 −17
  8. arch/sparc/lib/U1copy_from_user.S +8 −0
  9. arch/sparc/lib/U1copy_to_user.S +8 −0
  10. arch/sparc/lib/U1memcpy.S +27 −21
  11. arch/sparc/lib/U3copy_from_user.S +8 −0
  12. arch/sparc/lib/U3copy_to_user.S +8 −0
  13. arch/sparc/lib/U3memcpy.S +46 −40
arch/sparc/kernel/head_64.S+13−0
@@ -946,6 +946,12 @@ ENTRY(__retl_one) · 945 unmodified lines
946946 mov 1, %o0
947947 ENDPROC(__retl_one)
948948
949+ENTRY(__retl_one_fp)
950+ VISExitHalf
951+ retl
952+ mov 1, %o0
953+ENDPROC(__retl_one_fp)
954+
949955 ENTRY(__ret_one_asi)
950956 wr %g0, ASI_AIUS, %asi
951957 ret
@@ -958,6 +964,13 @@ ENTRY(__retl_one_asi) · 6 unmodified lines
958964 mov 1, %o0
959965 ENDPROC(__retl_one_asi)
960966
967+ENTRY(__retl_one_asi_fp)
968+ wr %g0, ASI_AIUS, %asi
969+ VISExitHalf
970+ retl
971+ mov 1, %o0
972+ENDPROC(__retl_one_asi_fp)
973+
961974 ENTRY(__retl_o1)
962975 retl
963976 mov %o1, %o0
arch/sparc/lib/NG2copy_from_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_LD_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_asi_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #ifndef ASI_AIUS
1523 #define ASI_AIUS 0x11
1624 #endif
arch/sparc/lib/NG2copy_to_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_ST_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_asi_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #ifndef ASI_AIUS
1523 #define ASI_AIUS 0x11
1624 #endif
arch/sparc/lib/NG2memcpy.S+62−56
@@ -34,10 +34,16 @@ · 33 unmodified lines
3434 #ifndef EX_LD
3535 #define EX_LD(x) x
3636 #endif
37+#ifndef EX_LD_FP
38+#define EX_LD_FP(x) x
39+#endif
3740
3841 #ifndef EX_ST
3942 #define EX_ST(x) x
4043 #endif
44+#ifndef EX_ST_FP
45+#define EX_ST_FP(x) x
46+#endif
4147
4248 #ifndef EX_RETVAL
4349 #define EX_RETVAL(x) x
@@ -134,40 +140,40 @@ · 90 unmodified lines
134140 fsrc2 %x6, %f12; \
135141 fsrc2 %x7, %f14;
136142 #define FREG_LOAD_1(base, x0) \
137− EX_LD(LOAD(ldd, base + 0x00, %x0))
143+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0))
138144 #define FREG_LOAD_2(base, x0, x1) \
139− EX_LD(LOAD(ldd, base + 0x00, %x0)); \
140− EX_LD(LOAD(ldd, base + 0x08, %x1));
145+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
146+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1));
141147 #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));
148+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
149+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
150+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2));
145151 #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));
152+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
153+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
154+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
155+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3));
150156 #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));
157+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
158+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
159+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
160+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
161+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4));
156162 #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+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
164+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
165+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
166+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
167+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
168+ EX_LD_FP(LOAD(ldd, base + 0x28, %x5));
163169 #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));
170+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
171+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
172+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
173+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
174+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
175+ EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); \
176+ EX_LD_FP(LOAD(ldd, base + 0x30, %x6));
171177
172178 .register %g2,#scratch
173179 .register %g3,#scratch
@@ -275,11 +281,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 101 unmodified lines
275281 nop
276282 /* fall through for 0 < low bits < 8 */
277283 110: sub %o4, 64, %g2
278− EX_LD(LOAD_BLK(%g2, %f0))
279−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
280− EX_LD(LOAD_BLK(%o4, %f16))
284+ EX_LD_FP(LOAD_BLK(%g2, %f0))
285+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
286+ EX_LD_FP(LOAD_BLK(%o4, %f16))
281287 FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
282− EX_ST(STORE_BLK(%f0, %o4 + %g3))
288+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
283289 FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
284290 subcc %g1, 64, %g1
285291 add %o4, 64, %o4
@@ -290,10 +296,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
290296
291297 120: sub %o4, 56, %g2
292298 FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
293−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
294− EX_LD(LOAD_BLK(%o4, %f16))
299+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
300+ EX_LD_FP(LOAD_BLK(%o4, %f16))
295301 FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
296− EX_ST(STORE_BLK(%f0, %o4 + %g3))
302+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
297303 FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
298304 subcc %g1, 64, %g1
299305 add %o4, 64, %o4
@@ -304,10 +310,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
304310
305311 130: sub %o4, 48, %g2
306312 FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
307−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
308− EX_LD(LOAD_BLK(%o4, %f16))
313+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
314+ EX_LD_FP(LOAD_BLK(%o4, %f16))
309315 FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
310− EX_ST(STORE_BLK(%f0, %o4 + %g3))
316+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
311317 FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
312318 subcc %g1, 64, %g1
313319 add %o4, 64, %o4
@@ -318,10 +324,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
318324
319325 140: sub %o4, 40, %g2
320326 FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
321−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
322− EX_LD(LOAD_BLK(%o4, %f16))
327+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
328+ EX_LD_FP(LOAD_BLK(%o4, %f16))
323329 FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
324− EX_ST(STORE_BLK(%f0, %o4 + %g3))
330+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
325331 FREG_MOVE_5(f22, f24, f26, f28, f30)
326332 subcc %g1, 64, %g1
327333 add %o4, 64, %o4
@@ -332,10 +338,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
332338
333339 150: sub %o4, 32, %g2
334340 FREG_LOAD_4(%g2, f0, f2, f4, f6)
335−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
336− EX_LD(LOAD_BLK(%o4, %f16))
341+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
342+ EX_LD_FP(LOAD_BLK(%o4, %f16))
337343 FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
338− EX_ST(STORE_BLK(%f0, %o4 + %g3))
344+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
339345 FREG_MOVE_4(f24, f26, f28, f30)
340346 subcc %g1, 64, %g1
341347 add %o4, 64, %o4
@@ -346,10 +352,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
346352
347353 160: sub %o4, 24, %g2
348354 FREG_LOAD_3(%g2, f0, f2, f4)
349−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
350− EX_LD(LOAD_BLK(%o4, %f16))
355+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
356+ EX_LD_FP(LOAD_BLK(%o4, %f16))
351357 FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
352− EX_ST(STORE_BLK(%f0, %o4 + %g3))
358+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
353359 FREG_MOVE_3(f26, f28, f30)
354360 subcc %g1, 64, %g1
355361 add %o4, 64, %o4
@@ -360,10 +366,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
360366
361367 170: sub %o4, 16, %g2
362368 FREG_LOAD_2(%g2, f0, f2)
363−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
364− EX_LD(LOAD_BLK(%o4, %f16))
369+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
370+ EX_LD_FP(LOAD_BLK(%o4, %f16))
365371 FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
366− EX_ST(STORE_BLK(%f0, %o4 + %g3))
372+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
367373 FREG_MOVE_2(f28, f30)
368374 subcc %g1, 64, %g1
369375 add %o4, 64, %o4
@@ -374,10 +380,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
374380
375381 180: sub %o4, 8, %g2
376382 FREG_LOAD_1(%g2, f0)
377−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
378− EX_LD(LOAD_BLK(%o4, %f16))
383+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
384+ EX_LD_FP(LOAD_BLK(%o4, %f16))
379385 FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
380− EX_ST(STORE_BLK(%f0, %o4 + %g3))
386+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
381387 FREG_MOVE_1(f30)
382388 subcc %g1, 64, %g1
383389 add %o4, 64, %o4
@@ -387,10 +393,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 3 unmodified lines
387393 nop
388394
389395 190:
390−1: EX_ST(STORE_INIT(%g0, %o4 + %g3))
396+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
391397 subcc %g1, 64, %g1
392− EX_LD(LOAD_BLK(%o4, %f0))
393− EX_ST(STORE_BLK(%f0, %o4 + %g3))
398+ EX_LD_FP(LOAD_BLK(%o4, %f0))
399+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
394400 add %o4, 64, %o4
395401 bne,pt %xcc, 1b
396402 LOAD(prefetch, %o4 + 64, #one_read)
arch/sparc/lib/NG4copy_from_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_LD_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_asi_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #ifndef ASI_AIUS
1523 #define ASI_AIUS 0x11
1624 #endif
arch/sparc/lib/NG4copy_to_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_ST_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_asi_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #ifndef ASI_AIUS
1523 #define ASI_AIUS 0x11
1624 #endif
arch/sparc/lib/NG4memcpy.S+23−17
@@ -48,10 +48,16 @@ · 47 unmodified lines
4848 #ifndef EX_LD
4949 #define EX_LD(x) x
5050 #endif
51+#ifndef EX_LD_FP
52+#define EX_LD_FP(x) x
53+#endif
5154
5255 #ifndef EX_ST
5356 #define EX_ST(x) x
5457 #endif
58+#ifndef EX_ST_FP
59+#define EX_ST_FP(x) x
60+#endif
5561
5662 #ifndef EX_RETVAL
5763 #define EX_RETVAL(x) x
@@ -210,17 +216,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 152 unmodified lines
210216 sub %o2, %o4, %o2
211217 alignaddr %o1, %g0, %g1
212218 add %o1, %o4, %o1
213− EX_LD(LOAD(ldd, %g1 + 0x00, %f0))
214−1: EX_LD(LOAD(ldd, %g1 + 0x08, %f2))
219+ EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0))
220+1: EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2))
215221 subcc %o4, 0x40, %o4
216− EX_LD(LOAD(ldd, %g1 + 0x10, %f4))
217− EX_LD(LOAD(ldd, %g1 + 0x18, %f6))
218− EX_LD(LOAD(ldd, %g1 + 0x20, %f8))
219− EX_LD(LOAD(ldd, %g1 + 0x28, %f10))
220− EX_LD(LOAD(ldd, %g1 + 0x30, %f12))
221− EX_LD(LOAD(ldd, %g1 + 0x38, %f14))
222+ EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4))
223+ EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6))
224+ EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8))
225+ EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10))
226+ EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12))
227+ EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14))
222228 faligndata %f0, %f2, %f16
223− EX_LD(LOAD(ldd, %g1 + 0x40, %f0))
229+ EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0))
224230 faligndata %f2, %f4, %f18
225231 add %g1, 0x40, %g1
226232 faligndata %f4, %f6, %f20
@@ -229,14 +235,14 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 2 unmodified lines
229235 faligndata %f10, %f12, %f26
230236 faligndata %f12, %f14, %f28
231237 faligndata %f14, %f0, %f30
232− EX_ST(STORE(std, %f16, %o0 + 0x00))
233− EX_ST(STORE(std, %f18, %o0 + 0x08))
234− EX_ST(STORE(std, %f20, %o0 + 0x10))
235− EX_ST(STORE(std, %f22, %o0 + 0x18))
236− EX_ST(STORE(std, %f24, %o0 + 0x20))
237− EX_ST(STORE(std, %f26, %o0 + 0x28))
238− EX_ST(STORE(std, %f28, %o0 + 0x30))
239− EX_ST(STORE(std, %f30, %o0 + 0x38))
238+ EX_ST_FP(STORE(std, %f16, %o0 + 0x00))
239+ EX_ST_FP(STORE(std, %f18, %o0 + 0x08))
240+ EX_ST_FP(STORE(std, %f20, %o0 + 0x10))
241+ EX_ST_FP(STORE(std, %f22, %o0 + 0x18))
242+ EX_ST_FP(STORE(std, %f24, %o0 + 0x20))
243+ EX_ST_FP(STORE(std, %f26, %o0 + 0x28))
244+ EX_ST_FP(STORE(std, %f28, %o0 + 0x30))
245+ EX_ST_FP(STORE(std, %f30, %o0 + 0x38))
240246 add %o0, 0x40, %o0
241247 bne,pt %icc, 1b
242248 LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
arch/sparc/lib/U1copy_from_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_LD_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #define FUNC_NAME ___copy_from_user
1523 #define LOAD(type,addr,dest) type##a [addr] %asi, dest
1624 #define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS, dest
arch/sparc/lib/U1copy_to_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_ST_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #define FUNC_NAME ___copy_to_user
1523 #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS
1624 #define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS
arch/sparc/lib/U1memcpy.S+27−21
@@ -25,10 +25,16 @@ · 24 unmodified lines
2525 #ifndef EX_LD
2626 #define EX_LD(x) x
2727 #endif
28+#ifndef EX_LD_FP
29+#define EX_LD_FP(x) x
30+#endif
2831
2932 #ifndef EX_ST
3033 #define EX_ST(x) x
3134 #endif
35+#ifndef EX_ST_FP
36+#define EX_ST_FP(x) x
37+#endif
3238
3339 #ifndef EX_RETVAL
3440 #define EX_RETVAL(x) x
@@ -73,8 +79,8 @@ · 38 unmodified lines
7379 faligndata %f8, %f9, %f62;
7480
7581 #define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \
76− EX_LD(LOAD_BLK(%src, %fdest)); \
77− EX_ST(STORE_BLK(%fsrc, %dest)); \
82+ EX_LD_FP(LOAD_BLK(%src, %fdest)); \
83+ EX_ST_FP(STORE_BLK(%fsrc, %dest)); \
7884 add %src, 0x40, %src; \
7985 subcc %len, 0x40, %len; \
8086 be,pn %xcc, jmptgt; \
@@ -89,12 +95,12 @@ · 8 unmodified lines
8995
9096 #define DO_SYNC membar #Sync;
9197 #define STORE_SYNC(dest, fsrc) \
92− EX_ST(STORE_BLK(%fsrc, %dest)); \
98+ EX_ST_FP(STORE_BLK(%fsrc, %dest)); \
9399 add %dest, 0x40, %dest; \
94100 DO_SYNC
95101
96102 #define STORE_JUMP(dest, fsrc, target) \
97− EX_ST(STORE_BLK(%fsrc, %dest)); \
103+ EX_ST_FP(STORE_BLK(%fsrc, %dest)); \
98104 add %dest, 0x40, %dest; \
99105 ba,pt %xcc, target; \
100106 nop;
@@ -103,7 +109,7 @@ · 2 unmodified lines
103109 subcc %left, 8, %left;\
104110 bl,pn %xcc, 95f; \
105111 faligndata %f0, %f1, %f48; \
106− EX_ST(STORE(std, %f48, %dest)); \
112+ EX_ST_FP(STORE(std, %f48, %dest)); \
107113 add %dest, 8, %dest;
108114
109115 #define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \
@@ -160,8 +166,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 50 unmodified lines
160166 and %g2, 0x38, %g2
161167
162168 1: subcc %g1, 0x1, %g1
163− EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
164− EX_ST(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
169+ EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
170+ EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
165171 bgu,pt %XCC, 1b
166172 add %o1, 0x1, %o1
167173
@@ -172,20 +178,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
172178 be,pt %icc, 3f
173179 alignaddr %o1, %g0, %o1
174180
175− EX_LD(LOAD(ldd, %o1, %f4))
176−1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
181+ EX_LD_FP(LOAD(ldd, %o1, %f4))
182+1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
177183 add %o1, 0x8, %o1
178184 subcc %g2, 0x8, %g2
179185 faligndata %f4, %f6, %f0
180− EX_ST(STORE(std, %f0, %o0))
186+ EX_ST_FP(STORE(std, %f0, %o0))
181187 be,pn %icc, 3f
182188 add %o0, 0x8, %o0
183189
184− EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
190+ EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
185191 add %o1, 0x8, %o1
186192 subcc %g2, 0x8, %g2
187193 faligndata %f6, %f4, %f0
188− EX_ST(STORE(std, %f0, %o0))
194+ EX_ST_FP(STORE(std, %f0, %o0))
189195 bne,pt %icc, 1b
190196 add %o0, 0x8, %o0
191197
@@ -208,13 +214,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 16 unmodified lines
208214 add %g1, %GLOBAL_SPARE, %g1
209215 subcc %o2, %g3, %o2
210216
211− EX_LD(LOAD_BLK(%o1, %f0))
217+ EX_LD_FP(LOAD_BLK(%o1, %f0))
212218 add %o1, 0x40, %o1
213219 add %g1, %g3, %g1
214− EX_LD(LOAD_BLK(%o1, %f16))
220+ EX_LD_FP(LOAD_BLK(%o1, %f16))
215221 add %o1, 0x40, %o1
216222 sub %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
217− EX_LD(LOAD_BLK(%o1, %f32))
223+ EX_LD_FP(LOAD_BLK(%o1, %f32))
218224 add %o1, 0x40, %o1
219225
220226 /* There are 8 instances of the unrolled loop,
@@ -426,28 +432,28 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 205 unmodified lines
426432 62: FINISH_VISCHUNK(o0, f44, f46, g3)
427433 63: UNEVEN_VISCHUNK_LAST(o0, f46, f0, g3)
428434
429−93: EX_LD(LOAD(ldd, %o1, %f2))
435+93: EX_LD_FP(LOAD(ldd, %o1, %f2))
430436 add %o1, 8, %o1
431437 subcc %g3, 8, %g3
432438 faligndata %f0, %f2, %f8
433− EX_ST(STORE(std, %f8, %o0))
439+ EX_ST_FP(STORE(std, %f8, %o0))
434440 bl,pn %xcc, 95f
435441 add %o0, 8, %o0
436− EX_LD(LOAD(ldd, %o1, %f0))
442+ EX_LD_FP(LOAD(ldd, %o1, %f0))
437443 add %o1, 8, %o1
438444 subcc %g3, 8, %g3
439445 faligndata %f2, %f0, %f8
440− EX_ST(STORE(std, %f8, %o0))
446+ EX_ST_FP(STORE(std, %f8, %o0))
441447 bge,pt %xcc, 93b
442448 add %o0, 8, %o0
443449
444450 95: brz,pt %o2, 2f
445451 mov %g1, %o1
446452
447−1: EX_LD(LOAD(ldub, %o1, %o3))
453+1: EX_LD_FP(LOAD(ldub, %o1, %o3))
448454 add %o1, 1, %o1
449455 subcc %o2, 1, %o2
450− EX_ST(STORE(stb, %o3, %o0))
456+ EX_ST_FP(STORE(stb, %o3, %o0))
451457 bne,pt %xcc, 1b
452458 add %o0, 1, %o0
453459
arch/sparc/lib/U3copy_from_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_LD_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #define FUNC_NAME U3copy_from_user
1523 #define LOAD(type,addr,dest) type##a [addr] %asi, dest
1624 #define EX_RETVAL(x) 0
arch/sparc/lib/U3copy_to_user.S+8−0
@@ -11,6 +11,14 @@ · 10 unmodified lines
1111 .text; \
1212 .align 4;
1313
14+#define EX_ST_FP(x) \
15+98: x; \
16+ .section __ex_table,"a";\
17+ .align 4; \
18+ .word 98b, __retl_one_fp;\
19+ .text; \
20+ .align 4;
21+
1422 #define FUNC_NAME U3copy_to_user
1523 #define STORE(type,src,addr) type##a src, [addr] ASI_AIUS
1624 #define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS
arch/sparc/lib/U3memcpy.S+46−40
@@ -24,10 +24,16 @@ · 23 unmodified lines
2424 #ifndef EX_LD
2525 #define EX_LD(x) x
2626 #endif
27+#ifndef EX_LD_FP
28+#define EX_LD_FP(x) x
29+#endif
2730
2831 #ifndef EX_ST
2932 #define EX_ST(x) x
3033 #endif
34+#ifndef EX_ST_FP
35+#define EX_ST_FP(x) x
36+#endif
3137
3238 #ifndef EX_RETVAL
3339 #define EX_RETVAL(x) x
@@ -120,8 +126,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 86 unmodified lines
120126 and %g2, 0x38, %g2
121127
122128 1: subcc %g1, 0x1, %g1
123− EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
124− EX_ST(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
129+ EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
130+ EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
125131 bgu,pt %XCC, 1b
126132 add %o1, 0x1, %o1
127133
@@ -132,20 +138,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
132138 be,pt %icc, 3f
133139 alignaddr %o1, %g0, %o1
134140
135− EX_LD(LOAD(ldd, %o1, %f4))
136−1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
141+ EX_LD_FP(LOAD(ldd, %o1, %f4))
142+1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
137143 add %o1, 0x8, %o1
138144 subcc %g2, 0x8, %g2
139145 faligndata %f4, %f6, %f0
140− EX_ST(STORE(std, %f0, %o0))
146+ EX_ST_FP(STORE(std, %f0, %o0))
141147 be,pn %icc, 3f
142148 add %o0, 0x8, %o0
143149
144− EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
150+ EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
145151 add %o1, 0x8, %o1
146152 subcc %g2, 0x8, %g2
147153 faligndata %f6, %f4, %f2
148− EX_ST(STORE(std, %f2, %o0))
154+ EX_ST_FP(STORE(std, %f2, %o0))
149155 bne,pt %icc, 1b
150156 add %o0, 0x8, %o0
151157
@@ -155,25 +161,25 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 3 unmodified lines
155161 LOAD(prefetch, %o1 + 0x080, #one_read)
156162 LOAD(prefetch, %o1 + 0x0c0, #one_read)
157163 LOAD(prefetch, %o1 + 0x100, #one_read)
158− EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
164+ EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0))
159165 LOAD(prefetch, %o1 + 0x140, #one_read)
160− EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
166+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
161167 LOAD(prefetch, %o1 + 0x180, #one_read)
162− EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
168+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
163169 LOAD(prefetch, %o1 + 0x1c0, #one_read)
164170 faligndata %f0, %f2, %f16
165− EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
171+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
166172 faligndata %f2, %f4, %f18
167− EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
173+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
168174 faligndata %f4, %f6, %f20
169− EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
175+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
170176 faligndata %f6, %f8, %f22
171177
172− EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
178+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
173179 faligndata %f8, %f10, %f24
174− EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
180+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
175181 faligndata %f10, %f12, %f26
176− EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
182+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
177183
178184 subcc GLOBAL_SPARE, 0x80, GLOBAL_SPARE
179185 add %o1, 0x40, %o1
@@ -184,26 +190,26 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 4 unmodified lines
184190
185191 .align 64
186192 1:
187− EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
193+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
188194 faligndata %f12, %f14, %f28
189− EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
195+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
190196 faligndata %f14, %f0, %f30
191− EX_ST(STORE_BLK(%f16, %o0))
192− EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
197+ EX_ST_FP(STORE_BLK(%f16, %o0))
198+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
193199 faligndata %f0, %f2, %f16
194200 add %o0, 0x40, %o0
195201
196− EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
202+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
197203 faligndata %f2, %f4, %f18
198− EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
204+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
199205 faligndata %f4, %f6, %f20
200− EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
206+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
201207 subcc %o3, 0x01, %o3
202208 faligndata %f6, %f8, %f22
203− EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
209+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
204210
205211 faligndata %f8, %f10, %f24
206− EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
212+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
207213 LOAD(prefetch, %o1 + 0x1c0, #one_read)
208214 faligndata %f10, %f12, %f26
209215 bg,pt %XCC, 1b
@@ -211,29 +217,29 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 1 unmodified line
211217
212218 /* Finally we copy the last full 64-byte block. */
213219 2:
214− EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
220+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
215221 faligndata %f12, %f14, %f28
216− EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
222+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
217223 faligndata %f14, %f0, %f30
218− EX_ST(STORE_BLK(%f16, %o0))
219− EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
224+ EX_ST_FP(STORE_BLK(%f16, %o0))
225+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
220226 faligndata %f0, %f2, %f16
221− EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
227+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
222228 faligndata %f2, %f4, %f18
223− EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
229+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
224230 faligndata %f4, %f6, %f20
225− EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
231+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
226232 faligndata %f6, %f8, %f22
227− EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
233+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
228234 faligndata %f8, %f10, %f24
229235 cmp %g1, 0
230236 be,pt %XCC, 1f
231237 add %o0, 0x40, %o0
232− EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
238+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
233239 1: faligndata %f10, %f12, %f26
234240 faligndata %f12, %f14, %f28
235241 faligndata %f14, %f0, %f30
236− EX_ST(STORE_BLK(%f16, %o0))
242+ EX_ST_FP(STORE_BLK(%f16, %o0))
237243 add %o0, 0x40, %o0
238244 add %o1, 0x40, %o1
239245 membar #Sync
@@ -253,20 +259,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ · 13 unmodified lines
253259
254260 sub %o2, %g2, %o2
255261 be,a,pt %XCC, 1f
256− EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
262+ EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0))
257263
258−1: EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
264+1: EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2))
259265 add %o1, 0x8, %o1
260266 subcc %g2, 0x8, %g2
261267 faligndata %f0, %f2, %f8
262− EX_ST(STORE(std, %f8, %o0))
268+ EX_ST_FP(STORE(std, %f8, %o0))
263269 be,pn %XCC, 2f
264270 add %o0, 0x8, %o0
265− EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
271+ EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0))
266272 add %o1, 0x8, %o1
267273 subcc %g2, 0x8, %g2
268274 faligndata %f2, %f0, %f8
269− EX_ST(STORE(std, %f8, %o0))
275+ EX_ST_FP(STORE(std, %f8, %o0))
270276 bne,pn %XCC, 1b
271277 add %o0, 0x8, %o0
272278