對entry-common.S和call.S的部分理解1 - 摩斯電碼
內核版本: linux-2.6.30.4
文件:
linux-2.6.30.4/arch/arm/kernel/entry-common.S
linux-2.6.30.4/arch/arm/kernel/calls.S
calls.S:
1: /*
2: * linux/arch/arm/kernel/calls.S
3: *
4: * Copyright (C) 1995-2005 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: * This file is included thrice in entry-common.S
11: */
12: /* 0 */ CALL(sys_restart_syscall)
13: CALL(sys_exit)
14: CALL(sys_fork_wrapper)
15: CALL(sys_read)
16: CALL(sys_write)
17: /* 5 */ CALL(sys_open)
18: CALL(sys_close)
19: CALL(sys_ni_syscall) /* was sys_waitpid */
20: CALL(sys_creat)
21: CALL(sys_link)
22: /* 10 */ CALL(sys_unlink)
23: CALL(sys_execve_wrapper)
24: CALL(sys_chdir)
25: CALL(OBSOLETE(sys_time)) /* used by libc4 */
26: CALL(sys_mknod)
27: /* 15 */ CALL(sys_chmod)
28: CALL(sys_lchown16)
29: CALL(sys_ni_syscall) /* was sys_break */
30: CALL(sys_ni_syscall) /* was sys_stat */
31: CALL(sys_lseek)
32: /* 20 */ CALL(sys_getpid)
33: CALL(sys_mount)
34: CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */
35: CALL(sys_setuid16)
36: CALL(sys_getuid16)
37: /* 25 */ CALL(OBSOLETE(sys_stime))
38: CALL(sys_ptrace)
39: CALL(OBSOLETE(sys_alarm)) /* used by libc4 */
40: CALL(sys_ni_syscall) /* was sys_fstat */
41: CALL(sys_pause)
42: /* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */
43: CALL(sys_ni_syscall) /* was sys_stty */
44: CALL(sys_ni_syscall) /* was sys_getty */
45: CALL(sys_access)
46: CALL(sys_nice)
47: /* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */
48: CALL(sys_sync)
49: CALL(sys_kill)
50: CALL(sys_rename)
51: CALL(sys_mkdir)
52: /* 40 */ CALL(sys_rmdir)
53: CALL(sys_dup)
54: CALL(sys_pipe)
55: CALL(sys_times)
56: CALL(sys_ni_syscall) /* was sys_prof */
57: /* 45 */ CALL(sys_brk)
58: CALL(sys_setgid16)
59: CALL(sys_getgid16)
60: CALL(sys_ni_syscall) /* was sys_signal */
61: CALL(sys_geteuid16)
62: /* 50 */ CALL(sys_getegid16)
63: CALL(sys_acct)
64: CALL(sys_umount)
65: CALL(sys_ni_syscall) /* was sys_lock */
66: CALL(sys_ioctl)
67: /* 55 */ CALL(sys_fcntl)
68: CALL(sys_ni_syscall) /* was sys_mpx */
69: CALL(sys_setpgid)
70: CALL(sys_ni_syscall) /* was sys_ulimit */
71: CALL(sys_ni_syscall) /* was sys_olduname */
72: /* 60 */ CALL(sys_umask)
73: CALL(sys_chroot)
74: CALL(sys_ustat)
75: CALL(sys_dup2)
76: CALL(sys_getppid)
77: /* 65 */ CALL(sys_getpgrp)
78: CALL(sys_setsid)
79: CALL(sys_sigaction)
80: CALL(sys_ni_syscall) /* was sys_sgetmask */
81: CALL(sys_ni_syscall) /* was sys_ssetmask */
82: /* 70 */ CALL(sys_setreuid16)
83: CALL(sys_setregid16)
84: CALL(sys_sigsuspend_wrapper)
85: CALL(sys_sigpending)
86: CALL(sys_sethostname)
87: /* 75 */ CALL(sys_setrlimit)
88: CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */
89: CALL(sys_getrusage)
90: CALL(sys_gettimeofday)
91: CALL(sys_settimeofday)
92: /* 80 */ CALL(sys_getgroups16)
93: CALL(sys_setgroups16)
94: CALL(OBSOLETE(old_select)) /* used by libc4 */
95: CALL(sys_symlink)
96: CALL(sys_ni_syscall) /* was sys_lstat */
97: /* 85 */ CALL(sys_readlink)
98: CALL(sys_uselib)
99: CALL(sys_swapon)
100: CALL(sys_reboot)
101: CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */
102: /* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */
103: CALL(sys_munmap)
104: CALL(sys_truncate)
105: CALL(sys_ftruncate)
106: CALL(sys_fchmod)
107: /* 95 */ CALL(sys_fchown16)
108: CALL(sys_getpriority)
109: CALL(sys_setpriority)
110: CALL(sys_ni_syscall) /* was sys_profil */
111: CALL(sys_statfs)
112: /* 100 */ CALL(sys_fstatfs)
113: CALL(sys_ni_syscall) /* sys_ioperm */
114: CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall)))
115: CALL(sys_syslog)
116: CALL(sys_setitimer)
117: /* 105 */ CALL(sys_getitimer)
118: CALL(sys_newstat)
119: CALL(sys_newlstat)
120: CALL(sys_newfstat)
121: CALL(sys_ni_syscall) /* was sys_uname */
122: /* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */
123: CALL(sys_vhangup)
124: CALL(sys_ni_syscall)
125: CALL(OBSOLETE(sys_syscall)) /* call a syscall */
126: CALL(sys_wait4)
127: /* 115 */ CALL(sys_swapoff)
128: CALL(sys_sysinfo)
129: CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
130: CALL(sys_fsync)
131: CALL(sys_sigreturn_wrapper)
132: /* 120 */ CALL(sys_clone_wrapper)
133: CALL(sys_setdomainname)
134: CALL(sys_newuname)
135: CALL(sys_ni_syscall) /* modify_ldt */
136: CALL(sys_adjtimex)
137: /* 125 */ CALL(sys_mprotect)
138: CALL(sys_sigprocmask)
139: CALL(sys_ni_syscall) /* was sys_create_module */
140: CALL(sys_init_module)
141: CALL(sys_delete_module)
142: /* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */
143: CALL(sys_quotactl)
144: CALL(sys_getpgid)
145: CALL(sys_fchdir)
146: CALL(sys_bdflush)
147: /* 135 */ CALL(sys_sysfs)
148: CALL(sys_personality)
149: CALL(sys_ni_syscall) /* reserved for afs_syscall */
150: CALL(sys_setfsuid16)
151: CALL(sys_setfsgid16)
152: /* 140 */ CALL(sys_llseek)
153: CALL(sys_getdents)
154: CALL(sys_select)
155: CALL(sys_flock)
156: CALL(sys_msync)
157: /* 145 */ CALL(sys_readv)
158: CALL(sys_writev)
159: CALL(sys_getsid)
160: CALL(sys_fdatasync)
161: CALL(sys_sysctl)
162: /* 150 */ CALL(sys_mlock)
163: CALL(sys_munlock)
164: CALL(sys_mlockall)
165: CALL(sys_munlockall)
166: CALL(sys_sched_setparam)
167: /* 155 */ CALL(sys_sched_getparam)
168: CALL(sys_sched_setscheduler)
169: CALL(sys_sched_getscheduler)
170: CALL(sys_sched_yield)
171: CALL(sys_sched_get_priority_max)
172: /* 160 */ CALL(sys_sched_get_priority_min)
173: CALL(sys_sched_rr_get_interval)
174: CALL(sys_nanosleep)
175: CALL(sys_arm_mremap)
176: CALL(sys_setresuid16)
177: /* 165 */ CALL(sys_getresuid16)
178: CALL(sys_ni_syscall) /* vm86 */
179: CALL(sys_ni_syscall) /* was sys_query_module */
180: CALL(sys_poll)
181: CALL(sys_nfsservctl)
182: /* 170 */ CALL(sys_setresgid16)
183: CALL(sys_getresgid16)
184: CALL(sys_prctl)
185: CALL(sys_rt_sigreturn_wrapper)
186: CALL(sys_rt_sigaction)
187: /* 175 */ CALL(sys_rt_sigprocmask)
188: CALL(sys_rt_sigpending)
189: CALL(sys_rt_sigtimedwait)
190: CALL(sys_rt_sigqueueinfo)
191: CALL(sys_rt_sigsuspend_wrapper)
192: /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
193: CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
194: CALL(sys_chown16)
195: CALL(sys_getcwd)
196: CALL(sys_capget)
197: /* 185 */ CALL(sys_capset)
198: CALL(sys_sigaltstack_wrapper)
199: CALL(sys_sendfile)
200: CALL(sys_ni_syscall) /* getpmsg */
201: CALL(sys_ni_syscall) /* putpmsg */
202: /* 190 */ CALL(sys_vfork_wrapper)
203: CALL(sys_getrlimit)
204: CALL(sys_mmap2)
205: CALL(ABI(sys_truncate64, sys_oabi_truncate64))
206: CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64))
207: /* 195 */ CALL(ABI(sys_stat64, sys_oabi_stat64))
208: CALL(ABI(sys_lstat64, sys_oabi_lstat64))
209: CALL(ABI(sys_fstat64, sys_oabi_fstat64))
210: CALL(sys_lchown)
211: CALL(sys_getuid)
212: /* 200 */ CALL(sys_getgid)
213: CALL(sys_geteuid)
214: CALL(sys_getegid)
215: CALL(sys_setreuid)
216: CALL(sys_setregid)
217: /* 205 */ CALL(sys_getgroups)
218: CALL(sys_setgroups)
219: CALL(sys_fchown)
220: CALL(sys_setresuid)
221: CALL(sys_getresuid)
222: /* 210 */ CALL(sys_setresgid)
223: CALL(sys_getresgid)
224: CALL(sys_chown)
225: CALL(sys_setuid)
226: CALL(sys_setgid)
227: /* 215 */ CALL(sys_setfsuid)
228: CALL(sys_setfsgid)
229: CALL(sys_getdents64)
230: CALL(sys_pivot_root)
231: CALL(sys_mincore)
232: /* 220 */ CALL(sys_madvise)
233: CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
234: CALL(sys_ni_syscall) /* TUX */
235: CALL(sys_ni_syscall)
236: CALL(sys_gettid)
237: /* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead))
238: CALL(sys_setxattr)
239: CALL(sys_lsetxattr)
240: CALL(sys_fsetxattr)
241: CALL(sys_getxattr)
242: /* 230 */ CALL(sys_lgetxattr)
243: CALL(sys_fgetxattr)
244: CALL(sys_listxattr)
245: CALL(sys_llistxattr)
246: CALL(sys_flistxattr)
247: /* 235 */ CALL(sys_removexattr)
248: CALL(sys_lremovexattr)
249: CALL(sys_fremovexattr)
250: CALL(sys_tkill)
251: CALL(sys_sendfile64)
252: /* 240 */ CALL(sys_futex)
253: CALL(sys_sched_setaffinity)
254: CALL(sys_sched_getaffinity)
255: CALL(sys_io_setup)
256: CALL(sys_io_destroy)
257: /* 245 */ CALL(sys_io_getevents)
258: CALL(sys_io_submit)
259: CALL(sys_io_cancel)
260: CALL(sys_exit_group)
261: CALL(sys_lookup_dcookie)
262: /* 250 */ CALL(sys_epoll_create)
263: CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl))
264: CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait))
265: CALL(sys_remap_file_pages)
266: CALL(sys_ni_syscall) /* sys_set_thread_area */
267: /* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */
268: CALL(sys_set_tid_address)
269: CALL(sys_timer_create)
270: CALL(sys_timer_settime)
271: CALL(sys_timer_gettime)
272: /* 260 */ CALL(sys_timer_getoverrun)
273: CALL(sys_timer_delete)
274: CALL(sys_clock_settime)
275: CALL(sys_clock_gettime)
276: CALL(sys_clock_getres)
277: /* 265 */ CALL(sys_clock_nanosleep)
278: CALL(sys_statfs64_wrapper)
279: CALL(sys_fstatfs64_wrapper)
280: CALL(sys_tgkill)
281: CALL(sys_utimes)
282: /* 270 */ CALL(sys_arm_fadvise64_64)
283: CALL(sys_pciconfig_iobase)
284: CALL(sys_pciconfig_read)
285: CALL(sys_pciconfig_write)
286: CALL(sys_mq_open)
287: /* 275 */ CALL(sys_mq_unlink)
288: CALL(sys_mq_timedsend)
289: CALL(sys_mq_timedreceive)
290: CALL(sys_mq_notify)
291: CALL(sys_mq_getsetattr)
292: /* 280 */ CALL(sys_waitid)
293: CALL(sys_socket)
294: CALL(ABI(sys_bind, sys_oabi_bind))
295: CALL(ABI(sys_connect, sys_oabi_connect))
296: CALL(sys_listen)
297: /* 285 */ CALL(sys_accept)
298: CALL(sys_getsockname)
299: CALL(sys_getpeername)
300: CALL(sys_socketpair)
301: CALL(sys_send)
302: /* 290 */ CALL(ABI(sys_sendto, sys_oabi_sendto))
303: CALL(sys_recv)
304: CALL(sys_recvfrom)
305: CALL(sys_shutdown)
306: CALL(sys_setsockopt)
307: /* 295 */ CALL(sys_getsockopt)
308: CALL(ABI(sys_sendmsg, sys_oabi_sendmsg))
309: CALL(sys_recvmsg)
310: CALL(ABI(sys_semop, sys_oabi_semop))
311: CALL(sys_semget)
312: /* 300 */ CALL(sys_semctl)
313: CALL(sys_msgsnd)
314: CALL(sys_msgrcv)
315: CALL(sys_msgget)
316: CALL(sys_msgctl)
317: /* 305 */ CALL(sys_shmat)
318: CALL(sys_shmdt)
319: CALL(sys_shmget)
320: CALL(sys_shmctl)
321: CALL(sys_add_key)
322: /* 310 */ CALL(sys_request_key)
323: CALL(sys_keyctl)
324: CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
325: /* vserver */ CALL(sys_ni_syscall)
326: CALL(sys_ioprio_set)
327: /* 315 */ CALL(sys_ioprio_get)
328: CALL(sys_inotify_init)
329: CALL(sys_inotify_add_watch)
330: CALL(sys_inotify_rm_watch)
331: CALL(sys_mbind)
332: /* 320 */ CALL(sys_get_mempolicy)
333: CALL(sys_set_mempolicy)
334: CALL(sys_openat)
335: CALL(sys_mkdirat)
336: CALL(sys_mknodat)
337: /* 325 */ CALL(sys_fchownat)
338: CALL(sys_futimesat)
339: CALL(ABI(sys_fstatat64, sys_oabi_fstatat64))
340: CALL(sys_unlinkat)
341: CALL(sys_renameat)
342: /* 330 */ CALL(sys_linkat)
343: CALL(sys_symlinkat)
344: CALL(sys_readlinkat)
345: CALL(sys_fchmodat)
346: CALL(sys_faccessat)
347: /* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
348: CALL(sys_ni_syscall) /* eventually ppoll */
349: CALL(sys_unshare)
350: CALL(sys_set_robust_list)
351: CALL(sys_get_robust_list)
352: /* 340 */ CALL(sys_splice)
353: CALL(sys_sync_file_range2)
354: CALL(sys_tee)
355: CALL(sys_vmsplice)
356: CALL(sys_move_pages)
357: /* 345 */ CALL(sys_getcpu)
358: CALL(sys_ni_syscall) /* eventually epoll_pwait */
359: CALL(sys_kexec_load)
360: CALL(sys_utimensat)
361: CALL(sys_signalfd)
362: /* 350 */ CALL(sys_timerfd_create)
363: CALL(sys_eventfd)
364: CALL(sys_fallocate)
365: CALL(sys_timerfd_settime)
366: CALL(sys_timerfd_gettime)
367: /* 355 */ CALL(sys_signalfd4)
368: CALL(sys_eventfd2)
369: CALL(sys_epoll_create1)
370: CALL(sys_dup3)
371: CALL(sys_pipe2)
372: /* 360 */ CALL(sys_inotify_init1)
373: CALL(sys_preadv)
374: CALL(sys_pwritev)
375: #ifndef syscalls_counted
376: .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
377: #define syscalls_counted
378: #endif
379: .rept syscalls_padding
380: CALL(sys_ni_syscall)
381: .endr
entry-common.S
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中:
1: .equ NR_syscalls,0
2: #define CALL(x) .equ NR_syscalls,NR_syscalls+1
3: #include "calls.S"
4: #undef CALL
5: #define CALL(x) .long x
在calls.S的結尾:
1: CALL(sys_preadv)
2: CALL(sys_pwritev)
3: #ifndef syscalls_counted
4: .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
5: #define syscalls_counted
6: #endif
7: .rept syscalls_padding
8: CALL(sys_ni_syscall)
9: .endr
分析:
.equ NR_syscalls,0 中涉及到匯編指令.equ:
.equ/.set: 賦值語句, 格式如下:
.equ(.set) 變量名,表達式
例如:
.equ abc 3 @讓abc=3
這裡只是定義了一個變量NR_syscalls,並將其初始化為0。可以理解為: NR_syscalls = 0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
即 將CALL(x) 定義為: NR_syscalls = NR_syscalls + 1
#include "calls.S" 將calls.S的內容包進來,因為上面對CALL(x)進行了定義所以相當於執行了多次NR_syscalls++,相當於統計了系統調用的個數,但是注意:在calls.S的結尾的對齊處理:
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
#endif
.rept syscalls_padding
CALL(sys_ni_syscall)
.endr
由於是第一次包含,故syscalls_counted沒有定義,
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
為了保證NR_syscalls是4的整數倍,上面的語句相當於:syscalls_padding = ((NR_syscalls + 3) & ~3) - NR_syscalls;
即:假如NR_syscalls 是1,那麼syscalls_padding 就是3
.rept syscalls_padding
CALL(sys_ni_syscall)
.endr
這裡涉及到匯編指令.rept的用法:
.rept:重復定義偽操作, 格式如下:
.rept 重復次數
數據定義
.endr @結束重復定義
例如:
.rept 3
.byte 0x23
.endr
繼續上面的例子:syscalls_padding 為3,那麼上面的rept語句塊相當於:
CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
即又執行了三次:NR_syscalls++,此時NR_syscalls就變成了4,對齊了。
第二次:
1: .type sys_call_table, #object
2: ENTRY(sys_call_table)
3: #include "calls.S"
4: #undef ABI
5: #undef OBSOLETE
6:
7:
8: @r0 = syscall number
9: @r8 = syscall table
10: sys_syscall:
11: bic scno, r0, #__NR_OABI_SYSCALL_BASE
12: cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
13: cmpne scno, #NR_syscalls @ check range
14: stmloia sp, {r5, r6} @ shuffle args
15: movlo r0, r1
16: movlo r1, r2
17: movlo r2, r3
18: movlo r3, r4
19: ldrlo pc, [tbl, scno, lsl #2]
20: b sys_ni_syscall
21: ENDPROC(sys_syscall)
第二次包含是建立在第一次包含的基礎上,第一次包含的結果是:
•#undef CALL
•#define CALL(x) .long x
•NR_syscalls 是系統調用的個數,並且進行了4的倍數對齊(最後幾個系統調用可能只是為了湊數)
•syscalls_padding的數值保證了CALL(x)的個數可以4倍對齊,即.long x 的個數是4的倍數。目的是在下面的sys_syscall函數中的:
ldrlo pc, [tbl, scno, lsl #2]
即將“系統調用表基地址tbl+系統調用號scno*4”地址單元(上面的某個.long x)的數據(也就是某個系統調用處理函數的入口地址)放到PC寄存器中(因為有了對齊,所以不會產生訪問越界的情況,又因為
cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
cmpne scno, #NR_syscalls @ check range
以上兩條語句保證了系統調用號scno的大小不會超出范圍)。
可以看到,在calls.S結尾的系統調用:sys_ni_syscall。它除了返回-ENOSYS之外啥也沒干:
1: /*
2: * Non-implemented system calls get redirected here.
3: */
4: asmlinkage long sys_ni_syscall(void)
5: {
6: return -ENOSYS;
7: }