blob: 397ac71d97f1ada251c6c030ad39b4e795f3f480 [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:
Paul Mundt83662462007-09-28 16:04:49 +0900179#if defined(CONFIG_GUSA) && !defined(CONFIG_PREEMPT)
Yoshinori Satode398402006-11-05 16:15:19 +0900180 ! 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
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900227 tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0
Yoshinori Satode398402006-11-05 16:15:19 +0900228 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...
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900237 mov r15, r4
238 mov #1, r5
Yoshinori Satode398402006-11-05 16:15:19 +0900239 mov.l 4f, r0 ! do_syscall_trace
240 jsr @r0
241 nop
242 bra resume_userspace
243 nop
244
245 .align 2
246syscall_trace_entry:
247 ! Yes it is traced.
248 ! XXX setup arguments...
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900249 mov r15, r4
250 mov #0, r5
Yoshinori Satode398402006-11-05 16:15:19 +0900251 mov.l 4f, r11 ! Call do_syscall_trace which notifies
252 jsr @r11 ! superior (will chomp R[0-7])
253 nop
254 ! Reload R0-R4 from kernel stack, where the
255 ! parent may have modified them using
256 ! ptrace(POKEUSR). (Note that R0-R2 are
257 ! used by the system call handler directly
258 ! from the kernel stack anyway, so don't need
259 ! to be reloaded here.) This allows the parent
260 ! to rewrite system calls and args on the fly.
261 mov.l @(OFF_R4,r15), r4 ! arg0
262 mov.l @(OFF_R5,r15), r5
263 mov.l @(OFF_R6,r15), r6
264 mov.l @(OFF_R7,r15), r7 ! arg3
265 mov.l @(OFF_R3,r15), r3 ! syscall_nr
Stuart Menefye0969e02006-11-24 13:01:36 +0900266 !
Yoshinori Satode398402006-11-05 16:15:19 +0900267 mov.l 2f, r10 ! Number of syscalls
268 cmp/hs r10, r3
269 bf syscall_call
270 mov #-ENOSYS, r0
271 bra syscall_exit
272 mov.l r0, @(OFF_R0,r15) ! Return value
273
274__restore_all:
Paul Mundtafbfb522006-12-04 18:17:28 +0900275 mov.l 1f, r0
Yoshinori Satode398402006-11-05 16:15:19 +0900276 jmp @r0
277 nop
278
279 .align 2
2801: .long restore_all
281
Stuart Menefye0969e02006-11-24 13:01:36 +0900282 .align 2
Stuart Menefye0969e02006-11-24 13:01:36 +0900283syscall_badsys: ! Bad syscall number
284 mov #-ENOSYS, r0
285 bra resume_userspace
286 mov.l r0, @(OFF_R0,r15) ! Return value
Paul Mundtf413d0d2006-12-13 17:40:05 +0900287
288/*
289 * The main debug trap handler.
290 *
291 * r8=TRA (not the trap number!)
292 *
293 * Note: This assumes that the trapa value is left in its original
294 * form (without the shlr2 shift) so the calculation for the jump
295 * call table offset remains a simple in place mask.
296 */
297debug_trap:
298 mov r8, r0
299 and #(0xf << 2), r0
300 mov.l 1f, r8
301 add r0, r8
302 mov.l @r8, r8
303 jmp @r8
304 nop
305
306 .align 2
3071: .long debug_trap_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900308
Yoshinori Satode398402006-11-05 16:15:19 +0900309/*
310 * Syscall interface:
311 *
312 * Syscall #: R3
313 * Arguments #0 to #3: R4--R7
314 * Arguments #4 to #6: R0, R1, R2
Paul Mundtf413d0d2006-12-13 17:40:05 +0900315 * TRA: (number of arguments + ABI revision) x 4
Yoshinori Satode398402006-11-05 16:15:19 +0900316 *
317 * This code also handles delegating other traps to the BIOS/gdb stub
318 * according to:
319 *
320 * Trap number
Paul Mundtf413d0d2006-12-13 17:40:05 +0900321 * (TRA>>2) Purpose
322 * -------- -------
323 * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
324 * 0x10-0x1f general SH-3/4 syscall ABI.
325 * 0x20-0x2f syscall ABI for SH-2 parts.
326 * 0x30-0x3f debug traps used by the kernel.
327 * 0x40-0xff Not supported by all parts, so left unhandled.
Yoshinori Satode398402006-11-05 16:15:19 +0900328 *
329 * Note: When we're first called, the TRA value must be shifted
330 * right 2 bits in order to get the value that was used as the "trapa"
331 * argument.
332 */
333
334 .align 2
335 .globl ret_from_fork
336ret_from_fork:
337 mov.l 1f, r8
338 jsr @r8
339 mov r0, r4
340 bra syscall_exit
341 nop
342 .align 2
3431: .long schedule_tail
Paul Mundtf413d0d2006-12-13 17:40:05 +0900344
345/*
346 * The poorly named main trapa decode and dispatch routine, for
347 * system calls and debug traps through their respective jump tables.
348 */
Yoshinori Satode398402006-11-05 16:15:19 +0900349ENTRY(system_call)
350#if !defined(CONFIG_CPU_SH2)
351 mov.l 1f, r9
352 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
353#endif
Paul Mundtf413d0d2006-12-13 17:40:05 +0900354 /*
355 * Check the trap type
356 */
357 mov #((0x20 << 2) - 1), r9
Yoshinori Satode398402006-11-05 16:15:19 +0900358 cmp/hi r9, r8
Paul Mundtf413d0d2006-12-13 17:40:05 +0900359 bt/s debug_trap ! it's a debug trap..
Yoshinori Satode398402006-11-05 16:15:19 +0900360 mov #OFF_TRA, r9
361 add r15, r9
Yoshinori Satode398402006-11-05 16:15:19 +0900362 mov.l r8, @r9 ! set TRA value to tra
Paul Mundtafbfb522006-12-04 18:17:28 +0900363#ifdef CONFIG_TRACE_IRQFLAGS
364 mov.l 5f, r10
365 jsr @r10
366 nop
367#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900368 sti
Paul Mundtafbfb522006-12-04 18:17:28 +0900369
Stuart Menefye0969e02006-11-24 13:01:36 +0900370 !
Yoshinori Satode398402006-11-05 16:15:19 +0900371 get_current_thread_info r8, r10
Yoshinori Satode398402006-11-05 16:15:19 +0900372 mov.l @(TI_FLAGS,r8), r8
Yuichi Nakamura1322b9d2007-11-10 19:21:34 +0900373 mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10
Yoshinori Satode398402006-11-05 16:15:19 +0900374 tst r10, r8
375 bf syscall_trace_entry
376 !
Stuart Menefye0969e02006-11-24 13:01:36 +0900377 mov.l 2f, r8 ! Number of syscalls
378 cmp/hs r8, r3
379 bt syscall_badsys
380 !
Yoshinori Satode398402006-11-05 16:15:19 +0900381syscall_call:
Stuart Menefye0969e02006-11-24 13:01:36 +0900382 shll2 r3 ! x4
Yoshinori Satode398402006-11-05 16:15:19 +0900383 mov.l 3f, r8 ! Load the address of sys_call_table
Stuart Menefye0969e02006-11-24 13:01:36 +0900384 add r8, r3
385 mov.l @r3, r8
Yoshinori Satode398402006-11-05 16:15:19 +0900386 jsr @r8 ! jump to specific syscall handler
387 nop
388 mov.l @(OFF_R0,r15), r12 ! save r0
389 mov.l r0, @(OFF_R0,r15) ! save the return value
390 !
391syscall_exit:
392 cli
Paul Mundtafbfb522006-12-04 18:17:28 +0900393#ifdef CONFIG_TRACE_IRQFLAGS
394 mov.l 6f, r0
395 jsr @r0
396 nop
397#endif
Yoshinori Satode398402006-11-05 16:15:19 +0900398 !
399 get_current_thread_info r8, r0
400 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
401 tst #_TIF_ALLWORK_MASK, r0
402 bf syscall_exit_work
403 bra __restore_all
404 nop
405 .align 2
406#if !defined(CONFIG_CPU_SH2)
4071: .long TRA
408#endif
4092: .long NR_syscalls
4103: .long sys_call_table
4114: .long do_syscall_trace
Paul Mundtafbfb522006-12-04 18:17:28 +0900412#ifdef CONFIG_TRACE_IRQFLAGS
4135: .long trace_hardirqs_on
4146: .long trace_hardirqs_off
415#endif