entry.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

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