diff options
author | Yoshinori Sato <ysato@users.sourceforge.jp> | 2006-11-05 02:15:19 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-12-05 20:45:36 -0500 |
commit | de39840646a223ae13a346048c280b7c871bf56e (patch) | |
tree | aa2449880c12310ccb92540bfd63e43e8a568745 | |
parent | 0983b31849bbe1fe82520947acc1bec97c457d4b (diff) |
sh: Exception vector rework and SH-2/SH-2A support.
This splits out common bits from the existing exception handler for
use between SH-2/SH-2A and SH-3/4, and adds support for the SH-2/2A
exceptions.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/kernel/cpu/sh2/entry.S | 325 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2/ex.S | 46 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S (renamed from arch/sh/kernel/entry.S) | 339 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/Makefile | 3 | ||||
-rw-r--r-- | arch/sh/kernel/entry-common.S | 372 | ||||
-rw-r--r-- | arch/sh/kernel/head.S | 12 |
7 files changed, 767 insertions, 332 deletions
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S new file mode 100644 index 000000000000..298d9191909d --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2/entry.S | ||
3 | * | ||
4 | * The SH-2 exception entry | ||
5 | * | ||
6 | * Copyright (C) 2005,2006 Yoshinori Sato | ||
7 | * Copyright (C) 2005 AXE,Inc. | ||
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 | ! already saved r0/r1 | ||
40 | mov.l r2,@-sp | ||
41 | mov.l r3,@-sp | ||
42 | mov r0,r1 | ||
43 | cli | ||
44 | mov.l $cpu_mode,r2 | ||
45 | mov.l @r2,r0 | ||
46 | mov.l @(5*4,r15),r3 ! previous SR | ||
47 | shll2 r3 ! set "S" flag | ||
48 | rotl r0 ! T <- "S" flag | ||
49 | rotl r0 ! "S" flag is LSB | ||
50 | rotcr r3 ! T -> r3:b30 | ||
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 | mov #1,r0 | ||
57 | rotr r0 | ||
58 | rotr r0 | ||
59 | mov.l r0,@r2 ! enter kernel mode | ||
60 | mov.l $current_thread_info,r2 | ||
61 | mov.l @r2,r2 | ||
62 | mov #0x20,r0 | ||
63 | shll8 r0 | ||
64 | add r2,r0 | ||
65 | mov r15,r2 ! r2 = user stack top | ||
66 | mov r0,r15 ! switch kernel stack | ||
67 | add #-4,r15 ! dummy | ||
68 | mov.l r1,@-r15 ! TRA | ||
69 | sts.l macl, @-r15 | ||
70 | sts.l mach, @-r15 | ||
71 | stc.l gbr, @-r15 | ||
72 | mov.l @(4*4,r2),r0 | ||
73 | mov.l @(5*4,r2),r1 | ||
74 | mov.l r1,@-r15 ! original SR | ||
75 | sts.l pr,@-r15 | ||
76 | mov.l r0,@-r15 ! original PC | ||
77 | mov r2,r3 | ||
78 | add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame | ||
79 | mov.l r3,@-r15 ! original SP | ||
80 | mov.l r14,@-r15 | ||
81 | mov.l r13,@-r15 | ||
82 | mov.l r12,@-r15 | ||
83 | mov.l r11,@-r15 | ||
84 | mov.l r10,@-r15 | ||
85 | mov.l r9,@-r15 | ||
86 | mov.l r8,@-r15 | ||
87 | mov.l r7,@-r15 | ||
88 | mov.l r6,@-r15 | ||
89 | mov.l r5,@-r15 | ||
90 | mov.l r4,@-r15 | ||
91 | mov r2,r8 ! copy user -> kernel stack | ||
92 | mov.l @r8+,r3 | ||
93 | mov.l r3,@-r15 | ||
94 | mov.l @r8+,r2 | ||
95 | mov.l r2,@-r15 | ||
96 | mov.l @r8+,r1 | ||
97 | mov.l r1,@-r15 | ||
98 | mov.l @r8+,r0 | ||
99 | bra 2f | ||
100 | mov.l r0,@-r15 | ||
101 | 1: | ||
102 | ! in kernel exception | ||
103 | mov #(22-4-4-1)*4+4,r0 | ||
104 | mov r15,r2 | ||
105 | sub r0,r15 | ||
106 | mov.l @r2+,r0 ! old R3 | ||
107 | mov.l r0,@-r15 | ||
108 | mov.l @r2+,r0 ! old R2 | ||
109 | mov.l r0,@-r15 | ||
110 | mov.l @r2+,r0 ! old R1 | ||
111 | mov.l r0,@-r15 | ||
112 | mov.l @r2+,r0 ! old R0 | ||
113 | mov.l r0,@-r15 | ||
114 | mov.l @r2+,r3 ! old PC | ||
115 | mov.l @r2+,r0 ! old SR | ||
116 | add #-4,r2 ! exception frame stub (sr) | ||
117 | mov.l r1,@-r2 ! TRA | ||
118 | sts.l macl, @-r2 | ||
119 | sts.l mach, @-r2 | ||
120 | stc.l gbr, @-r2 | ||
121 | mov.l r0,@-r2 ! save old SR | ||
122 | sts.l pr,@-r2 | ||
123 | mov.l r3,@-r2 ! save old PC | ||
124 | mov r2,r0 | ||
125 | add #8*4,r0 | ||
126 | mov.l r0,@-r2 ! save old SP | ||
127 | mov.l r14,@-r2 | ||
128 | mov.l r13,@-r2 | ||
129 | mov.l r12,@-r2 | ||
130 | mov.l r11,@-r2 | ||
131 | mov.l r10,@-r2 | ||
132 | mov.l r9,@-r2 | ||
133 | mov.l r8,@-r2 | ||
134 | mov.l r7,@-r2 | ||
135 | mov.l r6,@-r2 | ||
136 | mov.l r5,@-r2 | ||
137 | mov.l r4,@-r2 | ||
138 | mov.l @(OFF_R0,r15),r0 | ||
139 | mov.l @(OFF_R1,r15),r1 | ||
140 | mov.l @(OFF_R2,r15),r2 | ||
141 | mov.l @(OFF_R3,r15),r3 | ||
142 | 2: | ||
143 | mov #OFF_TRA,r8 | ||
144 | add r15,r8 | ||
145 | mov.l @r8,r9 | ||
146 | mov #64,r8 | ||
147 | cmp/hs r8,r9 | ||
148 | bt interrupt_entry ! vec >= 64 is interrupt | ||
149 | mov #32,r8 | ||
150 | cmp/hs r8,r9 | ||
151 | bt trap_entry ! 64 > vec >= 32 is trap | ||
152 | mov.l 4f,r8 | ||
153 | mov r9,r4 | ||
154 | shll2 r9 | ||
155 | add r9,r8 | ||
156 | mov.l @r8,r8 | ||
157 | mov #0,r9 | ||
158 | cmp/eq r9,r8 | ||
159 | bf 3f | ||
160 | mov.l 8f,r8 ! unhandled exception | ||
161 | 3: | ||
162 | mov.l 5f,r10 | ||
163 | jmp @r8 | ||
164 | lds r10,pr | ||
165 | |||
166 | interrupt_entry: | ||
167 | mov r9,r4 | ||
168 | mov.l 6f,r9 | ||
169 | mov.l 7f,r8 | ||
170 | jmp @r8 | ||
171 | lds r9,pr | ||
172 | |||
173 | .align 2 | ||
174 | 4: .long exception_handling_table | ||
175 | 5: .long ret_from_exception | ||
176 | 6: .long ret_from_irq | ||
177 | 7: .long do_IRQ | ||
178 | 8: .long do_exception_error | ||
179 | |||
180 | trap_entry: | ||
181 | add #-0x10,r9 | ||
182 | shll2 r9 ! TRA | ||
183 | mov #OFF_TRA,r8 | ||
184 | add r15,r8 | ||
185 | mov.l r9,@r8 | ||
186 | mov r9,r8 | ||
187 | sti | ||
188 | bra system_call | ||
189 | nop | ||
190 | |||
191 | .align 2 | ||
192 | 1: .long syscall_exit | ||
193 | 2: .long break_point_trap_software | ||
194 | 3: .long NR_syscalls | ||
195 | 4: .long sys_call_table | ||
196 | |||
197 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
198 | /* Unwind the stack and jmp to the debug entry */ | ||
199 | debug_kernel_fw: | ||
200 | mov r15,r0 | ||
201 | add #(22-4)*4-4,r0 | ||
202 | ldc.l @r0+,gbr | ||
203 | lds.l @r0+,mach | ||
204 | lds.l @r0+,macl | ||
205 | mov r15,r0 | ||
206 | mov.l @(OFF_SP,r0),r1 | ||
207 | mov #OFF_SR,r2 | ||
208 | mov.l @(r0,r2),r3 | ||
209 | mov.l r3,@-r1 | ||
210 | mov #OFF_SP,r2 | ||
211 | mov.l @(r0,r2),r3 | ||
212 | mov.l r3,@-r1 | ||
213 | mov r15,r0 | ||
214 | add #(22-4)*4-8,r0 | ||
215 | mov.l 1f,r2 | ||
216 | mov.l @r2,r2 | ||
217 | stc sr,r3 | ||
218 | mov.l r2,@r0 | ||
219 | mov.l r3,@r0 | ||
220 | mov.l r1,@(8,r0) | ||
221 | mov.l @r15+, r0 | ||
222 | mov.l @r15+, r1 | ||
223 | mov.l @r15+, r2 | ||
224 | mov.l @r15+, r3 | ||
225 | mov.l @r15+, r4 | ||
226 | mov.l @r15+, r5 | ||
227 | mov.l @r15+, r6 | ||
228 | mov.l @r15+, r7 | ||
229 | mov.l @r15+, r8 | ||
230 | mov.l @r15+, r9 | ||
231 | mov.l @r15+, r10 | ||
232 | mov.l @r15+, r11 | ||
233 | mov.l @r15+, r12 | ||
234 | mov.l @r15+, r13 | ||
235 | mov.l @r15+, r14 | ||
236 | add #8,r15 | ||
237 | lds.l @r15+, pr | ||
238 | rte | ||
239 | mov.l @r15+,r15 | ||
240 | .align 2 | ||
241 | 1: .long gdb_vbr_vector | ||
242 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
243 | |||
244 | ENTRY(address_error_handler) | ||
245 | mov r15,r4 ! regs | ||
246 | add #4,r4 | ||
247 | mov #OFF_PC,r0 | ||
248 | mov.l @(r0,r15),r6 ! pc | ||
249 | mov.l 1f,r0 | ||
250 | jmp @r0 | ||
251 | mov #0,r5 ! writeaccess is unknown | ||
252 | .align 2 | ||
253 | |||
254 | 1: .long do_address_error | ||
255 | |||
256 | restore_all: | ||
257 | cli | ||
258 | mov r15,r0 | ||
259 | mov.l $cpu_mode,r2 | ||
260 | mov #OFF_SR,r3 | ||
261 | mov.l @(r0,r3),r1 | ||
262 | mov.l r1,@r2 | ||
263 | shll2 r1 ! clear MD bit | ||
264 | shlr2 r1 | ||
265 | mov.l @(OFF_SP,r0),r2 | ||
266 | add #-8,r2 | ||
267 | mov.l r2,@(OFF_SP,r0) ! point exception frame top | ||
268 | mov.l r1,@(4,r2) ! set sr | ||
269 | mov #OFF_PC,r3 | ||
270 | mov.l @(r0,r3),r1 | ||
271 | mov.l r1,@r2 ! set pc | ||
272 | add #4*16+4,r0 | ||
273 | lds.l @r0+,pr | ||
274 | add #4,r0 ! skip sr | ||
275 | ldc.l @r0+,gbr | ||
276 | lds.l @r0+,mach | ||
277 | lds.l @r0+,macl | ||
278 | get_current_thread_info r0, r1 | ||
279 | mov.l $current_thread_info,r1 | ||
280 | mov.l r0,@r1 | ||
281 | mov.l @r15+,r0 | ||
282 | mov.l @r15+,r1 | ||
283 | mov.l @r15+,r2 | ||
284 | mov.l @r15+,r3 | ||
285 | mov.l @r15+,r4 | ||
286 | mov.l @r15+,r5 | ||
287 | mov.l @r15+,r6 | ||
288 | mov.l @r15+,r7 | ||
289 | mov.l @r15+,r8 | ||
290 | mov.l @r15+,r9 | ||
291 | mov.l @r15+,r10 | ||
292 | mov.l @r15+,r11 | ||
293 | mov.l @r15+,r12 | ||
294 | mov.l @r15+,r13 | ||
295 | mov.l @r15+,r14 | ||
296 | mov.l @r15,r15 | ||
297 | rte | ||
298 | nop | ||
299 | 2: | ||
300 | mov.l 1f,r8 | ||
301 | mov.l 2f,r9 | ||
302 | jmp @r9 | ||
303 | lds r8,pr | ||
304 | |||
305 | .align 2 | ||
306 | $current_thread_info: | ||
307 | .long __current_thread_info | ||
308 | $cpu_mode: | ||
309 | .long __cpu_mode | ||
310 | |||
311 | ! common exception handler | ||
312 | #include "../../entry-common.S" | ||
313 | |||
314 | .data | ||
315 | ! cpu operation mode | ||
316 | ! bit30 = MD (compatible SH3/4) | ||
317 | __cpu_mode: | ||
318 | .long 0x40000000 | ||
319 | |||
320 | .section .bss | ||
321 | __current_thread_info: | ||
322 | .long 0 | ||
323 | |||
324 | ENTRY(exception_handling_table) | ||
325 | .space 4*32 | ||
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S new file mode 100644 index 000000000000..6d285af7846c --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/ex.S | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2/ex.S | ||
3 | * | ||
4 | * The SH-2 exception vector table | ||
5 | * | ||
6 | * Copyright (C) 2005 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 | exception_entry: | ||
19 | no = 0 | ||
20 | .rept 256 | ||
21 | mov.l r0,@-sp | ||
22 | mov #no,r0 | ||
23 | bra exception_trampoline | ||
24 | and #0xff,r0 | ||
25 | no = no + 1 | ||
26 | .endr | ||
27 | exception_trampoline: | ||
28 | mov.l r1,@-sp | ||
29 | mov.l $exception_handler,r1 | ||
30 | jmp @r1 | ||
31 | |||
32 | .align 2 | ||
33 | $exception_entry: | ||
34 | .long exception_entry | ||
35 | $exception_handler: | ||
36 | .long exception_handler | ||
37 | ! | ||
38 | ! Exception Vector Base | ||
39 | ! | ||
40 | .align 2 | ||
41 | ENTRY(vbr_base) | ||
42 | vector = 0 | ||
43 | .rept 256 | ||
44 | .long exception_entry + vector * 8 | ||
45 | vector = vector + 1 | ||
46 | .endr | ||
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 58d3815695ff..83905e4e4387 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the Linux/SuperH SH-3 backends. | 2 | # Makefile for the Linux/SuperH SH-3 backends. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | # CPU subtype setup | 7 | # CPU subtype setup |
8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o | 8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o |
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 39aaefb2d83f..8bcd63f9f351 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/sh/entry.S | 2 | * arch/sh/kernel/entry.S |
3 | * | 3 | * |
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
5 | * Copyright (C) 2003 - 2006 Paul Mundt | 5 | * Copyright (C) 2003 - 2006 Paul Mundt |
@@ -7,7 +7,6 @@ | |||
7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
9 | * for more details. | 9 | * for more details. |
10 | * | ||
11 | */ | 10 | */ |
12 | #include <linux/sys.h> | 11 | #include <linux/sys.h> |
13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
@@ -81,6 +80,8 @@ OFF_TRA = (16*4+6*4) | |||
81 | #define k_g_imask r6_bank /* r6_bank1 */ | 80 | #define k_g_imask r6_bank /* r6_bank1 */ |
82 | #define current r7 /* r7_bank1 */ | 81 | #define current r7 /* r7_bank1 */ |
83 | 82 | ||
83 | #include <asm/entry-macros.S> | ||
84 | |||
84 | /* | 85 | /* |
85 | * Kernel mode register usage: | 86 | * Kernel mode register usage: |
86 | * k0 scratch | 87 | * k0 scratch |
@@ -107,26 +108,6 @@ OFF_TRA = (16*4+6*4) | |||
107 | ! this first version depends *much* on C implementation. | 108 | ! this first version depends *much* on C implementation. |
108 | ! | 109 | ! |
109 | 110 | ||
110 | #define CLI() \ | ||
111 | stc sr, r0; \ | ||
112 | or #0xf0, r0; \ | ||
113 | ldc r0, sr | ||
114 | |||
115 | #define STI() \ | ||
116 | mov.l __INV_IMASK, r11; \ | ||
117 | stc sr, r10; \ | ||
118 | and r11, r10; \ | ||
119 | stc k_g_imask, r11; \ | ||
120 | or r11, r10; \ | ||
121 | ldc r10, sr | ||
122 | |||
123 | #if defined(CONFIG_PREEMPT) | ||
124 | # define preempt_stop() CLI() | ||
125 | #else | ||
126 | # define preempt_stop() | ||
127 | # define resume_kernel restore_all | ||
128 | #endif | ||
129 | |||
130 | #if defined(CONFIG_MMU) | 111 | #if defined(CONFIG_MMU) |
131 | .align 2 | 112 | .align 2 |
132 | ENTRY(tlb_miss_load) | 113 | ENTRY(tlb_miss_load) |
@@ -168,7 +149,7 @@ call_dpf: | |||
168 | lds r10, pr | 149 | lds r10, pr |
169 | rts | 150 | rts |
170 | nop | 151 | nop |
171 | 0: STI() | 152 | 0: sti |
172 | mov.l 3f, r0 | 153 | mov.l 3f, r0 |
173 | mov r9, r6 | 154 | mov r9, r6 |
174 | mov r8, r5 | 155 | mov r8, r5 |
@@ -203,32 +184,6 @@ call_dae: | |||
203 | 2: .long do_address_error | 184 | 2: .long do_address_error |
204 | #endif /* CONFIG_MMU */ | 185 | #endif /* CONFIG_MMU */ |
205 | 186 | ||
206 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
207 | ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. | ||
208 | ! If both are configured, handle the debug traps (breakpoints) in SW, | ||
209 | ! but still allow BIOS traps to FW. | ||
210 | |||
211 | .align 2 | ||
212 | debug_kernel: | ||
213 | #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) | ||
214 | /* Force BIOS call to FW (debug_trap put TRA in r8) */ | ||
215 | mov r8,r0 | ||
216 | shlr2 r0 | ||
217 | cmp/eq #0x3f,r0 | ||
218 | bt debug_kernel_fw | ||
219 | #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ | ||
220 | |||
221 | debug_enter: | ||
222 | #if defined(CONFIG_SH_KGDB) | ||
223 | /* Jump to kgdb, pass stacked regs as arg */ | ||
224 | debug_kernel_sw: | ||
225 | mov.l 3f, r0 | ||
226 | jmp @r0 | ||
227 | mov r15, r4 | ||
228 | .align 2 | ||
229 | 3: .long kgdb_handle_exception | ||
230 | #endif /* CONFIG_SH_KGDB */ | ||
231 | |||
232 | #if defined(CONFIG_SH_STANDARD_BIOS) | 187 | #if defined(CONFIG_SH_STANDARD_BIOS) |
233 | /* Unwind the stack and jmp to the debug entry */ | 188 | /* Unwind the stack and jmp to the debug entry */ |
234 | debug_kernel_fw: | 189 | debug_kernel_fw: |
@@ -269,276 +224,6 @@ debug_kernel_fw: | |||
269 | 2: .long gdb_vbr_vector | 224 | 2: .long gdb_vbr_vector |
270 | #endif /* CONFIG_SH_STANDARD_BIOS */ | 225 | #endif /* CONFIG_SH_STANDARD_BIOS */ |
271 | 226 | ||
272 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
273 | |||
274 | |||
275 | .align 2 | ||
276 | debug_trap: | ||
277 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
278 | mov #OFF_SR, r0 | ||
279 | mov.l @(r0,r15), r0 ! get status register | ||
280 | shll r0 | ||
281 | shll r0 ! kernel space? | ||
282 | bt/s debug_kernel | ||
283 | #endif | ||
284 | mov.l @r15, r0 ! Restore R0 value | ||
285 | mov.l 1f, r8 | ||
286 | jmp @r8 | ||
287 | nop | ||
288 | |||
289 | .align 2 | ||
290 | ENTRY(exception_error) | ||
291 | ! | ||
292 | STI() | ||
293 | mov.l 2f, r0 | ||
294 | jmp @r0 | ||
295 | nop | ||
296 | |||
297 | ! | ||
298 | .align 2 | ||
299 | 1: .long break_point_trap_software | ||
300 | 2: .long do_exception_error | ||
301 | |||
302 | .align 2 | ||
303 | ret_from_exception: | ||
304 | preempt_stop() | ||
305 | ENTRY(ret_from_irq) | ||
306 | ! | ||
307 | mov #OFF_SR, r0 | ||
308 | mov.l @(r0,r15), r0 ! get status register | ||
309 | shll r0 | ||
310 | shll r0 ! kernel space? | ||
311 | bt/s resume_kernel ! Yes, it's from kernel, go back soon | ||
312 | GET_THREAD_INFO(r8) | ||
313 | |||
314 | #ifdef CONFIG_PREEMPT | ||
315 | bra resume_userspace | ||
316 | nop | ||
317 | ENTRY(resume_kernel) | ||
318 | mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count | ||
319 | tst r0, r0 | ||
320 | bf noresched | ||
321 | need_resched: | ||
322 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
323 | tst #_TIF_NEED_RESCHED, r0 ! need_resched set? | ||
324 | bt noresched | ||
325 | |||
326 | mov #OFF_SR, r0 | ||
327 | mov.l @(r0,r15), r0 ! get status register | ||
328 | and #0xf0, r0 ! interrupts off (exception path)? | ||
329 | cmp/eq #0xf0, r0 | ||
330 | bt noresched | ||
331 | |||
332 | mov.l 1f, r0 | ||
333 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
334 | |||
335 | STI() | ||
336 | mov.l 2f, r0 | ||
337 | jsr @r0 | ||
338 | nop | ||
339 | mov #0, r0 | ||
340 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
341 | CLI() | ||
342 | |||
343 | bra need_resched | ||
344 | nop | ||
345 | noresched: | ||
346 | bra restore_all | ||
347 | nop | ||
348 | |||
349 | .align 2 | ||
350 | 1: .long PREEMPT_ACTIVE | ||
351 | 2: .long schedule | ||
352 | #endif | ||
353 | |||
354 | ENTRY(resume_userspace) | ||
355 | ! r8: current_thread_info | ||
356 | CLI() | ||
357 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
358 | tst #_TIF_WORK_MASK, r0 | ||
359 | bt/s restore_all | ||
360 | tst #_TIF_NEED_RESCHED, r0 | ||
361 | |||
362 | .align 2 | ||
363 | work_pending: | ||
364 | ! r0: current_thread_info->flags | ||
365 | ! r8: current_thread_info | ||
366 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" | ||
367 | bf/s work_resched | ||
368 | tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 | ||
369 | work_notifysig: | ||
370 | bt/s restore_all | ||
371 | mov r15, r4 | ||
372 | mov r12, r5 ! set arg1(save_r0) | ||
373 | mov r0, r6 | ||
374 | mov.l 2f, r1 | ||
375 | mova restore_all, r0 | ||
376 | jmp @r1 | ||
377 | lds r0, pr | ||
378 | work_resched: | ||
379 | #ifndef CONFIG_PREEMPT | ||
380 | ! gUSA handling | ||
381 | mov.l @(OFF_SP,r15), r0 ! get user space stack pointer | ||
382 | mov r0, r1 | ||
383 | shll r0 | ||
384 | bf/s 1f | ||
385 | shll r0 | ||
386 | bf/s 1f | ||
387 | mov #OFF_PC, r0 | ||
388 | ! SP >= 0xc0000000 : gUSA mark | ||
389 | mov.l @(r0,r15), r2 ! get user space PC (program counter) | ||
390 | mov.l @(OFF_R0,r15), r3 ! end point | ||
391 | cmp/hs r3, r2 ! r2 >= r3? | ||
392 | bt 1f | ||
393 | add r3, r1 ! rewind point #2 | ||
394 | mov.l r1, @(r0,r15) ! reset PC to rewind point #2 | ||
395 | ! | ||
396 | 1: | ||
397 | #endif | ||
398 | mov.l 1f, r1 | ||
399 | jsr @r1 ! schedule | ||
400 | nop | ||
401 | CLI() | ||
402 | ! | ||
403 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
404 | tst #_TIF_WORK_MASK, r0 | ||
405 | bt restore_all | ||
406 | bra work_pending | ||
407 | tst #_TIF_NEED_RESCHED, r0 | ||
408 | |||
409 | .align 2 | ||
410 | 1: .long schedule | ||
411 | 2: .long do_notify_resume | ||
412 | |||
413 | .align 2 | ||
414 | syscall_exit_work: | ||
415 | ! r0: current_thread_info->flags | ||
416 | ! r8: current_thread_info | ||
417 | tst #_TIF_SYSCALL_TRACE, r0 | ||
418 | bt/s work_pending | ||
419 | tst #_TIF_NEED_RESCHED, r0 | ||
420 | STI() | ||
421 | ! XXX setup arguments... | ||
422 | mov.l 4f, r0 ! do_syscall_trace | ||
423 | jsr @r0 | ||
424 | nop | ||
425 | bra resume_userspace | ||
426 | nop | ||
427 | |||
428 | .align 2 | ||
429 | syscall_trace_entry: | ||
430 | ! Yes it is traced. | ||
431 | ! XXX setup arguments... | ||
432 | mov.l 4f, r11 ! Call do_syscall_trace which notifies | ||
433 | jsr @r11 ! superior (will chomp R[0-7]) | ||
434 | nop | ||
435 | ! Reload R0-R4 from kernel stack, where the | ||
436 | ! parent may have modified them using | ||
437 | ! ptrace(POKEUSR). (Note that R0-R2 are | ||
438 | ! used by the system call handler directly | ||
439 | ! from the kernel stack anyway, so don't need | ||
440 | ! to be reloaded here.) This allows the parent | ||
441 | ! to rewrite system calls and args on the fly. | ||
442 | mov.l @(OFF_R4,r15), r4 ! arg0 | ||
443 | mov.l @(OFF_R5,r15), r5 | ||
444 | mov.l @(OFF_R6,r15), r6 | ||
445 | mov.l @(OFF_R7,r15), r7 ! arg3 | ||
446 | mov.l @(OFF_R3,r15), r3 ! syscall_nr | ||
447 | ! Arrange for do_syscall_trace to be called | ||
448 | ! again as the system call returns. | ||
449 | mov.l 2f, r10 ! Number of syscalls | ||
450 | cmp/hs r10, r3 | ||
451 | bf syscall_call | ||
452 | mov #-ENOSYS, r0 | ||
453 | bra syscall_exit | ||
454 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
455 | |||
456 | /* | ||
457 | * Syscall interface: | ||
458 | * | ||
459 | * Syscall #: R3 | ||
460 | * Arguments #0 to #3: R4--R7 | ||
461 | * Arguments #4 to #6: R0, R1, R2 | ||
462 | * TRA: (number of arguments + 0x10) x 4 | ||
463 | * | ||
464 | * This code also handles delegating other traps to the BIOS/gdb stub | ||
465 | * according to: | ||
466 | * | ||
467 | * Trap number | ||
468 | * (TRA>>2) Purpose | ||
469 | * -------- ------- | ||
470 | * 0x0-0xf old syscall ABI | ||
471 | * 0x10-0x1f new syscall ABI | ||
472 | * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. | ||
473 | * | ||
474 | * Note: When we're first called, the TRA value must be shifted | ||
475 | * right 2 bits in order to get the value that was used as the "trapa" | ||
476 | * argument. | ||
477 | */ | ||
478 | |||
479 | .align 2 | ||
480 | .globl ret_from_fork | ||
481 | ret_from_fork: | ||
482 | mov.l 1f, r8 | ||
483 | jsr @r8 | ||
484 | mov r0, r4 | ||
485 | bra syscall_exit | ||
486 | nop | ||
487 | .align 2 | ||
488 | 1: .long schedule_tail | ||
489 | ! | ||
490 | ENTRY(system_call) | ||
491 | mov.l 1f, r9 | ||
492 | mov.l @r9, r8 ! Read from TRA (Trap Address) Register | ||
493 | ! | ||
494 | ! Is the trap argument >= 0x20? (TRA will be >= 0x80) | ||
495 | mov #0x7f, r9 | ||
496 | cmp/hi r9, r8 | ||
497 | bt/s 0f | ||
498 | mov #OFF_TRA, r9 | ||
499 | add r15, r9 | ||
500 | ! | ||
501 | mov.l r8, @r9 ! set TRA value to tra | ||
502 | STI() | ||
503 | ! Call the system call handler through the table. | ||
504 | ! First check for bad syscall number | ||
505 | mov r3, r9 | ||
506 | mov.l 2f, r8 ! Number of syscalls | ||
507 | cmp/hs r8, r9 | ||
508 | bf/s good_system_call | ||
509 | GET_THREAD_INFO(r8) | ||
510 | syscall_badsys: ! Bad syscall number | ||
511 | mov #-ENOSYS, r0 | ||
512 | bra resume_userspace | ||
513 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
514 | ! | ||
515 | 0: | ||
516 | bra debug_trap | ||
517 | nop | ||
518 | ! | ||
519 | good_system_call: ! Good syscall number | ||
520 | mov.l @(TI_FLAGS,r8), r8 | ||
521 | mov #_TIF_SYSCALL_TRACE, r10 | ||
522 | tst r10, r8 | ||
523 | bf syscall_trace_entry | ||
524 | ! | ||
525 | syscall_call: | ||
526 | shll2 r9 ! x4 | ||
527 | mov.l 3f, r8 ! Load the address of sys_call_table | ||
528 | add r8, r9 | ||
529 | mov.l @r9, r8 | ||
530 | jsr @r8 ! jump to specific syscall handler | ||
531 | nop | ||
532 | mov.l @(OFF_R0,r15), r12 ! save r0 | ||
533 | mov.l r0, @(OFF_R0,r15) ! save the return value | ||
534 | ! | ||
535 | syscall_exit: | ||
536 | CLI() | ||
537 | ! | ||
538 | GET_THREAD_INFO(r8) | ||
539 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
540 | tst #_TIF_ALLWORK_MASK, r0 | ||
541 | bf syscall_exit_work | ||
542 | restore_all: | 227 | restore_all: |
543 | mov.l @r15+, r0 | 228 | mov.l @r15+, r0 |
544 | mov.l @r15+, r1 | 229 | mov.l @r15+, r1 |
@@ -606,7 +291,9 @@ skip_restore: | |||
606 | ! | 291 | ! |
607 | ! Calculate new SR value | 292 | ! Calculate new SR value |
608 | mov k3, k2 ! original SR value | 293 | mov k3, k2 ! original SR value |
609 | mov.l 9f, k1 | 294 | mov #0xf0, k1 |
295 | extu.b k1, k1 | ||
296 | not k1, k1 | ||
610 | and k1, k2 ! Mask orignal SR value | 297 | and k1, k2 ! Mask orignal SR value |
611 | ! | 298 | ! |
612 | mov k3, k0 ! Calculate IMASK-bits | 299 | mov k3, k0 ! Calculate IMASK-bits |
@@ -632,16 +319,12 @@ skip_restore: | |||
632 | nop | 319 | nop |
633 | 320 | ||
634 | .align 2 | 321 | .align 2 |
635 | 1: .long TRA | ||
636 | 2: .long NR_syscalls | ||
637 | 3: .long sys_call_table | ||
638 | 4: .long do_syscall_trace | ||
639 | 5: .long 0x00001000 ! DSP | 322 | 5: .long 0x00001000 ! DSP |
640 | 7: .long 0x30000000 | 323 | 7: .long 0x30000000 |
641 | 9: | ||
642 | __INV_IMASK: | ||
643 | .long 0xffffff0f ! ~(IMASK) | ||
644 | 324 | ||
325 | ! common exception handler | ||
326 | #include "../../entry.S" | ||
327 | |||
645 | ! Exception Vector Base | 328 | ! Exception Vector Base |
646 | ! | 329 | ! |
647 | ! Should be aligned page boundary. | 330 | ! Should be aligned page boundary. |
@@ -761,7 +444,7 @@ skip_save: | |||
761 | ! Save the user registers on the stack. | 444 | ! Save the user registers on the stack. |
762 | mov.l k2, @-r15 ! EXPEVT | 445 | mov.l k2, @-r15 ! EXPEVT |
763 | 446 | ||
764 | mov #-1, k4 | 447 | mov #-1, k4 |
765 | mov.l k4, @-r15 ! set TRA (default: -1) | 448 | mov.l k4, @-r15 ! set TRA (default: -1) |
766 | ! | 449 | ! |
767 | sts.l macl, @-r15 | 450 | sts.l macl, @-r15 |
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8dbf3895ece7..6e415baf04b4 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | # Makefile for the Linux/SuperH SH-4 backends. | 2 | # Makefile for the Linux/SuperH SH-4 backends. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o common.o |
6 | common-y += $(addprefix ../sh3/, entry.o) | ||
6 | 7 | ||
7 | obj-$(CONFIG_SH_FPU) += fpu.o | 8 | obj-$(CONFIG_SH_FPU) += fpu.o |
8 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 9 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S new file mode 100644 index 000000000000..5bc7fa91d095 --- /dev/null +++ b/arch/sh/kernel/entry-common.S | |||
@@ -0,0 +1,372 @@ | |||
1 | /* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $ | ||
2 | * | ||
3 | * linux/arch/sh/entry.S | ||
4 | * | ||
5 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | ||
6 | * Copyright (C) 2003 Paul Mundt | ||
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 | |||
14 | ! NOTE: | ||
15 | ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address | ||
16 | ! to be jumped is too far, but it causes illegal slot exception. | ||
17 | |||
18 | /* | ||
19 | * entry.S contains the system-call and fault low-level handling routines. | ||
20 | * This also contains the timer-interrupt handler, as well as all interrupts | ||
21 | * and faults that can result in a task-switch. | ||
22 | * | ||
23 | * NOTE: This code handles signal-recognition, which happens every time | ||
24 | * after a timer-interrupt and after each system call. | ||
25 | * | ||
26 | * NOTE: This code uses a convention that instructions in the delay slot | ||
27 | * of a transfer-control instruction are indented by an extra space, thus: | ||
28 | * | ||
29 | * jmp @k0 ! control-transfer instruction | ||
30 | * ldc k1, ssr ! delay slot | ||
31 | * | ||
32 | * Stack layout in 'ret_from_syscall': | ||
33 | * ptrace needs to have all regs on the stack. | ||
34 | * if the order here is changed, it needs to be | ||
35 | * updated in ptrace.c and ptrace.h | ||
36 | * | ||
37 | * r0 | ||
38 | * ... | ||
39 | * r15 = stack pointer | ||
40 | * spc | ||
41 | * pr | ||
42 | * ssr | ||
43 | * gbr | ||
44 | * mach | ||
45 | * macl | ||
46 | * syscall # | ||
47 | * | ||
48 | */ | ||
49 | |||
50 | #if defined(CONFIG_PREEMPT) | ||
51 | # define preempt_stop() cli | ||
52 | #else | ||
53 | # define preempt_stop() | ||
54 | # define resume_kernel __restore_all | ||
55 | #endif | ||
56 | |||
57 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
58 | ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. | ||
59 | ! If both are configured, handle the debug traps (breakpoints) in SW, | ||
60 | ! but still allow BIOS traps to FW. | ||
61 | |||
62 | .align 2 | ||
63 | debug_kernel: | ||
64 | #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) | ||
65 | /* Force BIOS call to FW (debug_trap put TRA in r8) */ | ||
66 | mov r8,r0 | ||
67 | shlr2 r0 | ||
68 | cmp/eq #0x3f,r0 | ||
69 | bt debug_kernel_fw | ||
70 | #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ | ||
71 | |||
72 | debug_enter: | ||
73 | #if defined(CONFIG_SH_KGDB) | ||
74 | /* Jump to kgdb, pass stacked regs as arg */ | ||
75 | debug_kernel_sw: | ||
76 | mov.l 3f, r0 | ||
77 | jmp @r0 | ||
78 | mov r15, r4 | ||
79 | .align 2 | ||
80 | 3: .long kgdb_handle_exception | ||
81 | #endif /* CONFIG_SH_KGDB */ | ||
82 | |||
83 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
84 | |||
85 | |||
86 | .align 2 | ||
87 | debug_trap: | ||
88 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
89 | mov #OFF_SR, r0 | ||
90 | mov.l @(r0,r15), r0 ! get status register | ||
91 | shll r0 | ||
92 | shll r0 ! kernel space? | ||
93 | bt/s debug_kernel | ||
94 | #endif | ||
95 | mov.l @r15, r0 ! Restore R0 value | ||
96 | mov.l 1f, r8 | ||
97 | jmp @r8 | ||
98 | nop | ||
99 | |||
100 | .align 2 | ||
101 | ENTRY(exception_error) | ||
102 | ! | ||
103 | sti | ||
104 | mov.l 2f, r0 | ||
105 | jmp @r0 | ||
106 | nop | ||
107 | |||
108 | ! | ||
109 | .align 2 | ||
110 | 1: .long break_point_trap_software | ||
111 | 2: .long do_exception_error | ||
112 | |||
113 | .align 2 | ||
114 | ret_from_exception: | ||
115 | preempt_stop() | ||
116 | ENTRY(ret_from_irq) | ||
117 | ! | ||
118 | mov #OFF_SR, r0 | ||
119 | mov.l @(r0,r15), r0 ! get status register | ||
120 | shll r0 | ||
121 | shll r0 ! kernel space? | ||
122 | get_current_thread_info r8, r0 | ||
123 | bt resume_kernel ! Yes, it's from kernel, go back soon | ||
124 | |||
125 | #ifdef CONFIG_PREEMPT | ||
126 | bra resume_userspace | ||
127 | nop | ||
128 | ENTRY(resume_kernel) | ||
129 | mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count | ||
130 | tst r0, r0 | ||
131 | bf noresched | ||
132 | need_resched: | ||
133 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
134 | tst #_TIF_NEED_RESCHED, r0 ! need_resched set? | ||
135 | bt noresched | ||
136 | |||
137 | mov #OFF_SR, r0 | ||
138 | mov.l @(r0,r15), r0 ! get status register | ||
139 | and #0xf0, r0 ! interrupts off (exception path)? | ||
140 | cmp/eq #0xf0, r0 | ||
141 | bt noresched | ||
142 | |||
143 | mov.l 1f, r0 | ||
144 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
145 | |||
146 | sti | ||
147 | mov.l 2f, r0 | ||
148 | jsr @r0 | ||
149 | nop | ||
150 | mov #0, r0 | ||
151 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
152 | cli | ||
153 | |||
154 | bra need_resched | ||
155 | nop | ||
156 | noresched: | ||
157 | bra __restore_all | ||
158 | nop | ||
159 | |||
160 | .align 2 | ||
161 | 1: .long PREEMPT_ACTIVE | ||
162 | 2: .long schedule | ||
163 | #endif | ||
164 | |||
165 | ENTRY(resume_userspace) | ||
166 | ! r8: current_thread_info | ||
167 | cli | ||
168 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
169 | tst #_TIF_WORK_MASK, r0 | ||
170 | bt/s __restore_all | ||
171 | tst #_TIF_NEED_RESCHED, r0 | ||
172 | |||
173 | .align 2 | ||
174 | work_pending: | ||
175 | ! r0: current_thread_info->flags | ||
176 | ! r8: current_thread_info | ||
177 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" | ||
178 | bf/s work_resched | ||
179 | tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 | ||
180 | work_notifysig: | ||
181 | bt/s __restore_all | ||
182 | mov r15, r4 | ||
183 | mov r12, r5 ! set arg1(save_r0) | ||
184 | mov r0, r6 | ||
185 | mov.l 2f, r1 | ||
186 | mov.l 3f, r0 | ||
187 | jmp @r1 | ||
188 | lds r0, pr | ||
189 | work_resched: | ||
190 | #ifndef CONFIG_PREEMPT | ||
191 | ! gUSA handling | ||
192 | mov.l @(OFF_SP,r15), r0 ! get user space stack pointer | ||
193 | mov r0, r1 | ||
194 | shll r0 | ||
195 | bf/s 1f | ||
196 | shll r0 | ||
197 | bf/s 1f | ||
198 | mov #OFF_PC, r0 | ||
199 | ! SP >= 0xc0000000 : gUSA mark | ||
200 | mov.l @(r0,r15), r2 ! get user space PC (program counter) | ||
201 | mov.l @(OFF_R0,r15), r3 ! end point | ||
202 | cmp/hs r3, r2 ! r2 >= r3? | ||
203 | bt 1f | ||
204 | add r3, r1 ! rewind point #2 | ||
205 | mov.l r1, @(r0,r15) ! reset PC to rewind point #2 | ||
206 | ! | ||
207 | 1: | ||
208 | #endif | ||
209 | mov.l 1f, r1 | ||
210 | jsr @r1 ! schedule | ||
211 | nop | ||
212 | cli | ||
213 | ! | ||
214 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
215 | tst #_TIF_WORK_MASK, r0 | ||
216 | bt __restore_all | ||
217 | bra work_pending | ||
218 | tst #_TIF_NEED_RESCHED, r0 | ||
219 | |||
220 | .align 2 | ||
221 | 1: .long schedule | ||
222 | 2: .long do_notify_resume | ||
223 | 3: .long restore_all | ||
224 | |||
225 | .align 2 | ||
226 | syscall_exit_work: | ||
227 | ! r0: current_thread_info->flags | ||
228 | ! r8: current_thread_info | ||
229 | tst #_TIF_SYSCALL_TRACE, r0 | ||
230 | bt/s work_pending | ||
231 | tst #_TIF_NEED_RESCHED, r0 | ||
232 | sti | ||
233 | ! XXX setup arguments... | ||
234 | mov.l 4f, r0 ! do_syscall_trace | ||
235 | jsr @r0 | ||
236 | nop | ||
237 | bra resume_userspace | ||
238 | nop | ||
239 | |||
240 | .align 2 | ||
241 | syscall_trace_entry: | ||
242 | ! Yes it is traced. | ||
243 | ! XXX setup arguments... | ||
244 | mov.l 4f, r11 ! Call do_syscall_trace which notifies | ||
245 | jsr @r11 ! superior (will chomp R[0-7]) | ||
246 | nop | ||
247 | ! Reload R0-R4 from kernel stack, where the | ||
248 | ! parent may have modified them using | ||
249 | ! ptrace(POKEUSR). (Note that R0-R2 are | ||
250 | ! used by the system call handler directly | ||
251 | ! from the kernel stack anyway, so don't need | ||
252 | ! to be reloaded here.) This allows the parent | ||
253 | ! to rewrite system calls and args on the fly. | ||
254 | mov.l @(OFF_R4,r15), r4 ! arg0 | ||
255 | mov.l @(OFF_R5,r15), r5 | ||
256 | mov.l @(OFF_R6,r15), r6 | ||
257 | mov.l @(OFF_R7,r15), r7 ! arg3 | ||
258 | mov.l @(OFF_R3,r15), r3 ! syscall_nr | ||
259 | ! Arrange for do_syscall_trace to be called | ||
260 | ! again as the system call returns. | ||
261 | mov.l 2f, r10 ! Number of syscalls | ||
262 | cmp/hs r10, r3 | ||
263 | bf syscall_call | ||
264 | mov #-ENOSYS, r0 | ||
265 | bra syscall_exit | ||
266 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
267 | |||
268 | __restore_all: | ||
269 | mov.l 1f,r0 | ||
270 | jmp @r0 | ||
271 | nop | ||
272 | |||
273 | .align 2 | ||
274 | 1: .long restore_all | ||
275 | |||
276 | /* | ||
277 | * Syscall interface: | ||
278 | * | ||
279 | * Syscall #: R3 | ||
280 | * Arguments #0 to #3: R4--R7 | ||
281 | * Arguments #4 to #6: R0, R1, R2 | ||
282 | * TRA: (number of arguments + 0x10) x 4 | ||
283 | * | ||
284 | * This code also handles delegating other traps to the BIOS/gdb stub | ||
285 | * according to: | ||
286 | * | ||
287 | * Trap number | ||
288 | * (TRA>>2) Purpose | ||
289 | * -------- ------- | ||
290 | * 0x0-0xf old syscall ABI | ||
291 | * 0x10-0x1f new syscall ABI | ||
292 | * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. | ||
293 | * | ||
294 | * Note: When we're first called, the TRA value must be shifted | ||
295 | * right 2 bits in order to get the value that was used as the "trapa" | ||
296 | * argument. | ||
297 | */ | ||
298 | |||
299 | .align 2 | ||
300 | .globl ret_from_fork | ||
301 | ret_from_fork: | ||
302 | mov.l 1f, r8 | ||
303 | jsr @r8 | ||
304 | mov r0, r4 | ||
305 | bra syscall_exit | ||
306 | nop | ||
307 | .align 2 | ||
308 | 1: .long schedule_tail | ||
309 | ! | ||
310 | ENTRY(system_call) | ||
311 | #if !defined(CONFIG_CPU_SH2) | ||
312 | mov.l 1f, r9 | ||
313 | mov.l @r9, r8 ! Read from TRA (Trap Address) Register | ||
314 | #endif | ||
315 | ! | ||
316 | ! Is the trap argument >= 0x20? (TRA will be >= 0x80) | ||
317 | mov #0x7f, r9 | ||
318 | cmp/hi r9, r8 | ||
319 | bt/s 0f | ||
320 | mov #OFF_TRA, r9 | ||
321 | add r15, r9 | ||
322 | ! | ||
323 | mov.l r8, @r9 ! set TRA value to tra | ||
324 | sti | ||
325 | ! Call the system call handler through the table. | ||
326 | ! First check for bad syscall number | ||
327 | mov r3, r9 | ||
328 | mov.l 2f, r8 ! Number of syscalls | ||
329 | cmp/hs r8, r9 | ||
330 | get_current_thread_info r8, r10 | ||
331 | bf good_system_call | ||
332 | syscall_badsys: ! Bad syscall number | ||
333 | mov #-ENOSYS, r0 | ||
334 | bra resume_userspace | ||
335 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
336 | ! | ||
337 | 0: | ||
338 | bra debug_trap | ||
339 | nop | ||
340 | ! | ||
341 | good_system_call: ! Good syscall number | ||
342 | mov.l @(TI_FLAGS,r8), r8 | ||
343 | mov #_TIF_SYSCALL_TRACE, r10 | ||
344 | tst r10, r8 | ||
345 | bf syscall_trace_entry | ||
346 | ! | ||
347 | syscall_call: | ||
348 | shll2 r9 ! x4 | ||
349 | mov.l 3f, r8 ! Load the address of sys_call_table | ||
350 | add r8, r9 | ||
351 | mov.l @r9, r8 | ||
352 | jsr @r8 ! jump to specific syscall handler | ||
353 | nop | ||
354 | mov.l @(OFF_R0,r15), r12 ! save r0 | ||
355 | mov.l r0, @(OFF_R0,r15) ! save the return value | ||
356 | ! | ||
357 | syscall_exit: | ||
358 | cli | ||
359 | ! | ||
360 | get_current_thread_info r8, r0 | ||
361 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
362 | tst #_TIF_ALLWORK_MASK, r0 | ||
363 | bf syscall_exit_work | ||
364 | bra __restore_all | ||
365 | nop | ||
366 | .align 2 | ||
367 | #if !defined(CONFIG_CPU_SH2) | ||
368 | 1: .long TRA | ||
369 | #endif | ||
370 | 2: .long NR_syscalls | ||
371 | 3: .long sys_call_table | ||
372 | 4: .long do_syscall_trace | ||
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f5f53d14f245..b5ff23264617 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S | |||
@@ -53,8 +53,10 @@ ENTRY(_stext) | |||
53 | ldc r0, sr | 53 | ldc r0, sr |
54 | ! Initialize global interrupt mask | 54 | ! Initialize global interrupt mask |
55 | mov #0, r0 | 55 | mov #0, r0 |
56 | #ifdef CONFIG_CPU_HAS_SR_RB | ||
56 | ldc r0, r6_bank | 57 | ldc r0, r6_bank |
57 | 58 | #endif | |
59 | |||
58 | /* | 60 | /* |
59 | * Prefetch if possible to reduce cache miss penalty. | 61 | * Prefetch if possible to reduce cache miss penalty. |
60 | * | 62 | * |
@@ -71,8 +73,10 @@ ENTRY(_stext) | |||
71 | mov #(THREAD_SIZE >> 8), r1 | 73 | mov #(THREAD_SIZE >> 8), r1 |
72 | shll8 r1 ! r1 = THREAD_SIZE | 74 | shll8 r1 ! r1 = THREAD_SIZE |
73 | sub r1, r0 ! | 75 | sub r1, r0 ! |
76 | #ifdef CONFIG_CPU_HAS_SR_RB | ||
74 | ldc r0, r7_bank ! ... and initial thread_info | 77 | ldc r0, r7_bank ! ... and initial thread_info |
75 | 78 | #endif | |
79 | |||
76 | ! Clear BSS area | 80 | ! Clear BSS area |
77 | mov.l 3f, r1 | 81 | mov.l 3f, r1 |
78 | add #4, r1 | 82 | add #4, r1 |
@@ -95,7 +99,11 @@ ENTRY(_stext) | |||
95 | nop | 99 | nop |
96 | 100 | ||
97 | .balign 4 | 101 | .balign 4 |
102 | #if defined(CONFIG_CPU_SH2) | ||
103 | 1: .long 0x000000F0 ! IMASK=0xF | ||
104 | #else | ||
98 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF | 105 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF |
106 | #endif | ||
99 | 2: .long init_thread_union+THREAD_SIZE | 107 | 2: .long init_thread_union+THREAD_SIZE |
100 | 3: .long __bss_start | 108 | 3: .long __bss_start |
101 | 4: .long _end | 109 | 4: .long _end |