switch_to.S 13 KB

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