blob: ab4ebb856c2a3cc7ca9f2e75ceb94c32ebdc1c22 [file] [log] [blame]
Yoshinori Satode398402006-11-05 16:15:19 +09001/* $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
Yoshinori Satode398402006-11-05 16:15:19 +090057
58 .align 2
59ENTRY(exception_error)
60 !
Paul Mundtafbfb522006-12-04 18:17:28 +090061#ifdef CONFIG_TRACE_IRQFLAGS
Paul Mundtf413d0d2006-12-13 17:40:05 +090062 mov.l 2f, r0
Paul Mundtafbfb522006-12-04 18:17:28 +090063 jsr @r0
64 nop
65#endif
Yoshinori Satode398402006-11-05 16:15:19 +090066 sti
Paul Mundtf413d0d2006-12-13 17:40:05 +090067 mov.l 1f, r0
Yoshinori Satode398402006-11-05 16:15:19 +090068 jmp @r0
69 nop
70
Yoshinori Satode398402006-11-05 16:15:19 +090071 .align 2
Paul Mundtf413d0d2006-12-13 17:40:05 +0900721: .long do_exception_error
Paul Mundtafbfb522006-12-04 18:17:28 +090073#ifdef CONFIG_TRACE_IRQFLAGS
Paul Mundtf413d0d2006-12-13 17:40:05 +0900742: .long trace_hardirqs_on
Paul Mundtafbfb522006-12-04 18:17:28 +090075#endif
Yoshinori Satode398402006-11-05 16:15:19 +090076
77 .align 2
78ret_from_exception:
79 preempt_stop()
Paul Mundtafbfb522006-12-04 18:17:28 +090080#ifdef CONFIG_TRACE_IRQFLAGS
81 mov.l 4f, r0
82 jsr @r0
83 nop
84#endif
Yoshinori Satode398402006-11-05 16:15:19 +090085ENTRY(ret_from_irq)
86 !
87 mov #OFF_SR, r0
88 mov.l @(r0,r15), r0 ! get status register
89 shll r0
90 shll r0 ! kernel space?
91 get_current_thread_info r8, r0
92 bt resume_kernel ! Yes, it's from kernel, go back soon
93
94#ifdef CONFIG_PREEMPT
95 bra resume_userspace
96 nop
97ENTRY(resume_kernel)
98 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
99 tst r0, r0
100 bf noresched
101need_resched:
102 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
103 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
104 bt noresched
105
106 mov #OFF_SR, r0
107 mov.l @(r0,r15), r0 ! get status register
108 and #0xf0, r0 ! interrupts off (exception path)?
109 cmp/eq #0xf0, r0
110 bt noresched
111
112 mov.l 1f, r0
113 mov.l r0, @(TI_PRE_COUNT,r8)
114
Paul Mundtafbfb522006-12-04 18:17:28 +0900115#ifdef CONFIG_TRACE_IRQFLAGS
116 mov.l 3f, r0
117 jsr @r0
118 nop
119#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900120 sti
121 mov.l 2f, r0
122 jsr @r0
123 nop
124 mov #0, r0
125 mov.l r0, @(TI_PRE_COUNT,r8)
126 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900127#ifdef CONFIG_TRACE_IRQFLAGS
128 mov.l 4f, r0
129 jsr @r0
130 nop
131#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900132
133 bra need_resched
134 nop
Paul Mundtafbfb522006-12-04 18:17:28 +0900135
Yoshinori Satode398402006-11-05 16:15:19 +0900136noresched:
137 bra __restore_all
138 nop
139
140 .align 2
1411: .long PREEMPT_ACTIVE
1422: .long schedule
Paul Mundtafbfb522006-12-04 18:17:28 +0900143#ifdef CONFIG_TRACE_IRQFLAGS
1443: .long trace_hardirqs_on
1454: .long trace_hardirqs_off
146#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900147#endif
148
149ENTRY(resume_userspace)
150 ! r8: current_thread_info
151 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900152#ifdef CONFIG_TRACE_IRQFLAGS
153 mov.l 5f, r0
154 jsr @r0
155 nop
156#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900157 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
158 tst #_TIF_WORK_MASK, r0
159 bt/s __restore_all
160 tst #_TIF_NEED_RESCHED, r0
161
162 .align 2
163work_pending:
164 ! r0: current_thread_info->flags
165 ! r8: current_thread_info
166 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
167 bf/s work_resched
168 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
169work_notifysig:
170 bt/s __restore_all
171 mov r15, r4
172 mov r12, r5 ! set arg1(save_r0)
173 mov r0, r6
174 mov.l 2f, r1
175 mov.l 3f, r0
176 jmp @r1
177 lds r0, pr
178work_resched:
179#ifndef CONFIG_PREEMPT
180 ! gUSA handling
181 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
182 mov r0, r1
183 shll r0
184 bf/s 1f
185 shll r0
186 bf/s 1f
187 mov #OFF_PC, r0
188 ! SP >= 0xc0000000 : gUSA mark
189 mov.l @(r0,r15), r2 ! get user space PC (program counter)
190 mov.l @(OFF_R0,r15), r3 ! end point
191 cmp/hs r3, r2 ! r2 >= r3?
192 bt 1f
193 add r3, r1 ! rewind point #2
194 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
195 !
1961:
197#endif
198 mov.l 1f, r1
199 jsr @r1 ! schedule
200 nop
201 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900202#ifdef CONFIG_TRACE_IRQFLAGS
203 mov.l 5f, r0
204 jsr @r0
205 nop
206#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900207 !
208 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
209 tst #_TIF_WORK_MASK, r0
210 bt __restore_all
211 bra work_pending
212 tst #_TIF_NEED_RESCHED, r0
213
214 .align 2
2151: .long schedule
2162: .long do_notify_resume
2173: .long restore_all
Paul Mundtafbfb522006-12-04 18:17:28 +0900218#ifdef CONFIG_TRACE_IRQFLAGS
2194: .long trace_hardirqs_on
2205: .long trace_hardirqs_off
221#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900222
223 .align 2
224syscall_exit_work:
225 ! r0: current_thread_info->flags
226 ! r8: current_thread_info
227 tst #_TIF_SYSCALL_TRACE, r0
228 bt/s work_pending
229 tst #_TIF_NEED_RESCHED, r0
Paul Mundtafbfb522006-12-04 18:17:28 +0900230#ifdef CONFIG_TRACE_IRQFLAGS
231 mov.l 5f, r0
232 jsr @r0
233 nop
234#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900235 sti
236 ! XXX setup arguments...
237 mov.l 4f, r0 ! do_syscall_trace
238 jsr @r0
239 nop
240 bra resume_userspace
241 nop
242
243 .align 2
244syscall_trace_entry:
245 ! Yes it is traced.
246 ! XXX setup arguments...
247 mov.l 4f, r11 ! Call do_syscall_trace which notifies
248 jsr @r11 ! superior (will chomp R[0-7])
249 nop
250 ! Reload R0-R4 from kernel stack, where the
251 ! parent may have modified them using
252 ! ptrace(POKEUSR). (Note that R0-R2 are
253 ! used by the system call handler directly
254 ! from the kernel stack anyway, so don't need
255 ! to be reloaded here.) This allows the parent
256 ! to rewrite system calls and args on the fly.
257 mov.l @(OFF_R4,r15), r4 ! arg0
258 mov.l @(OFF_R5,r15), r5
259 mov.l @(OFF_R6,r15), r6
260 mov.l @(OFF_R7,r15), r7 ! arg3
261 mov.l @(OFF_R3,r15), r3 ! syscall_nr
Stuart Menefye0969e02006-11-24 13:01:36 +0900262 !
Yoshinori Satode398402006-11-05 16:15:19 +0900263 mov.l 2f, r10 ! Number of syscalls
264 cmp/hs r10, r3
265 bf syscall_call
266 mov #-ENOSYS, r0
267 bra syscall_exit
268 mov.l r0, @(OFF_R0,r15) ! Return value
269
270__restore_all:
Paul Mundtafbfb522006-12-04 18:17:28 +0900271 mov.l 1f, r0
Yoshinori Satode398402006-11-05 16:15:19 +0900272 jmp @r0
273 nop
274
275 .align 2
2761: .long restore_all
277
Stuart Menefye0969e02006-11-24 13:01:36 +0900278 .align 2
Stuart Menefye0969e02006-11-24 13:01:36 +0900279syscall_badsys: ! Bad syscall number
280 mov #-ENOSYS, r0
281 bra resume_userspace
282 mov.l r0, @(OFF_R0,r15) ! Return value
Paul Mundtf413d0d2006-12-13 17:40:05 +0900283
284/*
285 * The main debug trap handler.
286 *
287 * r8=TRA (not the trap number!)
288 *
289 * Note: This assumes that the trapa value is left in its original
290 * form (without the shlr2 shift) so the calculation for the jump
291 * call table offset remains a simple in place mask.
292 */
293debug_trap:
294 mov r8, r0
295 and #(0xf << 2), r0
296 mov.l 1f, r8
297 add r0, r8
298 mov.l @r8, r8
299 jmp @r8
300 nop
301
302 .align 2
3031: .long debug_trap_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900304
Yoshinori Satode398402006-11-05 16:15:19 +0900305/*
306 * Syscall interface:
307 *
308 * Syscall #: R3
309 * Arguments #0 to #3: R4--R7
310 * Arguments #4 to #6: R0, R1, R2
Paul Mundtf413d0d2006-12-13 17:40:05 +0900311 * TRA: (number of arguments + ABI revision) x 4
Yoshinori Satode398402006-11-05 16:15:19 +0900312 *
313 * This code also handles delegating other traps to the BIOS/gdb stub
314 * according to:
315 *
316 * Trap number
Paul Mundtf413d0d2006-12-13 17:40:05 +0900317 * (TRA>>2) Purpose
318 * -------- -------
319 * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
320 * 0x10-0x1f general SH-3/4 syscall ABI.
321 * 0x20-0x2f syscall ABI for SH-2 parts.
322 * 0x30-0x3f debug traps used by the kernel.
323 * 0x40-0xff Not supported by all parts, so left unhandled.
Yoshinori Satode398402006-11-05 16:15:19 +0900324 *
325 * Note: When we're first called, the TRA value must be shifted
326 * right 2 bits in order to get the value that was used as the "trapa"
327 * argument.
328 */
329
330 .align 2
331 .globl ret_from_fork
332ret_from_fork:
333 mov.l 1f, r8
334 jsr @r8
335 mov r0, r4
336 bra syscall_exit
337 nop
338 .align 2
3391: .long schedule_tail
Paul Mundtf413d0d2006-12-13 17:40:05 +0900340
341/*
342 * The poorly named main trapa decode and dispatch routine, for
343 * system calls and debug traps through their respective jump tables.
344 */
Yoshinori Satode398402006-11-05 16:15:19 +0900345ENTRY(system_call)
346#if !defined(CONFIG_CPU_SH2)
347 mov.l 1f, r9
348 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
349#endif
Paul Mundtf413d0d2006-12-13 17:40:05 +0900350 /*
351 * Check the trap type
352 */
353 mov #((0x20 << 2) - 1), r9
Yoshinori Satode398402006-11-05 16:15:19 +0900354 cmp/hi r9, r8
Paul Mundtf413d0d2006-12-13 17:40:05 +0900355 bt/s debug_trap ! it's a debug trap..
Yoshinori Satode398402006-11-05 16:15:19 +0900356 mov #OFF_TRA, r9
357 add r15, r9
Yoshinori Satode398402006-11-05 16:15:19 +0900358 mov.l r8, @r9 ! set TRA value to tra
Paul Mundtafbfb522006-12-04 18:17:28 +0900359#ifdef CONFIG_TRACE_IRQFLAGS
360 mov.l 5f, r10
361 jsr @r10
362 nop
363#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900364 sti
Paul Mundtafbfb522006-12-04 18:17:28 +0900365
Stuart Menefye0969e02006-11-24 13:01:36 +0900366 !
Yoshinori Satode398402006-11-05 16:15:19 +0900367 get_current_thread_info r8, r10
Yoshinori Satode398402006-11-05 16:15:19 +0900368 mov.l @(TI_FLAGS,r8), r8
369 mov #_TIF_SYSCALL_TRACE, r10
370 tst r10, r8
371 bf syscall_trace_entry
372 !
Stuart Menefye0969e02006-11-24 13:01:36 +0900373 mov.l 2f, r8 ! Number of syscalls
374 cmp/hs r8, r3
375 bt syscall_badsys
376 !
Yoshinori Satode398402006-11-05 16:15:19 +0900377syscall_call:
Stuart Menefye0969e02006-11-24 13:01:36 +0900378 shll2 r3 ! x4
Yoshinori Satode398402006-11-05 16:15:19 +0900379 mov.l 3f, r8 ! Load the address of sys_call_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900380 add r8, r3
381 mov.l @r3, r8
Yoshinori Satode398402006-11-05 16:15:19 +0900382 jsr @r8 ! jump to specific syscall handler
383 nop
384 mov.l @(OFF_R0,r15), r12 ! save r0
385 mov.l r0, @(OFF_R0,r15) ! save the return value
386 !
387syscall_exit:
388 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900389#ifdef CONFIG_TRACE_IRQFLAGS
390 mov.l 6f, r0
391 jsr @r0
392 nop
393#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900394 !
395 get_current_thread_info r8, r0
396 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
397 tst #_TIF_ALLWORK_MASK, r0
398 bf syscall_exit_work
399 bra __restore_all
400 nop
401 .align 2
402#if !defined(CONFIG_CPU_SH2)
4031: .long TRA
404#endif
4052: .long NR_syscalls
4063: .long sys_call_table
4074: .long do_syscall_trace
Paul Mundtafbfb522006-12-04 18:17:28 +0900408#ifdef CONFIG_TRACE_IRQFLAGS
4095: .long trace_hardirqs_on
4106: .long trace_hardirqs_off
411#endif