aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-08-19 21:59:49 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-19 21:59:49 -0400
commitb8d9598c41e999fb094d3811019248197c54274a (patch)
treef934dada0798c769331886481dd0e7538c2842fd /arch
parent01c314a0c0f6367960a7cb1ffb5796560ccaa1c1 (diff)
parent83c4e43722a2c8a8438b8d165047720fd36aaea4 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c5
-rw-r--r--arch/sparc64/kernel/Makefile2
-rw-r--r--arch/sparc64/kernel/traps.c3
-rw-r--r--arch/sparc64/kernel/una_asm.S153
-rw-r--r--arch/sparc64/kernel/unaligned.c261
5 files changed, 219 insertions, 205 deletions
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 1bd430d0ca06..8faa8dc4de43 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -98,8 +98,9 @@ extern void ___rw_write_enter(void);
98 * The module references will be fixed up by module_frob_arch_sections. 98 * The module references will be fixed up by module_frob_arch_sections.
99 */ 99 */
100#define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \ 100#define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \
101 extern __ret __x(__arg1, __arg2) \ 101 extern __ret __x(__arg1, __arg2); \
102 __attribute__((weak, alias("." # __x))); 102 asm(".weak " #__x);\
103 asm(#__x "=." #__x);
103 104
104DOT_ALIAS2(int, div, int, int) 105DOT_ALIAS2(int, div, int, int)
105DOT_ALIAS2(int, mul, int, int) 106DOT_ALIAS2(int, mul, int, int)
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 093281bdf85f..6f00ab8b9d23 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror
8extra-y := head.o init_task.o vmlinux.lds 8extra-y := head.o init_task.o vmlinux.lds
9 9
10obj-y := process.o setup.o cpu.o idprom.o \ 10obj-y := process.o setup.o cpu.o idprom.o \
11 traps.o devices.o auxio.o \ 11 traps.o devices.o auxio.o una_asm.o \
12 irq.o ptrace.o time.o sys_sparc.o signal.o \ 12 irq.o ptrace.o time.o sys_sparc.o signal.o \
13 unaligned.o central.o pci.o starfire.o semaphore.o \ 13 unaligned.o central.o pci.o starfire.o semaphore.o \
14 power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o 14 power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 100b0107c4be..0c9e54b2f0c8 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -2127,6 +2127,9 @@ void __init trap_init(void)
2127 TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || 2127 TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
2128 TI_NEW_CHILD != offsetof(struct thread_info, new_child) || 2128 TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
2129 TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || 2129 TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
2130 TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
2131 TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
2132 TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
2130 TI_FPREGS != offsetof(struct thread_info, fpregs) || 2133 TI_FPREGS != offsetof(struct thread_info, fpregs) ||
2131 (TI_FPREGS & (64 - 1))) 2134 (TI_FPREGS & (64 - 1)))
2132 thread_info_offsets_are_bolixed_dave(); 2135 thread_info_offsets_are_bolixed_dave();
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S
new file mode 100644
index 000000000000..cbb40585253c
--- /dev/null
+++ b/arch/sparc64/kernel/una_asm.S
@@ -0,0 +1,153 @@
1/* una_asm.S: Kernel unaligned trap assembler helpers.
2 *
3 * Copyright (C) 1996,2005 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 */
6
7 .text
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
17__do_int_store:
18 rd %asi, %o4
19 wr %o3, 0, %asi
20 ldx [%o2], %g3
21 cmp %o1, 2
22 be,pn %icc, 2f
23 cmp %o1, 4
24 be,pt %icc, 1f
25 srlx %g3, 24, %g2
26 srlx %g3, 56, %g1
27 srlx %g3, 48, %g7
284: stba %g1, [%o0] %asi
29 srlx %g3, 40, %g1
305: stba %g7, [%o0 + 1] %asi
31 srlx %g3, 32, %g7
326: stba %g1, [%o0 + 2] %asi
337: stba %g7, [%o0 + 3] %asi
34 srlx %g3, 16, %g1
358: stba %g2, [%o0 + 4] %asi
36 srlx %g3, 8, %g7
379: stba %g1, [%o0 + 5] %asi
3810: stba %g7, [%o0 + 6] %asi
39 ba,pt %xcc, 0f
4011: stba %g3, [%o0 + 7] %asi
411: srl %g3, 16, %g7
4212: stba %g2, [%o0] %asi
43 srl %g3, 8, %g2
4413: stba %g7, [%o0 + 1] %asi
4514: stba %g2, [%o0 + 2] %asi
46 ba,pt %xcc, 0f
4715: stba %g3, [%o0 + 3] %asi
482: srl %g3, 8, %g2
4916: stba %g2, [%o0] %asi
5017: stba %g3, [%o0 + 1] %asi
510:
52 wr %o4, 0x0, %asi
53 retl
54 nop
55 .size __do_int_store, .-__do_int_store
56
57 .section __ex_table
58 .word 4b, kernel_unaligned_trap_fault
59 .word 5b, kernel_unaligned_trap_fault
60 .word 6b, kernel_unaligned_trap_fault
61 .word 7b, kernel_unaligned_trap_fault
62 .word 8b, kernel_unaligned_trap_fault
63 .word 9b, kernel_unaligned_trap_fault
64 .word 10b, kernel_unaligned_trap_fault
65 .word 11b, kernel_unaligned_trap_fault
66 .word 12b, kernel_unaligned_trap_fault
67 .word 13b, kernel_unaligned_trap_fault
68 .word 14b, kernel_unaligned_trap_fault
69 .word 15b, kernel_unaligned_trap_fault
70 .word 16b, kernel_unaligned_trap_fault
71 .word 17b, kernel_unaligned_trap_fault
72 .previous
73
74 .globl do_int_load
75do_int_load:
76 rd %asi, %o5
77 wr %o4, 0, %asi
78 cmp %o1, 8
79 bge,pn %icc, 9f
80 cmp %o1, 4
81 be,pt %icc, 6f
824: lduba [%o2] %asi, %g2
835: lduba [%o2 + 1] %asi, %g3
84 sll %g2, 8, %g2
85 brz,pt %o3, 3f
86 add %g2, %g3, %g2
87 sllx %g2, 48, %g2
88 srax %g2, 48, %g2
893: ba,pt %xcc, 0f
90 stx %g2, [%o0]
916: lduba [%o2 + 1] %asi, %g3
92 sll %g2, 24, %g2
937: lduba [%o2 + 2] %asi, %g7
94 sll %g3, 16, %g3
958: lduba [%o2 + 3] %asi, %g1
96 sll %g7, 8, %g7
97 or %g2, %g3, %g2
98 or %g7, %g1, %g7
99 or %g2, %g7, %g2
100 brnz,a,pt %o3, 3f
101 sra %g2, 0, %g2
1023: ba,pt %xcc, 0f
103 stx %g2, [%o0]
1049: lduba [%o2] %asi, %g2
10510: lduba [%o2 + 1] %asi, %g3
106 sllx %g2, 56, %g2
10711: lduba [%o2 + 2] %asi, %g7
108 sllx %g3, 48, %g3
10912: lduba [%o2 + 3] %asi, %g1
110 sllx %g7, 40, %g7
111 sllx %g1, 32, %g1
112 or %g2, %g3, %g2
113 or %g7, %g1, %g7
11413: lduba [%o2 + 4] %asi, %g3
115 or %g2, %g7, %g7
11614: lduba [%o2 + 5] %asi, %g1
117 sllx %g3, 24, %g3
11815: lduba [%o2 + 6] %asi, %g2
119 sllx %g1, 16, %g1
120 or %g7, %g3, %g7
12116: lduba [%o2 + 7] %asi, %g3
122 sllx %g2, 8, %g2
123 or %g7, %g1, %g7
124 or %g2, %g3, %g2
125 or %g7, %g2, %g7
126 cmp %o1, 8
127 be,a,pt %icc, 0f
128 stx %g7, [%o0]
129 srlx %g7, 32, %g2
130 sra %g7, 0, %g7
131 stx %g2, [%o0]
132 stx %g7, [%o0 + 8]
1330:
134 wr %o5, 0x0, %asi
135 retl
136 nop
137 .size __do_int_load, .-__do_int_load
138
139 .section __ex_table
140 .word 4b, kernel_unaligned_trap_fault
141 .word 5b, kernel_unaligned_trap_fault
142 .word 6b, kernel_unaligned_trap_fault
143 .word 7b, kernel_unaligned_trap_fault
144 .word 8b, kernel_unaligned_trap_fault
145 .word 9b, kernel_unaligned_trap_fault
146 .word 10b, kernel_unaligned_trap_fault
147 .word 11b, kernel_unaligned_trap_fault
148 .word 12b, kernel_unaligned_trap_fault
149 .word 13b, kernel_unaligned_trap_fault
150 .word 14b, kernel_unaligned_trap_fault
151 .word 15b, kernel_unaligned_trap_fault
152 .word 16b, kernel_unaligned_trap_fault
153 .previous
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 4372bf32ecf6..11c3e88732e4 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -180,169 +180,28 @@ 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
183#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({ \ 183extern void do_int_load(unsigned long *dest_reg, int size,
184__asm__ __volatile__ ( \ 184 unsigned long *saddr, int is_signed, int asi);
185 "wr %4, 0, %%asi\n\t" \
186 "cmp %1, 8\n\t" \
187 "bge,pn %%icc, 9f\n\t" \
188 " cmp %1, 4\n\t" \
189 "be,pt %%icc, 6f\n" \
190"4:\t" " lduba [%2] %%asi, %%l1\n" \
191"5:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \
192 "sll %%l1, 8, %%l1\n\t" \
193 "brz,pt %3, 3f\n\t" \
194 " add %%l1, %%l2, %%l1\n\t" \
195 "sllx %%l1, 48, %%l1\n\t" \
196 "srax %%l1, 48, %%l1\n" \
197"3:\t" "ba,pt %%xcc, 0f\n\t" \
198 " stx %%l1, [%0]\n" \
199"6:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \
200 "sll %%l1, 24, %%l1\n" \
201"7:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \
202 "sll %%l2, 16, %%l2\n" \
203"8:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \
204 "sll %%g7, 8, %%g7\n\t" \
205 "or %%l1, %%l2, %%l1\n\t" \
206 "or %%g7, %%g1, %%g7\n\t" \
207 "or %%l1, %%g7, %%l1\n\t" \
208 "brnz,a,pt %3, 3f\n\t" \
209 " sra %%l1, 0, %%l1\n" \
210"3:\t" "ba,pt %%xcc, 0f\n\t" \
211 " stx %%l1, [%0]\n" \
212"9:\t" "lduba [%2] %%asi, %%l1\n" \
213"10:\t" "lduba [%2 + 1] %%asi, %%l2\n\t" \
214 "sllx %%l1, 56, %%l1\n" \
215"11:\t" "lduba [%2 + 2] %%asi, %%g7\n\t" \
216 "sllx %%l2, 48, %%l2\n" \
217"12:\t" "lduba [%2 + 3] %%asi, %%g1\n\t" \
218 "sllx %%g7, 40, %%g7\n\t" \
219 "sllx %%g1, 32, %%g1\n\t" \
220 "or %%l1, %%l2, %%l1\n\t" \
221 "or %%g7, %%g1, %%g7\n" \
222"13:\t" "lduba [%2 + 4] %%asi, %%l2\n\t" \
223 "or %%l1, %%g7, %%g7\n" \
224"14:\t" "lduba [%2 + 5] %%asi, %%g1\n\t" \
225 "sllx %%l2, 24, %%l2\n" \
226"15:\t" "lduba [%2 + 6] %%asi, %%l1\n\t" \
227 "sllx %%g1, 16, %%g1\n\t" \
228 "or %%g7, %%l2, %%g7\n" \
229"16:\t" "lduba [%2 + 7] %%asi, %%l2\n\t" \
230 "sllx %%l1, 8, %%l1\n\t" \
231 "or %%g7, %%g1, %%g7\n\t" \
232 "or %%l1, %%l2, %%l1\n\t" \
233 "or %%g7, %%l1, %%g7\n\t" \
234 "cmp %1, 8\n\t" \
235 "be,a,pt %%icc, 0f\n\t" \
236 " stx %%g7, [%0]\n\t" \
237 "srlx %%g7, 32, %%l1\n\t" \
238 "sra %%g7, 0, %%g7\n\t" \
239 "stx %%l1, [%0]\n\t" \
240 "stx %%g7, [%0 + 8]\n" \
241"0:\n\t" \
242 "wr %%g0, %5, %%asi\n\n\t" \
243 ".section __ex_table\n\t" \
244 ".word 4b, " #errh "\n\t" \
245 ".word 5b, " #errh "\n\t" \
246 ".word 6b, " #errh "\n\t" \
247 ".word 7b, " #errh "\n\t" \
248 ".word 8b, " #errh "\n\t" \
249 ".word 9b, " #errh "\n\t" \
250 ".word 10b, " #errh "\n\t" \
251 ".word 11b, " #errh "\n\t" \
252 ".word 12b, " #errh "\n\t" \
253 ".word 13b, " #errh "\n\t" \
254 ".word 14b, " #errh "\n\t" \
255 ".word 15b, " #errh "\n\t" \
256 ".word 16b, " #errh "\n\n\t" \
257 ".previous\n\t" \
258 : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), \
259 "r" (asi), "i" (ASI_AIUS) \
260 : "l1", "l2", "g7", "g1", "cc"); \
261})
262 185
263#define store_common(dst_addr, size, src_val, asi, errh) ({ \ 186extern void __do_int_store(unsigned long *dst_addr, int size,
264__asm__ __volatile__ ( \ 187 unsigned long *src_val, int asi);
265 "wr %3, 0, %%asi\n\t" \ 188
266 "ldx [%2], %%l1\n" \ 189static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
267 "cmp %1, 2\n\t" \ 190 struct pt_regs *regs, int asi)
268 "be,pn %%icc, 2f\n\t" \ 191{
269 " cmp %1, 4\n\t" \ 192 unsigned long zero = 0;
270 "be,pt %%icc, 1f\n\t" \ 193 unsigned long *src_val = &zero;
271 " srlx %%l1, 24, %%l2\n\t" \ 194
272 "srlx %%l1, 56, %%g1\n\t" \ 195 if (size == 16) {
273 "srlx %%l1, 48, %%g7\n" \ 196 size = 8;
274"4:\t" "stba %%g1, [%0] %%asi\n\t" \ 197 zero = (((long)(reg_num ?
275 "srlx %%l1, 40, %%g1\n" \ 198 (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) |
276"5:\t" "stba %%g7, [%0 + 1] %%asi\n\t" \ 199 (unsigned)fetch_reg(reg_num + 1, regs);
277 "srlx %%l1, 32, %%g7\n" \ 200 } else if (reg_num) {
278"6:\t" "stba %%g1, [%0 + 2] %%asi\n" \ 201 src_val = fetch_reg_addr(reg_num, regs);
279"7:\t" "stba %%g7, [%0 + 3] %%asi\n\t" \ 202 }
280 "srlx %%l1, 16, %%g1\n" \ 203 __do_int_store(dst_addr, size, src_val, asi);
281"8:\t" "stba %%l2, [%0 + 4] %%asi\n\t" \ 204}
282 "srlx %%l1, 8, %%g7\n" \
283"9:\t" "stba %%g1, [%0 + 5] %%asi\n" \
284"10:\t" "stba %%g7, [%0 + 6] %%asi\n\t" \
285 "ba,pt %%xcc, 0f\n" \
286"11:\t" " stba %%l1, [%0 + 7] %%asi\n" \
287"1:\t" "srl %%l1, 16, %%g7\n" \
288"12:\t" "stba %%l2, [%0] %%asi\n\t" \
289 "srl %%l1, 8, %%l2\n" \
290"13:\t" "stba %%g7, [%0 + 1] %%asi\n" \
291"14:\t" "stba %%l2, [%0 + 2] %%asi\n\t" \
292 "ba,pt %%xcc, 0f\n" \
293"15:\t" " stba %%l1, [%0 + 3] %%asi\n" \
294"2:\t" "srl %%l1, 8, %%l2\n" \
295"16:\t" "stba %%l2, [%0] %%asi\n" \
296"17:\t" "stba %%l1, [%0 + 1] %%asi\n" \
297"0:\n\t" \
298 "wr %%g0, %4, %%asi\n\n\t" \
299 ".section __ex_table\n\t" \
300 ".word 4b, " #errh "\n\t" \
301 ".word 5b, " #errh "\n\t" \
302 ".word 6b, " #errh "\n\t" \
303 ".word 7b, " #errh "\n\t" \
304 ".word 8b, " #errh "\n\t" \
305 ".word 9b, " #errh "\n\t" \
306 ".word 10b, " #errh "\n\t" \
307 ".word 11b, " #errh "\n\t" \
308 ".word 12b, " #errh "\n\t" \
309 ".word 13b, " #errh "\n\t" \
310 ".word 14b, " #errh "\n\t" \
311 ".word 15b, " #errh "\n\t" \
312 ".word 16b, " #errh "\n\t" \
313 ".word 17b, " #errh "\n\n\t" \
314 ".previous\n\t" \
315 : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\
316 : "l1", "l2", "g7", "g1", "cc"); \
317})
318
319#define do_integer_store(reg_num, size, dst_addr, regs, asi, errh) ({ \
320 unsigned long zero = 0; \
321 unsigned long *src_val = &zero; \
322 \
323 if (size == 16) { \
324 size = 8; \
325 zero = (((long)(reg_num ? \
326 (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | \
327 (unsigned)fetch_reg(reg_num + 1, regs); \
328 } else if (reg_num) src_val = fetch_reg_addr(reg_num, regs); \
329 store_common(dst_addr, size, src_val, asi, errh); \
330})
331
332extern void smp_capture(void);
333extern void smp_release(void);
334
335#define do_atomic(srcdest_reg, mem, errh) ({ \
336 unsigned long flags, tmp; \
337 \
338 smp_capture(); \
339 local_irq_save(flags); \
340 tmp = *srcdest_reg; \
341 do_integer_load(srcdest_reg, 4, mem, 0, errh); \
342 store_common(mem, 4, &tmp, errh); \
343 local_irq_restore(flags); \
344 smp_release(); \
345})
346 205
347static inline void advance(struct pt_regs *regs) 206static inline void advance(struct pt_regs *regs)
348{ 207{
@@ -364,24 +223,29 @@ static inline int ok_for_kernel(unsigned int insn)
364 return !floating_point_load_or_store_p(insn); 223 return !floating_point_load_or_store_p(insn);
365} 224}
366 225
367void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault"); 226void kernel_mna_trap_fault(void)
368
369void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
370{ 227{
371 unsigned long g2 = regs->u_regs [UREG_G2]; 228 struct pt_regs *regs = current_thread_info()->kern_una_regs;
229 unsigned int insn = current_thread_info()->kern_una_insn;
230 unsigned long g2 = regs->u_regs[UREG_G2];
372 unsigned long fixup = search_extables_range(regs->tpc, &g2); 231 unsigned long fixup = search_extables_range(regs->tpc, &g2);
373 232
374 if (!fixup) { 233 if (!fixup) {
375 unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); 234 unsigned long address;
235
236 address = compute_effective_address(regs, insn,
237 ((insn >> 25) & 0x1f));
376 if (address < PAGE_SIZE) { 238 if (address < PAGE_SIZE) {
377 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler"); 239 printk(KERN_ALERT "Unable to handle kernel NULL "
240 "pointer dereference in mna handler");
378 } else 241 } else
379 printk(KERN_ALERT "Unable to handle kernel paging request in mna handler"); 242 printk(KERN_ALERT "Unable to handle kernel paging "
243 "request in mna handler");
380 printk(KERN_ALERT " at virtual address %016lx\n",address); 244 printk(KERN_ALERT " at virtual address %016lx\n",address);
381 printk(KERN_ALERT "current->{mm,active_mm}->context = %016lx\n", 245 printk(KERN_ALERT "current->{active_,}mm->context = %016lx\n",
382 (current->mm ? CTX_HWBITS(current->mm->context) : 246 (current->mm ? CTX_HWBITS(current->mm->context) :
383 CTX_HWBITS(current->active_mm->context))); 247 CTX_HWBITS(current->active_mm->context)));
384 printk(KERN_ALERT "current->{mm,active_mm}->pgd = %016lx\n", 248 printk(KERN_ALERT "current->{active_,}mm->pgd = %016lx\n",
385 (current->mm ? (unsigned long) current->mm->pgd : 249 (current->mm ? (unsigned long) current->mm->pgd :
386 (unsigned long) current->active_mm->pgd)); 250 (unsigned long) current->active_mm->pgd));
387 die_if_kernel("Oops", regs); 251 die_if_kernel("Oops", regs);
@@ -400,48 +264,41 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
400 enum direction dir = decode_direction(insn); 264 enum direction dir = decode_direction(insn);
401 int size = decode_access_size(insn); 265 int size = decode_access_size(insn);
402 266
267 current_thread_info()->kern_una_regs = regs;
268 current_thread_info()->kern_una_insn = insn;
269
403 if (!ok_for_kernel(insn) || dir == both) { 270 if (!ok_for_kernel(insn) || dir == both) {
404 printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n", 271 printk("Unsupported unaligned load/store trap for kernel "
405 regs->tpc); 272 "at <%016lx>.\n", regs->tpc);
406 unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs); 273 unaligned_panic("Kernel does fpu/atomic "
407 274 "unaligned load/store.", regs);
408 __asm__ __volatile__ ("\n" 275
409"kernel_unaligned_trap_fault:\n\t" 276 kernel_mna_trap_fault();
410 "mov %0, %%o0\n\t"
411 "call kernel_mna_trap_fault\n\t"
412 " mov %1, %%o1\n\t"
413 :
414 : "r" (regs), "r" (insn)
415 : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
416 "g1", "g2", "g3", "g4", "g7", "cc");
417 } else { 277 } else {
418 unsigned long addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); 278 unsigned long addr;
419 279
280 addr = compute_effective_address(regs, insn,
281 ((insn >> 25) & 0x1f));
420#ifdef DEBUG_MNA 282#ifdef DEBUG_MNA
421 printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] retpc[%016lx]\n", 283 printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] "
422 regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); 284 "retpc[%016lx]\n",
285 regs->tpc, dirstrings[dir], addr, size,
286 regs->u_regs[UREG_RETPC]);
423#endif 287#endif
424 switch (dir) { 288 switch (dir) {
425 case load: 289 case load:
426 do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs), 290 do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
427 size, (unsigned long *) addr, 291 size, (unsigned long *) addr,
428 decode_signedness(insn), decode_asi(insn, regs), 292 decode_signedness(insn),
429 kernel_unaligned_trap_fault); 293 decode_asi(insn, regs));
430 break; 294 break;
431 295
432 case store: 296 case store:
433 do_integer_store(((insn>>25)&0x1f), size, 297 do_int_store(((insn>>25)&0x1f), size,
434 (unsigned long *) addr, regs, 298 (unsigned long *) addr, regs,
435 decode_asi(insn, regs), 299 decode_asi(insn, regs));
436 kernel_unaligned_trap_fault);
437 break;
438#if 0 /* unsupported */
439 case both:
440 do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
441 (unsigned long *) addr,
442 kernel_unaligned_trap_fault);
443 break; 300 break;
444#endif 301
445 default: 302 default:
446 panic("Impossible kernel unaligned trap."); 303 panic("Impossible kernel unaligned trap.");
447 /* Not reached... */ 304 /* Not reached... */