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/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>
31 # address of frame 0 (userspace) on current kernel stack
32 .globl __kernel_frame0_ptr
34 .long init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
36 # address of current task
37 .globl __kernel_current_task
38 __kernel_current_task:
44 ###############################################################################
46 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
47 # struct thread_struct *next_thread,
48 # struct task_struct *prev)
50 ###############################################################################
53 # save outgoing process's context
54 sethi.p %hi(__switch_back),gr13
55 setlo %lo(__switch_back),gr13
58 stdi gr28,@(gr8,#__THREAD_FRAME)
59 sti sp ,@(gr8,#__THREAD_SP)
60 sti fp ,@(gr8,#__THREAD_FP)
61 stdi gr12,@(gr8,#__THREAD_LR)
62 stdi gr16,@(gr8,#__THREAD_GR(16))
63 stdi gr18,@(gr8,#__THREAD_GR(18))
64 stdi gr20,@(gr8,#__THREAD_GR(20))
65 stdi gr22,@(gr8,#__THREAD_GR(22))
66 stdi gr24,@(gr8,#__THREAD_GR(24))
67 stdi.p gr26,@(gr8,#__THREAD_GR(26))
70 ldi.p @(gr8,#__THREAD_USER),gr8
74 # retrieve the new context
75 sethi.p %hi(__kernel_frame0_ptr),gr6
76 setlo %lo(__kernel_frame0_ptr),gr6
79 lddi.p @(gr9,#__THREAD_FRAME),gr10
80 or gr10,gr10,gr27 ; save prev for the return value
82 ldi @(gr11,#4),gr19 ; get new_current->thread_info
84 lddi @(gr9,#__THREAD_SP),gr12
85 ldi @(gr9,#__THREAD_LR),gr14
86 ldi @(gr9,#__THREAD_PC),gr18
87 ldi.p @(gr9,#__THREAD_FRAME0),gr7
89 # actually switch kernel contexts with ordinary exceptions disabled
93 or.p gr10,gr0,gr28 ; set __frame
94 or gr11,gr0,gr29 ; set __current
97 or gr19,gr0,gr15 ; set __current_thread_info
99 sti gr7,@(gr6,#0) ; set __kernel_frame0_ptr
100 sti gr29,@(gr6,#4) ; set __kernel_current_task
106 subicc gr5,#0xc,gr0,icc0
112 # jump to __switch_back or ret_from_fork as appropriate
118 ###############################################################################
120 # restore incoming process's context
122 # - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
123 # - GR8 will point to the outgoing task_struct
124 # - GR9 will point to the incoming thread_struct
126 ###############################################################################
128 lddi @(gr9,#__THREAD_GR(16)),gr16
129 lddi @(gr9,#__THREAD_GR(18)),gr18
130 lddi @(gr9,#__THREAD_GR(20)),gr20
131 lddi @(gr9,#__THREAD_GR(22)),gr22
132 lddi @(gr9,#__THREAD_GR(24)),gr24
133 lddi @(gr9,#__THREAD_GR(26)),gr26
135 # fall through into restore_user_regs()
136 ldi.p @(gr9,#__THREAD_USER),gr8
139 ###############################################################################
141 # restore extra general regs and FP/Media regs
142 # - void *restore_user_regs(const struct user_context *target, void *retval)
144 # - GR8 will point to the user context to swap in
145 # - GR9 will contain the value to be returned in GR8 (prev task on context switch)
147 ###############################################################################
148 .globl restore_user_regs
151 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
156 ori gr7,#PSR_EF|PSR_EM,gr7
162 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
167 lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16
168 lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18
169 ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20
170 ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21
171 ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22
172 ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23
183 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
184 subicc.p gr7,#0x50,gr0,icc0
185 subicc gr7,#0x31,gr0,icc1
186 beq icc0,#0,__restore_acc_fr451
187 beq icc1,#0,__restore_acc_fr555
190 # some CPU's have GR32-GR63
191 setlos #HSR0_FRHE,gr4
192 andcc gr6,gr4,gr0,icc0
193 beq icc0,#1,__restore_skip_gr32_gr63
195 lddi @(gr8,#__INT_GR(32)),gr32
196 lddi @(gr8,#__INT_GR(34)),gr34
197 lddi @(gr8,#__INT_GR(36)),gr36
198 lddi @(gr8,#__INT_GR(38)),gr38
199 lddi @(gr8,#__INT_GR(40)),gr40
200 lddi @(gr8,#__INT_GR(42)),gr42
201 lddi @(gr8,#__INT_GR(44)),gr44
202 lddi @(gr8,#__INT_GR(46)),gr46
203 lddi @(gr8,#__INT_GR(48)),gr48
204 lddi @(gr8,#__INT_GR(50)),gr50
205 lddi @(gr8,#__INT_GR(52)),gr52
206 lddi @(gr8,#__INT_GR(54)),gr54
207 lddi @(gr8,#__INT_GR(56)),gr56
208 lddi @(gr8,#__INT_GR(58)),gr58
209 lddi @(gr8,#__INT_GR(60)),gr60
210 lddi @(gr8,#__INT_GR(62)),gr62
211 __restore_skip_gr32_gr63:
213 # all CPU's have FR0-FR31
214 lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0
215 lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2
216 lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4
217 lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6
218 lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8
219 lddfi @(gr8,#__FPMEDIA_FR(10)),fr10
220 lddfi @(gr8,#__FPMEDIA_FR(12)),fr12
221 lddfi @(gr8,#__FPMEDIA_FR(14)),fr14
222 lddfi @(gr8,#__FPMEDIA_FR(16)),fr16
223 lddfi @(gr8,#__FPMEDIA_FR(18)),fr18
224 lddfi @(gr8,#__FPMEDIA_FR(20)),fr20
225 lddfi @(gr8,#__FPMEDIA_FR(22)),fr22
226 lddfi @(gr8,#__FPMEDIA_FR(24)),fr24
227 lddfi @(gr8,#__FPMEDIA_FR(26)),fr26
228 lddfi @(gr8,#__FPMEDIA_FR(28)),fr28
229 lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30
231 # some CPU's have FR32-FR63
232 setlos #HSR0_FRHE,gr4
233 andcc gr6,gr4,gr0,icc0
234 beq icc0,#1,__restore_skip_fr32_fr63
236 lddfi @(gr8,#__FPMEDIA_FR(32)),fr32
237 lddfi @(gr8,#__FPMEDIA_FR(34)),fr34
238 lddfi @(gr8,#__FPMEDIA_FR(36)),fr36
239 lddfi @(gr8,#__FPMEDIA_FR(38)),fr38
240 lddfi @(gr8,#__FPMEDIA_FR(40)),fr40
241 lddfi @(gr8,#__FPMEDIA_FR(42)),fr42
242 lddfi @(gr8,#__FPMEDIA_FR(44)),fr44
243 lddfi @(gr8,#__FPMEDIA_FR(46)),fr46
244 lddfi @(gr8,#__FPMEDIA_FR(48)),fr48
245 lddfi @(gr8,#__FPMEDIA_FR(50)),fr50
246 lddfi @(gr8,#__FPMEDIA_FR(52)),fr52
247 lddfi @(gr8,#__FPMEDIA_FR(54)),fr54
248 lddfi @(gr8,#__FPMEDIA_FR(56)),fr56
249 lddfi @(gr8,#__FPMEDIA_FR(58)),fr58
250 lddfi @(gr8,#__FPMEDIA_FR(60)),fr60
251 lddfi @(gr8,#__FPMEDIA_FR(62)),fr62
252 __restore_skip_fr32_fr63:
254 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
260 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
262 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
263 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
264 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
265 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
266 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
267 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
277 bra __restore_acc_cont
279 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
281 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
282 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
283 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
284 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
285 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
286 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
305 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
308 bra __restore_acc_cont
311 ###############################################################################
313 # save extra general regs and FP/Media regs
314 # - void save_user_regs(struct user_context *target)
316 ###############################################################################
317 .globl save_user_regs
320 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
325 ori gr7,#PSR_EF|PSR_EM,gr7
333 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
335 # some CPU's have GR32-GR63
336 setlos #HSR0_GRHE,gr4
337 andcc gr6,gr4,gr0,icc0
338 beq icc0,#1,__save_skip_gr32_gr63
340 stdi gr32,@(gr8,#__INT_GR(32))
341 stdi gr34,@(gr8,#__INT_GR(34))
342 stdi gr36,@(gr8,#__INT_GR(36))
343 stdi gr38,@(gr8,#__INT_GR(38))
344 stdi gr40,@(gr8,#__INT_GR(40))
345 stdi gr42,@(gr8,#__INT_GR(42))
346 stdi gr44,@(gr8,#__INT_GR(44))
347 stdi gr46,@(gr8,#__INT_GR(46))
348 stdi gr48,@(gr8,#__INT_GR(48))
349 stdi gr50,@(gr8,#__INT_GR(50))
350 stdi gr52,@(gr8,#__INT_GR(52))
351 stdi gr54,@(gr8,#__INT_GR(54))
352 stdi gr56,@(gr8,#__INT_GR(56))
353 stdi gr58,@(gr8,#__INT_GR(58))
354 stdi gr60,@(gr8,#__INT_GR(60))
355 stdi gr62,@(gr8,#__INT_GR(62))
356 __save_skip_gr32_gr63:
358 # all CPU's have FR0-FR31
359 stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0))
360 stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2))
361 stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4))
362 stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6))
363 stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8))
364 stdfi fr10,@(gr8,#__FPMEDIA_FR(10))
365 stdfi fr12,@(gr8,#__FPMEDIA_FR(12))
366 stdfi fr14,@(gr8,#__FPMEDIA_FR(14))
367 stdfi fr16,@(gr8,#__FPMEDIA_FR(16))
368 stdfi fr18,@(gr8,#__FPMEDIA_FR(18))
369 stdfi fr20,@(gr8,#__FPMEDIA_FR(20))
370 stdfi fr22,@(gr8,#__FPMEDIA_FR(22))
371 stdfi fr24,@(gr8,#__FPMEDIA_FR(24))
372 stdfi fr26,@(gr8,#__FPMEDIA_FR(26))
373 stdfi fr28,@(gr8,#__FPMEDIA_FR(28))
374 stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30))
376 # some CPU's have FR32-FR63
377 setlos #HSR0_FRHE,gr4
378 andcc gr6,gr4,gr0,icc0
379 beq icc0,#1,__save_skip_fr32_fr63
381 stdfi fr32,@(gr8,#__FPMEDIA_FR(32))
382 stdfi fr34,@(gr8,#__FPMEDIA_FR(34))
383 stdfi fr36,@(gr8,#__FPMEDIA_FR(36))
384 stdfi fr38,@(gr8,#__FPMEDIA_FR(38))
385 stdfi fr40,@(gr8,#__FPMEDIA_FR(40))
386 stdfi fr42,@(gr8,#__FPMEDIA_FR(42))
387 stdfi fr44,@(gr8,#__FPMEDIA_FR(44))
388 stdfi fr46,@(gr8,#__FPMEDIA_FR(46))
389 stdfi fr48,@(gr8,#__FPMEDIA_FR(48))
390 stdfi fr50,@(gr8,#__FPMEDIA_FR(50))
391 stdfi fr52,@(gr8,#__FPMEDIA_FR(52))
392 stdfi fr54,@(gr8,#__FPMEDIA_FR(54))
393 stdfi fr56,@(gr8,#__FPMEDIA_FR(56))
394 stdfi fr58,@(gr8,#__FPMEDIA_FR(58))
395 stdfi fr60,@(gr8,#__FPMEDIA_FR(60))
396 stdfi fr62,@(gr8,#__FPMEDIA_FR(62))
397 __save_skip_fr32_fr63:
402 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
407 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
410 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
413 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
416 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
419 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
424 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
426 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
427 subicc.p gr7,#0x50,gr0,icc0
428 subicc gr7,#0x31,gr0,icc1
429 beq icc0,#0,__save_acc_fr451
430 beq icc1,#0,__save_acc_fr555
433 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
434 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
437 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
442 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
447 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
450 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
453 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
456 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
459 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
462 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
469 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
476 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
480 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
484 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
488 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
492 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
495 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))