diff options
author | Yoshinori Sato <ysato@users.sourceforge.jp> | 2008-07-09 12:20:03 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-07-28 05:10:34 -0400 |
commit | 6e80f5e8c4c685eb7bc34c3916e3d986b03f9981 (patch) | |
tree | 3c8768bdb748ba6b1bc923d798b1a8e3b91df4eb /arch/sh | |
parent | cafd63b0076b78bc8f114abbeb724c7e5f5bfe5d (diff) |
sh2(A) exception handler update
This patch is
By sh2
- Remove duplicate code
- Reduce stack usage
- Cleanup and little optimize
By sh2a
- Add missing handler(256 to 511)
- Use sh2a instructions handler
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/kernel/cpu/sh2/entry.S | 133 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2/ex.S | 15 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/entry.S | 249 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/ex.S | 72 | ||||
-rw-r--r-- | arch/sh/kernel/traps_32.c | 4 |
6 files changed, 385 insertions, 90 deletions
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index 0fc89069d8c7..ee894e5a45e7 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * The SH-2 exception entry | 4 | * The SH-2 exception entry |
5 | * | 5 | * |
6 | * Copyright (C) 2005,2006 Yoshinori Sato | 6 | * Copyright (C) 2005-2008 Yoshinori Sato |
7 | * Copyright (C) 2005 AXE,Inc. | 7 | * Copyright (C) 2005 AXE,Inc. |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -36,43 +36,41 @@ OFF_TRA = (16*4+6*4) | |||
36 | #include <asm/entry-macros.S> | 36 | #include <asm/entry-macros.S> |
37 | 37 | ||
38 | ENTRY(exception_handler) | 38 | ENTRY(exception_handler) |
39 | ! already saved r0/r1 | 39 | ! stack |
40 | ! r0 <- point sp | ||
41 | ! r1 | ||
42 | ! pc | ||
43 | ! sr | ||
44 | ! r0 = temporary | ||
45 | ! r1 = vector (pseudo EXPEVT / INTEVT / TRA) | ||
40 | mov.l r2,@-sp | 46 | mov.l r2,@-sp |
41 | mov.l r3,@-sp | 47 | mov.l r3,@-sp |
42 | mov r0,r1 | ||
43 | cli | 48 | cli |
44 | mov.l $cpu_mode,r2 | 49 | mov.l $cpu_mode,r2 |
45 | mov.l @r2,r0 | 50 | mov.l @r2,r0 |
46 | mov.l @(5*4,r15),r3 ! previous SR | 51 | mov.l @(5*4,r15),r3 ! previous SR |
47 | shll2 r3 ! set "S" flag | 52 | or r0,r3 ! set MD |
48 | rotl r0 ! T <- "S" flag | 53 | tst r0,r0 |
49 | rotl r0 ! "S" flag is LSB | 54 | bf/s 1f ! previous mode check |
50 | rotcr r3 ! T -> r3:b30 | 55 | mov.l r3,@(5*4,r15) ! update SR |
51 | shlr r3 | ||
52 | shlr r0 | ||
53 | bt/s 1f | ||
54 | mov.l r3,@(5*4,r15) ! copy cpu mode to SR | ||
55 | ! switch to kernel mode | 56 | ! switch to kernel mode |
56 | mov #1,r0 | 57 | mov.l __md_bit,r0 |
57 | rotr r0 | ||
58 | rotr r0 | ||
59 | mov.l r0,@r2 ! enter kernel mode | 58 | mov.l r0,@r2 ! enter kernel mode |
60 | mov.l $current_thread_info,r2 | 59 | mov.l $current_thread_info,r2 |
61 | mov.l @r2,r2 | 60 | mov.l @r2,r2 |
62 | mov #0x20,r0 | 61 | mov #(THREAD_SIZE >> 8),r0 |
63 | shll8 r0 | 62 | shll8 r0 |
64 | add r2,r0 | 63 | add r2,r0 |
65 | mov r15,r2 ! r2 = user stack top | 64 | mov r15,r2 ! r2 = user stack top |
66 | mov r0,r15 ! switch kernel stack | 65 | mov r0,r15 ! switch kernel stack |
67 | add #-4,r15 ! dummy | ||
68 | mov.l r1,@-r15 ! TRA | 66 | mov.l r1,@-r15 ! TRA |
69 | sts.l macl, @-r15 | 67 | sts.l macl, @-r15 |
70 | sts.l mach, @-r15 | 68 | sts.l mach, @-r15 |
71 | stc.l gbr, @-r15 | 69 | stc.l gbr, @-r15 |
72 | mov.l @(4*4,r2),r0 | 70 | mov.l @(5*4,r2),r0 |
73 | mov.l @(5*4,r2),r1 | 71 | mov.l r0,@-r15 ! original SR |
74 | mov.l r1,@-r15 ! original SR | ||
75 | sts.l pr,@-r15 | 72 | sts.l pr,@-r15 |
73 | mov.l @(4*4,r2),r0 | ||
76 | mov.l r0,@-r15 ! original PC | 74 | mov.l r0,@-r15 ! original PC |
77 | mov r2,r3 | 75 | mov r2,r3 |
78 | add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame | 76 | add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame |
@@ -88,14 +86,15 @@ ENTRY(exception_handler) | |||
88 | mov.l r6,@-r15 | 86 | mov.l r6,@-r15 |
89 | mov.l r5,@-r15 | 87 | mov.l r5,@-r15 |
90 | mov.l r4,@-r15 | 88 | mov.l r4,@-r15 |
89 | mov r1,r9 ! save TRA | ||
91 | mov r2,r8 ! copy user -> kernel stack | 90 | mov r2,r8 ! copy user -> kernel stack |
92 | mov.l @r8+,r3 | 91 | mov.l @(0,r8),r3 |
93 | mov.l r3,@-r15 | 92 | mov.l r3,@-r15 |
94 | mov.l @r8+,r2 | 93 | mov.l @(4,r8),r2 |
95 | mov.l r2,@-r15 | 94 | mov.l r2,@-r15 |
96 | mov.l @r8+,r1 | 95 | mov.l @(12,r8),r1 |
97 | mov.l r1,@-r15 | 96 | mov.l r1,@-r15 |
98 | mov.l @r8+,r0 | 97 | mov.l @(8,r8),r0 |
99 | bra 2f | 98 | bra 2f |
100 | mov.l r0,@-r15 | 99 | mov.l r0,@-r15 |
101 | 1: | 100 | 1: |
@@ -107,10 +106,11 @@ ENTRY(exception_handler) | |||
107 | mov.l r0,@-r15 | 106 | mov.l r0,@-r15 |
108 | mov.l @r2+,r0 ! old R2 | 107 | mov.l @r2+,r0 ! old R2 |
109 | mov.l r0,@-r15 | 108 | mov.l r0,@-r15 |
110 | mov.l @r2+,r0 ! old R1 | 109 | mov.l @(4,r2),r0 ! old R1 |
111 | mov.l r0,@-r15 | ||
112 | mov.l @r2+,r0 ! old R0 | ||
113 | mov.l r0,@-r15 | 110 | mov.l r0,@-r15 |
111 | mov.l @r2,r0 ! old R0 | ||
112 | mov.l r0,@-r15 | ||
113 | add #8,r2 | ||
114 | mov.l @r2+,r3 ! old PC | 114 | mov.l @r2+,r3 ! old PC |
115 | mov.l @r2+,r0 ! old SR | 115 | mov.l @r2+,r0 ! old SR |
116 | add #-4,r2 ! exception frame stub (sr) | 116 | add #-4,r2 ! exception frame stub (sr) |
@@ -135,14 +135,12 @@ ENTRY(exception_handler) | |||
135 | mov.l r6,@-r2 | 135 | mov.l r6,@-r2 |
136 | mov.l r5,@-r2 | 136 | mov.l r5,@-r2 |
137 | mov.l r4,@-r2 | 137 | mov.l r4,@-r2 |
138 | mov r1,r9 | ||
138 | mov.l @(OFF_R0,r15),r0 | 139 | mov.l @(OFF_R0,r15),r0 |
139 | mov.l @(OFF_R1,r15),r1 | 140 | mov.l @(OFF_R1,r15),r1 |
140 | mov.l @(OFF_R2,r15),r2 | 141 | mov.l @(OFF_R2,r15),r2 |
141 | mov.l @(OFF_R3,r15),r3 | 142 | mov.l @(OFF_R3,r15),r3 |
142 | 2: | 143 | 2: |
143 | mov #OFF_TRA,r8 | ||
144 | add r15,r8 | ||
145 | mov.l @r8,r9 | ||
146 | mov #64,r8 | 144 | mov #64,r8 |
147 | cmp/hs r8,r9 | 145 | cmp/hs r8,r9 |
148 | bt interrupt_entry ! vec >= 64 is interrupt | 146 | bt interrupt_entry ! vec >= 64 is interrupt |
@@ -150,26 +148,14 @@ ENTRY(exception_handler) | |||
150 | cmp/hs r8,r9 | 148 | cmp/hs r8,r9 |
151 | bt trap_entry ! 64 > vec >= 32 is trap | 149 | bt trap_entry ! 64 > vec >= 32 is trap |
152 | 150 | ||
153 | #if defined(CONFIG_SH_FPU) | ||
154 | mov #13,r8 | ||
155 | cmp/eq r8,r9 | ||
156 | bt 10f ! fpu | ||
157 | nop | ||
158 | #endif | ||
159 | |||
160 | mov.l 4f,r8 | 151 | mov.l 4f,r8 |
161 | mov r9,r4 | 152 | mov r9,r4 |
162 | shll2 r9 | 153 | shll2 r9 |
163 | add r9,r8 | 154 | add r9,r8 |
164 | mov.l @r8,r8 | 155 | mov.l @r8,r8 ! exception handler address |
165 | mov #0,r9 | 156 | tst r8,r8 |
166 | cmp/eq r9,r8 | ||
167 | bf 3f | 157 | bf 3f |
168 | mov.l 8f,r8 ! unhandled exception | 158 | mov.l 8f,r8 ! unhandled exception |
169 | #if defined(CONFIG_SH_FPU) | ||
170 | 10: | ||
171 | mov.l 9f, r8 ! unhandled exception | ||
172 | #endif | ||
173 | 3: | 159 | 3: |
174 | mov.l 5f,r10 | 160 | mov.l 5f,r10 |
175 | jmp @r8 | 161 | jmp @r8 |
@@ -188,10 +174,7 @@ interrupt_entry: | |||
188 | 5: .long ret_from_exception | 174 | 5: .long ret_from_exception |
189 | 6: .long ret_from_irq | 175 | 6: .long ret_from_irq |
190 | 7: .long do_IRQ | 176 | 7: .long do_IRQ |
191 | 8: .long do_exception_error | 177 | 8: .long exception_error |
192 | #ifdef CONFIG_SH_FPU | ||
193 | 9: .long fpu_error_trap_handler | ||
194 | #endif | ||
195 | 178 | ||
196 | trap_entry: | 179 | trap_entry: |
197 | mov #0x30,r8 | 180 | mov #0x30,r8 |
@@ -200,24 +183,9 @@ trap_entry: | |||
200 | add #-0x10,r9 ! convert SH2 to SH3/4 ABI | 183 | add #-0x10,r9 ! convert SH2 to SH3/4 ABI |
201 | 1: | 184 | 1: |
202 | shll2 r9 ! TRA | 185 | shll2 r9 ! TRA |
203 | mov #OFF_TRA,r8 | 186 | bra system_call ! jump common systemcall entry |
204 | add r15,r8 | 187 | mov r9,r8 |
205 | mov.l r9,@r8 | ||
206 | mov r9,r8 | ||
207 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
208 | mov.l 2f, r9 | ||
209 | jsr @r9 | ||
210 | nop | ||
211 | #endif | ||
212 | sti | ||
213 | bra system_call | ||
214 | nop | ||
215 | 188 | ||
216 | .align 2 | ||
217 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
218 | 2: .long trace_hardirqs_on | ||
219 | #endif | ||
220 | |||
221 | #if defined(CONFIG_SH_STANDARD_BIOS) | 189 | #if defined(CONFIG_SH_STANDARD_BIOS) |
222 | /* Unwind the stack and jmp to the debug entry */ | 190 | /* Unwind the stack and jmp to the debug entry */ |
223 | ENTRY(sh_bios_handler) | 191 | ENTRY(sh_bios_handler) |
@@ -240,7 +208,7 @@ ENTRY(sh_bios_handler) | |||
240 | mov.l @r2,r2 | 208 | mov.l @r2,r2 |
241 | stc sr,r3 | 209 | stc sr,r3 |
242 | mov.l r2,@r0 | 210 | mov.l r2,@r0 |
243 | mov.l r3,@r0 | 211 | mov.l r3,@(4,r0) |
244 | mov.l r1,@(8,r0) | 212 | mov.l r1,@(8,r0) |
245 | mov.l @r15+, r0 | 213 | mov.l @r15+, r0 |
246 | mov.l @r15+, r1 | 214 | mov.l @r15+, r1 |
@@ -272,22 +240,30 @@ ENTRY(address_error_trap_handler) | |||
272 | mov.l 1f,r0 | 240 | mov.l 1f,r0 |
273 | jmp @r0 | 241 | jmp @r0 |
274 | mov #0,r5 ! writeaccess is unknown | 242 | mov #0,r5 ! writeaccess is unknown |
275 | .align 2 | ||
276 | 243 | ||
244 | .align 2 | ||
277 | 1: .long do_address_error | 245 | 1: .long do_address_error |
278 | 246 | ||
279 | restore_all: | 247 | restore_all: |
280 | cli | 248 | stc sr,r0 |
281 | #ifdef CONFIG_TRACE_IRQFLAGS | 249 | or #0xf0,r0 |
282 | mov.l 1f, r0 | 250 | ldc r0,sr ! all interrupt block (same BL = 1) |
283 | jsr @r0 | 251 | ! restore special register |
284 | nop | 252 | ! overlap exception frame |
285 | #endif | 253 | mov r15,r0 |
254 | add #17*4,r0 | ||
255 | lds.l @r0+,pr | ||
256 | add #4,r0 | ||
257 | ldc.l @r0+,gbr | ||
258 | lds.l @r0+,mach | ||
259 | lds.l @r0+,macl | ||
286 | mov r15,r0 | 260 | mov r15,r0 |
287 | mov.l $cpu_mode,r2 | 261 | mov.l $cpu_mode,r2 |
288 | mov #OFF_SR,r3 | 262 | mov #OFF_SR,r3 |
289 | mov.l @(r0,r3),r1 | 263 | mov.l @(r0,r3),r1 |
290 | mov.l r1,@r2 | 264 | mov.l __md_bit,r3 |
265 | and r1,r3 ! copy MD bit | ||
266 | mov.l r3,@r2 | ||
291 | shll2 r1 ! clear MD bit | 267 | shll2 r1 ! clear MD bit |
292 | shlr2 r1 | 268 | shlr2 r1 |
293 | mov.l @(OFF_SP,r0),r2 | 269 | mov.l @(OFF_SP,r0),r2 |
@@ -297,12 +273,6 @@ restore_all: | |||
297 | mov #OFF_PC,r3 | 273 | mov #OFF_PC,r3 |
298 | mov.l @(r0,r3),r1 | 274 | mov.l @(r0,r3),r1 |
299 | mov.l r1,@r2 ! set pc | 275 | mov.l r1,@r2 ! set pc |
300 | add #4*16+4,r0 | ||
301 | lds.l @r0+,pr | ||
302 | add #4,r0 ! skip sr | ||
303 | ldc.l @r0+,gbr | ||
304 | lds.l @r0+,mach | ||
305 | lds.l @r0+,macl | ||
306 | get_current_thread_info r0, r1 | 276 | get_current_thread_info r0, r1 |
307 | mov.l $current_thread_info,r1 | 277 | mov.l $current_thread_info,r1 |
308 | mov.l r0,@r1 | 278 | mov.l r0,@r1 |
@@ -326,9 +296,8 @@ restore_all: | |||
326 | nop | 296 | nop |
327 | 297 | ||
328 | .align 2 | 298 | .align 2 |
329 | #ifdef CONFIG_TRACE_IRQFLAGS | 299 | __md_bit: |
330 | 1: .long trace_hardirqs_off | 300 | .long 0x40000000 |
331 | #endif | ||
332 | $current_thread_info: | 301 | $current_thread_info: |
333 | .long __current_thread_info | 302 | .long __current_thread_info |
334 | $cpu_mode: | 303 | $cpu_mode: |
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S index 6d285af7846c..85b0bf81fc1d 100644 --- a/arch/sh/kernel/cpu/sh2/ex.S +++ b/arch/sh/kernel/cpu/sh2/ex.S | |||
@@ -18,16 +18,17 @@ | |||
18 | exception_entry: | 18 | exception_entry: |
19 | no = 0 | 19 | no = 0 |
20 | .rept 256 | 20 | .rept 256 |
21 | mov.l r0,@-sp | 21 | mov.l r1,@-sp |
22 | mov #no,r0 | ||
23 | bra exception_trampoline | 22 | bra exception_trampoline |
24 | and #0xff,r0 | 23 | mov #no,r1 |
25 | no = no + 1 | 24 | no = no + 1 |
26 | .endr | 25 | .endr |
27 | exception_trampoline: | 26 | exception_trampoline: |
28 | mov.l r1,@-sp | 27 | mov.l r0,@-sp |
29 | mov.l $exception_handler,r1 | 28 | mov.l $exception_handler,r0 |
30 | jmp @r1 | 29 | extu.b r1,r1 |
30 | jmp @r0 | ||
31 | extu.w r1,r1 | ||
31 | 32 | ||
32 | .align 2 | 33 | .align 2 |
33 | $exception_entry: | 34 | $exception_entry: |
@@ -41,6 +42,6 @@ $exception_handler: | |||
41 | ENTRY(vbr_base) | 42 | ENTRY(vbr_base) |
42 | vector = 0 | 43 | vector = 0 |
43 | .rept 256 | 44 | .rept 256 |
44 | .long exception_entry + vector * 8 | 45 | .long exception_entry + vector * 6 |
45 | vector = vector + 1 | 46 | vector = vector + 1 |
46 | .endr | 47 | .endr |
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile index 7e2b90cfa7bf..1ab1ecf4c768 100644 --- a/arch/sh/kernel/cpu/sh2a/Makefile +++ b/arch/sh/kernel/cpu/sh2a/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-y := common.o probe.o opcode_helper.o | 5 | obj-y := common.o probe.o opcode_helper.o |
6 | 6 | ||
7 | common-y += $(addprefix ../sh2/, ex.o entry.o) | 7 | common-y += ex.o entry.o |
8 | 8 | ||
9 | obj-$(CONFIG_SH_FPU) += fpu.o | 9 | obj-$(CONFIG_SH_FPU) += fpu.o |
10 | 10 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S new file mode 100644 index 000000000000..47096dc3d206 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/entry.S | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2a/entry.S | ||
3 | * | ||
4 | * The SH-2A exception entry | ||
5 | * | ||
6 | * Copyright (C) 2008 Yoshinori Sato | ||
7 | * Based on arch/sh/kernel/cpu/sh2/entry.S | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/linkage.h> | ||
15 | #include <asm/asm-offsets.h> | ||
16 | #include <asm/thread_info.h> | ||
17 | #include <asm/cpu/mmu_context.h> | ||
18 | #include <asm/unistd.h> | ||
19 | #include <asm/errno.h> | ||
20 | #include <asm/page.h> | ||
21 | |||
22 | /* Offsets to the stack */ | ||
23 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | ||
24 | OFF_R1 = 4 /* New ABI: arg5 */ | ||
25 | OFF_R2 = 8 /* New ABI: arg6 */ | ||
26 | OFF_R3 = 12 /* New ABI: syscall_nr */ | ||
27 | OFF_R4 = 16 /* New ABI: arg0 */ | ||
28 | OFF_R5 = 20 /* New ABI: arg1 */ | ||
29 | OFF_R6 = 24 /* New ABI: arg2 */ | ||
30 | OFF_R7 = 28 /* New ABI: arg3 */ | ||
31 | OFF_SP = (15*4) | ||
32 | OFF_PC = (16*4) | ||
33 | OFF_SR = (16*4+2*4) | ||
34 | OFF_TRA = (16*4+6*4) | ||
35 | |||
36 | #include <asm/entry-macros.S> | ||
37 | |||
38 | ENTRY(exception_handler) | ||
39 | ! stack | ||
40 | ! r0 <- point sp | ||
41 | ! r1 | ||
42 | ! pc | ||
43 | ! sr | ||
44 | ! r0 = temporary | ||
45 | ! r1 = vector (pseudo EXPEVT / INTEVT / TRA) | ||
46 | mov.l r2,@-sp | ||
47 | cli | ||
48 | mov.l $cpu_mode,r2 | ||
49 | bld.b #6,@(0,r2) !previus SR.MD | ||
50 | bst.b #6,@(4*4,r15) !set cpu mode to SR.MD | ||
51 | bt 1f | ||
52 | ! switch to kernel mode | ||
53 | bset.b #6,@(0,r2) !set SR.MD | ||
54 | mov.l $current_thread_info,r2 | ||
55 | mov.l @r2,r2 | ||
56 | mov #(THREAD_SIZE >> 8),r0 | ||
57 | shll8 r0 | ||
58 | add r2,r0 ! r0 = kernel stack tail | ||
59 | mov r15,r2 ! r2 = user stack top | ||
60 | mov r0,r15 ! switch kernel stack | ||
61 | mov.l r1,@-r15 ! TRA | ||
62 | sts.l macl, @-r15 | ||
63 | sts.l mach, @-r15 | ||
64 | stc.l gbr, @-r15 | ||
65 | mov.l @(4*4,r2),r0 | ||
66 | mov.l r0,@-r15 ! original SR | ||
67 | sts.l pr,@-r15 | ||
68 | mov.l @(3*4,r2),r0 | ||
69 | mov.l r0,@-r15 ! original PC | ||
70 | mov r2,r0 | ||
71 | add #(3+2)*4,r0 ! rewind r0 - r3 + exception frame | ||
72 | lds r0,pr ! pr = original SP | ||
73 | movmu.l r3,@-r15 ! save regs | ||
74 | mov r2,r8 ! r8 = previus stack top | ||
75 | mov r1,r9 ! r9 = interrupt vector | ||
76 | ! restore previous stack | ||
77 | mov.l @r8+,r2 | ||
78 | mov.l @r8+,r0 | ||
79 | mov.l @r8+,r1 | ||
80 | bra 2f | ||
81 | movml.l r2,@-r15 | ||
82 | 1: | ||
83 | ! in kernel exception | ||
84 | mov r15,r2 | ||
85 | add #-((OFF_TRA + 4) - OFF_PC) + 5*4,r15 | ||
86 | movmu.l r3,@-r15 | ||
87 | mov r2,r8 ! r8 = previous stack top | ||
88 | mov r1,r9 ! r9 = interrupt vector | ||
89 | ! restore exception frame & regs | ||
90 | mov.l @r8+,r2 ! old R2 | ||
91 | mov.l @r8+,r0 ! old R0 | ||
92 | mov.l @r8+,r1 ! old R1 | ||
93 | mov.l @r8+,r10 ! old PC | ||
94 | mov.l @r8+,r11 ! old SR | ||
95 | movml.l r2,@-r15 | ||
96 | mov.l r10,@(OFF_PC,r15) | ||
97 | mov.l r11,@(OFF_SR,r15) | ||
98 | mov.l r8,@(OFF_SP,r15) ! save old sp | ||
99 | mov r15,r8 | ||
100 | add #OFF_TRA + 4,r8 | ||
101 | mov.l r9,@-r8 | ||
102 | sts.l macl,@-r8 | ||
103 | sts.l mach,@-r8 | ||
104 | stc.l gbr,@-r8 | ||
105 | add #-4,r8 | ||
106 | sts.l pr,@-r8 | ||
107 | 2: | ||
108 | ! dispatch exception / interrupt | ||
109 | mov #64,r8 | ||
110 | cmp/hs r8,r9 | ||
111 | bt interrupt_entry ! vec >= 64 is interrupt | ||
112 | mov #32,r8 | ||
113 | cmp/hs r8,r9 | ||
114 | bt trap_entry ! 64 > vec >= 32 is trap | ||
115 | |||
116 | mov.l 4f,r8 | ||
117 | mov r9,r4 | ||
118 | shll2 r9 | ||
119 | add r9,r8 | ||
120 | mov.l @r8,r8 ! exception handler address | ||
121 | tst r8,r8 | ||
122 | bf 3f | ||
123 | mov.l 8f,r8 ! unhandled exception | ||
124 | 3: | ||
125 | mov.l 5f,r10 | ||
126 | jmp @r8 | ||
127 | lds r10,pr | ||
128 | |||
129 | interrupt_entry: | ||
130 | mov r9,r4 | ||
131 | mov r15,r5 | ||
132 | mov.l 7f,r8 | ||
133 | mov.l 6f,r9 | ||
134 | jmp @r8 | ||
135 | lds r9,pr | ||
136 | |||
137 | .align 2 | ||
138 | 4: .long exception_handling_table | ||
139 | 5: .long ret_from_exception | ||
140 | 6: .long ret_from_irq | ||
141 | 7: .long do_IRQ | ||
142 | 8: .long exception_error | ||
143 | |||
144 | trap_entry: | ||
145 | mov #0x30,r8 | ||
146 | cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall | ||
147 | bt 1f | ||
148 | add #-0x10,r9 ! convert SH2 to SH3/4 ABI | ||
149 | 1: | ||
150 | shll2 r9 ! TRA | ||
151 | bra system_call ! jump common systemcall entry | ||
152 | mov r9,r8 | ||
153 | |||
154 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
155 | /* Unwind the stack and jmp to the debug entry */ | ||
156 | ENTRY(sh_bios_handler) | ||
157 | mov r15,r0 | ||
158 | add #(22-4)*4-4,r0 | ||
159 | ldc.l @r0+,gbr | ||
160 | lds.l @r0+,mach | ||
161 | lds.l @r0+,macl | ||
162 | mov r15,r0 | ||
163 | mov.l @(OFF_SP,r0),r1 | ||
164 | mov.l @(OFF_SR,r2),r3 | ||
165 | mov.l r3,@-r1 | ||
166 | mov.l @(OFF_SP,r2),r3 | ||
167 | mov.l r3,@-r1 | ||
168 | mov r15,r0 | ||
169 | add #(22-4)*4-8,r0 | ||
170 | mov.l 1f,r2 | ||
171 | mov.l @r2,r2 | ||
172 | stc sr,r3 | ||
173 | mov.l r2,@r0 | ||
174 | mov.l r3,@(4,r0) | ||
175 | mov.l r1,@(8,r0) | ||
176 | movml.l @r15+,r14 | ||
177 | add #8,r15 | ||
178 | lds.l @r15+, pr | ||
179 | rte | ||
180 | mov.l @r15+,r15 | ||
181 | .align 2 | ||
182 | 1: .long gdb_vbr_vector | ||
183 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
184 | |||
185 | ENTRY(address_error_trap_handler) | ||
186 | mov r15,r4 ! regs | ||
187 | mov.l @(OFF_PC,r15),r6 ! pc | ||
188 | mov.l 1f,r0 | ||
189 | jmp @r0 | ||
190 | mov #0,r5 ! writeaccess is unknown | ||
191 | |||
192 | .align 2 | ||
193 | 1: .long do_address_error | ||
194 | |||
195 | restore_all: | ||
196 | stc sr,r0 | ||
197 | or #0xf0,r0 | ||
198 | ldc r0,sr ! all interrupt block (same BL = 1) | ||
199 | ! restore special register | ||
200 | ! overlap exception frame | ||
201 | mov r15,r0 | ||
202 | add #17*4,r0 | ||
203 | lds.l @r0+,pr | ||
204 | add #4,r0 | ||
205 | ldc.l @r0+,gbr | ||
206 | lds.l @r0+,mach | ||
207 | lds.l @r0+,macl | ||
208 | mov r15,r0 | ||
209 | mov.l $cpu_mode,r2 | ||
210 | bld.b #6,@(OFF_SR,r15) | ||
211 | bst.b #6,@(0,r2) ! save CPU mode | ||
212 | mov.l @(OFF_SR,r0),r1 | ||
213 | shll2 r1 | ||
214 | shlr2 r1 ! clear MD bit | ||
215 | mov.l @(OFF_SP,r0),r2 | ||
216 | add #-8,r2 | ||
217 | mov.l r2,@(OFF_SP,r0) ! point exception frame top | ||
218 | mov.l r1,@(4,r2) ! set sr | ||
219 | mov.l @(OFF_PC,r0),r1 | ||
220 | mov.l r1,@r2 ! set pc | ||
221 | get_current_thread_info r0, r1 | ||
222 | mov.l $current_thread_info,r1 | ||
223 | mov.l r0,@r1 | ||
224 | movml.l @r15+,r14 | ||
225 | mov.l @r15,r15 | ||
226 | rte | ||
227 | nop | ||
228 | |||
229 | .align 2 | ||
230 | $current_thread_info: | ||
231 | .long __current_thread_info | ||
232 | $cpu_mode: | ||
233 | .long __cpu_mode | ||
234 | |||
235 | ! common exception handler | ||
236 | #include "../../entry-common.S" | ||
237 | |||
238 | .data | ||
239 | ! cpu operation mode | ||
240 | ! bit30 = MD (compatible SH3/4) | ||
241 | __cpu_mode: | ||
242 | .long 0x40000000 | ||
243 | |||
244 | .section .bss | ||
245 | __current_thread_info: | ||
246 | .long 0 | ||
247 | |||
248 | ENTRY(exception_handling_table) | ||
249 | .space 4*32 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/ex.S b/arch/sh/kernel/cpu/sh2a/ex.S new file mode 100644 index 000000000000..3ead9e63965a --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/ex.S | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2a/ex.S | ||
3 | * | ||
4 | * The SH-2A exception vector table | ||
5 | * | ||
6 | * Copyright (C) 2008 Yoshinori Sato | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/linkage.h> | ||
14 | |||
15 | ! | ||
16 | ! convert Exception Vector to Exception Number | ||
17 | ! | ||
18 | |||
19 | ! exception no 0 to 255 | ||
20 | exception_entry0: | ||
21 | no = 0 | ||
22 | .rept 256 | ||
23 | mov.l r1,@-sp | ||
24 | bra exception_trampoline0 | ||
25 | mov #no,r1 | ||
26 | no = no + 1 | ||
27 | .endr | ||
28 | exception_trampoline0: | ||
29 | mov.l r0,@-sp | ||
30 | mov.l 1f,r0 | ||
31 | extu.b r1,r1 | ||
32 | jmp @r0 | ||
33 | extu.w r1,r1 | ||
34 | |||
35 | .align 2 | ||
36 | 1: .long exception_handler | ||
37 | |||
38 | ! exception no 256 to 511 | ||
39 | exception_entry1: | ||
40 | no = 0 | ||
41 | .rept 256 | ||
42 | mov.l r1,@-sp | ||
43 | bra exception_trampoline1 | ||
44 | mov #no,r1 | ||
45 | no = no + 1 | ||
46 | .endr | ||
47 | exception_trampoline1: | ||
48 | mov.l r0,@-sp | ||
49 | extu.b r1,r1 | ||
50 | movi20 #0x100,r0 | ||
51 | add r0,r1 | ||
52 | mov.l 1f,r0 | ||
53 | jmp @r0 | ||
54 | extu.w r1,r1 | ||
55 | |||
56 | .align 2 | ||
57 | 1: .long exception_handler | ||
58 | |||
59 | ! | ||
60 | ! Exception Vector Base | ||
61 | ! | ||
62 | .align 2 | ||
63 | ENTRY(vbr_base) | ||
64 | vector = 0 | ||
65 | .rept 256 | ||
66 | .long exception_entry0 + vector * 6 | ||
67 | vector = vector + 1 | ||
68 | .endr | ||
69 | .rept 256 | ||
70 | .long exception_entry1 + vector * 6 | ||
71 | vector = vector + 1 | ||
72 | .endr | ||
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index e08b3bfeb656..511a9426cec5 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -43,6 +43,7 @@ | |||
43 | # define TRAP_ILLEGAL_SLOT_INST 6 | 43 | # define TRAP_ILLEGAL_SLOT_INST 6 |
44 | # define TRAP_ADDRESS_ERROR 9 | 44 | # define TRAP_ADDRESS_ERROR 9 |
45 | # ifdef CONFIG_CPU_SH2A | 45 | # ifdef CONFIG_CPU_SH2A |
46 | # define TRAP_FPU_ERROR 13 | ||
46 | # define TRAP_DIVZERO_ERROR 17 | 47 | # define TRAP_DIVZERO_ERROR 17 |
47 | # define TRAP_DIVOVF_ERROR 18 | 48 | # define TRAP_DIVOVF_ERROR 18 |
48 | # endif | 49 | # endif |
@@ -851,6 +852,9 @@ void __init trap_init(void) | |||
851 | #ifdef CONFIG_CPU_SH2A | 852 | #ifdef CONFIG_CPU_SH2A |
852 | set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); | 853 | set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); |
853 | set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); | 854 | set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); |
855 | #ifdef CONFIG_SH_FPU | ||
856 | set_exception_table_vec(TRAP_FPU_ERROR, fpu_error_trap_handler); | ||
857 | #endif | ||
854 | #endif | 858 | #endif |
855 | 859 | ||
856 | /* Setup VBR for boot cpu */ | 860 | /* Setup VBR for boot cpu */ |