sh: x3 - fix setup_bootmem_node() compile error with shx3_defconfig
[linux-block.git] / arch / sh / kernel / entry-common.S
CommitLineData
de398406
YS
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
de398406
YS
57
58 .align 2
59ENTRY(exception_error)
60 !
afbfb52e 61#ifdef CONFIG_TRACE_IRQFLAGS
f413d0d9 62 mov.l 2f, r0
afbfb52e
PM
63 jsr @r0
64 nop
65#endif
de398406 66 sti
f413d0d9 67 mov.l 1f, r0
de398406
YS
68 jmp @r0
69 nop
70
de398406 71 .align 2
f413d0d9 721: .long do_exception_error
afbfb52e 73#ifdef CONFIG_TRACE_IRQFLAGS
f413d0d9 742: .long trace_hardirqs_on
afbfb52e 75#endif
de398406
YS
76
77 .align 2
78ret_from_exception:
79 preempt_stop()
afbfb52e
PM
80#ifdef CONFIG_TRACE_IRQFLAGS
81 mov.l 4f, r0
82 jsr @r0
83 nop
84#endif
de398406
YS
85ENTRY(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
afbfb52e
PM
115#ifdef CONFIG_TRACE_IRQFLAGS
116 mov.l 3f, r0
117 jsr @r0
118 nop
119#endif
de398406
YS
120 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
afbfb52e
PM
127#ifdef CONFIG_TRACE_IRQFLAGS
128 mov.l 4f, r0
129 jsr @r0
130 nop
131#endif
de398406
YS
132
133 bra need_resched
134 nop
afbfb52e 135
de398406
YS
136noresched:
137 bra __restore_all
138 nop
139
140 .align 2
1411: .long PREEMPT_ACTIVE
1422: .long schedule
afbfb52e
PM
143#ifdef CONFIG_TRACE_IRQFLAGS
1443: .long trace_hardirqs_on
1454: .long trace_hardirqs_off
146#endif
de398406
YS
147#endif
148
149ENTRY(resume_userspace)
150 ! r8: current_thread_info
151 cli
afbfb52e
PM
152#ifdef CONFIG_TRACE_IRQFLAGS
153 mov.l 5f, r0
154 jsr @r0
155 nop
156#endif
de398406
YS
157 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
afbfb52e
PM
202#ifdef CONFIG_TRACE_IRQFLAGS
203 mov.l 5f, r0
204 jsr @r0
205 nop
206#endif
de398406
YS
207 !
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
afbfb52e
PM
218#ifdef CONFIG_TRACE_IRQFLAGS
2194: .long trace_hardirqs_on
2205: .long trace_hardirqs_off
221#endif
de398406
YS
222
223 .align 2
224syscall_exit_work:
225 ! r0: current_thread_info->flags
226 ! r8: current_thread_info
9432f968 227 tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0
de398406
YS
228 bt/s work_pending
229 tst #_TIF_NEED_RESCHED, r0
afbfb52e
PM
230#ifdef CONFIG_TRACE_IRQFLAGS
231 mov.l 5f, r0
232 jsr @r0
233 nop
234#endif
de398406
YS
235 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
e0969e0c 262 !
de398406
YS
263 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:
afbfb52e 271 mov.l 1f, r0
de398406
YS
272 jmp @r0
273 nop
274
275 .align 2
2761: .long restore_all
277
e0969e0c
SM
278 .align 2
279syscall_badsys: ! Bad syscall number
280 mov #-ENOSYS, r0
281 bra resume_userspace
282 mov.l r0, @(OFF_R0,r15) ! Return value
f413d0d9
PM
283
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
e0969e0c 304
de398406
YS
305/*
306 * Syscall interface:
307 *
308 * Syscall #: R3
309 * Arguments #0 to #3: R4--R7
310 * Arguments #4 to #6: R0, R1, R2
f413d0d9 311 * TRA: (number of arguments + ABI revision) x 4
de398406
YS
312 *
313 * This code also handles delegating other traps to the BIOS/gdb stub
314 * according to:
315 *
316 * Trap number
f413d0d9
PM
317 * (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.
de398406
YS
324 *
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
f413d0d9
PM
340
341/*
342 * The poorly named main trapa decode and dispatch routine, for
343 * system calls and debug traps through their respective jump tables.
344 */
de398406
YS
345ENTRY(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
f413d0d9
PM
350 /*
351 * Check the trap type
352 */
353 mov #((0x20 << 2) - 1), r9
de398406 354 cmp/hi r9, r8
f413d0d9 355 bt/s debug_trap ! it's a debug trap..
de398406
YS
356 mov #OFF_TRA, r9
357 add r15, r9
de398406 358 mov.l r8, @r9 ! set TRA value to tra
afbfb52e
PM
359#ifdef CONFIG_TRACE_IRQFLAGS
360 mov.l 5f, r10
361 jsr @r10
362 nop
363#endif
de398406 364 sti
afbfb52e 365
de398406 366 !
e0969e0c 367 get_current_thread_info r8, r10
de398406
YS
368 mov.l @(TI_FLAGS,r8), r8
369 mov #_TIF_SYSCALL_TRACE, r10
370 tst r10, r8
371 bf syscall_trace_entry
372 !
e0969e0c
SM
373 mov.l 2f, r8 ! Number of syscalls
374 cmp/hs r8, r3
375 bt syscall_badsys
376 !
de398406 377syscall_call:
e0969e0c 378 shll2 r3 ! x4
de398406 379 mov.l 3f, r8 ! Load the address of sys_call_table
e0969e0c
SM
380 add r8, r3
381 mov.l @r3, r8
de398406
YS
382 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
afbfb52e
PM
389#ifdef CONFIG_TRACE_IRQFLAGS
390 mov.l 6f, r0
391 jsr @r0
392 nop
393#endif
de398406
YS
394 !
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
afbfb52e
PM
408#ifdef CONFIG_TRACE_IRQFLAGS
4095: .long trace_hardirqs_on
4106: .long trace_hardirqs_off
411#endif