aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:41:45 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:41:45 -0400
commit5fd29752f09cabff582f65c0ce35518db4c64937 (patch)
treeb46e5c2c596d26125a7c2aac619fe1b52431f978
parent8cf14af0a740fb7e9f94a203b5a989beb875d58f (diff)
[SPARC64]: Fix fault handling in unaligned trap handler.
We were not calling kernel_mna_trap_fault() correctly. Instead of being fancy, just return 0 vs. -EFAULT from the assembler stubs, and handle that return value as appropriate. Create an "__retl_efault" stub for assembler exception table entries and use it where possible. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/head.S7
-rw-r--r--arch/sparc64/kernel/sys32.S57
-rw-r--r--arch/sparc64/kernel/una_asm.S65
-rw-r--r--arch/sparc64/kernel/unaligned.c36
-rw-r--r--arch/sparc64/lib/strncpy_from_user.S16
-rw-r--r--include/asm-sparc64/uaccess.h1
6 files changed, 95 insertions, 87 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index ecc748fb9ad7..89406f9649a9 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -540,8 +540,11 @@ bootup_user_stack_end:
540prom_tba: .xword 0 540prom_tba: .xword 0
541tlb_type: .word 0 /* Must NOT end up in BSS */ 541tlb_type: .word 0 /* Must NOT end up in BSS */
542 .section ".fixup",#alloc,#execinstr 542 .section ".fixup",#alloc,#execinstr
543 .globl __ret_efault 543
544 .globl __ret_efault, __retl_efault
544__ret_efault: 545__ret_efault:
545 ret 546 ret
546 restore %g0, -EFAULT, %o0 547 restore %g0, -EFAULT, %o0
547 548__retl_efault:
549 retl
550 mov -EFAULT, %o0
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index 4fb99e0bc7c3..9cd272ac3ac1 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -157,6 +157,9 @@ sys32_socketcall: /* %o0=call, %o1=args */
157 or %g2, %lo(__socketcall_table_begin), %g2 157 or %g2, %lo(__socketcall_table_begin), %g2
158 jmpl %g2 + %o0, %g0 158 jmpl %g2 + %o0, %g0
159 nop 159 nop
160do_einval:
161 retl
162 mov -EINVAL, %o0
160 163
161 .align 32 164 .align 32
162__socketcall_table_begin: 165__socketcall_table_begin:
@@ -316,29 +319,37 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int)
316 nop 319 nop
317 nop 320 nop
318 321
319do_einval:
320 retl
321 mov -EINVAL, %o0
322do_efault:
323 retl
324 mov -EFAULT, %o0
325
326 .section __ex_table 322 .section __ex_table
327 .align 4 323 .align 4
328 .word 1b, do_efault, 2b, do_efault, 3b, do_efault, 4b, do_efault 324 .word 1b, __retl_efault, 2b, __retl_efault
329 .word 5b, do_efault, 6b, do_efault, 7b, do_efault, 8b, do_efault 325 .word 3b, __retl_efault, 4b, __retl_efault
330 .word 9b, do_efault, 10b, do_efault, 11b, do_efault, 12b, do_efault 326 .word 5b, __retl_efault, 6b, __retl_efault
331 .word 13b, do_efault, 14b, do_efault, 15b, do_efault, 16b, do_efault 327 .word 7b, __retl_efault, 8b, __retl_efault
332 .word 17b, do_efault, 18b, do_efault, 19b, do_efault, 20b, do_efault 328 .word 9b, __retl_efault, 10b, __retl_efault
333 .word 21b, do_efault, 22b, do_efault, 23b, do_efault, 24b, do_efault 329 .word 11b, __retl_efault, 12b, __retl_efault
334 .word 25b, do_efault, 26b, do_efault, 27b, do_efault, 28b, do_efault 330 .word 13b, __retl_efault, 14b, __retl_efault
335 .word 29b, do_efault, 30b, do_efault, 31b, do_efault, 32b, do_efault 331 .word 15b, __retl_efault, 16b, __retl_efault
336 .word 33b, do_efault, 34b, do_efault, 35b, do_efault, 36b, do_efault 332 .word 17b, __retl_efault, 18b, __retl_efault
337 .word 37b, do_efault, 38b, do_efault, 39b, do_efault, 40b, do_efault 333 .word 19b, __retl_efault, 20b, __retl_efault
338 .word 41b, do_efault, 42b, do_efault, 43b, do_efault, 44b, do_efault 334 .word 21b, __retl_efault, 22b, __retl_efault
339 .word 45b, do_efault, 46b, do_efault, 47b, do_efault, 48b, do_efault 335 .word 23b, __retl_efault, 24b, __retl_efault
340 .word 49b, do_efault, 50b, do_efault, 51b, do_efault, 52b, do_efault 336 .word 25b, __retl_efault, 26b, __retl_efault
341 .word 53b, do_efault, 54b, do_efault, 55b, do_efault, 56b, do_efault 337 .word 27b, __retl_efault, 28b, __retl_efault
342 .word 57b, do_efault, 58b, do_efault, 59b, do_efault, 60b, do_efault 338 .word 29b, __retl_efault, 30b, __retl_efault
343 .word 61b, do_efault, 62b, do_efault 339 .word 31b, __retl_efault, 32b, __retl_efault
340 .word 33b, __retl_efault, 34b, __retl_efault
341 .word 35b, __retl_efault, 36b, __retl_efault
342 .word 37b, __retl_efault, 38b, __retl_efault
343 .word 39b, __retl_efault, 40b, __retl_efault
344 .word 41b, __retl_efault, 42b, __retl_efault
345 .word 43b, __retl_efault, 44b, __retl_efault
346 .word 45b, __retl_efault, 46b, __retl_efault
347 .word 47b, __retl_efault, 48b, __retl_efault
348 .word 49b, __retl_efault, 50b, __retl_efault
349 .word 51b, __retl_efault, 52b, __retl_efault
350 .word 53b, __retl_efault, 54b, __retl_efault
351 .word 55b, __retl_efault, 56b, __retl_efault
352 .word 57b, __retl_efault, 58b, __retl_efault
353 .word 59b, __retl_efault, 60b, __retl_efault
354 .word 61b, __retl_efault, 62b, __retl_efault
344 .previous 355 .previous
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S
index da48400bcc95..1f5b5b708ce7 100644
--- a/arch/sparc64/kernel/una_asm.S
+++ b/arch/sparc64/kernel/una_asm.S
@@ -6,13 +6,6 @@
6 6
7 .text 7 .text
8 8
9kernel_unaligned_trap_fault:
10 call kernel_mna_trap_fault
11 nop
12 retl
13 nop
14 .size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault
15
16 .globl __do_int_store 9 .globl __do_int_store
17__do_int_store: 10__do_int_store:
18 rd %asi, %o4 11 rd %asi, %o4
@@ -51,24 +44,24 @@ __do_int_store:
510: 440:
52 wr %o4, 0x0, %asi 45 wr %o4, 0x0, %asi
53 retl 46 retl
54 nop 47 mov 0, %o0
55 .size __do_int_store, .-__do_int_store 48 .size __do_int_store, .-__do_int_store
56 49
57 .section __ex_table 50 .section __ex_table
58 .word 4b, kernel_unaligned_trap_fault 51 .word 4b, __retl_efault
59 .word 5b, kernel_unaligned_trap_fault 52 .word 5b, __retl_efault
60 .word 6b, kernel_unaligned_trap_fault 53 .word 6b, __retl_efault
61 .word 7b, kernel_unaligned_trap_fault 54 .word 7b, __retl_efault
62 .word 8b, kernel_unaligned_trap_fault 55 .word 8b, __retl_efault
63 .word 9b, kernel_unaligned_trap_fault 56 .word 9b, __retl_efault
64 .word 10b, kernel_unaligned_trap_fault 57 .word 10b, __retl_efault
65 .word 11b, kernel_unaligned_trap_fault 58 .word 11b, __retl_efault
66 .word 12b, kernel_unaligned_trap_fault 59 .word 12b, __retl_efault
67 .word 13b, kernel_unaligned_trap_fault 60 .word 13b, __retl_efault
68 .word 14b, kernel_unaligned_trap_fault 61 .word 14b, __retl_efault
69 .word 15b, kernel_unaligned_trap_fault 62 .word 15b, __retl_efault
70 .word 16b, kernel_unaligned_trap_fault 63 .word 16b, __retl_efault
71 .word 17b, kernel_unaligned_trap_fault 64 .word 17b, __retl_efault
72 .previous 65 .previous
73 66
74 .globl do_int_load 67 .globl do_int_load
@@ -133,21 +126,21 @@ do_int_load:
1330: 1260:
134 wr %o5, 0x0, %asi 127 wr %o5, 0x0, %asi
135 retl 128 retl
136 nop 129 mov 0, %o0
137 .size __do_int_load, .-__do_int_load 130 .size __do_int_load, .-__do_int_load
138 131
139 .section __ex_table 132 .section __ex_table
140 .word 4b, kernel_unaligned_trap_fault 133 .word 4b, __retl_efault
141 .word 5b, kernel_unaligned_trap_fault 134 .word 5b, __retl_efault
142 .word 6b, kernel_unaligned_trap_fault 135 .word 6b, __retl_efault
143 .word 7b, kernel_unaligned_trap_fault 136 .word 7b, __retl_efault
144 .word 8b, kernel_unaligned_trap_fault 137 .word 8b, __retl_efault
145 .word 9b, kernel_unaligned_trap_fault 138 .word 9b, __retl_efault
146 .word 10b, kernel_unaligned_trap_fault 139 .word 10b, __retl_efault
147 .word 11b, kernel_unaligned_trap_fault 140 .word 11b, __retl_efault
148 .word 12b, kernel_unaligned_trap_fault 141 .word 12b, __retl_efault
149 .word 13b, kernel_unaligned_trap_fault 142 .word 13b, __retl_efault
150 .word 14b, kernel_unaligned_trap_fault 143 .word 14b, __retl_efault
151 .word 15b, kernel_unaligned_trap_fault 144 .word 15b, __retl_efault
152 .word 16b, kernel_unaligned_trap_fault 145 .word 16b, __retl_efault
153 .previous 146 .previous
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 9d6be20f4125..70faf630603b 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -180,14 +180,14 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
180 die_if_kernel(str, regs); 180 die_if_kernel(str, regs);
181} 181}
182 182
183extern void do_int_load(unsigned long *dest_reg, int size, 183extern int do_int_load(unsigned long *dest_reg, int size,
184 unsigned long *saddr, int is_signed, int asi); 184 unsigned long *saddr, int is_signed, int asi);
185 185
186extern void __do_int_store(unsigned long *dst_addr, int size, 186extern int __do_int_store(unsigned long *dst_addr, int size,
187 unsigned long src_val, int asi); 187 unsigned long src_val, int asi);
188 188
189static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, 189static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
190 struct pt_regs *regs, int asi, int orig_asi) 190 struct pt_regs *regs, int asi, int orig_asi)
191{ 191{
192 unsigned long zero = 0; 192 unsigned long zero = 0;
193 unsigned long *src_val_p = &zero; 193 unsigned long *src_val_p = &zero;
@@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
219 break; 219 break;
220 }; 220 };
221 } 221 }
222 __do_int_store(dst_addr, size, src_val, asi); 222 return __do_int_store(dst_addr, size, src_val, asi);
223} 223}
224 224
225static inline void advance(struct pt_regs *regs) 225static inline void advance(struct pt_regs *regs)
@@ -242,7 +242,7 @@ static inline int ok_for_kernel(unsigned int insn)
242 return !floating_point_load_or_store_p(insn); 242 return !floating_point_load_or_store_p(insn);
243} 243}
244 244
245void kernel_mna_trap_fault(void) 245static void kernel_mna_trap_fault(void)
246{ 246{
247 struct pt_regs *regs = current_thread_info()->kern_una_regs; 247 struct pt_regs *regs = current_thread_info()->kern_una_regs;
248 unsigned int insn = current_thread_info()->kern_una_insn; 248 unsigned int insn = current_thread_info()->kern_una_insn;
@@ -294,7 +294,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
294 kernel_mna_trap_fault(); 294 kernel_mna_trap_fault();
295 } else { 295 } else {
296 unsigned long addr, *reg_addr; 296 unsigned long addr, *reg_addr;
297 int orig_asi, asi; 297 int orig_asi, asi, err;
298 298
299 addr = compute_effective_address(regs, insn, 299 addr = compute_effective_address(regs, insn,
300 ((insn >> 25) & 0x1f)); 300 ((insn >> 25) & 0x1f));
@@ -319,9 +319,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
319 switch (dir) { 319 switch (dir) {
320 case load: 320 case load:
321 reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); 321 reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
322 do_int_load(reg_addr, size, (unsigned long *) addr, 322 err = do_int_load(reg_addr, size,
323 decode_signedness(insn), asi); 323 (unsigned long *) addr,
324 if (unlikely(asi != orig_asi)) { 324 decode_signedness(insn), asi);
325 if (likely(!err) && unlikely(asi != orig_asi)) {
325 unsigned long val_in = *reg_addr; 326 unsigned long val_in = *reg_addr;
326 switch (size) { 327 switch (size) {
327 case 2: 328 case 2:
@@ -343,16 +344,19 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
343 break; 344 break;
344 345
345 case store: 346 case store:
346 do_int_store(((insn>>25)&0x1f), size, 347 err = do_int_store(((insn>>25)&0x1f), size,
347 (unsigned long *) addr, regs, 348 (unsigned long *) addr, regs,
348 asi, orig_asi); 349 asi, orig_asi);
349 break; 350 break;
350 351
351 default: 352 default:
352 panic("Impossible kernel unaligned trap."); 353 panic("Impossible kernel unaligned trap.");
353 /* Not reached... */ 354 /* Not reached... */
354 } 355 }
355 advance(regs); 356 if (unlikely(err))
357 kernel_mna_trap_fault();
358 else
359 advance(regs);
356 } 360 }
357} 361}
358 362
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/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index c099aa339784..bc8ddbb1cbed 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -77,6 +77,7 @@ struct exception_table_entry {
77}; 77};
78 78
79extern void __ret_efault(void); 79extern void __ret_efault(void);
80extern void __retl_efault(void);
80 81
81/* Uh, these should become the main single-value transfer routines.. 82/* Uh, these should become the main single-value transfer routines..
82 * They automatically use the right size if we just have the right 83 * They automatically use the right size if we just have the right