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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/ppc64/kernel/entry.S
  3.  *
  4.  *  PowerPC version 
  5.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  6.  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
  7.  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
  8.  *  Adapted for Power Macintosh by Paul Mackerras.
  9.  *  Low-level exception handlers and MMU support
  10.  *  rewritten by Paul Mackerras.
  11.  *    Copyright (C) 1996 Paul Mackerras.
  12.  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
  13.  *
  14.  *  This file contains the system call entry code, context switch
  15.  *  code, and exception/interrupt return code for PowerPC.
  16.  *
  17.  *  This program is free software; you can redistribute it and/or
  18.  *  modify it under the terms of the GNU General Public License
  19.  *  as published by the Free Software Foundation; either version
  20.  *  2 of the License, or (at your option) any later version.
  21.  */
  22. #include "ppc_asm.h"
  23. #include <asm/processor.h>
  24. #include <asm/page.h>
  25. #include <asm/mmu.h>
  26. #include <linux/errno.h>
  27. #include <linux/sys.h>
  28. #include <linux/config.h>
  29. #ifdef CONFIG_PPC_ISERIES
  30. #define DO_SOFT_DISABLE
  31. #endif
  32. #undef SHOW_SYSCALLS
  33. #undef SHOW_SYSCALLS_TASK
  34. #ifdef SHOW_SYSCALLS_TASK
  35. .data
  36. show_syscalls_task:
  37. .long -1
  38. #endif
  39. /*
  40.  * Handle a system call.
  41.  */
  42. .text
  43. _GLOBAL(DoSyscall)
  44. std r0,THREAD+LAST_SYSCALL(r13)
  45. ld r11,_CCR(r1) /* Clear SO bit in CR */
  46. lis r10,0x1000
  47. andc r11,r11,r10
  48. std r11,_CCR(r1)
  49. #ifdef SHOW_SYSCALLS
  50. #ifdef SHOW_SYSCALLS_TASK
  51. LOADBASE(r31,show_syscalls_task)
  52. ld r31,show_syscalls_task@l(r31)
  53. cmp 0,r13,r31
  54. bne 1f
  55. #endif
  56. LOADADDR(r3,7f)
  57. ld r4,GPR0(r1)
  58. ld r5,GPR3(r1)
  59. ld r6,GPR4(r1)
  60. ld r7,GPR5(r1)
  61. ld r8,GPR6(r1)
  62. ld r9,GPR7(r1)
  63. bl .printk
  64. LOADADDR(r3,77f)
  65. ld r4,GPR8(r1)
  66. ld r5,GPR9(r1)
  67. mr r6,r13
  68. bl .printk
  69. ld r0,GPR0(r1)
  70. ld r3,GPR3(r1)
  71. ld r4,GPR4(r1)
  72. ld r5,GPR5(r1)
  73. ld r6,GPR6(r1)
  74. ld r7,GPR7(r1)
  75. ld r8,GPR8(r1)
  76. 1:
  77. #endif /* SHOW_SYSCALLS */
  78. ld r10,TASK_PTRACE(r13)
  79. andi. r10,r10,PT_TRACESYS
  80. bne- 50f
  81. cmpli 0,r0,NR_syscalls
  82. bge- 66f
  83. /* Ken Aaker: Need to vector to 32 Bit or default sys_call_table here,
  84.  *            based on caller's run-mode / personality.
  85.  *
  86.  */
  87. #ifdef CONFIG_BINFMT_ELF32
  88. ld r10,THREAD+THREAD_FLAGS(r13)
  89. andi. r10,r10,PPC_FLAG_32BIT
  90. beq- 15f
  91. LOADADDR(r10,.sys_call_table32)
  92. /* Now mung the first 4 parameters into shape, by making certain that
  93.  * the high bits (most significant 32 bits in 64 bit reg) are 0
  94.  * for the first 4 parameter regs(3-6).
  95.  */
  96. clrldi r3,r3,32
  97. clrldi r4,r4,32
  98. clrldi r5,r5,32
  99. clrldi r6,r6,32
  100. b 17f
  101. 15:
  102. #endif
  103. LOADADDR(r10,.sys_call_table)
  104. 17:
  105. slwi r0,r0,3
  106. ldx r10,r10,r0 /* Fetch system call handler [ptr] */
  107. mtlr r10
  108. addi r9,r1,STACK_FRAME_OVERHEAD
  109. blrl /* Call handler */
  110. _GLOBAL(ret_from_syscall_1)
  111. 20: std r3,RESULT(r1) /* Save result */
  112. #ifdef SHOW_SYSCALLS
  113. #ifdef SHOW_SYSCALLS_TASK
  114. cmp 0,r13,r31
  115. bne 91f
  116. #endif
  117. mr r4,r3
  118. LOADADDR(r3,79f)
  119. bl .printk
  120. ld r3,RESULT(r1)
  121. 91:
  122. #endif
  123. li r10,-_LAST_ERRNO
  124. cmpl 0,r3,r10
  125. blt 30f
  126. neg r3,r3
  127. cmpi 0,r3,ERESTARTNOHAND
  128. bne 22f
  129. li r3,EINTR
  130. 22: ld r10,_CCR(r1) /* Set SO bit in CR */
  131. oris r10,r10,0x1000
  132. std r10,_CCR(r1)
  133. 30: std r3,GPR3(r1) /* Update return value */
  134. b .ret_from_except
  135. 66: li r3,ENOSYS
  136. b 22b
  137.         
  138. /* Traced system call support */
  139. 50: bl .syscall_trace
  140. ld r0,GPR0(r1) /* Restore original registers */
  141. ld r3,GPR3(r1)
  142. ld r4,GPR4(r1)
  143. ld r5,GPR5(r1)
  144. ld r6,GPR6(r1)
  145. ld r7,GPR7(r1)
  146. ld r8,GPR8(r1)
  147. ld r9,GPR9(r1)
  148. cmpli 0,r0,NR_syscalls
  149. bge- 66f
  150. #ifdef CONFIG_BINFMT_ELF32
  151. ld r10,THREAD+THREAD_FLAGS(r13)
  152. andi. r10,r10,PPC_FLAG_32BIT
  153. beq- 55f
  154. LOADADDR(r10,.sys_call_table32)
  155. /* Now mung the first 4 parameters into shape, by making certain that
  156.  * the high bits (most significant 32 bits in 64 bit reg) are 0
  157.  * for the first 4 parameter regs(3-6).
  158.  */
  159. clrldi r3,r3,32
  160. clrldi r4,r4,32
  161. clrldi r5,r5,32
  162. clrldi r6,r6,32
  163. b 57f
  164. 55:
  165. #endif
  166. LOADADDR(r10,.sys_call_table)
  167. 57:
  168. slwi r0,r0,3
  169. ldx r10,r10,r0 /* Fetch system call handler [ptr] */
  170. mtlr r10
  171. addi r9,r1,STACK_FRAME_OVERHEAD
  172. blrl /* Call handler */
  173. _GLOBAL(ret_from_syscall_2)
  174. 58: std r3,RESULT(r1) /* Save result */
  175. std r3,GPR0(r1) /* temporary gross hack to make strace work */
  176. li r10,-_LAST_ERRNO
  177. cmpl 0,r3,r10
  178. blt 60f
  179. neg r3,r3
  180. cmpi 0,r3,ERESTARTNOHAND
  181. bne 57f
  182. li r3,EINTR
  183. 57: ld r10,_CCR(r1) /* Set SO bit in CR */
  184. oris r10,r10,0x1000
  185. std r10,_CCR(r1)
  186. 60: std r3,GPR3(r1) /* Update return value */
  187. bl .syscall_trace
  188. b .ret_from_except
  189. 66: li r3,ENOSYS
  190. b 57b
  191. #ifdef SHOW_SYSCALLS
  192. 7: .string "syscall %d(%x, %x, %x, %x, %x, "
  193. 77: .string "%x, %x), current=%pn"
  194. 79: .string " -> %xn"
  195. .align 2,0
  196. #endif
  197. _GLOBAL(ppc32_sigreturn)
  198. bl .sys32_sigreturn
  199. b 80f
  200. _GLOBAL(ppc32_rt_sigreturn)
  201. bl .sys32_rt_sigreturn
  202. b 80f
  203. _GLOBAL(ppc64_sigreturn)
  204. bl .sys_sigreturn
  205. b 80f
  206. _GLOBAL(ppc64_rt_sigreturn)
  207. bl .sys_rt_sigreturn
  208. 80: ld r10,TASK_PTRACE(r13)
  209. andi. r10,r10,PT_TRACESYS
  210. bne- 81f
  211. cmpi 0,r3,0
  212. bge .ret_from_except
  213. b 20b
  214. 81: cmpi 0,r3,0
  215. blt 58b
  216. bl .syscall_trace
  217. b .ret_from_except
  218. /*
  219.  * This routine switches between two different tasks.  The process
  220.  * state of one is saved on its kernel stack.  Then the state
  221.  * of the other is restored from its kernel stack.  The memory
  222.  * management hardware is updated to the second process's state.
  223.  * Finally, we can return to the second process, via ret_from_except.
  224.  * On entry, r3 points to the THREAD for the current task, r4
  225.  * points to the THREAD for the new task.
  226.  *
  227.  * Note: there are two ways to get to the "going out" portion
  228.  * of this code; either by coming in via the entry (_switch)
  229.  * or via "fork" which must set up an environment equivalent
  230.  * to the "_switch" path.  If you change this (or in particular, the
  231.  * SAVE_REGS macro), you'll have to change the fork code also.
  232.  *
  233.  * The code which creates the new task context is in 'copy_thread'
  234.  * in arch/ppc64/kernel/process.c
  235.  */
  236. _GLOBAL(_switch)
  237. stdu r1,-INT_FRAME_SIZE(r1)
  238. ld r6,0(r1)
  239. std r6,GPR1(r1)
  240. /* r3-r13 are caller saved -- Cort */
  241. SAVE_GPR(2, r1)
  242. SAVE_8GPRS(14, r1)
  243. SAVE_10GPRS(22, r1)
  244. mflr r20 /* Return to switch caller */
  245. mfmsr r22
  246. li r6,MSR_FP /* Disable floating-point */
  247. andc r22,r22,r6
  248. mtmsrd r22
  249. isync
  250. std r20,_NIP(r1)
  251. std r22,_MSR(r1)
  252. std r20,_LINK(r1)
  253. mfcr r20
  254. std r20,_CCR(r1)
  255. li r6,0x0ff0
  256. std r6,TRAP(r1)
  257. std r1,KSP(r3) /* Set old stack pointer */
  258. mfspr r5,SPRG3 /* Get Paca */
  259. addi r3,r3,-THREAD /* old 'current' for return value */
  260. addi r13,r4,-THREAD /* Convert THREAD to 'current' */
  261. std r13,PACACURRENT(r5) /* Set new 'current' */
  262. #ifdef CONFIG_PPC_ISERIES
  263. ld r7,THREAD_FLAGS(r4) /* Get run light flag */
  264. mfspr r9,CTRLF
  265. srdi r7,r7,1 /* Align to run light bit in CTRL reg */
  266. insrdi r9,r7,1,63 /* Insert run light into CTRL */
  267. mtspr CTRLT,r9
  268. #endif
  269. ld r1,KSP(r4) /* Load new stack pointer */
  270. ld r6,_CCR(r1)
  271. mtcrf 0xFF,r6
  272. /* r3-r13 are destroyed -- Cort */
  273. REST_8GPRS(14, r1)
  274. REST_10GPRS(22, r1)
  275. ld r7,_NIP(r1) /* Return to _switch caller in new task */
  276. ld r1,GPR1(r1)
  277. mtlr r7
  278. blr
  279. _GLOBAL(ret_from_fork)
  280. bl .schedule_tail
  281. ld r0,TASK_PTRACE(r13)
  282. andi. r0,r0,PT_TRACESYS
  283. beq+ .ret_from_except
  284. bl .syscall_trace
  285. b .ret_from_except
  286. _GLOBAL(ret_from_except)
  287. #ifdef CONFIG_PPC_ISERIES
  288. ld r5,SOFTE(r1)
  289. cmpdi 0,r5,0
  290. beq 4f
  291. irq_recheck:
  292. /* Check for pending interrupts (iSeries) */
  293. CHECKANYINT(r3,r4)
  294. beq+ 4f /* skip do_IRQ if no interrupts */
  295. mfspr r5,SPRG3
  296. li r3,0
  297. stb r3,PACAPROCENABLED(r5) /* ensure we are disabled */
  298. addi r3,r1,STACK_FRAME_OVERHEAD
  299. bl .do_IRQ
  300. b irq_recheck /* loop back and handle more */
  301. 4:
  302. #endif
  303. _GLOBAL(do_bottom_half_ret)
  304. ld r3,_MSR(r1) /* Returning to user mode? */
  305. andi. r3,r3,MSR_PR
  306. beq+ restore /* if so, check need_resched and signals */
  307. _GLOBAL(ret_to_user_hook)
  308. nop
  309. /* NEED_RESCHED is a volatile long (64-bits) */ 
  310. ld r3,NEED_RESCHED(r13)
  311. cmpi 0,r3,0 /* check need_resched flag */
  312. beq+ 7f
  313. bl .schedule
  314. /* SIGPENDING is an int (32-bits) */
  315. 7:
  316. lwz r5,SIGPENDING(r13) /* Check for pending unblocked signals */
  317. cmpwi 0,r5,0
  318. beq+ restore
  319. li r3,0
  320. addi r4,r1,STACK_FRAME_OVERHEAD
  321. bl .do_signal
  322. _GLOBAL(do_signal_ret)
  323. restore:
  324. ld r3,_CTR(r1)
  325. ld r0,_LINK(r1)
  326. mtctr r3
  327. mtlr r0
  328. ld r3,_XER(r1)
  329. mtspr XER,r3
  330. REST_8GPRS(5, r1)
  331. REST_10GPRS(14, r1)
  332. REST_8GPRS(24, r1)
  333. /* make sure we hard disable here, even if rtl is active, to protect
  334.  * SRR[01] and SPRG2 -- Cort 
  335.  */
  336. mfmsr r0 /* Get current interrupt state */
  337. li r4,0
  338. ori r4,r4,MSR_EE|MSR_RI
  339. andc r0,r0,r4 /* clear MSR_EE and MSR_RI */
  340. mtmsrd r0 /* Update machine state */
  341. #ifdef CONFIG_PPC_ISERIES
  342. ld r0,SOFTE(r1)
  343. cmpi 0,r0,0
  344. beq+ 1f
  345. CHECKANYINT(r4,r3)
  346. beq+ 1f
  347. mfmsr r0
  348. ori r0,r0,MSR_EE|MSR_RI
  349. mtmsrd r0
  350. b irq_recheck
  351. 1:
  352. #endif
  353. stdcx. r0,0,r1 /* to clear the reservation */
  354. mfspr r4,SPRG3 /* current task's PACA */
  355. #ifdef DO_SOFT_DISABLE
  356. ld r0,SOFTE(r1)
  357. stb r0,PACAPROCENABLED(r4)
  358. #endif
  359. /* if returning to user mode, save kernel SP */
  360. ld r0,_MSR(r1)
  361. andi. r0,r0,MSR_PR
  362. beq+ 1f
  363. addi r0,r1,INT_FRAME_SIZE /* size of frame */
  364. std r0,THREAD+KSP(r13) /* save kernel stack pointer */
  365. std r1,PACAKSAVE(r4) /* save exception stack pointer */
  366. 1:
  367. ld r0,_MSR(r1)
  368. mtspr SRR1,r0
  369. ld r2,_CCR(r1)
  370. mtcrf 0xFF,r2
  371. ld r2,_NIP(r1)
  372. mtspr SRR0,r2
  373. REST_GPR(13,r1)
  374. ld r0,GPR0(r1)
  375. ld r2,GPR2(r1)
  376. ld r3,GPR3(r1)
  377. ld r4,GPR4(r1)
  378. ld r1,GPR1(r1)
  379. rfid
  380. /*
  381.  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
  382.  * called with the MMU off.
  383.  *
  384.  * In addition, we need to be in 32b mode, at least for now.
  385.  * 
  386.  * Note: r3 is an input parameter to rtas, so don't trash it...
  387.  */
  388. _GLOBAL(enter_rtas)
  389. mflr r0
  390. std r0,16(r1)
  391.         stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */
  392. /* Because RTAS is running in 32b mode, it clobbers the high order half
  393.  * of all registers that it saves.  We therefore save those registers
  394.  * RTAS might touch to the stack.  (r0, r3-r13 are caller saved)
  395.      */
  396. SAVE_GPR(2, r1) /* Save the TOC */
  397. SAVE_GPR(13, r1) /* Save current */
  398. SAVE_8GPRS(14, r1) /* Save the non-volatiles */
  399. SAVE_10GPRS(22, r1) /* ditto */
  400. mfcr r4
  401. std r4,_CCR(r1)
  402. mfctr r5
  403. std r5,_CTR(r1)
  404. mfspr r6,XER
  405. std r6,_XER(r1)
  406. mfdar r7
  407. std r7,_DAR(r1)
  408. mfdsisr r8
  409. std r8,_DSISR(r1)
  410. mfsrr0 r9
  411. std r9,_SRR0(r1)
  412. mfsrr1 r10
  413. std r10,_SRR1(r1)
  414. /* Unfortunatly, the stack pointer and the MSR are also clobbered,
  415.  * so they are saved in the PACA (SPRG3) which allows us to restore
  416.  * our original state after RTAS returns.
  417.          */
  418. mfspr r4,SPRG3 /* Get PACA */
  419. std r1,PACAR1(r4)
  420. mfmsr r6
  421.         std r6,PACASAVEDMSR(r4)
  422. /* Setup our real return addr */
  423. SET_REG_TO_LABEL(r4,.rtas_return_loc)
  424. SET_REG_TO_CONST(r9,KERNELBASE)
  425. sub r4,r4,r9
  426.         mtlr r4
  427. li r0,0
  428. ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI
  429. andc r0,r6,r0
  430.         li      r9,1
  431.         rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
  432. ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI
  433. andc r6,r0,r9
  434. sync /* disable interrupts so SRR0/1 */
  435. mtmsrd r0 /* don't get trashed */
  436. SET_REG_TO_LABEL(r4,rtas)
  437. ld r5,RTASENTRY(r4) /* get the rtas->entry value */
  438. ld r4,RTASBASE(r4) /* get the rtas->base value */
  439. mtspr SRR0,r5
  440. mtspr SRR1,r6
  441. rfid
  442. _STATIC(rtas_return_loc)
  443. /* relocation is off at this point */
  444. mfspr r4,SPRG3         /* Get PACA */
  445. SET_REG_TO_CONST(r5, KERNELBASE)
  446.         sub     r4,r4,r5                /* RELOC the PACA base pointer */
  447.         
  448.         ld r1,PACAR1(r4)           /* Restore our SP */
  449. LOADADDR(r3,.rtas_restore_regs)
  450.         ld r4,PACASAVEDMSR(r4)     /* Restore our MSR */
  451. mtspr SRR0,r3
  452. mtspr SRR1,r4
  453. rfid
  454. _STATIC(rtas_restore_regs)
  455. /* relocation is on at this point */
  456. REST_GPR(2, r1) /* Restore the TOC */
  457. REST_GPR(13, r1) /* Restore current */
  458. REST_8GPRS(14, r1) /* Restore the non-volatiles */
  459. REST_10GPRS(22, r1) /* ditto */
  460. /* put back current in r13 */
  461.         mfspr r4,SPRG3
  462. ld r13,PACACURRENT(r4)
  463. ld r4,_CCR(r1)
  464. mtcr r4
  465. ld r5,_CTR(r1)
  466. mtctr r5
  467. ld r6,_XER(r1)
  468. mtspr XER,r6
  469. ld r7,_DAR(r1)
  470. mtdar r7
  471. ld r8,_DSISR(r1)
  472. mtdsisr r8
  473. ld r9,_SRR0(r1)
  474. mtsrr0 r9
  475. ld r10,_SRR1(r1)
  476. mtsrr1 r10
  477.         addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */
  478. ld r0,16(r1) /* get return address */
  479. mtlr    r0
  480.         blr /* return to caller */
  481. _GLOBAL(enter_prom)
  482. mflr r0
  483. std r0,16(r1)
  484.         stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
  485. /* Because PROM is running in 32b mode, it clobbers the high order half
  486.  * of all registers that it saves.  We therefore save those registers
  487.  * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
  488.      */
  489. SAVE_8GPRS(2, r1) /* Save the TOC & incoming param(s) */
  490. SAVE_GPR(13, r1) /* Save current */
  491. SAVE_8GPRS(14, r1) /* Save the non-volatiles */
  492. SAVE_10GPRS(22, r1) /* ditto */
  493. mfcr r4
  494. std r4,_CCR(r1)
  495. mfctr r5
  496. std r5,_CTR(r1)
  497. mfspr r6,XER
  498. std r6,_XER(r1)
  499. mfdar r7
  500. std r7,_DAR(r1)
  501. mfdsisr r8
  502. std r8,_DSISR(r1)
  503. mfsrr0 r9
  504. std r9,_SRR0(r1)
  505. mfsrr1 r10
  506. std r10,_SRR1(r1)
  507. mfmsr r11
  508. std r11,_MSR(r1)
  509. /* Unfortunatly, the stack pointer is also clobbered, so it is saved
  510.  * in the SPRG2 which allows us to restore our original state after
  511.  * PROM returns.
  512.          */
  513. mtspr SPRG2,r1
  514.         /* put a relocation offset into r3 */
  515.         bl      .reloc_offset
  516. LOADADDR(r12,prom)
  517. sub r12,r12,r3
  518. ld r12,PROMENTRY(r12) /* get the prom->entry value */
  519. mtlr r12
  520.         mfmsr   r11 /* grab the current MSR */
  521.         li      r12,1
  522.         rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
  523.         andc    r11,r11,r12
  524.         li      r12,1
  525.         rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
  526.         andc    r11,r11,r12
  527.         mtmsrd  r11
  528.         isync
  529. REST_8GPRS(2, r1) /* Restore the TOC & param(s) */
  530. REST_GPR(13, r1) /* Restore current */
  531. REST_8GPRS(14, r1) /* Restore the non-volatiles */
  532. REST_10GPRS(22, r1) /* ditto */
  533. blrl /* Entering PROM here... */
  534. mfspr r1,SPRG2 /* Restore the stack pointer */
  535. ld r6,_MSR(r1) /* Restore the MSR */
  536. mtmsrd r6
  537.         isync
  538. REST_GPR(2, r1) /* Restore the TOC */
  539. REST_GPR(13, r1) /* Restore current */
  540. REST_8GPRS(14, r1) /* Restore the non-volatiles */
  541. REST_10GPRS(22, r1) /* ditto */
  542. ld r4,_CCR(r1)
  543. mtcr r4
  544. ld r5,_CTR(r1)
  545. mtctr r5
  546. ld r6,_XER(r1)
  547. mtspr XER,r6
  548. ld r7,_DAR(r1)
  549. mtdar r7
  550. ld r8,_DSISR(r1)
  551. mtdsisr r8
  552. ld r9,_SRR0(r1)
  553. mtsrr0 r9
  554. ld r10,_SRR1(r1)
  555. mtsrr1 r10
  556.         addi r1,r1,PROM_FRAME_SIZE
  557. ld r0,16(r1) /* get return address */
  558. mtlr    r0
  559.         blr /* return to caller */