1 ###############################################################################
3 # switch_to.S: context switch operation
5 # Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
6 # Written by David Howells (dhowells@redhat.com)
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.
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>
30 # address of frame 0 (userspace) on current kernel stack
31 .globl __kernel_frame0_ptr
33 .long init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
35 # address of current task
36 .globl __kernel_current_task
37 __kernel_current_task:
43 ###############################################################################
45 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
46 # struct thread_struct *next_thread,
47 # struct task_struct *prev)
49 ###############################################################################
52 # save outgoing process's context
53 sethi.p %hi(__switch_back),gr13
54 setlo %lo(__switch_back),gr13
57 stdi gr28,@(gr8,#__THREAD_FRAME)
58 sti sp ,@(gr8,#__THREAD_SP)
59 sti fp ,@(gr8,#__THREAD_FP)
60 stdi gr12,@(gr8,#__THREAD_LR)
61 stdi gr16,@(gr8,#__THREAD_GR(16))
62 stdi gr18,@(gr8,#__THREAD_GR(18))
63 stdi gr20,@(gr8,#__THREAD_GR(20))
64 stdi gr22,@(gr8,#__THREAD_GR(22))
65 stdi gr24,@(gr8,#__THREAD_GR(24))
66 stdi.p gr26,@(gr8,#__THREAD_GR(26))
69 ldi.p @(gr8,#__THREAD_USER),gr8
73 # retrieve the new context
74 sethi.p %hi(__kernel_frame0_ptr),gr6
75 setlo %lo(__kernel_frame0_ptr),gr6
78 lddi.p @(gr9,#__THREAD_FRAME),gr10
79 or gr10,gr10,gr27 ; save prev for the return value
81 ldi @(gr11,#4),gr19 ; get new_current->thread_info
83 lddi @(gr9,#__THREAD_SP),gr12
84 ldi @(gr9,#__THREAD_LR),gr14
85 ldi @(gr9,#__THREAD_PC),gr18
86 ldi.p @(gr9,#__THREAD_FRAME0),gr7
88 # actually switch kernel contexts with ordinary exceptions disabled
92 or.p gr10,gr0,gr28 ; set __frame
93 or gr11,gr0,gr29 ; set __current
96 or gr19,gr0,gr15 ; set __current_thread_info
98 sti gr7,@(gr6,#0) ; set __kernel_frame0_ptr
99 sti gr29,@(gr6,#4) ; set __kernel_current_task
105 subicc gr5,#0xc,gr0,icc0
111 # jump to __switch_back or ret_from_fork as appropriate
117 ###############################################################################
119 # restore incoming process's context
121 # - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
122 # - GR8 will point to the outgoing task_struct
123 # - GR9 will point to the incoming thread_struct
125 ###############################################################################
127 lddi @(gr9,#__THREAD_GR(16)),gr16
128 lddi @(gr9,#__THREAD_GR(18)),gr18
129 lddi @(gr9,#__THREAD_GR(20)),gr20
130 lddi @(gr9,#__THREAD_GR(22)),gr22
131 lddi @(gr9,#__THREAD_GR(24)),gr24
132 lddi @(gr9,#__THREAD_GR(26)),gr26
134 # fall through into restore_user_regs()
135 ldi.p @(gr9,#__THREAD_USER),gr8
138 ###############################################################################
140 # restore extra general regs and FP/Media regs
141 # - void *restore_user_regs(const struct user_context *target, void *retval)
143 # - GR8 will point to the user context to swap in
144 # - GR9 will contain the value to be returned in GR8 (prev task on context switch)
146 ###############################################################################
147 .globl restore_user_regs
150 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
155 ori gr7,#PSR_EF|PSR_EM,gr7
161 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
166 lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16
167 lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18
168 ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20
169 ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21
170 ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22
171 ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23
182 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
183 subicc.p gr7,#0x50,gr0,icc0
184 subicc gr7,#0x31,gr0,icc1
185 beq icc0,#0,__restore_acc_fr451
186 beq icc1,#0,__restore_acc_fr555
189 # some CPU's have GR32-GR63
190 setlos #HSR0_FRHE,gr4
191 andcc gr6,gr4,gr0,icc0
192 beq icc0,#1,__restore_skip_gr32_gr63
194 lddi @(gr8,#__INT_GR(32)),gr32
195 lddi @(gr8,#__INT_GR(34)),gr34
196 lddi @(gr8,#__INT_GR(36)),gr36
197 lddi @(gr8,#__INT_GR(38)),gr38
198 lddi @(gr8,#__INT_GR(40)),gr40
199 lddi @(gr8,#__INT_GR(42)),gr42
200 lddi @(gr8,#__INT_GR(44)),gr44
201 lddi @(gr8,#__INT_GR(46)),gr46
202 lddi @(gr8,#__INT_GR(48)),gr48
203 lddi @(gr8,#__INT_GR(50)),gr50
204 lddi @(gr8,#__INT_GR(52)),gr52
205 lddi @(gr8,#__INT_GR(54)),gr54
206 lddi @(gr8,#__INT_GR(56)),gr56
207 lddi @(gr8,#__INT_GR(58)),gr58
208 lddi @(gr8,#__INT_GR(60)),gr60
209 lddi @(gr8,#__INT_GR(62)),gr62
210 __restore_skip_gr32_gr63:
212 # all CPU's have FR0-FR31
213 lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0
214 lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2
215 lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4
216 lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6
217 lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8
218 lddfi @(gr8,#__FPMEDIA_FR(10)),fr10
219 lddfi @(gr8,#__FPMEDIA_FR(12)),fr12
220 lddfi @(gr8,#__FPMEDIA_FR(14)),fr14
221 lddfi @(gr8,#__FPMEDIA_FR(16)),fr16
222 lddfi @(gr8,#__FPMEDIA_FR(18)),fr18
223 lddfi @(gr8,#__FPMEDIA_FR(20)),fr20
224 lddfi @(gr8,#__FPMEDIA_FR(22)),fr22
225 lddfi @(gr8,#__FPMEDIA_FR(24)),fr24
226 lddfi @(gr8,#__FPMEDIA_FR(26)),fr26
227 lddfi @(gr8,#__FPMEDIA_FR(28)),fr28
228 lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30
230 # some CPU's have FR32-FR63
231 setlos #HSR0_FRHE,gr4
232 andcc gr6,gr4,gr0,icc0
233 beq icc0,#1,__restore_skip_fr32_fr63
235 lddfi @(gr8,#__FPMEDIA_FR(32)),fr32
236 lddfi @(gr8,#__FPMEDIA_FR(34)),fr34
237 lddfi @(gr8,#__FPMEDIA_FR(36)),fr36
238 lddfi @(gr8,#__FPMEDIA_FR(38)),fr38
239 lddfi @(gr8,#__FPMEDIA_FR(40)),fr40
240 lddfi @(gr8,#__FPMEDIA_FR(42)),fr42
241 lddfi @(gr8,#__FPMEDIA_FR(44)),fr44
242 lddfi @(gr8,#__FPMEDIA_FR(46)),fr46
243 lddfi @(gr8,#__FPMEDIA_FR(48)),fr48
244 lddfi @(gr8,#__FPMEDIA_FR(50)),fr50
245 lddfi @(gr8,#__FPMEDIA_FR(52)),fr52
246 lddfi @(gr8,#__FPMEDIA_FR(54)),fr54
247 lddfi @(gr8,#__FPMEDIA_FR(56)),fr56
248 lddfi @(gr8,#__FPMEDIA_FR(58)),fr58
249 lddfi @(gr8,#__FPMEDIA_FR(60)),fr60
250 lddfi @(gr8,#__FPMEDIA_FR(62)),fr62
251 __restore_skip_fr32_fr63:
253 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
259 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
261 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
262 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
263 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
264 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
265 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
266 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
276 bra __restore_acc_cont
278 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
280 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
281 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
282 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
283 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
284 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
285 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
304 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
307 bra __restore_acc_cont
310 ###############################################################################
312 # save extra general regs and FP/Media regs
313 # - void save_user_regs(struct user_context *target)
315 ###############################################################################
316 .globl save_user_regs
319 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
324 ori gr7,#PSR_EF|PSR_EM,gr7
332 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
334 # some CPU's have GR32-GR63
335 setlos #HSR0_GRHE,gr4
336 andcc gr6,gr4,gr0,icc0
337 beq icc0,#1,__save_skip_gr32_gr63
339 stdi gr32,@(gr8,#__INT_GR(32))
340 stdi gr34,@(gr8,#__INT_GR(34))
341 stdi gr36,@(gr8,#__INT_GR(36))
342 stdi gr38,@(gr8,#__INT_GR(38))
343 stdi gr40,@(gr8,#__INT_GR(40))
344 stdi gr42,@(gr8,#__INT_GR(42))
345 stdi gr44,@(gr8,#__INT_GR(44))
346 stdi gr46,@(gr8,#__INT_GR(46))
347 stdi gr48,@(gr8,#__INT_GR(48))
348 stdi gr50,@(gr8,#__INT_GR(50))
349 stdi gr52,@(gr8,#__INT_GR(52))
350 stdi gr54,@(gr8,#__INT_GR(54))
351 stdi gr56,@(gr8,#__INT_GR(56))
352 stdi gr58,@(gr8,#__INT_GR(58))
353 stdi gr60,@(gr8,#__INT_GR(60))
354 stdi gr62,@(gr8,#__INT_GR(62))
355 __save_skip_gr32_gr63:
357 # all CPU's have FR0-FR31
358 stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0))
359 stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2))
360 stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4))
361 stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6))
362 stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8))
363 stdfi fr10,@(gr8,#__FPMEDIA_FR(10))
364 stdfi fr12,@(gr8,#__FPMEDIA_FR(12))
365 stdfi fr14,@(gr8,#__FPMEDIA_FR(14))
366 stdfi fr16,@(gr8,#__FPMEDIA_FR(16))
367 stdfi fr18,@(gr8,#__FPMEDIA_FR(18))
368 stdfi fr20,@(gr8,#__FPMEDIA_FR(20))
369 stdfi fr22,@(gr8,#__FPMEDIA_FR(22))
370 stdfi fr24,@(gr8,#__FPMEDIA_FR(24))
371 stdfi fr26,@(gr8,#__FPMEDIA_FR(26))
372 stdfi fr28,@(gr8,#__FPMEDIA_FR(28))
373 stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30))
375 # some CPU's have FR32-FR63
376 setlos #HSR0_FRHE,gr4
377 andcc gr6,gr4,gr0,icc0
378 beq icc0,#1,__save_skip_fr32_fr63
380 stdfi fr32,@(gr8,#__FPMEDIA_FR(32))
381 stdfi fr34,@(gr8,#__FPMEDIA_FR(34))
382 stdfi fr36,@(gr8,#__FPMEDIA_FR(36))
383 stdfi fr38,@(gr8,#__FPMEDIA_FR(38))
384 stdfi fr40,@(gr8,#__FPMEDIA_FR(40))
385 stdfi fr42,@(gr8,#__FPMEDIA_FR(42))
386 stdfi fr44,@(gr8,#__FPMEDIA_FR(44))
387 stdfi fr46,@(gr8,#__FPMEDIA_FR(46))
388 stdfi fr48,@(gr8,#__FPMEDIA_FR(48))
389 stdfi fr50,@(gr8,#__FPMEDIA_FR(50))
390 stdfi fr52,@(gr8,#__FPMEDIA_FR(52))
391 stdfi fr54,@(gr8,#__FPMEDIA_FR(54))
392 stdfi fr56,@(gr8,#__FPMEDIA_FR(56))
393 stdfi fr58,@(gr8,#__FPMEDIA_FR(58))
394 stdfi fr60,@(gr8,#__FPMEDIA_FR(60))
395 stdfi fr62,@(gr8,#__FPMEDIA_FR(62))
396 __save_skip_fr32_fr63:
401 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
406 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
409 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
412 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
415 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
418 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
423 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
425 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
426 subicc.p gr7,#0x50,gr0,icc0
427 subicc gr7,#0x31,gr0,icc1
428 beq icc0,#0,__save_acc_fr451
429 beq icc1,#0,__save_acc_fr555
432 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
433 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
436 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
441 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
446 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
449 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
452 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
455 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
458 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
461 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
468 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
475 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
479 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
483 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
487 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
491 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
494 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))