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 ! reloaded from the kernel stack by syscall_call
197 ! below, so don't need to be reloaded here.)
198 ! This allows the parent to rewrite system calls
199 ! 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
291
292
293
294
295
296
297
298
299 .align 2
300 .globl ret_from_fork
301ret_from_fork:
302 mov.l 1f, r8
303 jsr @r8
304 mov r0, r4
305 bra syscall_exit
306 nop
307
308 .align 2
309 .globl ret_from_kernel_thread
310ret_from_kernel_thread:
311 mov.l 1f, r8
312 jsr @r8
313 mov r0, r4
314 mov.l @(OFF_R5,r15), r5 ! fn
315 jsr @r5
316 mov.l @(OFF_R4,r15), r4 ! arg
317 bra syscall_exit
318 nop
319
320 .align 2
3211: .long schedule_tail
322
323
324
325
326
327ENTRY(system_call)
328 setup_frame_reg
329
330 mov.l 1f, r9
331 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
332#endif
333
334 mov
335 add r15, r10
336 mov.l r8, @r10 ! set TRA value to tra
337
338
339
340
341 mov
342 cmp/hi r9, r8
343 bt/s debug_trap ! it's a debug trap..
344 nop
345
346 TRACE_IRQS_ON
347 sti
348
349 !
350 get_current_thread_info r8, r10
351 mov.l @(TI_FLAGS,r8), r8
352 mov
353 mov
354 tst r10, r8
355 shll8 r9
356 bf syscall_trace_entry
357 tst r9, r8
358 bf syscall_trace_entry
359 !
360 mov.l 2f, r8 ! Number of syscalls
361 cmp/hs r8, r3
362 bt syscall_badsys
363 !
364syscall_call:
365 shll2 r3 ! x4
366 mov.l 3f, r8 ! Load the address of sys_call_table
367 add r8, r3
368 mov.l @r3, r8
369 mov.l @(OFF_R2,r15), r2
370 mov.l @(OFF_R1,r15), r1
371 mov.l @(OFF_R0,r15), r0
372 mov.l r2, @-r15
373 mov.l r1, @-r15
374 mov.l r0, @-r15
375 jsr @r8 ! jump to specific syscall handler
376 nop
377 add
378 mov.l @(OFF_R0,r15), r12 ! save r0
379 mov.l r0, @(OFF_R0,r15) ! save the return value
380 !
381syscall_exit:
382 cli
383 TRACE_IRQS_OFF
384 !
385 get_current_thread_info r8, r0
386 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
387 tst
388 mov
389 bf syscall_exit_work
390 shlr8 r0
391 tst r0, r1
392 bf syscall_exit_work
393 bra __restore_all
394 nop
395 .align 2
396
3971: .long TRA
398#endif
3992: .long NR_syscalls
4003: .long sys_call_table
4017: .long do_syscall_trace_enter
4028: .long do_syscall_trace_leave
403