Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
[deliverable/linux.git] / arch / frv / kernel / switch_to.S
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
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
21 .macro LEDS val
22 setlos #~\val,gr27
23 st gr27,@(gr30,gr0)
24 membar
25 dcf @(gr30,gr0)
26 .endm
27
28 .section .sdata
29 .balign 8
30
31 # address of frame 0 (userspace) on current kernel stack
32 .globl __kernel_frame0_ptr
33 __kernel_frame0_ptr:
34 .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
35
36 # address of current task
37 .globl __kernel_current_task
38 __kernel_current_task:
39 .long init_task
40
41 .section .text
42 .balign 4
43
44 ###############################################################################
45 #
46 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
47 # struct thread_struct *next_thread,
48 # struct task_struct *prev)
49 #
50 ###############################################################################
51 .globl __switch_to
52 __switch_to:
53 # save outgoing process's context
54 sethi.p %hi(__switch_back),gr13
55 setlo %lo(__switch_back),gr13
56 movsg lr,gr12
57
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))
68
69 or gr8,gr8,gr22
70 ldi.p @(gr8,#__THREAD_USER),gr8
71 call save_user_regs
72 or gr22,gr22,gr8
73
74 # retrieve the new context
75 sethi.p %hi(__kernel_frame0_ptr),gr6
76 setlo %lo(__kernel_frame0_ptr),gr6
77 movsg psr,gr4
78
79 lddi.p @(gr9,#__THREAD_FRAME),gr10
80 or gr10,gr10,gr27 ; save prev for the return value
81
82 ldi @(gr11,#4),gr19 ; get new_current->thread_info
83
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
88
89 # actually switch kernel contexts with ordinary exceptions disabled
90 andi gr4,#~PSR_ET,gr5
91 movgs gr5,psr
92
93 or.p gr10,gr0,gr28 ; set __frame
94 or gr11,gr0,gr29 ; set __current
95 or.p gr12,gr0,sp
96 or gr13,gr0,fp
97 or gr19,gr0,gr15 ; set __current_thread_info
98
99 sti gr7,@(gr6,#0) ; set __kernel_frame0_ptr
100 sti gr29,@(gr6,#4) ; set __kernel_current_task
101
102 movgs gr14,lr
103 bar
104
105 # jump to __switch_back or ret_from_fork as appropriate
106 # - move prev to GR8
107 movgs gr4,psr
108 jmpl.p @(gr18,gr0)
109 or gr27,gr27,gr8
110
111 ###############################################################################
112 #
113 # restore incoming process's context
114 # - on entry:
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
118 #
119 ###############################################################################
120 __switch_back:
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
127
128 # fall through into restore_user_regs()
129 ldi.p @(gr9,#__THREAD_USER),gr8
130 or gr8,gr8,gr9
131
132 ###############################################################################
133 #
134 # restore extra general regs and FP/Media regs
135 # - void *restore_user_regs(const struct user_context *target, void *retval)
136 # - on entry:
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)
139 #
140 ###############################################################################
141 .globl restore_user_regs
142 restore_user_regs:
143 movsg hsr0,gr6
144 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
145 movgs gr6,hsr0
146 movsg hsr0,gr6
147
148 movsg psr,gr7
149 ori gr7,#PSR_EF|PSR_EM,gr7
150 movgs gr7,psr
151 movsg psr,gr7
152 srli gr7,#24,gr7
153 bar
154
155 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
156
157 movgs gr4,msr0
158 movgs gr5,msr1
159
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
166
167 mwtacc fr16,acc0
168 mwtacc fr17,acc1
169 mwtacc fr18,acc2
170 mwtacc fr19,acc3
171 mwtaccg fr20,accg0
172 mwtaccg fr21,accg1
173 mwtaccg fr22,accg2
174 mwtaccg fr23,accg3
175
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
181 __restore_acc_cont:
182
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
187
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:
205
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
223
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
228
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:
246
247 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
248 movsg fner0,gr4
249 movsg fner1,gr5
250 or.p gr9,gr9,gr8
251 bralr
252
253 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
254 __restore_acc_fr451:
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
261
262 mwtacc fr16,acc8
263 mwtacc fr17,acc9
264 mwtacc fr18,acc10
265 mwtacc fr19,acc11
266 mwtaccg fr20,accg8
267 mwtaccg fr21,accg9
268 mwtaccg fr22,accg10
269 mwtaccg fr23,accg11
270 bra __restore_acc_cont
271
272 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
273 __restore_acc_fr555:
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
280
281 mnop.p
282 mwtacc fr16,acc4
283 mnop.p
284 mwtacc fr17,acc5
285 mnop.p
286 mwtacc fr18,acc6
287 mnop.p
288 mwtacc fr19,acc7
289 mnop.p
290 mwtaccg fr20,accg4
291 mnop.p
292 mwtaccg fr21,accg5
293 mnop.p
294 mwtaccg fr22,accg6
295 mnop.p
296 mwtaccg fr23,accg7
297
298 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
299 movgs gr4,fsr0
300
301 bra __restore_acc_cont
302
303
304 ###############################################################################
305 #
306 # save extra general regs and FP/Media regs
307 # - void save_user_regs(struct user_context *target)
308 #
309 ###############################################################################
310 .globl save_user_regs
311 save_user_regs:
312 movsg hsr0,gr6
313 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
314 movgs gr6,hsr0
315 movsg hsr0,gr6
316
317 movsg psr,gr7
318 ori gr7,#PSR_EF|PSR_EM,gr7
319 movgs gr7,psr
320 movsg psr,gr7
321 srli gr7,#24,gr7
322 bar
323
324 movsg fner0,gr4
325 movsg fner1,gr5
326 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
327
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
332
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:
350
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))
368
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
373
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:
391
392 mrdacc acc0 ,fr4
393 mrdacc acc1 ,fr5
394
395 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
396
397 mrdacc acc2 ,fr6
398 mrdacc acc3 ,fr7
399
400 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
401
402 mrdaccg accg0,fr4
403 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
404
405 mrdaccg accg1,fr5
406 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
407
408 mrdaccg accg2,fr6
409 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
410
411 mrdaccg accg3,fr7
412 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
413
414 movsg msr0 ,gr4
415 movsg msr1 ,gr5
416
417 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
418
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
424 __save_acc_cont:
425
426 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
427 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
428 bralr
429
430 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
431 __save_acc_fr451:
432 mrdacc acc8 ,fr4
433 mrdacc acc9 ,fr5
434
435 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
436
437 mrdacc acc10,fr6
438 mrdacc acc11,fr7
439
440 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
441
442 mrdaccg accg8,fr4
443 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
444
445 mrdaccg accg9,fr5
446 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
447
448 mrdaccg accg10,fr6
449 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
450
451 mrdaccg accg11,fr7
452 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
453 bra __save_acc_cont
454
455 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
456 __save_acc_fr555:
457 mnop.p
458 mrdacc acc4 ,fr4
459 mnop.p
460 mrdacc acc5 ,fr5
461
462 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
463
464 mnop.p
465 mrdacc acc6 ,fr6
466 mnop.p
467 mrdacc acc7 ,fr7
468
469 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
470
471 mnop.p
472 mrdaccg accg4,fr4
473 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
474
475 mnop.p
476 mrdaccg accg5,fr5
477 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
478
479 mnop.p
480 mrdaccg accg6,fr6
481 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
482
483 mnop.p
484 mrdaccg accg7,fr7
485 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
486
487 movsg fsr0 ,gr4
488 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))
489 bra __save_acc_cont
This page took 0.118069 seconds and 5 git commands to generate.