switch_to.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. ###############################################################################
  2. #
  3. # switch_to.S: context switch operation
  4. #
  5. # Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
  6. # Written by David Howells (dhowells@redhat.com)
  7. #
  8. # This program is free software; you can redistribute it and/or
  9. # modify it under the terms of the GNU General Public License
  10. # as published by the Free Software Foundation; either version
  11. # 2 of the License, or (at your option) any later version.
  12. #
  13. ###############################################################################
  14. #include <linux/linkage.h>
  15. #include <asm/thread_info.h>
  16. #include <asm/processor.h>
  17. #include <asm/registers.h>
  18. #include <asm/spr-regs.h>
  19. .macro LEDS val
  20. setlos #~\val,gr27
  21. st gr27,@(gr30,gr0)
  22. membar
  23. dcf @(gr30,gr0)
  24. .endm
  25. .section .sdata
  26. .balign 8
  27. # address of frame 0 (userspace) on current kernel stack
  28. .globl __kernel_frame0_ptr
  29. __kernel_frame0_ptr:
  30. .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
  31. # address of current task
  32. .globl __kernel_current_task
  33. __kernel_current_task:
  34. .long init_task
  35. .section .text
  36. .balign 4
  37. ###############################################################################
  38. #
  39. # struct task_struct *__switch_to(struct thread_struct *prev_thread,
  40. # struct thread_struct *next_thread,
  41. # struct task_struct *prev)
  42. #
  43. ###############################################################################
  44. .globl __switch_to
  45. __switch_to:
  46. # save outgoing process's context
  47. sethi.p %hi(__switch_back),gr13
  48. setlo %lo(__switch_back),gr13
  49. movsg lr,gr12
  50. stdi gr28,@(gr8,#__THREAD_FRAME)
  51. sti sp ,@(gr8,#__THREAD_SP)
  52. sti fp ,@(gr8,#__THREAD_FP)
  53. stdi gr12,@(gr8,#__THREAD_LR)
  54. stdi gr16,@(gr8,#__THREAD_GR(16))
  55. stdi gr18,@(gr8,#__THREAD_GR(18))
  56. stdi gr20,@(gr8,#__THREAD_GR(20))
  57. stdi gr22,@(gr8,#__THREAD_GR(22))
  58. stdi gr24,@(gr8,#__THREAD_GR(24))
  59. stdi.p gr26,@(gr8,#__THREAD_GR(26))
  60. or gr8,gr8,gr22
  61. ldi.p @(gr8,#__THREAD_USER),gr8
  62. call save_user_regs
  63. or gr22,gr22,gr8
  64. # retrieve the new context
  65. sethi.p %hi(__kernel_frame0_ptr),gr6
  66. setlo %lo(__kernel_frame0_ptr),gr6
  67. movsg psr,gr4
  68. lddi.p @(gr9,#__THREAD_FRAME),gr10
  69. or gr10,gr10,gr27 ; save prev for the return value
  70. ldi @(gr11,#4),gr19 ; get new_current->thread_info
  71. lddi @(gr9,#__THREAD_SP),gr12
  72. ldi @(gr9,#__THREAD_LR),gr14
  73. ldi @(gr9,#__THREAD_PC),gr18
  74. ldi.p @(gr9,#__THREAD_FRAME0),gr7
  75. # actually switch kernel contexts with ordinary exceptions disabled
  76. andi gr4,#~PSR_ET,gr5
  77. movgs gr5,psr
  78. or.p gr10,gr0,gr28 ; set __frame
  79. or gr11,gr0,gr29 ; set __current
  80. or.p gr12,gr0,sp
  81. or gr13,gr0,fp
  82. or gr19,gr0,gr15 ; set __current_thread_info
  83. sti gr7,@(gr6,#0) ; set __kernel_frame0_ptr
  84. sti gr29,@(gr6,#4) ; set __kernel_current_task
  85. movgs gr14,lr
  86. bar
  87. # jump to __switch_back or ret_from_fork as appropriate
  88. # - move prev to GR8
  89. movgs gr4,psr
  90. jmpl.p @(gr18,gr0)
  91. or gr27,gr27,gr8
  92. ###############################################################################
  93. #
  94. # restore incoming process's context
  95. # - on entry:
  96. # - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
  97. # - GR8 will point to the outgoing task_struct
  98. # - GR9 will point to the incoming thread_struct
  99. #
  100. ###############################################################################
  101. __switch_back:
  102. lddi @(gr9,#__THREAD_GR(16)),gr16
  103. lddi @(gr9,#__THREAD_GR(18)),gr18
  104. lddi @(gr9,#__THREAD_GR(20)),gr20
  105. lddi @(gr9,#__THREAD_GR(22)),gr22
  106. lddi @(gr9,#__THREAD_GR(24)),gr24
  107. lddi @(gr9,#__THREAD_GR(26)),gr26
  108. # fall through into restore_user_regs()
  109. ldi.p @(gr9,#__THREAD_USER),gr8
  110. or gr8,gr8,gr9
  111. ###############################################################################
  112. #
  113. # restore extra general regs and FP/Media regs
  114. # - void *restore_user_regs(const struct user_context *target, void *retval)
  115. # - on entry:
  116. # - GR8 will point to the user context to swap in
  117. # - GR9 will contain the value to be returned in GR8 (prev task on context switch)
  118. #
  119. ###############################################################################
  120. .globl restore_user_regs
  121. restore_user_regs:
  122. movsg hsr0,gr6
  123. ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
  124. movgs gr6,hsr0
  125. movsg hsr0,gr6
  126. movsg psr,gr7
  127. ori gr7,#PSR_EF|PSR_EM,gr7
  128. movgs gr7,psr
  129. movsg psr,gr7
  130. srli gr7,#24,gr7
  131. bar
  132. lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
  133. movgs gr4,msr0
  134. movgs gr5,msr1
  135. lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16
  136. lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18
  137. ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20
  138. ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21
  139. ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22
  140. ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23
  141. mwtacc fr16,acc0
  142. mwtacc fr17,acc1
  143. mwtacc fr18,acc2
  144. mwtacc fr19,acc3
  145. mwtaccg fr20,accg0
  146. mwtaccg fr21,accg1
  147. mwtaccg fr22,accg2
  148. mwtaccg fr23,accg3
  149. # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
  150. subicc.p gr7,#0x50,gr0,icc0
  151. subicc gr7,#0x31,gr0,icc1
  152. beq icc0,#0,__restore_acc_fr451
  153. beq icc1,#0,__restore_acc_fr555
  154. __restore_acc_cont:
  155. # some CPU's have GR32-GR63
  156. setlos #HSR0_FRHE,gr4
  157. andcc gr6,gr4,gr0,icc0
  158. beq icc0,#1,__restore_skip_gr32_gr63
  159. lddi @(gr8,#__INT_GR(32)),gr32
  160. lddi @(gr8,#__INT_GR(34)),gr34
  161. lddi @(gr8,#__INT_GR(36)),gr36
  162. lddi @(gr8,#__INT_GR(38)),gr38
  163. lddi @(gr8,#__INT_GR(40)),gr40
  164. lddi @(gr8,#__INT_GR(42)),gr42
  165. lddi @(gr8,#__INT_GR(44)),gr44
  166. lddi @(gr8,#__INT_GR(46)),gr46
  167. lddi @(gr8,#__INT_GR(48)),gr48
  168. lddi @(gr8,#__INT_GR(50)),gr50
  169. lddi @(gr8,#__INT_GR(52)),gr52
  170. lddi @(gr8,#__INT_GR(54)),gr54
  171. lddi @(gr8,#__INT_GR(56)),gr56
  172. lddi @(gr8,#__INT_GR(58)),gr58
  173. lddi @(gr8,#__INT_GR(60)),gr60
  174. lddi @(gr8,#__INT_GR(62)),gr62
  175. __restore_skip_gr32_gr63:
  176. # all CPU's have FR0-FR31
  177. lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0
  178. lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2
  179. lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4
  180. lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6
  181. lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8
  182. lddfi @(gr8,#__FPMEDIA_FR(10)),fr10
  183. lddfi @(gr8,#__FPMEDIA_FR(12)),fr12
  184. lddfi @(gr8,#__FPMEDIA_FR(14)),fr14
  185. lddfi @(gr8,#__FPMEDIA_FR(16)),fr16
  186. lddfi @(gr8,#__FPMEDIA_FR(18)),fr18
  187. lddfi @(gr8,#__FPMEDIA_FR(20)),fr20
  188. lddfi @(gr8,#__FPMEDIA_FR(22)),fr22
  189. lddfi @(gr8,#__FPMEDIA_FR(24)),fr24
  190. lddfi @(gr8,#__FPMEDIA_FR(26)),fr26
  191. lddfi @(gr8,#__FPMEDIA_FR(28)),fr28
  192. lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30
  193. # some CPU's have FR32-FR63
  194. setlos #HSR0_FRHE,gr4
  195. andcc gr6,gr4,gr0,icc0
  196. beq icc0,#1,__restore_skip_fr32_fr63
  197. lddfi @(gr8,#__FPMEDIA_FR(32)),fr32
  198. lddfi @(gr8,#__FPMEDIA_FR(34)),fr34
  199. lddfi @(gr8,#__FPMEDIA_FR(36)),fr36
  200. lddfi @(gr8,#__FPMEDIA_FR(38)),fr38
  201. lddfi @(gr8,#__FPMEDIA_FR(40)),fr40
  202. lddfi @(gr8,#__FPMEDIA_FR(42)),fr42
  203. lddfi @(gr8,#__FPMEDIA_FR(44)),fr44
  204. lddfi @(gr8,#__FPMEDIA_FR(46)),fr46
  205. lddfi @(gr8,#__FPMEDIA_FR(48)),fr48
  206. lddfi @(gr8,#__FPMEDIA_FR(50)),fr50
  207. lddfi @(gr8,#__FPMEDIA_FR(52)),fr52
  208. lddfi @(gr8,#__FPMEDIA_FR(54)),fr54
  209. lddfi @(gr8,#__FPMEDIA_FR(56)),fr56
  210. lddfi @(gr8,#__FPMEDIA_FR(58)),fr58
  211. lddfi @(gr8,#__FPMEDIA_FR(60)),fr60
  212. lddfi @(gr8,#__FPMEDIA_FR(62)),fr62
  213. __restore_skip_fr32_fr63:
  214. lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
  215. movsg fner0,gr4
  216. movsg fner1,gr5
  217. or.p gr9,gr9,gr8
  218. bralr
  219. # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
  220. __restore_acc_fr451:
  221. lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
  222. lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
  223. ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
  224. ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
  225. ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
  226. ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
  227. mwtacc fr16,acc8
  228. mwtacc fr17,acc9
  229. mwtacc fr18,acc10
  230. mwtacc fr19,acc11
  231. mwtaccg fr20,accg8
  232. mwtaccg fr21,accg9
  233. mwtaccg fr22,accg10
  234. mwtaccg fr23,accg11
  235. bra __restore_acc_cont
  236. # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
  237. __restore_acc_fr555:
  238. lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
  239. lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
  240. ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
  241. ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
  242. ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
  243. ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
  244. mnop.p
  245. mwtacc fr16,acc4
  246. mnop.p
  247. mwtacc fr17,acc5
  248. mnop.p
  249. mwtacc fr18,acc6
  250. mnop.p
  251. mwtacc fr19,acc7
  252. mnop.p
  253. mwtaccg fr20,accg4
  254. mnop.p
  255. mwtaccg fr21,accg5
  256. mnop.p
  257. mwtaccg fr22,accg6
  258. mnop.p
  259. mwtaccg fr23,accg7
  260. ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
  261. movgs gr4,fsr0
  262. bra __restore_acc_cont
  263. ###############################################################################
  264. #
  265. # save extra general regs and FP/Media regs
  266. # - void save_user_regs(struct user_context *target)
  267. #
  268. ###############################################################################
  269. .globl save_user_regs
  270. save_user_regs:
  271. movsg hsr0,gr6
  272. ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
  273. movgs gr6,hsr0
  274. movsg hsr0,gr6
  275. movsg psr,gr7
  276. ori gr7,#PSR_EF|PSR_EM,gr7
  277. movgs gr7,psr
  278. movsg psr,gr7
  279. srli gr7,#24,gr7
  280. bar
  281. movsg fner0,gr4
  282. movsg fner1,gr5
  283. stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
  284. # some CPU's have GR32-GR63
  285. setlos #HSR0_GRHE,gr4
  286. andcc gr6,gr4,gr0,icc0
  287. beq icc0,#1,__save_skip_gr32_gr63
  288. stdi gr32,@(gr8,#__INT_GR(32))
  289. stdi gr34,@(gr8,#__INT_GR(34))
  290. stdi gr36,@(gr8,#__INT_GR(36))
  291. stdi gr38,@(gr8,#__INT_GR(38))
  292. stdi gr40,@(gr8,#__INT_GR(40))
  293. stdi gr42,@(gr8,#__INT_GR(42))
  294. stdi gr44,@(gr8,#__INT_GR(44))
  295. stdi gr46,@(gr8,#__INT_GR(46))
  296. stdi gr48,@(gr8,#__INT_GR(48))
  297. stdi gr50,@(gr8,#__INT_GR(50))
  298. stdi gr52,@(gr8,#__INT_GR(52))
  299. stdi gr54,@(gr8,#__INT_GR(54))
  300. stdi gr56,@(gr8,#__INT_GR(56))
  301. stdi gr58,@(gr8,#__INT_GR(58))
  302. stdi gr60,@(gr8,#__INT_GR(60))
  303. stdi gr62,@(gr8,#__INT_GR(62))
  304. __save_skip_gr32_gr63:
  305. # all CPU's have FR0-FR31
  306. stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0))
  307. stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2))
  308. stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4))
  309. stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6))
  310. stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8))
  311. stdfi fr10,@(gr8,#__FPMEDIA_FR(10))
  312. stdfi fr12,@(gr8,#__FPMEDIA_FR(12))
  313. stdfi fr14,@(gr8,#__FPMEDIA_FR(14))
  314. stdfi fr16,@(gr8,#__FPMEDIA_FR(16))
  315. stdfi fr18,@(gr8,#__FPMEDIA_FR(18))
  316. stdfi fr20,@(gr8,#__FPMEDIA_FR(20))
  317. stdfi fr22,@(gr8,#__FPMEDIA_FR(22))
  318. stdfi fr24,@(gr8,#__FPMEDIA_FR(24))
  319. stdfi fr26,@(gr8,#__FPMEDIA_FR(26))
  320. stdfi fr28,@(gr8,#__FPMEDIA_FR(28))
  321. stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30))
  322. # some CPU's have FR32-FR63
  323. setlos #HSR0_FRHE,gr4
  324. andcc gr6,gr4,gr0,icc0
  325. beq icc0,#1,__save_skip_fr32_fr63
  326. stdfi fr32,@(gr8,#__FPMEDIA_FR(32))
  327. stdfi fr34,@(gr8,#__FPMEDIA_FR(34))
  328. stdfi fr36,@(gr8,#__FPMEDIA_FR(36))
  329. stdfi fr38,@(gr8,#__FPMEDIA_FR(38))
  330. stdfi fr40,@(gr8,#__FPMEDIA_FR(40))
  331. stdfi fr42,@(gr8,#__FPMEDIA_FR(42))
  332. stdfi fr44,@(gr8,#__FPMEDIA_FR(44))
  333. stdfi fr46,@(gr8,#__FPMEDIA_FR(46))
  334. stdfi fr48,@(gr8,#__FPMEDIA_FR(48))
  335. stdfi fr50,@(gr8,#__FPMEDIA_FR(50))
  336. stdfi fr52,@(gr8,#__FPMEDIA_FR(52))
  337. stdfi fr54,@(gr8,#__FPMEDIA_FR(54))
  338. stdfi fr56,@(gr8,#__FPMEDIA_FR(56))
  339. stdfi fr58,@(gr8,#__FPMEDIA_FR(58))
  340. stdfi fr60,@(gr8,#__FPMEDIA_FR(60))
  341. stdfi fr62,@(gr8,#__FPMEDIA_FR(62))
  342. __save_skip_fr32_fr63:
  343. mrdacc acc0 ,fr4
  344. mrdacc acc1 ,fr5
  345. stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
  346. mrdacc acc2 ,fr6
  347. mrdacc acc3 ,fr7
  348. stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
  349. mrdaccg accg0,fr4
  350. stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
  351. mrdaccg accg1,fr5
  352. stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
  353. mrdaccg accg2,fr6
  354. stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
  355. mrdaccg accg3,fr7
  356. stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
  357. movsg msr0 ,gr4
  358. movsg msr1 ,gr5
  359. stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
  360. # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
  361. subicc.p gr7,#0x50,gr0,icc0
  362. subicc gr7,#0x31,gr0,icc1
  363. beq icc0,#0,__save_acc_fr451
  364. beq icc1,#0,__save_acc_fr555
  365. __save_acc_cont:
  366. lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
  367. lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
  368. bralr
  369. # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
  370. __save_acc_fr451:
  371. mrdacc acc8 ,fr4
  372. mrdacc acc9 ,fr5
  373. stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
  374. mrdacc acc10,fr6
  375. mrdacc acc11,fr7
  376. stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
  377. mrdaccg accg8,fr4
  378. stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
  379. mrdaccg accg9,fr5
  380. stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
  381. mrdaccg accg10,fr6
  382. stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
  383. mrdaccg accg11,fr7
  384. stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
  385. bra __save_acc_cont
  386. # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
  387. __save_acc_fr555:
  388. mnop.p
  389. mrdacc acc4 ,fr4
  390. mnop.p
  391. mrdacc acc5 ,fr5
  392. stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
  393. mnop.p
  394. mrdacc acc6 ,fr6
  395. mnop.p
  396. mrdacc acc7 ,fr7
  397. stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
  398. mnop.p
  399. mrdaccg accg4,fr4
  400. stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
  401. mnop.p
  402. mrdaccg accg5,fr5
  403. stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
  404. mnop.p
  405. mrdaccg accg6,fr6
  406. stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
  407. mnop.p
  408. mrdaccg accg7,fr7
  409. stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
  410. movsg fsr0 ,gr4
  411. sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))
  412. bra __save_acc_cont