aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoshinori Sato <ysato@users.sourceforge.jp>2006-11-05 02:15:19 -0500
committerPaul Mundt <lethal@linux-sh.org>2006-12-05 20:45:36 -0500
commitde39840646a223ae13a346048c280b7c871bf56e (patch)
treeaa2449880c12310ccb92540bfd63e43e8a568745
parent0983b31849bbe1fe82520947acc1bec97c457d4b (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.S325
-rw-r--r--arch/sh/kernel/cpu/sh2/ex.S46
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile2
-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/Makefile3
-rw-r--r--arch/sh/kernel/entry-common.S372
-rw-r--r--arch/sh/kernel/head.S12
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 */
23OFF_R0 = 0 /* Return value. New ABI also arg4 */
24OFF_R1 = 4 /* New ABI: arg5 */
25OFF_R2 = 8 /* New ABI: arg6 */
26OFF_R3 = 12 /* New ABI: syscall_nr */
27OFF_R4 = 16 /* New ABI: arg0 */
28OFF_R5 = 20 /* New ABI: arg1 */
29OFF_R6 = 24 /* New ABI: arg2 */
30OFF_R7 = 28 /* New ABI: arg3 */
31OFF_SP = (15*4)
32OFF_PC = (16*4)
33OFF_SR = (16*4+2*4)
34OFF_TRA = (16*4+6*4)
35
36#include <asm/entry-macros.S>
37
38ENTRY(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
1011:
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
1422:
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
1613:
162 mov.l 5f,r10
163 jmp @r8
164 lds r10,pr
165
166interrupt_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
1744: .long exception_handling_table
1755: .long ret_from_exception
1766: .long ret_from_irq
1777: .long do_IRQ
1788: .long do_exception_error
179
180trap_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
1921: .long syscall_exit
1932: .long break_point_trap_software
1943: .long NR_syscalls
1954: .long sys_call_table
196
197#if defined(CONFIG_SH_STANDARD_BIOS)
198 /* Unwind the stack and jmp to the debug entry */
199debug_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
2411: .long gdb_vbr_vector
242#endif /* CONFIG_SH_STANDARD_BIOS */
243
244ENTRY(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
2541: .long do_address_error
255
256restore_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
2992:
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
324ENTRY(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!
18exception_entry:
19no = 0
20 .rept 256
21 mov.l r0,@-sp
22 mov #no,r0
23 bra exception_trampoline
24 and #0xff,r0
25no = no + 1
26 .endr
27exception_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
41ENTRY(vbr_base)
42vector = 0
43 .rept 256
44 .long exception_entry + vector * 8
45vector = 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
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o entry.o
6 6
7# CPU subtype setup 7# CPU subtype setup
8obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o 8obj-$(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
132ENTRY(tlb_miss_load) 113ENTRY(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
1710: STI() 1520: 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:
2032: .long do_address_error 1842: .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
212debug_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
221debug_enter:
222#if defined(CONFIG_SH_KGDB)
223 /* Jump to kgdb, pass stacked regs as arg */
224debug_kernel_sw:
225 mov.l 3f, r0
226 jmp @r0
227 mov r15, r4
228 .align 2
2293: .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 */
234debug_kernel_fw: 189debug_kernel_fw:
@@ -269,276 +224,6 @@ debug_kernel_fw:
2692: .long gdb_vbr_vector 2242: .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
276debug_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
290ENTRY(exception_error)
291 !
292 STI()
293 mov.l 2f, r0
294 jmp @r0
295 nop
296
297!
298 .align 2
2991: .long break_point_trap_software
3002: .long do_exception_error
301
302 .align 2
303ret_from_exception:
304 preempt_stop()
305ENTRY(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
317ENTRY(resume_kernel)
318 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
319 tst r0, r0
320 bf noresched
321need_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
345noresched:
346 bra restore_all
347 nop
348
349 .align 2
3501: .long PREEMPT_ACTIVE
3512: .long schedule
352#endif
353
354ENTRY(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
363work_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
369work_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
378work_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 !
3961:
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
4101: .long schedule
4112: .long do_notify_resume
412
413 .align 2
414syscall_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
429syscall_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
481ret_from_fork:
482 mov.l 1f, r8
483 jsr @r8
484 mov r0, r4
485 bra syscall_exit
486 nop
487 .align 2
4881: .long schedule_tail
489 !
490ENTRY(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)
510syscall_badsys: ! Bad syscall number
511 mov #-ENOSYS, r0
512 bra resume_userspace
513 mov.l r0, @(OFF_R0,r15) ! Return value
514 !
5150:
516 bra debug_trap
517 nop
518 !
519good_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 !
525syscall_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 !
535syscall_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
542restore_all: 227restore_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
6351: .long TRA
6362: .long NR_syscalls
6373: .long sys_call_table
6384: .long do_syscall_trace
6395: .long 0x00001000 ! DSP 3225: .long 0x00001000 ! DSP
6407: .long 0x30000000 3237: .long 0x30000000
6419:
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
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o common.o
6common-y += $(addprefix ../sh3/, entry.o)
6 7
7obj-$(CONFIG_SH_FPU) += fpu.o 8obj-$(CONFIG_SH_FPU) += fpu.o
8obj-$(CONFIG_SH_STORE_QUEUES) += sq.o 9obj-$(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
63debug_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
72debug_enter:
73#if defined(CONFIG_SH_KGDB)
74 /* Jump to kgdb, pass stacked regs as arg */
75debug_kernel_sw:
76 mov.l 3f, r0
77 jmp @r0
78 mov r15, r4
79 .align 2
803: .long kgdb_handle_exception
81#endif /* CONFIG_SH_KGDB */
82
83#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
84
85
86 .align 2
87debug_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
101ENTRY(exception_error)
102 !
103 sti
104 mov.l 2f, r0
105 jmp @r0
106 nop
107
108!
109 .align 2
1101: .long break_point_trap_software
1112: .long do_exception_error
112
113 .align 2
114ret_from_exception:
115 preempt_stop()
116ENTRY(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
128ENTRY(resume_kernel)
129 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
130 tst r0, r0
131 bf noresched
132need_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
156noresched:
157 bra __restore_all
158 nop
159
160 .align 2
1611: .long PREEMPT_ACTIVE
1622: .long schedule
163#endif
164
165ENTRY(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
174work_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
180work_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
189work_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 !
2071:
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
2211: .long schedule
2222: .long do_notify_resume
2233: .long restore_all
224
225 .align 2
226syscall_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
241syscall_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
2741: .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
301ret_from_fork:
302 mov.l 1f, r8
303 jsr @r8
304 mov r0, r4
305 bra syscall_exit
306 nop
307 .align 2
3081: .long schedule_tail
309 !
310ENTRY(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
332syscall_badsys: ! Bad syscall number
333 mov #-ENOSYS, r0
334 bra resume_userspace
335 mov.l r0, @(OFF_R0,r15) ! Return value
336 !
3370:
338 bra debug_trap
339 nop
340 !
341good_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 !
347syscall_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 !
357syscall_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)
3681: .long TRA
369#endif
3702: .long NR_syscalls
3713: .long sys_call_table
3724: .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)
1031: .long 0x000000F0 ! IMASK=0xF
104#else
981: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 1051: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
106#endif
992: .long init_thread_union+THREAD_SIZE 1072: .long init_thread_union+THREAD_SIZE
1003: .long __bss_start 1083: .long __bss_start
1014: .long _end 1094: .long _end