entry-common.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <linux/config.h>
  11. #include "entry-header.S"
  12. /* 
  13.  * We rely on the fact that R0 is at the bottom of the stack (due to
  14.  * slow/fast restore user regs).
  15.  */
  16. #if S_R0 != 0
  17. #error "Please fix"
  18. #endif
  19. /*
  20.  * Our do_softirq out of line code.  See include/asm-arm/softirq.h for
  21.  * the calling assembly.
  22.  */
  23. ENTRY(__do_softirq)
  24. stmfd sp!, {r0 - r3, ip, lr}
  25. bl do_softirq
  26. ldmfd sp!, {r0 - r3, ip, pc}
  27. .align 5
  28. /*
  29.  * This is the fast syscall return path.  We do as little as
  30.  * possible here, and this includes saving r0 back into the SVC
  31.  * stack.
  32.  */
  33. ret_fast_syscall:
  34. ldr r1, [tsk, #TSK_NEED_RESCHED]
  35. ldr r2, [tsk, #TSK_SIGPENDING]
  36. teq r1, #0 @ need_resched || sigpending
  37. teqeq r2, #0
  38. bne slow
  39. fast_restore_user_regs
  40. /*
  41.  * Ok, we need to do extra processing, enter the slow path.
  42.  */
  43. slow: str r0, [sp, #S_R0+S_OFF]! @ returned r0
  44. b 1f
  45. /*
  46.  * "slow" syscall return path.  "why" tells us if this was a real syscall.
  47.  */
  48. reschedule:
  49. bl SYMBOL_NAME(schedule)
  50. ENTRY(ret_to_user)
  51. ret_slow_syscall:
  52. ldr r1, [tsk, #TSK_NEED_RESCHED]
  53. ldr r2, [tsk, #TSK_SIGPENDING]
  54. 1: teq r1, #0 @ need_resched => schedule()
  55. bne reschedule
  56. teq r2, #0 @ sigpending => do_signal()
  57. blne __do_signal
  58. restore_user_regs
  59. __do_signal:
  60. mov r0, #0 @ NULL 'oldset'
  61. mov r1, sp @ 'regs'
  62. mov r2, why @ 'syscall'
  63. b SYMBOL_NAME(do_signal) @ note the bl above sets lr
  64. /*
  65.  * This is how we return from a fork.  __switch_to will be calling us
  66.  * with r0 pointing at the previous task that was running (ready for
  67.  * calling schedule_tail).
  68.  */
  69. ENTRY(ret_from_fork)
  70. bl SYMBOL_NAME(schedule_tail)
  71. get_current_task tsk
  72. ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
  73. mov why, #1
  74. tst ip, #PT_TRACESYS @ are we tracing syscalls?
  75. beq ret_slow_syscall
  76. mov r1, sp
  77. mov r0, #1 @ trace exit [IP = 1]
  78. bl SYMBOL_NAME(syscall_trace)
  79. b ret_slow_syscall
  80. #include "calls.S"
  81. /*=============================================================================
  82.  * SWI handler
  83.  *-----------------------------------------------------------------------------
  84.  */
  85. /* If we're optimising for StrongARM the resulting code won't 
  86.    run on an ARM7 and we can save a couple of instructions.  
  87. --pb */
  88. #ifdef CONFIG_CPU_ARM710
  89. .macro arm710_bug_check, instr, temp
  90. and temp, instr, #0x0f000000 @ check for SWI
  91. teq temp, #0x0f000000
  92. bne .Larm700bug
  93. .endm
  94. .Larm700bug:
  95. ldr r0, [sp, #S_PSR] @ Get calling cpsr
  96. sub lr, lr, #4
  97. str lr, [r8]
  98. msr spsr, r0
  99. ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
  100. mov r0, r0
  101. ldr lr, [sp, #S_PC] @ Get PC
  102. add sp, sp, #S_FRAME_SIZE
  103. movs pc, lr
  104. #else
  105. .macro arm710_bug_check, instr, temp
  106. .endm
  107. #endif
  108. .align 5
  109. ENTRY(vector_swi)
  110. save_user_regs
  111. zero_fp
  112. get_scno
  113. arm710_bug_check scno, ip
  114. #ifdef CONFIG_ALIGNMENT_TRAP
  115. ldr ip, __cr_alignment
  116. ldr ip, [ip]
  117. mcr p15, 0, ip, c1, c0 @ update control register
  118. #endif
  119. enable_irqs ip
  120. str r4, [sp, #-S_OFF]! @ push fifth arg
  121. get_current_task tsk
  122. ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
  123. bic scno, scno, #0xff000000 @ mask off SWI op-code
  124. eor scno, scno, #OS_NUMBER << 20 @ check OS number
  125. adr tbl, sys_call_table @ load syscall table pointer
  126. tst ip, #PT_TRACESYS @ are we tracing syscalls?
  127. bne __sys_trace
  128. adrsvc al, lr, ret_fast_syscall @ return address
  129. cmp scno, #NR_syscalls @ check upper syscall limit
  130. ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
  131. add r1, sp, #S_OFF
  132. 2: mov why, #0 @ no longer a real syscall
  133. cmp scno, #ARMSWI_OFFSET
  134. eor r0, scno, #OS_NUMBER << 20 @ put OS number back
  135. bcs SYMBOL_NAME(arm_syscall)
  136. b SYMBOL_NAME(sys_ni_syscall) @ not private func
  137. /*
  138.  * This is the really slow path.  We're going to be doing
  139.  * context switches, and waiting for our parent to respond.
  140.  */
  141. __sys_trace:
  142. add r1, sp, #S_OFF
  143. mov r0, #0 @ trace entry [IP = 0]
  144. bl SYMBOL_NAME(syscall_trace)
  145. adrsvc al, lr, __sys_trace_return @ return address
  146. add r1, sp, #S_R0 + S_OFF @ pointer to regs
  147. cmp scno, #NR_syscalls @ check upper syscall limit
  148. ldmccia r1, {r0 - r3} @ have to reload r0 - r3
  149. ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
  150. b 2b
  151. __sys_trace_return:
  152. str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
  153. mov r1, sp
  154. mov r0, #1 @ trace exit [IP = 1]
  155. bl SYMBOL_NAME(syscall_trace)
  156. b ret_slow_syscall
  157. .align 5
  158. #ifdef CONFIG_ALIGNMENT_TRAP
  159. .type __cr_alignment, #object
  160. __cr_alignment:
  161. .word SYMBOL_NAME(cr_alignment)
  162. #endif
  163. .type sys_call_table, #object
  164. ENTRY(sys_call_table)
  165. #include "calls.S"
  166. /*============================================================================
  167.  * Special system call wrappers
  168.  */
  169. @ r0 = syscall number
  170. @ r5 = syscall table
  171. .type sys_syscall, #function
  172. SYMBOL_NAME(sys_syscall):
  173. eor scno, r0, #OS_NUMBER << 20
  174. cmp scno, #NR_syscalls @ check range
  175. stmleia sp, {r5, r6} @ shuffle args
  176. movle r0, r1
  177. movle r1, r2
  178. movle r2, r3
  179. movle r3, r4
  180. ldrle pc, [tbl, scno, lsl #2]
  181. b sys_ni_syscall
  182. sys_fork_wrapper:
  183. add r0, sp, #S_OFF
  184. b SYMBOL_NAME(sys_fork)
  185. sys_vfork_wrapper:
  186. add r0, sp, #S_OFF
  187. b SYMBOL_NAME(sys_vfork)
  188. sys_execve_wrapper:
  189. add r3, sp, #S_OFF
  190. b SYMBOL_NAME(sys_execve)
  191. sys_clone_wapper:
  192. add r2, sp, #S_OFF
  193. b SYMBOL_NAME(sys_clone)
  194. sys_sigsuspend_wrapper:
  195. add r3, sp, #S_OFF
  196. b SYMBOL_NAME(sys_sigsuspend)
  197. sys_rt_sigsuspend_wrapper:
  198. add r2, sp, #S_OFF
  199. b SYMBOL_NAME(sys_rt_sigsuspend)
  200. sys_sigreturn_wrapper:
  201. add r0, sp, #S_OFF
  202. b SYMBOL_NAME(sys_sigreturn)
  203. sys_rt_sigreturn_wrapper:
  204. add r0, sp, #S_OFF
  205. b SYMBOL_NAME(sys_rt_sigreturn)
  206. sys_sigaltstack_wrapper:
  207. ldr r2, [sp, #S_OFF + S_SP]
  208. b do_sigaltstack
  209. /*
  210.  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
  211.  * offset, we return EINVAL.
  212.  */
  213. sys_mmap2:
  214. #if PAGE_SHIFT > 12
  215. tst r5, #PGOFF_MASK
  216. moveq r5, r5, lsr #PAGE_SHIFT - 12
  217. streq r5, [sp, #4]
  218. beq do_mmap2
  219. mov r0, #-EINVAL
  220. RETINSTR(mov,pc, lr)
  221. #else
  222. str r5, [sp, #4]
  223. b do_mmap2
  224. #endif