]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/frv/kernel/switch_to.S
Linux-2.6.12-rc2
[mirror_ubuntu-artful-kernel.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 #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>
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 - USER_CONTEXT_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 srli gr15,#28,gr5
106 subicc gr5,#0xc,gr0,icc0
107 beq icc0,#0,111f
108 break
109 nop
110 111:
111
112 # jump to __switch_back or ret_from_fork as appropriate
113 # - move prev to GR8
114 movgs gr4,psr
115 jmpl.p @(gr18,gr0)
116 or gr27,gr27,gr8
117
118 ###############################################################################
119 #
120 # restore incoming process's context
121 # - on entry:
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
125 #
126 ###############################################################################
127 __switch_back:
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
134
135 # fall through into restore_user_regs()
136 ldi.p @(gr9,#__THREAD_USER),gr8
137 or gr8,gr8,gr9
138
139 ###############################################################################
140 #
141 # restore extra general regs and FP/Media regs
142 # - void *restore_user_regs(const struct user_context *target, void *retval)
143 # - on entry:
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)
146 #
147 ###############################################################################
148 .globl restore_user_regs
149 restore_user_regs:
150 movsg hsr0,gr6
151 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
152 movgs gr6,hsr0
153 movsg hsr0,gr6
154
155 movsg psr,gr7
156 ori gr7,#PSR_EF|PSR_EM,gr7
157 movgs gr7,psr
158 movsg psr,gr7
159 srli gr7,#24,gr7
160 bar
161
162 lddi @(gr8,#__FPMEDIA_MSR(0)),gr4
163
164 movgs gr4,msr0
165 movgs gr5,msr1
166
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
173
174 mwtacc fr16,acc0
175 mwtacc fr17,acc1
176 mwtacc fr18,acc2
177 mwtacc fr19,acc3
178 mwtaccg fr20,accg0
179 mwtaccg fr21,accg1
180 mwtaccg fr22,accg2
181 mwtaccg fr23,accg3
182
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
188 __restore_acc_cont:
189
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
194
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:
212
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
230
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
235
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:
253
254 lddi @(gr8,#__FPMEDIA_FNER(0)),gr4
255 movsg fner0,gr4
256 movsg fner1,gr5
257 or.p gr9,gr9,gr8
258 bralr
259
260 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
261 __restore_acc_fr451:
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
268
269 mwtacc fr16,acc8
270 mwtacc fr17,acc9
271 mwtacc fr18,acc10
272 mwtacc fr19,acc11
273 mwtaccg fr20,accg8
274 mwtaccg fr21,accg9
275 mwtaccg fr22,accg10
276 mwtaccg fr23,accg11
277 bra __restore_acc_cont
278
279 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
280 __restore_acc_fr555:
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
287
288 mnop.p
289 mwtacc fr16,acc4
290 mnop.p
291 mwtacc fr17,acc5
292 mnop.p
293 mwtacc fr18,acc6
294 mnop.p
295 mwtacc fr19,acc7
296 mnop.p
297 mwtaccg fr20,accg4
298 mnop.p
299 mwtaccg fr21,accg5
300 mnop.p
301 mwtaccg fr22,accg6
302 mnop.p
303 mwtaccg fr23,accg7
304
305 ldi @(gr8,#__FPMEDIA_FSR(0)),gr4
306 movgs gr4,fsr0
307
308 bra __restore_acc_cont
309
310
311 ###############################################################################
312 #
313 # save extra general regs and FP/Media regs
314 # - void save_user_regs(struct user_context *target)
315 #
316 ###############################################################################
317 .globl save_user_regs
318 save_user_regs:
319 movsg hsr0,gr6
320 ori gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
321 movgs gr6,hsr0
322 movsg hsr0,gr6
323
324 movsg psr,gr7
325 ori gr7,#PSR_EF|PSR_EM,gr7
326 movgs gr7,psr
327 movsg psr,gr7
328 srli gr7,#24,gr7
329 bar
330
331 movsg fner0,gr4
332 movsg fner1,gr5
333 stdi.p gr4,@(gr8,#__FPMEDIA_FNER(0))
334
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
339
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:
357
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))
375
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
380
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:
398
399 mrdacc acc0 ,fr4
400 mrdacc acc1 ,fr5
401
402 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(0))
403
404 mrdacc acc2 ,fr6
405 mrdacc acc3 ,fr7
406
407 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(2))
408
409 mrdaccg accg0,fr4
410 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
411
412 mrdaccg accg1,fr5
413 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
414
415 mrdaccg accg2,fr6
416 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
417
418 mrdaccg accg3,fr7
419 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
420
421 movsg msr0 ,gr4
422 movsg msr1 ,gr5
423
424 stdi gr4 ,@(gr8,#__FPMEDIA_MSR(0))
425
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
431 __save_acc_cont:
432
433 lddfi @(gr8,#__FPMEDIA_FR(4)),fr4
434 lddfi.p @(gr8,#__FPMEDIA_FR(6)),fr6
435 bralr
436
437 # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
438 __save_acc_fr451:
439 mrdacc acc8 ,fr4
440 mrdacc acc9 ,fr5
441
442 stdfi.p fr4 ,@(gr8,#__FPMEDIA_ACC(4))
443
444 mrdacc acc10,fr6
445 mrdacc acc11,fr7
446
447 stdfi.p fr6 ,@(gr8,#__FPMEDIA_ACC(6))
448
449 mrdaccg accg8,fr4
450 stbfi.p fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
451
452 mrdaccg accg9,fr5
453 stbfi.p fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
454
455 mrdaccg accg10,fr6
456 stbfi.p fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
457
458 mrdaccg accg11,fr7
459 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
460 bra __save_acc_cont
461
462 # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
463 __save_acc_fr555:
464 mnop.p
465 mrdacc acc4 ,fr4
466 mnop.p
467 mrdacc acc5 ,fr5
468
469 stdfi fr4 ,@(gr8,#__FPMEDIA_ACC(4))
470
471 mnop.p
472 mrdacc acc6 ,fr6
473 mnop.p
474 mrdacc acc7 ,fr7
475
476 stdfi fr6 ,@(gr8,#__FPMEDIA_ACC(6))
477
478 mnop.p
479 mrdaccg accg4,fr4
480 stbfi fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
481
482 mnop.p
483 mrdaccg accg5,fr5
484 stbfi fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
485
486 mnop.p
487 mrdaccg accg6,fr6
488 stbfi fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
489
490 mnop.p
491 mrdaccg accg7,fr7
492 stbfi fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
493
494 movsg fsr0 ,gr4
495 sti gr4 ,@(gr8,#__FPMEDIA_FSR(0))
496 bra __save_acc_cont