1
2
3
4
5
6
7
8
9
10
11! NOTE:
12! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
13! to be jumped is too far, but it causes illegal slot exception.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <asm/dwarf.h>
47
48
49# define preempt_stop() cli ; TRACE_IRQS_OFF
50#else
51# define preempt_stop()
52# define resume_kernel __restore_all
53#endif
54
55
56 .align 2
57ENTRY(exception_error)
58 !
59 TRACE_IRQS_ON
60 sti
61 mov.l 1f, r0
62 jmp @r0
63 nop
64
65 .align 2
661: .long do_exception_error
67
68 .align 2
69ret_from_exception:
70 CFI_STARTPROC simple
71 CFI_DEF_CFA r14, 0
72 CFI_REL_OFFSET 17, 64
73 CFI_REL_OFFSET 15, 60
74 CFI_REL_OFFSET 14, 56
75 CFI_REL_OFFSET 13, 52
76 CFI_REL_OFFSET 12, 48
77 CFI_REL_OFFSET 11, 44
78 CFI_REL_OFFSET 10, 40
79 CFI_REL_OFFSET 9, 36
80 CFI_REL_OFFSET 8, 32
81 preempt_stop()
82ENTRY(ret_from_irq)
83 !
84 mov
85 mov.l @(r0,r15), r0 ! get status register
86 shll r0
87 shll r0 ! kernel space?
88 get_current_thread_info r8, r0
89 bt resume_kernel ! Yes, it's from kernel, go back soon
90
91#ifdef CONFIG_PREEMPT
92 bra resume_userspace
93 nop
94ENTRY(resume_kernel)
95 cli
96 TRACE_IRQS_OFF
97 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
98 tst r0, r0
99 bf noresched
100need_resched:
101 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
102 tst
103 bt noresched
104
105 mov
106 mov.l @(r0,r15), r0 ! get status register
107 shlr r0
108 and
109 cmp/eq
110 bt noresched
111 mov.l 1f, r0
112 jsr @r0 ! call preempt_schedule_irq
113 nop
114 bra need_resched
115 nop
116
117noresched:
118 bra __restore_all
119 nop
120
121 .align 2
1221: .long preempt_schedule_irq
123#endif
124
125ENTRY(resume_userspace)
126 ! r8: current_thread_info
127 cli
128 TRACE_IRQS_OFF
129 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
130 tst
131 bt/s __restore_all
132 tst
133
134 .align 2
135work_pending:
136 ! r0: current_thread_info->flags
137 ! r8: current_thread_info
138 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
139 bf/s work_resched
140 tst
141work_notifysig:
142 bt/s __restore_all
143 mov r15, r4
144 mov r12, r5 ! set arg1(save_r0)
145 mov r0, r6
146 sti
147 mov.l 2f, r1
148 mov.l 3f, r0
149 jmp @r1
150 lds r0, pr
151work_resched:
152 mov.l 1f, r1
153 jsr @r1 ! schedule
154 nop
155 cli
156 TRACE_IRQS_OFF
157 !
158 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
159 tst
160 bt __restore_all
161 bra work_pending
162 tst
163
164 .align 2
1651: .long schedule
1662: .long do_notify_resume
1673: .long resume_userspace
168
169 .align 2
170syscall_exit_work:
171 ! r0: current_thread_info->flags
172 ! r8: current_thread_info
173 tst
174 bt/s work_pending
175 tst
176 TRACE_IRQS_ON
177 sti
178 mov r15, r4
179 mov.l 8f, r0 ! do_syscall_trace_leave
180 jsr @r0
181 nop
182 bra resume_userspace
183 nop
184
185 .align 2
186syscall_trace_entry:
187 ! Yes it is traced.
188 mov r15, r4
189 mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies
190 jsr @r11 ! superior (will chomp R[0-7])
191 nop
192 mov.l r0, @(OFF_R0,r15) ! Save return value
193 ! Reload R0-R4 from kernel stack, where the
194 ! parent may have modified them using
195 ! ptrace(POKEUSR). (Note that R0-R2 are
196 ! used by the system call handler directly
197 ! from the kernel stack anyway, so don't need
198 ! to be reloaded here.) This allows the parent
199 ! to rewrite system calls and args on the fly.
200 mov.l @(OFF_R4,r15), r4 ! arg0
201 mov.l @(OFF_R5,r15), r5
202 mov.l @(OFF_R6,r15), r6
203 mov.l @(OFF_R7,r15), r7 ! arg3
204 mov.l @(OFF_R3,r15), r3 ! syscall_nr
205 !
206 mov.l 2f, r10 ! Number of syscalls
207 cmp/hs r10, r3
208 bf syscall_call
209 mov
210 bra syscall_exit
211 mov.l r0, @(OFF_R0,r15) ! Return value
212
213__restore_all:
214 mov
215 mov.l @(r0,r15), r0 ! get status register
216
217 shlr2 r0
218 and
219 cmp/eq
220 bt 1f
221 TRACE_IRQS_ON
222 bra 2f
223 nop
2241:
225 TRACE_IRQS_OFF
2262:
227 mov.l 3f, r0
228 jmp @r0
229 nop
230
231 .align 2
2323: .long restore_all
233
234 .align 2
235syscall_badsys: ! Bad syscall number
236 get_current_thread_info r8, r0
237 mov
238 bra resume_userspace
239 mov.l r0, @(OFF_R0,r15) ! Return value
240
241
242
243
244
245
246
247
248
249
250debug_trap:
251 mov r8, r0
252 and
253 mov.l 1f, r8
254 add r0, r8
255 mov.l @r8, r8
256 jsr @r8
257 nop
258 bra __restore_all
259 nop
260 CFI_ENDPROC
261
262 .align 2
2631: .long debug_trap_table
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 .align 2
291 .globl ret_from_fork
292ret_from_fork:
293 mov.l 1f, r8
294 jsr @r8
295 mov r0, r4
296 bra syscall_exit
297 nop
298
299 .align 2
300 .globl ret_from_kernel_thread
301ret_from_kernel_thread:
302 mov.l 1f, r8
303 jsr @r8
304 mov r0, r4
305 mov.l @(OFF_R5,r15), r5 ! fn
306 jsr @r5
307 mov.l @(OFF_R4,r15), r4 ! arg
308 bra syscall_exit
309 nop
310
311 .align 2
3121: .long schedule_tail
313
314
315
316
317
318ENTRY(system_call)
319 setup_frame_reg
320
321 mov.l 1f, r9
322 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
323#endif
324
325 mov
326 add r15, r10
327 mov.l r8, @r10 ! set TRA value to tra
328
329
330
331
332 mov
333 cmp/hi r9, r8
334 bt/s debug_trap ! it's a debug trap..
335 nop
336
337 TRACE_IRQS_ON
338 sti
339
340 !
341 get_current_thread_info r8, r10
342 mov.l @(TI_FLAGS,r8), r8
343 mov
344 mov
345 tst r10, r8
346 shll8 r9
347 bf syscall_trace_entry
348 tst r9, r8
349 bf syscall_trace_entry
350 !
351 mov.l 2f, r8 ! Number of syscalls
352 cmp/hs r8, r3
353 bt syscall_badsys
354 !
355syscall_call:
356 shll2 r3 ! x4
357 mov.l 3f, r8 ! Load the address of sys_call_table
358 add r8, r3
359 mov.l @r3, r8
360 jsr @r8 ! jump to specific syscall handler
361 nop
362 mov.l @(OFF_R0,r15), r12 ! save r0
363 mov.l r0, @(OFF_R0,r15) ! save the return value
364 !
365syscall_exit:
366 cli
367 TRACE_IRQS_OFF
368 !
369 get_current_thread_info r8, r0
370 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
371 tst
372 mov
373 bf syscall_exit_work
374 shlr8 r0
375 tst r0, r1
376 bf syscall_exit_work
377 bra __restore_all
378 nop
379 .align 2
380
3811: .long TRA
382#endif
3832: .long NR_syscalls
3843: .long sys_call_table
3857: .long do_syscall_trace_enter
3868: .long do_syscall_trace_leave
387