blob: 9a1837d5b54e33e7365e1031e66ebf38efdebad6 [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:
Yoshinori Satode398402006-11-05 16:15:19 +0900179 mov.l 1f, r1
180 jsr @r1 ! schedule
181 nop
182 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900183#ifdef CONFIG_TRACE_IRQFLAGS
184 mov.l 5f, r0
185 jsr @r0
186 nop
187#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900188 !
189 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
190 tst #_TIF_WORK_MASK, r0
191 bt __restore_all
192 bra work_pending
193 tst #_TIF_NEED_RESCHED, r0
194
195 .align 2
1961: .long schedule
1972: .long do_notify_resume
1983: .long restore_all
Paul Mundtafbfb522006-12-04 18:17:28 +0900199#ifdef CONFIG_TRACE_IRQFLAGS
2004: .long trace_hardirqs_on
2015: .long trace_hardirqs_off
202#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900203
204 .align 2
205syscall_exit_work:
206 ! r0: current_thread_info->flags
207 ! r8: current_thread_info
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900208 tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0
Yoshinori Satode398402006-11-05 16:15:19 +0900209 bt/s work_pending
210 tst #_TIF_NEED_RESCHED, r0
Paul Mundtafbfb522006-12-04 18:17:28 +0900211#ifdef CONFIG_TRACE_IRQFLAGS
212 mov.l 5f, r0
213 jsr @r0
214 nop
215#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900216 sti
217 ! XXX setup arguments...
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900218 mov r15, r4
219 mov #1, r5
Yoshinori Satode398402006-11-05 16:15:19 +0900220 mov.l 4f, r0 ! do_syscall_trace
221 jsr @r0
222 nop
223 bra resume_userspace
224 nop
225
226 .align 2
227syscall_trace_entry:
228 ! Yes it is traced.
229 ! XXX setup arguments...
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900230 mov r15, r4
231 mov #0, r5
Yoshinori Satode398402006-11-05 16:15:19 +0900232 mov.l 4f, r11 ! Call do_syscall_trace which notifies
233 jsr @r11 ! superior (will chomp R[0-7])
234 nop
235 ! Reload R0-R4 from kernel stack, where the
236 ! parent may have modified them using
237 ! ptrace(POKEUSR). (Note that R0-R2 are
238 ! used by the system call handler directly
239 ! from the kernel stack anyway, so don't need
240 ! to be reloaded here.) This allows the parent
241 ! to rewrite system calls and args on the fly.
242 mov.l @(OFF_R4,r15), r4 ! arg0
243 mov.l @(OFF_R5,r15), r5
244 mov.l @(OFF_R6,r15), r6
245 mov.l @(OFF_R7,r15), r7 ! arg3
246 mov.l @(OFF_R3,r15), r3 ! syscall_nr
Stuart Menefye0969e02006-11-24 13:01:36 +0900247 !
Yoshinori Satode398402006-11-05 16:15:19 +0900248 mov.l 2f, r10 ! Number of syscalls
249 cmp/hs r10, r3
250 bf syscall_call
251 mov #-ENOSYS, r0
252 bra syscall_exit
253 mov.l r0, @(OFF_R0,r15) ! Return value
254
255__restore_all:
Paul Mundtafbfb522006-12-04 18:17:28 +0900256 mov.l 1f, r0
Yoshinori Satode398402006-11-05 16:15:19 +0900257 jmp @r0
258 nop
259
260 .align 2
2611: .long restore_all
262
Stuart Menefye0969e02006-11-24 13:01:36 +0900263 .align 2
Stuart Menefye0969e02006-11-24 13:01:36 +0900264syscall_badsys: ! Bad syscall number
Hideo Saito561c2bc2008-05-15 13:30:05 +0900265 get_current_thread_info r8, r0
Stuart Menefye0969e02006-11-24 13:01:36 +0900266 mov #-ENOSYS, r0
267 bra resume_userspace
268 mov.l r0, @(OFF_R0,r15) ! Return value
Paul Mundtf413d0d2006-12-13 17:40:05 +0900269
270/*
271 * The main debug trap handler.
272 *
273 * r8=TRA (not the trap number!)
274 *
275 * Note: This assumes that the trapa value is left in its original
276 * form (without the shlr2 shift) so the calculation for the jump
277 * call table offset remains a simple in place mask.
278 */
279debug_trap:
280 mov r8, r0
281 and #(0xf << 2), r0
282 mov.l 1f, r8
283 add r0, r8
284 mov.l @r8, r8
285 jmp @r8
286 nop
287
288 .align 2
2891: .long debug_trap_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900290
Yoshinori Satode398402006-11-05 16:15:19 +0900291/*
292 * Syscall interface:
293 *
294 * Syscall #: R3
295 * Arguments #0 to #3: R4--R7
296 * Arguments #4 to #6: R0, R1, R2
Paul Mundtf413d0d2006-12-13 17:40:05 +0900297 * TRA: (number of arguments + ABI revision) x 4
Yoshinori Satode398402006-11-05 16:15:19 +0900298 *
299 * This code also handles delegating other traps to the BIOS/gdb stub
300 * according to:
301 *
302 * Trap number
Paul Mundtf413d0d2006-12-13 17:40:05 +0900303 * (TRA>>2) Purpose
304 * -------- -------
305 * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
306 * 0x10-0x1f general SH-3/4 syscall ABI.
307 * 0x20-0x2f syscall ABI for SH-2 parts.
308 * 0x30-0x3f debug traps used by the kernel.
309 * 0x40-0xff Not supported by all parts, so left unhandled.
Yoshinori Satode398402006-11-05 16:15:19 +0900310 *
311 * Note: When we're first called, the TRA value must be shifted
312 * right 2 bits in order to get the value that was used as the "trapa"
313 * argument.
314 */
315
316 .align 2
317 .globl ret_from_fork
318ret_from_fork:
319 mov.l 1f, r8
320 jsr @r8
321 mov r0, r4
322 bra syscall_exit
323 nop
324 .align 2
3251: .long schedule_tail
Paul Mundtf413d0d2006-12-13 17:40:05 +0900326
327/*
328 * The poorly named main trapa decode and dispatch routine, for
329 * system calls and debug traps through their respective jump tables.
330 */
Yoshinori Satode398402006-11-05 16:15:19 +0900331ENTRY(system_call)
332#if !defined(CONFIG_CPU_SH2)
333 mov.l 1f, r9
334 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
335#endif
Paul Mundtf413d0d2006-12-13 17:40:05 +0900336 /*
337 * Check the trap type
338 */
339 mov #((0x20 << 2) - 1), r9
Yoshinori Satode398402006-11-05 16:15:19 +0900340 cmp/hi r9, r8
Paul Mundtf413d0d2006-12-13 17:40:05 +0900341 bt/s debug_trap ! it's a debug trap..
Yoshinori Satode398402006-11-05 16:15:19 +0900342 mov #OFF_TRA, r9
343 add r15, r9
Yoshinori Satode398402006-11-05 16:15:19 +0900344 mov.l r8, @r9 ! set TRA value to tra
Paul Mundtafbfb522006-12-04 18:17:28 +0900345#ifdef CONFIG_TRACE_IRQFLAGS
346 mov.l 5f, r10
347 jsr @r10
348 nop
349#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900350 sti
Paul Mundtafbfb522006-12-04 18:17:28 +0900351
Stuart Menefye0969e02006-11-24 13:01:36 +0900352 !
Yoshinori Satode398402006-11-05 16:15:19 +0900353 get_current_thread_info r8, r10
Yoshinori Satode398402006-11-05 16:15:19 +0900354 mov.l @(TI_FLAGS,r8), r8
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900355 mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10
Yoshinori Satode398402006-11-05 16:15:19 +0900356 tst r10, r8
357 bf syscall_trace_entry
358 !
Stuart Menefye0969e02006-11-24 13:01:36 +0900359 mov.l 2f, r8 ! Number of syscalls
360 cmp/hs r8, r3
361 bt syscall_badsys
362 !
Yoshinori Satode398402006-11-05 16:15:19 +0900363syscall_call:
Stuart Menefye0969e02006-11-24 13:01:36 +0900364 shll2 r3 ! x4
Yoshinori Satode398402006-11-05 16:15:19 +0900365 mov.l 3f, r8 ! Load the address of sys_call_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900366 add r8, r3
367 mov.l @r3, r8
Yoshinori Satode398402006-11-05 16:15:19 +0900368 jsr @r8 ! jump to specific syscall handler
369 nop
370 mov.l @(OFF_R0,r15), r12 ! save r0
371 mov.l r0, @(OFF_R0,r15) ! save the return value
372 !
373syscall_exit:
374 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900375#ifdef CONFIG_TRACE_IRQFLAGS
376 mov.l 6f, r0
377 jsr @r0
378 nop
379#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900380 !
381 get_current_thread_info r8, r0
382 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
383 tst #_TIF_ALLWORK_MASK, r0
384 bf syscall_exit_work
385 bra __restore_all
386 nop
387 .align 2
388#if !defined(CONFIG_CPU_SH2)
3891: .long TRA
390#endif
3912: .long NR_syscalls
3923: .long sys_call_table
3934: .long do_syscall_trace
Paul Mundtafbfb522006-12-04 18:17:28 +0900394#ifdef CONFIG_TRACE_IRQFLAGS
3955: .long trace_hardirqs_on
3966: .long trace_hardirqs_off
397#endif