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