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 ###############################################################################
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 - FRV_FRAME0_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
105 # jump to __switch_back or ret_from_fork as appropriate
111 ###############################################################################
113 # restore incoming process's context
115 # - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
116 # - GR8 will point to the outgoing task_struct
117 # - GR9 will point to the incoming thread_struct
119 ###############################################################################
121 lddi @(gr9,#__THREAD_GR(16)),gr16
122 lddi @(gr9,#__THREAD_GR(18)),gr18
123 lddi @(gr9,#__THREAD_GR(20)),gr20
124 lddi @(gr9,#__THREAD_GR(22)),gr22
125 lddi @(gr9,#__THREAD_GR(24)),gr24
126 lddi @(gr9,#__THREAD_GR(26)),gr26
128 # fall through into restore_user_regs()
129 ldi.p @(gr9,#__THREAD_USER),gr8
132 ###############################################################################
134 # restore extra general regs and FP/Media regs
135 # - void *restore_user_regs(const struct user_context *target, void *retval)
137 # - GR8 will point to the user context to swap in
138 # - GR9 will contain the value to be returned in GR8 (prev task on context switch)
140 ###############################################################################
141 .globl restore_user_regs
144 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
149 ori gr7,#PSR_EF|PSR_EM,gr7
155 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
160 lddfi @(gr8,#__FPMEDIA_ACC(0)),fr16
161 lddfi @(gr8,#__FPMEDIA_ACC(2)),fr18
162 ldbfi @(gr8,#__FPMEDIA_ACCG(0)),fr20
163 ldbfi @(gr8,#__FPMEDIA_ACCG(1)),fr21
164 ldbfi @(gr8,#__FPMEDIA_ACCG(2)),fr22
165 ldbfi @(gr8,#__FPMEDIA_ACCG(3)),fr23
176 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
177 subicc.p gr7,#0x50,gr0,icc0
178 subicc gr7,#0x31,gr0,icc1
179 beq icc0,#0,__restore_acc_fr451
180 beq icc1,#0,__restore_acc_fr555
183 # some CPU's have GR32-GR63
184 setlos #HSR0_FRHE,gr4
185 andcc gr6,gr4,gr0,icc0
186 beq icc0,#1,__restore_skip_gr32_gr63
188 lddi @(gr8,#__INT_GR(32)),gr32
189 lddi @(gr8,#__INT_GR(34)),gr34
190 lddi @(gr8,#__INT_GR(36)),gr36
191 lddi @(gr8,#__INT_GR(38)),gr38
192 lddi @(gr8,#__INT_GR(40)),gr40
193 lddi @(gr8,#__INT_GR(42)),gr42
194 lddi @(gr8,#__INT_GR(44)),gr44
195 lddi @(gr8,#__INT_GR(46)),gr46
196 lddi @(gr8,#__INT_GR(48)),gr48
197 lddi @(gr8,#__INT_GR(50)),gr50
198 lddi @(gr8,#__INT_GR(52)),gr52
199 lddi @(gr8,#__INT_GR(54)),gr54
200 lddi @(gr8,#__INT_GR(56)),gr56
201 lddi @(gr8,#__INT_GR(58)),gr58
202 lddi @(gr8,#__INT_GR(60)),gr60
203 lddi @(gr8,#__INT_GR(62)),gr62
204 __restore_skip_gr32_gr63:
206 # all CPU's have FR0-FR31
207 lddfi @(gr8,#__FPMEDIA_FR( 0)),fr0
208 lddfi @(gr8,#__FPMEDIA_FR( 2)),fr2
209 lddfi @(gr8,#__FPMEDIA_FR( 4)),fr4
210 lddfi @(gr8,#__FPMEDIA_FR( 6)),fr6
211 lddfi @(gr8,#__FPMEDIA_FR( 8)),fr8
212 lddfi @(gr8,#__FPMEDIA_FR(10)),fr10
213 lddfi @(gr8,#__FPMEDIA_FR(12)),fr12
214 lddfi @(gr8,#__FPMEDIA_FR(14)),fr14
215 lddfi @(gr8,#__FPMEDIA_FR(16)),fr16
216 lddfi @(gr8,#__FPMEDIA_FR(18)),fr18
217 lddfi @(gr8,#__FPMEDIA_FR(20)),fr20
218 lddfi @(gr8,#__FPMEDIA_FR(22)),fr22
219 lddfi @(gr8,#__FPMEDIA_FR(24)),fr24
220 lddfi @(gr8,#__FPMEDIA_FR(26)),fr26
221 lddfi @(gr8,#__FPMEDIA_FR(28)),fr28
222 lddfi.p @(gr8,#__FPMEDIA_FR(30)),fr30
224 # some CPU's have FR32-FR63
225 setlos #HSR0_FRHE,gr4
226 andcc gr6,gr4,gr0,icc0
227 beq icc0,#1,__restore_skip_fr32_fr63
229 lddfi @(gr8,#__FPMEDIA_FR(32)),fr32
230 lddfi @(gr8,#__FPMEDIA_FR(34)),fr34
231 lddfi @(gr8,#__FPMEDIA_FR(36)),fr36
232 lddfi @(gr8,#__FPMEDIA_FR(38)),fr38
233 lddfi @(gr8,#__FPMEDIA_FR(40)),fr40
234 lddfi @(gr8,#__FPMEDIA_FR(42)),fr42
235 lddfi @(gr8,#__FPMEDIA_FR(44)),fr44
236 lddfi @(gr8,#__FPMEDIA_FR(46)),fr46
237 lddfi @(gr8,#__FPMEDIA_FR(48)),fr48
238 lddfi @(gr8,#__FPMEDIA_FR(50)),fr50
239 lddfi @(gr8,#__FPMEDIA_FR(52)),fr52
240 lddfi @(gr8,#__FPMEDIA_FR(54)),fr54
241 lddfi @(gr8,#__FPMEDIA_FR(56)),fr56
242 lddfi @(gr8,#__FPMEDIA_FR(58)),fr58
243 lddfi @(gr8,#__FPMEDIA_FR(60)),fr60
244 lddfi @(gr8,#__FPMEDIA_FR(62)),fr62
245 __restore_skip_fr32_fr63:
247 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
253 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
255 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
256 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
257 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
258 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
259 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
260 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
270 bra __restore_acc_cont
272 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
274 lddfi @(gr8,#__FPMEDIA_ACC(4)),fr16
275 lddfi @(gr8,#__FPMEDIA_ACC(6)),fr18
276 ldbfi @(gr8,#__FPMEDIA_ACCG(4)),fr20
277 ldbfi @(gr8,#__FPMEDIA_ACCG(5)),fr21
278 ldbfi @(gr8,#__FPMEDIA_ACCG(6)),fr22
279 ldbfi @(gr8,#__FPMEDIA_ACCG(7)),fr23
298 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
301 bra __restore_acc_cont
304 ###############################################################################
306 # save extra general regs and FP/Media regs
307 # - void save_user_regs(struct user_context *target)
309 ###############################################################################
310 .globl save_user_regs
313 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
318 ori gr7,#PSR_EF|PSR_EM,gr7
326 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
328 # some CPU's have GR32-GR63
329 setlos #HSR0_GRHE,gr4
330 andcc gr6,gr4,gr0,icc0
331 beq icc0,#1,__save_skip_gr32_gr63
333 stdi gr32,@(gr8,#__INT_GR(32))
334 stdi gr34,@(gr8,#__INT_GR(34))
335 stdi gr36,@(gr8,#__INT_GR(36))
336 stdi gr38,@(gr8,#__INT_GR(38))
337 stdi gr40,@(gr8,#__INT_GR(40))
338 stdi gr42,@(gr8,#__INT_GR(42))
339 stdi gr44,@(gr8,#__INT_GR(44))
340 stdi gr46,@(gr8,#__INT_GR(46))
341 stdi gr48,@(gr8,#__INT_GR(48))
342 stdi gr50,@(gr8,#__INT_GR(50))
343 stdi gr52,@(gr8,#__INT_GR(52))
344 stdi gr54,@(gr8,#__INT_GR(54))
345 stdi gr56,@(gr8,#__INT_GR(56))
346 stdi gr58,@(gr8,#__INT_GR(58))
347 stdi gr60,@(gr8,#__INT_GR(60))
348 stdi gr62,@(gr8,#__INT_GR(62))
349 __save_skip_gr32_gr63:
351 # all CPU's have FR0-FR31
352 stdfi fr0 ,@(gr8,#__FPMEDIA_FR( 0))
353 stdfi fr2 ,@(gr8,#__FPMEDIA_FR( 2))
354 stdfi fr4 ,@(gr8,#__FPMEDIA_FR( 4))
355 stdfi fr6 ,@(gr8,#__FPMEDIA_FR( 6))
356 stdfi fr8 ,@(gr8,#__FPMEDIA_FR( 8))
357 stdfi fr10,@(gr8,#__FPMEDIA_FR(10))
358 stdfi fr12,@(gr8,#__FPMEDIA_FR(12))
359 stdfi fr14,@(gr8,#__FPMEDIA_FR(14))
360 stdfi fr16,@(gr8,#__FPMEDIA_FR(16))
361 stdfi fr18,@(gr8,#__FPMEDIA_FR(18))
362 stdfi fr20,@(gr8,#__FPMEDIA_FR(20))
363 stdfi fr22,@(gr8,#__FPMEDIA_FR(22))
364 stdfi fr24,@(gr8,#__FPMEDIA_FR(24))
365 stdfi fr26,@(gr8,#__FPMEDIA_FR(26))
366 stdfi fr28,@(gr8,#__FPMEDIA_FR(28))
367 stdfi.p fr30,@(gr8,#__FPMEDIA_FR(30))
369 # some CPU's have FR32-FR63
370 setlos #HSR0_FRHE,gr4
371 andcc gr6,gr4,gr0,icc0
372 beq icc0,#1,__save_skip_fr32_fr63
374 stdfi fr32,@(gr8,#__FPMEDIA_FR(32))
375 stdfi fr34,@(gr8,#__FPMEDIA_FR(34))
376 stdfi fr36,@(gr8,#__FPMEDIA_FR(36))
377 stdfi fr38,@(gr8,#__FPMEDIA_FR(38))
378 stdfi fr40,@(gr8,#__FPMEDIA_FR(40))
379 stdfi fr42,@(gr8,#__FPMEDIA_FR(42))
380 stdfi fr44,@(gr8,#__FPMEDIA_FR(44))
381 stdfi fr46,@(gr8,#__FPMEDIA_FR(46))
382 stdfi fr48,@(gr8,#__FPMEDIA_FR(48))
383 stdfi fr50,@(gr8,#__FPMEDIA_FR(50))
384 stdfi fr52,@(gr8,#__FPMEDIA_FR(52))
385 stdfi fr54,@(gr8,#__FPMEDIA_FR(54))
386 stdfi fr56,@(gr8,#__FPMEDIA_FR(56))
387 stdfi fr58,@(gr8,#__FPMEDIA_FR(58))
388 stdfi fr60,@(gr8,#__FPMEDIA_FR(60))
389 stdfi fr62,@(gr8,#__FPMEDIA_FR(62))
390 __save_skip_fr32_fr63:
395 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
400 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
403 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
406 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
409 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
412 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
417 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
419 # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
420 subicc.p gr7,#0x50,gr0,icc0
421 subicc gr7,#0x31,gr0,icc1
422 beq icc0,#0,__save_acc_fr451
423 beq icc1,#0,__save_acc_fr555
426 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
427 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
430 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
435 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
440 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
443 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
446 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
449 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
452 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
455 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
462 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
469 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
473 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
477 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
481 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
485 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
488 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))