1: /*
2: * linux/arch/arm/kernel/entry-common.S
3: *
4: * Copyright (C) 2000 Russell King
5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License version 2 as
8: * published by the Free Software Foundation.
9: */
10:
11: #include <asm/unistd.h>
12: #include <asm/ftrace.h>
13: #include <mach/entry-macro.S>
14: #include <asm/unwind.h>
15:
16: #include "entry-header.S"
17:
18:
19: .align 5
20: /*
21: * This is the fast syscall return path. We do as little as
22: * possible here, and this includes saving r0 back into the SVC
23: * stack.
24: */
25: ret_fast_syscall:
26: UNWIND(.fnstart )
27: UNWIND(.cantunwind )
28: disable_irq @ disable interrupts
29: ldr r1, [tsk, #TI_FLAGS]
30: tst r1, #_TIF_WORK_MASK
31: bne fast_work_pending
32:
33: /* perform architecture specific actions before user return */
34: arch_ret_to_user r1, lr
35:
36: @ fast_restore_user_regs
37: ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
38: ldr lr, [sp, #S_OFF + S_PC]! @ get pc
39: msr spsr_cxsf, r1 @ save in spsr_svc
40: ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
41: mov r0, r0
42: add sp, sp, #S_FRAME_SIZE - S_PC
43: movs pc, lr @ return & move spsr_svc into cpsr
44: UNWIND(.fnend )
45:
46: /*
47: * Ok, we need to do extra processing, enter the slow path.
48: */
49: fast_work_pending:
50: str r0, [sp, #S_R0+S_OFF]! @ returned r0
51: work_pending:
52: tst r1, #_TIF_NEED_RESCHED
53: bne work_resched
54: tst r1, #_TIF_SIGPENDING
55: beq no_work_pending
56: mov r0, sp @ 'regs'
57: mov r2, why @ 'syscall'
58: bl do_notify_resume
59: b ret_slow_syscall @ Check work again
60:
61: work_resched:
62: bl schedule
63: /*
64: * "slow" syscall return path. "why" tells us if this was a real syscall.
65: */
66: ENTRY(ret_to_user)
67: ret_slow_syscall:
68: disable_irq @ disable interrupts
69: ldr r1, [tsk, #TI_FLAGS]
70: tst r1, #_TIF_WORK_MASK
71: bne work_pending
72: no_work_pending:
73: /* perform architecture specific actions before user return */
74: arch_ret_to_user r1, lr
75:
76: @ slow_restore_user_regs
77: ldr r1, [sp, #S_PSR] @ get calling cpsr
78: ldr lr, [sp, #S_PC]! @ get pc
79: msr spsr_cxsf, r1 @ save in spsr_svc
80: ldmdb sp, {r0 - lr}^ @ get calling r0 - lr
81: mov r0, r0
82: add sp, sp, #S_FRAME_SIZE - S_PC
83: movs pc, lr @ return & move spsr_svc into cpsr
84: ENDPROC(ret_to_user)
85:
86: /*
87: * This is how we return from a fork.
88: */
89: ENTRY(ret_from_fork)
90: bl schedule_tail
91: get_thread_info tsk
92: ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
93: mov why, #1
94: tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
95: beq ret_slow_syscall
96: mov r1, sp
97: mov r0, #1 @ trace exit [IP = 1]
98: bl syscall_trace
99: b ret_slow_syscall
100: ENDPROC(ret_from_fork)
101:
102: .equ NR_syscalls,0
103: #define CALL(x) .equ NR_syscalls,NR_syscalls+1
104: #include "calls.S"
105: #undef CALL
106: #define CALL(x) .long x
107:
108: #ifdef CONFIG_FUNCTION_TRACER
109: #ifdef CONFIG_DYNAMIC_FTRACE
110: ENTRY(mcount)
111: stmdb sp!, {r0-r3, lr}
112: mov r0, lr
113: sub r0, r0, #MCOUNT_INSN_SIZE
114:
115: .globl mcount_call
116: mcount_call:
117: bl ftrace_stub
118: ldr lr, [fp, #-4] @ restore lr
119: ldmia sp!, {r0-r3, pc}
120:
121: ENTRY(ftrace_caller)
122: stmdb sp!, {r0-r3, lr}
123: ldr r1, [fp, #-4]
124: mov r0, lr
125: sub r0, r0, #MCOUNT_INSN_SIZE
126:
127: .globl ftrace_call
128: ftrace_call:
129: bl ftrace_stub
130: ldr lr, [fp, #-4] @ restore lr
131: ldmia sp!, {r0-r3, pc}
132:
133: #else
134:
135: ENTRY(mcount)
136: stmdb sp!, {r0-r3, lr}
137: ldr r0, =ftrace_trace_function
138: ldr r2, [r0]
139: adr r0, ftrace_stub
140: cmp r0, r2
141: bne trace
142: ldr lr, [fp, #-4] @ restore lr
143: ldmia sp!, {r0-r3, pc}
144:
145: trace:
146: ldr r1, [fp, #-4] @ lr of instrumented routine
147: mov r0, lr
148: sub r0, r0, #MCOUNT_INSN_SIZE
149: mov lr, pc
150: mov pc, r2
151: mov lr, r1 @ restore lr
152: ldmia sp!, {r0-r3, pc}
153:
154: #endif /* CONFIG_DYNAMIC_FTRACE */
155:
156: .globl ftrace_stub
157: ftrace_stub:
158: mov pc, lr
159:
160: #endif /* CONFIG_FUNCTION_TRACER */
161:
162: /*=============================================================================
163: * SWI handler
164: *-----------------------------------------------------------------------------
165: */
166:
167: /* If we're optimising for StrongARM the resulting code won't
168: run on an ARM7 and we can save a couple of instructions.
169: --pb */
170: #ifdef CONFIG_CPU_ARM710
171: #define A710(code...) code
172: .Larm710bug:
173: ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
174: mov r0, r0
175: add sp, sp, #S_FRAME_SIZE
176: subs pc, lr, #4
177: #else
178: #define A710(code...)
179: #endif
180:
181: .align 5
182: ENTRY(vector_swi)
183: sub sp, sp, #S_FRAME_SIZE
184: stmia sp, {r0 - r12} @ Calling r0 - r12
185: add r8, sp, #S_PC
186: stmdb r8, {sp, lr}^ @ Calling sp, lr
187: mrs r8, spsr @ called from non-FIQ mode, so ok.
188: str lr, [sp, #S_PC] @ Save calling PC
189: str r8, [sp, #S_PSR] @ Save CPSR
190: str r0, [sp, #S_OLD_R0] @ Save OLD_R0
191: zero_fp
192:
193: /*
194: * Get the system call number.
195: */
196:
197: #if defined(CONFIG_OABI_COMPAT)
198:
199: /*
200: * If we have CONFIG_OABI_COMPAT then we need to look at the swi
201: * value to determine if it is an EABI or an old ABI call.
202: */
203: #ifdef CONFIG_ARM_THUMB
204: tst r8, #PSR_T_BIT
205: movne r10, #0 @ no thumb OABI emulation
206: ldreq r10, [lr, #-4] @ get SWI instruction
207: #else
208: ldr r10, [lr, #-4] @ get SWI instruction
209: A710( and ip, r10, #0x0f000000 @ check for SWI )
210: A710( teq ip, #0x0f000000 )
211: A710( bne .Larm710bug )
212: #endif
213:
214: #elif defined(CONFIG_AEABI)
215:
216: /*
217: * Pure EABI user space always put syscall number into scno (r7).
218: */
219: A710( ldr ip, [lr, #-4] @ get SWI instruction )
220: A710( and ip, ip, #0x0f000000 @ check for SWI )
221: A710( teq ip, #0x0f000000 )
222: A710( bne .Larm710bug )
223:
224: #elif defined(CONFIG_ARM_THUMB)
225:
226: /* Legacy ABI only, possibly thumb mode. */
227: tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
228: addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
229: ldreq scno, [lr, #-4]
230:
231: #else
232:
233: /* Legacy ABI only. */
234: ldr scno, [lr, #-4] @ get SWI instruction
235: A710( and ip, scno, #0x0f000000 @ check for SWI )
236: A710( teq ip, #0x0f000000 )
237: A710( bne .Larm710bug )
238:
239: #endif
240:
241: #ifdef CONFIG_ALIGNMENT_TRAP
242: ldr ip, __cr_alignment
243: ldr ip, [ip]
244: mcr p15, 0, ip, c1, c0 @ update control register
245: #endif
246: enable_irq
247:
248: get_thread_info tsk
249: adr tbl, sys_call_table @ load syscall table pointer
250: ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
251:
252: #if defined(CONFIG_OABI_COMPAT)
253: /*
254: * If the swi argument is zero, this is an EABI call and we do nothing.
255: *
256: * If this is an old ABI call, get the syscall number into scno and
257: * get the old ABI syscall table address.
258: */
259: bics r10, r10, #0xff000000
260: eorne scno, r10, #__NR_OABI_SYSCALL_BASE
261: ldrne tbl, =sys_oabi_call_table
262: #elif !defined(CONFIG_AEABI)
263: bic scno, scno, #0xff000000 @ mask off SWI op-code
264: eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
265: #endif
266:
267: stmdb sp!, {r4, r5} @ push fifth and sixth args
268: tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
269: bne __sys_trace
270:
271: cmp scno, #NR_syscalls @ check upper syscall limit
272: adr lr, ret_fast_syscall @ return address
273: ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
274:
275: add r1, sp, #S_OFF
276: 2: mov why, #0 @ no longer a real syscall
277: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
278: eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
279: bcs arm_syscall
280: b sys_ni_syscall @ not private func
281: ENDPROC(vector_swi)
282:
283: /*
284: * This is the really slow path. We're going to be doing
285: * context switches, and waiting for our parent to respond.
286: */
287: __sys_trace:
288: mov r2, scno
289: add r1, sp, #S_OFF
290: mov r0, #0 @ trace entry [IP = 0]
291: bl syscall_trace
292:
293: adr lr, __sys_trace_return @ return address
294: mov scno, r0 @ syscall number (possibly new)
295: add r1, sp, #S_R0 + S_OFF @ pointer to regs
296: cmp scno, #NR_syscalls @ check upper syscall limit
297: ldmccia r1, {r0 - r3} @ have to reload r0 - r3
298: ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
299: b 2b
300:
301: __sys_trace_return:
302: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
303: mov r2, scno
304: mov r1, sp
305: mov r0, #1 @ trace exit [IP = 1]
306: bl syscall_trace
307: b ret_slow_syscall
308:
309: .align 5
310: #ifdef CONFIG_ALIGNMENT_TRAP
311: .type __cr_alignment, #object
312: __cr_alignment:
313: .word cr_alignment
314: #endif
315: .ltorg
316:
317: /*
318: * This is the syscall table declaration for native ABI syscalls.
319: * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
320: */
321: #define ABI(native, compat) native
322: #ifdef CONFIG_AEABI
323: #define OBSOLETE(syscall) sys_ni_syscall
324: #else
325: #define OBSOLETE(syscall) syscall
326: #endif
327:
328: .type sys_call_table, #object
329: ENTRY(sys_call_table)
330: #include "calls.S"
331: #undef ABI
332: #undef OBSOLETE
333:
334: /*============================================================================
335: * Special system call wrappers
336: */
337: @ r0 = syscall number
338: @ r8 = syscall table
339: sys_syscall:
340: bic scno, r0, #__NR_OABI_SYSCALL_BASE
341: cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
342: cmpne scno, #NR_syscalls @ check range
343: stmloia sp, {r5, r6} @ shuffle args
344: movlo r0, r1
345: movlo r1, r2
346: movlo r2, r3
347: movlo r3, r4
348: ldrlo pc, [tbl, scno, lsl #2]
349: b sys_ni_syscall
350: ENDPROC(sys_syscall)
351:
352: sys_fork_wrapper:
353: add r0, sp, #S_OFF
354: b sys_fork
355: ENDPROC(sys_fork_wrapper)
356:
357: sys_vfork_wrapper:
358: add r0, sp, #S_OFF
359: b sys_vfork
360: ENDPROC(sys_vfork_wrapper)
361:
362: sys_execve_wrapper:
363: add r3, sp, #S_OFF
364: b sys_execve
365: ENDPROC(sys_execve_wrapper)
366:
367: sys_clone_wrapper:
368: add ip, sp, #S_OFF
369: str ip, [sp, #4]
370: b sys_clone
371: ENDPROC(sys_clone_wrapper)
372:
373: sys_sigsuspend_wrapper:
374: add r3, sp, #S_OFF
375: b sys_sigsuspend
376: ENDPROC(sys_sigsuspend_wrapper)
377:
378: sys_rt_sigsuspend_wrapper:
379: add r2, sp, #S_OFF
380: b sys_rt_sigsuspend
381: ENDPROC(sys_rt_sigsuspend_wrapper)
382:
383: sys_sigreturn_wrapper:
384: add r0, sp, #S_OFF
385: b sys_sigreturn
386: ENDPROC(sys_sigreturn_wrapper)
387:
388: sys_rt_sigreturn_wrapper:
389: add r0, sp, #S_OFF
390: b sys_rt_sigreturn
391: ENDPROC(sys_rt_sigreturn_wrapper)
392:
393: sys_sigaltstack_wrapper:
394: ldr r2, [sp, #S_OFF + S_SP]
395: b do_sigaltstack
396: ENDPROC(sys_sigaltstack_wrapper)
397:
398: sys_statfs64_wrapper:
399: teq r1, #88
400: moveq r1, #84
401: b sys_statfs64
402: ENDPROC(sys_statfs64_wrapper)
403:
404: sys_fstatfs64_wrapper:
405: teq r1, #88
406: moveq r1, #84
407: b sys_fstatfs64
408: ENDPROC(sys_fstatfs64_wrapper)
409:
410: /*
411: * Note: off_4k (r5) is always units of 4K. If we can't do the requested
412: * offset, we return EINVAL.
413: */
414: sys_mmap2:
415: #if PAGE_SHIFT > 12
416: tst r5, #PGOFF_MASK
417: moveq r5, r5, lsr #PAGE_SHIFT - 12
418: streq r5, [sp, #4]
419: beq do_mmap2
420: mov r0, #-EINVAL
421: mov pc, lr
422: #else
423: str r5, [sp, #4]
424: b do_mmap2
425: #endif
426: ENDPROC(sys_mmap2)
427:
428: ENTRY(pabort_ifar)
429: mrc p15, 0, r0, cr6, cr0, 2
430: ENTRY(pabort_noifar)
431: mov pc, lr
432: ENDPROC(pabort_ifar)
433: ENDPROC(pabort_noifar)
434:
435: #ifdef CONFIG_OABI_COMPAT
436:
437: /*
438: * These are syscalls with argument register differences
439: */
440:
441: sys_oabi_pread64:
442: stmia sp, {r3, r4}
443: b sys_pread64
444: ENDPROC(sys_oabi_pread64)
445:
446: sys_oabi_pwrite64:
447: stmia sp, {r3, r4}
448: b sys_pwrite64
449: ENDPROC(sys_oabi_pwrite64)
450:
451: sys_oabi_truncate64:
452: mov r3, r2
453: mov r2, r1
454: b sys_truncate64
455: ENDPROC(sys_oabi_truncate64)
456:
457: sys_oabi_ftruncate64:
458: mov r3, r2
459: mov r2, r1
460: b sys_ftruncate64
461: ENDPROC(sys_oabi_ftruncate64)
462:
463: sys_oabi_readahead:
464: str r3, [sp]
465: mov r3, r2
466: mov r2, r1
467: b sys_readahead
468: ENDPROC(sys_oabi_readahead)
469:
470: /*
471: * Let's declare a second syscall table for old ABI binaries
472: * using the compatibility syscall entries.
473: */
474: #define ABI(native, compat) compat
475: #define OBSOLETE(syscall) syscall
476:
477: .type sys_oabi_call_table, #object
478: ENTRY(sys_oabi_call_table)
479: #include "calls.S"
480: #undef ABI
481: #undef OBSOLETE
482:
483: #endif
484:
在entry-common.S中包含了上次calls.S,这里简单分析前两次:
第一次:
在entry-common.S中: