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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: rtrap.S,v 1.57.2.1 2001/12/24 04:32:33 davem Exp $
  2.  * rtrap.S: Preparing for return from trap on Sparc V9.
  3.  *
  4.  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  6.  */
  7. #include <asm/asi.h>
  8. #include <asm/pstate.h>
  9. #include <asm/ptrace.h>
  10. #include <asm/spitfire.h>
  11. #include <asm/head.h>
  12. #include <asm/visasm.h>
  13. #include <asm/processor.h>
  14. #define PTREGS_OFF (STACK_BIAS + REGWIN_SZ)
  15. #define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
  16. #define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
  17. #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
  18. /* Register %l6 keeps track of whether we are returning
  19.  * from a system call or not.  It is cleared if we call
  20.  * do_signal, and it must not be otherwise modified until
  21.  * we fully commit to returning to userspace.
  22.  */
  23. .text
  24. .align 32
  25. __handle_softirq:
  26. call do_softirq
  27.  nop
  28. ba,a,pt %xcc, __handle_softirq_continue
  29.  nop
  30. __handle_preemption:
  31. call schedule
  32.  wrpr %g0, RTRAP_PSTATE, %pstate
  33. ba,pt %xcc, __handle_preemption_continue
  34.  wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  35. __handle_user_windows:
  36. call fault_in_user_windows
  37.  wrpr %g0, RTRAP_PSTATE, %pstate
  38. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  39. /* Redo sched+sig checks */
  40. ldx [%g6 + AOFF_task_need_resched], %l0
  41. brz,pt %l0, 1f
  42.  nop
  43. call schedule
  44.  wrpr %g0, RTRAP_PSTATE, %pstate
  45. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  46. 1: lduw [%g6 + AOFF_task_sigpending], %l0
  47. brz,pt %l0, __handle_user_windows_continue
  48.  nop
  49. clr %o0
  50. mov %l5, %o2
  51. mov %l6, %o3
  52. add %sp, STACK_BIAS + REGWIN_SZ, %o1
  53. call do_signal
  54.  wrpr %g0, RTRAP_PSTATE, %pstate
  55. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  56. clr %l6
  57. /* Signal delivery can modify pt_regs tstate, so we must
  58.  * reload it.
  59.  */
  60. ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  61. sethi %hi(0xf << 20), %l4
  62. and %l1, %l4, %l4
  63. ba,pt %xcc, __handle_user_windows_continue
  64.  andn %l1, %l4, %l1
  65. __handle_perfctrs:
  66. call update_perfctrs
  67.  wrpr %g0, RTRAP_PSTATE, %pstate
  68. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  69. ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
  70. brz,pt %o2, 1f
  71.  nop
  72. /* Redo userwin+sched+sig checks */
  73. call fault_in_user_windows
  74.  wrpr %g0, RTRAP_PSTATE, %pstate
  75. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  76. 1: ldx [%g6 + AOFF_task_need_resched], %l0
  77. brz,pt %l0, 1f
  78.  nop
  79. call schedule
  80.  wrpr %g0, RTRAP_PSTATE, %pstate
  81. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  82. 1: lduw [%g6 + AOFF_task_sigpending], %l0
  83. brz,pt %l0, __handle_perfctrs_continue
  84.  sethi %hi(TSTATE_PEF), %o0
  85. clr %o0
  86. mov %l5, %o2
  87. mov %l6, %o3
  88. add %sp, STACK_BIAS + REGWIN_SZ, %o1
  89. call do_signal
  90.  wrpr %g0, RTRAP_PSTATE, %pstate
  91. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  92. clr %l6
  93. /* Signal delivery can modify pt_regs tstate, so we must
  94.  * reload it.
  95.  */
  96. ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  97. sethi %hi(0xf << 20), %l4
  98. and %l1, %l4, %l4
  99. andn %l1, %l4, %l1
  100. ba,pt %xcc, __handle_perfctrs_continue
  101.  sethi %hi(TSTATE_PEF), %o0
  102. __handle_userfpu:
  103. rd %fprs, %l5
  104. andcc %l5, FPRS_FEF, %g0
  105. sethi %hi(TSTATE_PEF), %o0
  106. be,a,pn %icc, __handle_userfpu_continue
  107.  andn %l1, %o0, %l1
  108. ba,a,pt %xcc, __handle_userfpu_continue
  109. __handle_signal:
  110. clr %o0
  111. mov %l5, %o2
  112. mov %l6, %o3
  113. add %sp, STACK_BIAS + REGWIN_SZ, %o1
  114. call do_signal
  115.  wrpr %g0, RTRAP_PSTATE, %pstate
  116. wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  117. clr %l6
  118. /* Signal delivery can modify pt_regs tstate, so we must
  119.  * reload it.
  120.  */
  121. ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  122. sethi %hi(0xf << 20), %l4
  123. and %l1, %l4, %l4
  124. ba,pt %xcc, __handle_signal_continue
  125.  andn %l1, %l4, %l1
  126. .align 64
  127. .globl rtrap_clr_l6, rtrap, irqsz_patchme
  128. rtrap_clr_l6: clr %l6
  129. rtrap: lduw [%g6 + AOFF_task_processor], %l0
  130. sethi %hi(irq_stat), %l2 ! &softirq_active
  131. or %l2, %lo(irq_stat), %l2 ! &softirq_active
  132. irqsz_patchme: sllx %l0, 0, %l0
  133. lduw [%l2 + %l0], %l1 ! softirq_pending
  134. cmp %l1, 0
  135. bne,pn %icc, __handle_softirq
  136.  ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  137. __handle_softirq_continue:
  138. sethi %hi(0xf << 20), %l4
  139. andcc %l1, TSTATE_PRIV, %l3
  140. and %l1, %l4, %l4
  141. bne,pn %icc, to_kernel
  142.  andn %l1, %l4, %l1
  143. /* We must hold IRQs off and atomically test schedule+signal
  144.  * state, then hold them off all the way back to userspace.
  145.  * If we are returning to kernel, none of this matters.
  146.  *
  147.  * If we do not do this, there is a window where we would do
  148.  * the tests, later the signal/resched event arrives but we do
  149.  * not process it since we are still in kernel mode.  It would
  150.  * take until the next local IRQ before the signal/resched
  151.  * event would be handled.
  152.  *
  153.  * This also means that if we have to deal with performance
  154.  * counters or user windows, we have to redo all of these
  155.  * sched+signal checks with IRQs disabled.
  156.  */
  157. to_user: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
  158. __handle_preemption_continue:
  159. ldx [%g6 + AOFF_task_need_resched], %l0
  160. brnz,pn %l0, __handle_preemption
  161.  lduw [%g6 + AOFF_task_sigpending], %l0
  162. brnz,pn %l0, __handle_signal
  163.  nop
  164. __handle_signal_continue:
  165. ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
  166. brnz,pn %o2, __handle_user_windows
  167.  nop
  168. __handle_user_windows_continue:
  169. ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5
  170. andcc %l5, SPARC_FLAG_PERFCTR, %g0
  171. sethi %hi(TSTATE_PEF), %o0
  172. bne,pn %xcc, __handle_perfctrs
  173. __handle_perfctrs_continue:
  174.  andcc %l1, %o0, %g0
  175. /* This fpdepth clear is neccessary for non-syscall rtraps only */
  176. bne,pn %xcc, __handle_userfpu
  177.  stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
  178. __handle_userfpu_continue:
  179. rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
  180. ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2
  181. ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3
  182. ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4
  183. ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5
  184. ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6
  185. ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7
  186. wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
  187. ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
  188. ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
  189. ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2
  190. ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3
  191. ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4
  192. ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5
  193. ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6
  194. ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7
  195. ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2
  196. ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2
  197. ld [%sp + PTREGS_OFF + PT_V9_Y], %o3
  198. wr %o3, %g0, %y
  199. srl %l4, 20, %l4
  200. wrpr %l4, 0x0, %pil
  201. wrpr %g0, 0x1, %tl
  202. wrpr %l1, %g0, %tstate
  203. wrpr %l2, %g0, %tpc
  204. wrpr %o2, %g0, %tnpc
  205. brnz,pn %l3, kern_rtt
  206.  mov PRIMARY_CONTEXT, %l7
  207. ldxa [%l7 + %l7] ASI_DMMU, %l0
  208. stxa %l0, [%l7] ASI_DMMU
  209. flush %g6
  210. rdpr %wstate, %l1
  211. rdpr %otherwin, %l2
  212. srl %l1, 3, %l1
  213. wrpr %l2, %g0, %canrestore
  214. wrpr %l1, %g0, %wstate
  215. wrpr %g0, %g0, %otherwin
  216. restore
  217. rdpr %canrestore, %g1
  218. wrpr %g1, 0x0, %cleanwin
  219. retry
  220. nop
  221. kern_rtt: restore
  222. retry
  223. to_kernel: ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5
  224. brz,pt %l5, rt_continue
  225.  srl %l5, 1, %o0
  226. add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6
  227. ldub [%l6 + %o0], %l2
  228. sub %l5, 2, %l5
  229. add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1
  230. andcc %l2, (FPRS_FEF|FPRS_DU), %g0
  231. be,pt %icc, 2f
  232.  and %l2, FPRS_DL, %l6
  233. andcc %l2, FPRS_FEF, %g0
  234. be,pn %icc, 5f
  235.  sll %o0, 3, %o5
  236. rd %fprs, %g5
  237. wr %g5, FPRS_FEF, %fprs
  238. ldx [%o1 + %o5], %g5
  239. add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1
  240. membar #StoreLoad | #LoadLoad
  241. sll %o0, 8, %o2
  242. add %g6, AOFF_task_fpregs, %o3
  243. brz,pn %l6, 1f
  244.  add %g6, AOFF_task_fpregs+0x40, %o4
  245. ldda [%o3 + %o2] ASI_BLK_P, %f0
  246. ldda [%o4 + %o2] ASI_BLK_P, %f16
  247. 1: andcc %l2, FPRS_DU, %g0
  248. be,pn %icc, 1f
  249.  wr %g5, 0, %gsr
  250. add %o2, 0x80, %o2
  251. ldda [%o3 + %o2] ASI_BLK_P, %f32
  252. ldda [%o4 + %o2] ASI_BLK_P, %f48
  253. 1: membar #Sync
  254. ldx [%o1 + %o5], %fsr
  255. 2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
  256. ba,pt %xcc, rt_continue
  257.  nop
  258. 5: wr %g0, FPRS_FEF, %fprs
  259. membar #StoreLoad | #LoadLoad
  260. sll %o0, 8, %o2
  261. add %g6, AOFF_task_fpregs+0x80, %o3
  262. add %g6, AOFF_task_fpregs+0xc0, %o4
  263. ldda [%o3 + %o2] ASI_BLK_P, %f32
  264. ldda [%o4 + %o2] ASI_BLK_P, %f48
  265. membar #Sync
  266. wr %g0, FPRS_DU, %fprs
  267. ba,pt %xcc, rt_continue
  268.  stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
  269. #undef PTREGS_OFF