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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.entry.S 1.26 01/25/02 15:15:24 benh
  3.  */
  4. /*
  5.  *  PowerPC version 
  6.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  7.  *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
  8.  *    Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
  9.  *  Adapted for Power Macintosh by Paul Mackerras.
  10.  *  Low-level exception handlers and MMU support
  11.  *  rewritten by Paul Mackerras.
  12.  *    Copyright (C) 1996 Paul Mackerras.
  13.  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
  14.  *
  15.  *  This file contains the system call entry code, context switch
  16.  *  code, and exception/interrupt return code for PowerPC.
  17.  *
  18.  *  This program is free software; you can redistribute it and/or
  19.  *  modify it under the terms of the GNU General Public License
  20.  *  as published by the Free Software Foundation; either version
  21.  *  2 of the License, or (at your option) any later version.
  22.  *
  23.  */
  24. #include "ppc_asm.h"
  25. #include <linux/config.h>
  26. #include <linux/errno.h>
  27. #include <linux/sys.h>
  28. #include <linux/threads.h>
  29. #include <asm/processor.h>
  30. #include <asm/page.h>
  31. #include <asm/mmu.h>
  32. #include <asm/cputable.h>
  33. #undef SHOW_SYSCALLS
  34. #undef SHOW_SYSCALLS_TASK
  35. #ifdef SHOW_SYSCALLS_TASK
  36. .data
  37. show_syscalls_task:
  38. .long -1
  39. #endif
  40. /*
  41.  * Handle a system call.
  42.  */
  43. .text
  44. _GLOBAL(DoSyscall)
  45. stw r0,THREAD+LAST_SYSCALL(r2)
  46. lwz r11,_CCR(r1) /* Clear SO bit in CR */
  47. lis r10,0x1000
  48. andc r11,r11,r10
  49. stw r11,_CCR(r1)
  50. #ifdef SHOW_SYSCALLS
  51. #ifdef SHOW_SYSCALLS_TASK
  52. lis r31,show_syscalls_task@ha
  53. lwz r31,show_syscalls_task@l(r31)
  54. cmp 0,r2,r31
  55. bne 1f
  56. #endif
  57. lis r3,7f@ha
  58. addi r3,r3,7f@l
  59. lwz r4,GPR0(r1)
  60. lwz r5,GPR3(r1)
  61. lwz r6,GPR4(r1)
  62. lwz r7,GPR5(r1)
  63. lwz r8,GPR6(r1)
  64. lwz r9,GPR7(r1)
  65. bl printk
  66. lis r3,77f@ha
  67. addi r3,r3,77f@l
  68. lwz r4,GPR8(r1)
  69. lwz r5,GPR9(r1)
  70. mr r6,r2
  71. bl printk
  72. lwz r0,GPR0(r1)
  73. lwz r3,GPR3(r1)
  74. lwz r4,GPR4(r1)
  75. lwz r5,GPR5(r1)
  76. lwz r6,GPR6(r1)
  77. lwz r7,GPR7(r1)
  78. lwz r8,GPR8(r1)
  79. 1:
  80. #endif /* SHOW_SYSCALLS */
  81. cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
  82. beq- 10f
  83. cmpi    0,r0,0x6666     /* Special case for 'sys_rt_sigreturn' */
  84. beq-    16f
  85. lwz r10,TASK_PTRACE(r2)
  86. andi. r10,r10,PT_TRACESYS
  87. bne- 50f
  88. cmpli 0,r0,NR_syscalls
  89. bge- 66f
  90. lis r10,sys_call_table@h
  91. ori r10,r10,sys_call_table@l
  92. slwi r0,r0,2
  93. lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
  94. cmpi 0,r10,0
  95. beq- 66f
  96. mtlr r10
  97. addi r9,r1,STACK_FRAME_OVERHEAD
  98. blrl /* Call handler */
  99. .globl ret_from_syscall_1
  100. ret_from_syscall_1:
  101. 20: stw r3,RESULT(r1) /* Save result */
  102. #ifdef SHOW_SYSCALLS
  103. #ifdef SHOW_SYSCALLS_TASK
  104. cmp 0,r2,r31
  105. bne 91f
  106. #endif
  107. mr r4,r3
  108. lis r3,79f@ha
  109. addi r3,r3,79f@l
  110. bl printk
  111. lwz r3,RESULT(r1)
  112. 91:
  113. #endif
  114. li r10,-_LAST_ERRNO
  115. cmpl 0,r3,r10
  116. blt 30f
  117. neg r3,r3
  118. cmpi 0,r3,ERESTARTNOHAND
  119. bne 22f
  120. li r3,EINTR
  121. 22: lwz r10,_CCR(r1) /* Set SO bit in CR */
  122. oris r10,r10,0x1000
  123. stw r10,_CCR(r1)
  124. 30: stw r3,GPR3(r1) /* Update return value */
  125. b ret_from_except
  126. 66: li r3,ENOSYS
  127. b 22b
  128. /* sys_sigreturn */
  129. 10: addi r3,r1,STACK_FRAME_OVERHEAD
  130. bl sys_sigreturn
  131. cmpi    0,r3,0          /* Check for restarted system call */
  132. bge     ret_from_except
  133. b       20b
  134. /* sys_rt_sigreturn */
  135. 16: addi    r3,r1,STACK_FRAME_OVERHEAD
  136. bl      sys_rt_sigreturn
  137. cmpi 0,r3,0 /* Check for restarted system call */
  138. bge ret_from_except
  139. b 20b
  140. /* Traced system call support */
  141. 50: bl syscall_trace
  142. lwz r0,GPR0(r1) /* Restore original registers */
  143. lwz r3,GPR3(r1)
  144. lwz r4,GPR4(r1)
  145. lwz r5,GPR5(r1)
  146. lwz r6,GPR6(r1)
  147. lwz r7,GPR7(r1)
  148. lwz r8,GPR8(r1)
  149. lwz r9,GPR9(r1)
  150. cmpli 0,r0,NR_syscalls
  151. bge- 66f
  152. lis r10,sys_call_table@h
  153. ori r10,r10,sys_call_table@l
  154. slwi r0,r0,2
  155. lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
  156. cmpi 0,r10,0
  157. beq- 66f
  158. mtlr r10
  159. addi r9,r1,STACK_FRAME_OVERHEAD
  160. blrl /* Call handler */
  161. .globl ret_from_syscall_2
  162. ret_from_syscall_2:
  163. stw r3,RESULT(r1) /* Save result */
  164. stw r3,GPR0(r1) /* temporary gross hack to make strace work */
  165. li r10,-_LAST_ERRNO
  166. cmpl 0,r3,r10
  167. blt 60f
  168. neg r3,r3
  169. cmpi 0,r3,ERESTARTNOHAND
  170. bne 52f
  171. li r3,EINTR
  172. 52: lwz r10,_CCR(r1) /* Set SO bit in CR */
  173. oris r10,r10,0x1000
  174. stw r10,_CCR(r1)
  175. 60: stw r3,GPR3(r1) /* Update return value */
  176. bl syscall_trace
  177. b ret_from_except
  178. 66: li r3,ENOSYS
  179. b 52b
  180. #ifdef SHOW_SYSCALLS
  181. 7: .string "syscall %d(%x, %x, %x, %x, %x, "
  182. 77: .string "%x, %x), current=%pn"
  183. 79: .string " -> %xn"
  184. .align 2,0
  185. #endif
  186. /*
  187.  * This routine switches between two different tasks.  The process
  188.  * state of one is saved on its kernel stack.  Then the state
  189.  * of the other is restored from its kernel stack.  The memory
  190.  * management hardware is updated to the second process's state.
  191.  * Finally, we can return to the second process.
  192.  * On entry, r3 points to the THREAD for the current task, r4
  193.  * points to the THREAD for the new task.
  194.  *
  195.  * Note: there are two ways to get to the "going out" portion
  196.  * of this code; either by coming in via the entry (_switch)
  197.  * or via "fork" which must set up an environment equivalent
  198.  * to the "_switch" path.  If you change this , you'll have to
  199.  * change the fork code also.
  200.  *
  201.  * The code which creates the new task context is in 'copy_thread'
  202.  * in arch/ppc/kernel/process.c
  203.  */
  204. _GLOBAL(_switch)
  205. stwu r1,-INT_FRAME_SIZE(r1)
  206. stw r0,GPR0(r1)
  207. lwz r0,0(r1)
  208. stw r0,GPR1(r1)
  209. /* r3-r13 are caller saved -- Cort */
  210. SAVE_GPR(2, r1)
  211. SAVE_8GPRS(14, r1)
  212. SAVE_10GPRS(22, r1)
  213. mflr r20 /* Return to switch caller */
  214. stw r20,INT_FRAME_SIZE+4(r1)
  215. mfmsr r22
  216. li r0,MSR_FP /* Disable floating-point */
  217. #ifdef CONFIG_ALTIVEC
  218. BEGIN_FTR_SECTION
  219. oris r0,r0,MSR_VEC@h /* Disable altivec */
  220. END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  221. #endif /* CONFIG_ALTIVEC */
  222. and. r0,r0,r22 /* FP or altivec enabled? */
  223. beq+ 1f
  224. andc r22,r22,r0
  225. mtmsr r22
  226. isync
  227. 1: stw r20,_NIP(r1)
  228. stw r22,_MSR(r1)
  229. stw r20,_LINK(r1)
  230. mfcr r20
  231. mfctr r22
  232. mfspr r23,XER
  233. stw r20,_CCR(r1)
  234. stw r22,_CTR(r1)
  235. stw r23,_XER(r1)
  236. li r0,0x0ff0
  237. stw r0,TRAP(r1)
  238. stw r1,KSP(r3) /* Set old stack pointer */
  239. tophys(r0,r4)
  240. CLR_TOP32(r0)
  241. mtspr SPRG3,r0 /* Update current THREAD phys addr */
  242. lwz r1,KSP(r4) /* Load new stack pointer */
  243. /* save the old current 'last' for return value */
  244. mr r3,r2
  245. addi r2,r4,-THREAD /* Update current */
  246. lwz r0,_CCR(r1)
  247. mtcrf 0xFF,r0
  248. /* r3-r13 are destroyed -- Cort */
  249. REST_2GPRS(14, r1)
  250. REST_8GPRS(16, r1)
  251. REST_8GPRS(24, r1)
  252. lwz r4,_NIP(r1) /* Return to _switch caller in new task */
  253. mtlr r4
  254. addi r1,r1,INT_FRAME_SIZE
  255. blr
  256. .globl ret_from_fork
  257. ret_from_fork:
  258. bl schedule_tail
  259. lwz r0,TASK_PTRACE(r2)
  260. andi. r0,r0,PT_TRACESYS
  261. bnel- syscall_trace
  262. b ret_from_except
  263. .globl ret_from_intercept
  264. ret_from_intercept:
  265. /*
  266.  * We may be returning from RTL and cannot do the normal checks
  267.  * -- Cort
  268.  */
  269. cmpi 0,r3,0
  270. beq restore
  271. .globl ret_from_except
  272. ret_from_except:
  273. lwz r3,_MSR(r1) /* Returning to user mode? */
  274. andi. r3,r3,MSR_PR
  275. beq+ do_signal_ret /* if so, check need_resched and signals */
  276. lwz r3,NEED_RESCHED(r2)
  277. cmpi 0,r3,0 /* check need_resched flag */
  278. beq+ 7f
  279. bl schedule
  280. 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */
  281. cmpwi 0,r5,0
  282. beq+ do_signal_ret
  283. li r3,0
  284. addi r4,r1,STACK_FRAME_OVERHEAD
  285. bl do_signal
  286. .globl do_signal_ret
  287. do_signal_ret:
  288. .globl ret_to_user_hook
  289. ret_to_user_hook:
  290. nop
  291. restore:
  292. lwz r3,_XER(r1)
  293. mtspr XER,r3
  294. REST_10GPRS(9,r1)
  295. REST_10GPRS(19,r1)
  296. REST_2GPRS(29,r1)
  297. REST_GPR(31,r1)
  298. /* make sure we hard disable here, even if rtl is active, to protect
  299.  * SRR[01] and SPRG2 -- Cort 
  300.  */
  301. mfmsr r0 /* Get current interrupt state */
  302. rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
  303. SYNC /* Some chip revs have problems here... */
  304. mtmsr r0 /* Update machine state */
  305. stwcx. r0,0,r1 /* to clear the reservation */
  306. /* if returning to user mode, set new sprg2 and save kernel SP */
  307. lwz r0,_MSR(r1)
  308. andi. r0,r0,MSR_PR
  309. beq+ 1f
  310. #ifdef CONFIG_ALTIVEC
  311. BEGIN_FTR_SECTION
  312. lwz r0,THREAD+THREAD_VRSAVE(r2)
  313. mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
  314. END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  315. #endif /* CONFIG_ALTIVEC */
  316. addi r0,r1,INT_FRAME_SIZE /* size of frame */
  317. stw r0,THREAD+KSP(r2) /* save kernel stack pointer */
  318. tophys(r8,r1)
  319. CLR_TOP32(r8)
  320. mtspr SPRG2,r8 /* phys exception stack pointer */
  321. 1:
  322. lwz r3,_CTR(r1)
  323. lwz r0,_LINK(r1)
  324. mtctr r3
  325. mtlr r0
  326. REST_4GPRS(3, r1)
  327. REST_2GPRS(7, r1)
  328. #ifndef CONFIG_SMP
  329. /* We have to "dummy" load from the context save area in case
  330.  * these instructions cause an MMU fault.  If this happens
  331.  * after we load SRR0/SRR1, our return context is hosed.  -- Dan
  332.  * 
  333.  * This workaround is not enough, we must also make sure the
  334.  * actual code for this routine is in the TLB or BAT mapped.
  335.  * For 6xx/Power3, we know the code is in a BAT, so this should
  336.  * be enough in UP. In SMP, I limit lowmem to the amount of
  337.  * RAM that can be BAT mapped. Other CPUs may need additional
  338.  * tweaks, especially if used SMP or if the code for this routine
  339.  * crosses page boundaries. The TLB pin down for 4xx should help
  340.  * for example. --BenH.
  341.  */
  342. lwz r0,GPR0(r1)
  343. lwz r0,GPR2(r1)
  344. lwz r0,GPR1(r1)
  345. #endif /* ndef CONFIG_SMP */
  346. /* We re-use r3,r4 here (the load above was to cause the MMU
  347.  * fault if necessary).  Using r3,r4 removes the need to "dummy"
  348.  * load the CCR and NIP.  Since we load them we may as well
  349.  * use them.
  350.  */
  351. lwz r3,_CCR(r1)
  352. lwz r4,_NIP(r1)
  353. lwz r0,_MSR(r1)
  354. FIX_SRR1(r0,r2)
  355. mtspr SRR1,r0
  356. mtcrf 0xFF,r3
  357. mtspr SRR0,r4
  358. lwz r0,GPR0(r1)
  359. lwz r2,GPR2(r1)
  360. lwz r3,GPR3(r1)
  361. lwz r4,GPR4(r1)
  362. lwz r1,GPR1(r1)
  363. SYNC
  364. RFI
  365. /*
  366.  * PROM code for specific machines follows.  Put it 
  367.  * here so it's easy to add arch-specific sections later.
  368.  * -- Cort
  369.  */
  370. #if defined(CONFIG_ALL_PPC)
  371. /*
  372.  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
  373.  * called with the MMU off.
  374.  */
  375. .globl enter_rtas
  376. enter_rtas:
  377. mflr r0
  378. stw r0,20(r1)
  379. lis r4,rtas_data@ha
  380. lwz r4,rtas_data@l(r4)
  381. lis r6,1f@ha /* physical return address for rtas */
  382. addi r6,r6,1f@l
  383. addis r6,r6,-KERNELBASE@h
  384. subi r7,r1,INT_FRAME_SIZE
  385. addis r7,r7,-KERNELBASE@h
  386. lis r8,rtas_entry@ha
  387. lwz r8,rtas_entry@l(r8)
  388. mfmsr r9
  389. stw r9,8(r1)
  390. li r0,0
  391. ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_FE0|MSR_FE1
  392. andc r0,r9,r0
  393. li r10,MSR_IR|MSR_DR|MSR_FP
  394. andc r9,r0,r10
  395. SYNC /* disable interrupts so SRR0/1 */
  396. mtmsr r0 /* don't get trashed */
  397. mtlr r6
  398. CLR_TOP32(r7)
  399. mtspr SPRG2,r7
  400. mtspr SRR0,r8
  401. mtspr SRR1,r9
  402. RFI
  403. 1: addis r9,r1,-KERNELBASE@h
  404. lwz r8,20(r9) /* get return address */
  405. lwz r9,8(r9) /* original msr value */
  406. FIX_SRR1(r9,r0)
  407. li r0,0
  408. mtspr SPRG2,r0
  409. mtspr SRR0,r8
  410. mtspr SRR1,r9
  411. RFI /* return to caller */
  412. #endif /* CONFIG_ALL_PPC */