aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/lib')
-rw-r--r--arch/sparc64/lib/VISsave.S8
-rw-r--r--arch/sparc64/lib/strncpy_from_user.S16
-rw-r--r--arch/sparc64/lib/user_fixup.c63
3 files changed, 40 insertions, 47 deletions
diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S
index 4e18989bd602..a0ded5c5aa5c 100644
--- a/arch/sparc64/lib/VISsave.S
+++ b/arch/sparc64/lib/VISsave.S
@@ -59,15 +59,17 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
59 be,pn %icc, 9b 59 be,pn %icc, 9b
60 add %g6, TI_FPREGS, %g2 60 add %g6, TI_FPREGS, %g2
61 andcc %o5, FPRS_DL, %g0 61 andcc %o5, FPRS_DL, %g0
62 membar #StoreStore | #LoadStore
63 62
64 be,pn %icc, 4f 63 be,pn %icc, 4f
65 add %g6, TI_FPREGS+0x40, %g3 64 add %g6, TI_FPREGS+0x40, %g3
65 membar #Sync
66 stda %f0, [%g2 + %g1] ASI_BLK_P 66 stda %f0, [%g2 + %g1] ASI_BLK_P
67 stda %f16, [%g3 + %g1] ASI_BLK_P 67 stda %f16, [%g3 + %g1] ASI_BLK_P
68 membar #Sync
68 andcc %o5, FPRS_DU, %g0 69 andcc %o5, FPRS_DU, %g0
69 be,pn %icc, 5f 70 be,pn %icc, 5f
704: add %g1, 128, %g1 714: add %g1, 128, %g1
72 membar #Sync
71 stda %f32, [%g2 + %g1] ASI_BLK_P 73 stda %f32, [%g2 + %g1] ASI_BLK_P
72 74
73 stda %f48, [%g3 + %g1] ASI_BLK_P 75 stda %f48, [%g3 + %g1] ASI_BLK_P
@@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
87 sll %g1, 5, %g1 89 sll %g1, 5, %g1
88 add %g6, TI_FPREGS+0xc0, %g3 90 add %g6, TI_FPREGS+0xc0, %g3
89 wr %g0, FPRS_FEF, %fprs 91 wr %g0, FPRS_FEF, %fprs
90 membar #StoreStore | #LoadStore 92 membar #Sync
91 stda %f32, [%g2 + %g1] ASI_BLK_P 93 stda %f32, [%g2 + %g1] ASI_BLK_P
92 stda %f48, [%g3 + %g1] ASI_BLK_P 94 stda %f48, [%g3 + %g1] ASI_BLK_P
93 membar #Sync 95 membar #Sync
@@ -128,8 +130,8 @@ VISenterhalf:
128 be,pn %icc, 4f 130 be,pn %icc, 4f
129 add %g6, TI_FPREGS, %g2 131 add %g6, TI_FPREGS, %g2
130 132
131 membar #StoreStore | #LoadStore
132 add %g6, TI_FPREGS+0x40, %g3 133 add %g6, TI_FPREGS+0x40, %g3
134 membar #Sync
133 stda %f0, [%g2 + %g1] ASI_BLK_P 135 stda %f0, [%g2 + %g1] ASI_BLK_P
134 stda %f16, [%g3 + %g1] ASI_BLK_P 136 stda %f16, [%g3 + %g1] ASI_BLK_P
135 membar #Sync 137 membar #Sync
diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S
index 09cbbaa0ebf4..e1264650ca7a 100644
--- a/arch/sparc64/lib/strncpy_from_user.S
+++ b/arch/sparc64/lib/strncpy_from_user.S
@@ -125,15 +125,11 @@ __strncpy_from_user:
125 add %o2, %o3, %o0 125 add %o2, %o3, %o0
126 .size __strncpy_from_user, .-__strncpy_from_user 126 .size __strncpy_from_user, .-__strncpy_from_user
127 127
128 .section .fixup,#alloc,#execinstr
129 .align 4
1304: retl
131 mov -EFAULT, %o0
132
133 .section __ex_table,#alloc 128 .section __ex_table,#alloc
134 .align 4 129 .align 4
135 .word 60b, 4b 130 .word 60b, __retl_efault
136 .word 61b, 4b 131 .word 61b, __retl_efault
137 .word 62b, 4b 132 .word 62b, __retl_efault
138 .word 63b, 4b 133 .word 63b, __retl_efault
139 .word 64b, 4b 134 .word 64b, __retl_efault
135 .previous
diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c
index 0278e34125db..19d1fdb17d0e 100644
--- a/arch/sparc64/lib/user_fixup.c
+++ b/arch/sparc64/lib/user_fixup.c
@@ -11,61 +11,56 @@
11 11
12/* Calculating the exact fault address when using 12/* Calculating the exact fault address when using
13 * block loads and stores can be very complicated. 13 * block loads and stores can be very complicated.
14 *
14 * Instead of trying to be clever and handling all 15 * Instead of trying to be clever and handling all
15 * of the cases, just fix things up simply here. 16 * of the cases, just fix things up simply here.
16 */ 17 */
17 18
18unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) 19static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
19{ 20{
20 char *dst = to; 21 unsigned long fault_addr = current_thread_info()->fault_address;
21 const char __user *src = from; 22 unsigned long end = start + size;
22 23
23 while (size) { 24 if (fault_addr < start || fault_addr >= end) {
24 if (__get_user(*dst, src)) 25 *offset = 0;
25 break; 26 } else {
26 dst++; 27 *offset = start - fault_addr;
27 src++; 28 size = end - fault_addr;
28 size--;
29 } 29 }
30 return size;
31}
30 32
31 if (size) 33unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
32 memset(dst, 0, size); 34{
35 unsigned long offset;
36
37 size = compute_size((unsigned long) from, size, &offset);
38 if (likely(size))
39 memset(to + offset, 0, size);
33 40
34 return size; 41 return size;
35} 42}
36 43
37unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) 44unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
38{ 45{
39 char __user *dst = to; 46 unsigned long offset;
40 const char *src = from;
41
42 while (size) {
43 if (__put_user(*src, dst))
44 break;
45 dst++;
46 src++;
47 size--;
48 }
49 47
50 return size; 48 return compute_size((unsigned long) to, size, &offset);
51} 49}
52 50
53unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) 51unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
54{ 52{
55 char __user *dst = to; 53 unsigned long fault_addr = current_thread_info()->fault_address;
56 char __user *src = from; 54 unsigned long start = (unsigned long) to;
55 unsigned long end = start + size;
57 56
58 while (size) { 57 if (fault_addr >= start && fault_addr < end)
59 char tmp; 58 return end - fault_addr;
60 59
61 if (__get_user(tmp, src)) 60 start = (unsigned long) from;
62 break; 61 end = start + size;
63 if (__put_user(tmp, dst)) 62 if (fault_addr >= start && fault_addr < end)
64 break; 63 return end - fault_addr;
65 dst++;
66 src++;
67 size--;
68 }
69 64
70 return size; 65 return size;
71} 66}