Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[sfrench/cifs-2.6.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/linkage.h>
15 #include <asm/thread_info.h>
16 #include <asm/processor.h>
17 #include <asm/registers.h>
18 #include <asm/spr-regs.h>
19
20 .macro LEDS val
21         setlos          #~\val,gr27
22         st              gr27,@(gr30,gr0)
23         membar
24         dcf             @(gr30,gr0)
25 .endm
26
27         .section        .sdata
28         .balign         8
29
30         # address of frame 0 (userspace) on current kernel stack
31         .globl          __kernel_frame0_ptr
32 __kernel_frame0_ptr:
33         .long           init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE
34
35         # address of current task
36         .globl          __kernel_current_task
37 __kernel_current_task:
38         .long           init_task
39
40         .section        .text
41         .balign         4
42
43 ###############################################################################
44 #
45 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
46 #                                 struct thread_struct *next_thread,
47 #                                 struct task_struct *prev)
48 #
49 ###############################################################################
50         .globl          __switch_to
51 __switch_to:
52         # save outgoing process's context
53         sethi.p         %hi(__switch_back),gr13
54         setlo           %lo(__switch_back),gr13
55         movsg           lr,gr12
56
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))
67
68         or              gr8,gr8,gr22
69         ldi.p           @(gr8,#__THREAD_USER),gr8
70         call            save_user_regs
71         or              gr22,gr22,gr8
72         
73         # retrieve the new context
74         sethi.p         %hi(__kernel_frame0_ptr),gr6
75         setlo           %lo(__kernel_frame0_ptr),gr6
76         movsg           psr,gr4
77
78         lddi.p          @(gr9,#__THREAD_FRAME),gr10
79         or              gr10,gr10,gr27          ; save prev for the return value
80
81         ldi             @(gr11,#4),gr19         ; get new_current->thread_info
82
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
87
88         # actually switch kernel contexts with ordinary exceptions disabled
89         andi            gr4,#~PSR_ET,gr5
90         movgs           gr5,psr
91
92         or.p            gr10,gr0,gr28           ; set __frame
93         or              gr11,gr0,gr29           ; set __current
94         or.p            gr12,gr0,sp
95         or              gr13,gr0,fp
96         or              gr19,gr0,gr15           ; set __current_thread_info
97
98         sti             gr7,@(gr6,#0)           ; set __kernel_frame0_ptr
99         sti             gr29,@(gr6,#4)          ; set __kernel_current_task
100
101         movgs           gr14,lr
102         bar
103
104         srli            gr15,#28,gr5
105         subicc          gr5,#0xc,gr0,icc0
106         beq             icc0,#0,111f
107         break
108         nop
109 111:
110
111         # jump to __switch_back or ret_from_fork as appropriate
112         # - move prev to GR8
113         movgs           gr4,psr
114         jmpl.p          @(gr18,gr0)
115         or              gr27,gr27,gr8
116
117 ###############################################################################
118 #
119 # restore incoming process's context
120 # - on entry:
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
124 #
125 ###############################################################################
126 __switch_back:
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
133
134         # fall through into restore_user_regs()
135         ldi.p           @(gr9,#__THREAD_USER),gr8
136         or              gr8,gr8,gr9
137
138 ###############################################################################
139 #
140 # restore extra general regs and FP/Media regs
141 # - void *restore_user_regs(const struct user_context *target, void *retval)
142 # - on entry:
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)
145 #
146 ###############################################################################
147         .globl          restore_user_regs
148 restore_user_regs:
149         movsg           hsr0,gr6
150         ori             gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
151         movgs           gr6,hsr0
152         movsg           hsr0,gr6
153
154         movsg           psr,gr7
155         ori             gr7,#PSR_EF|PSR_EM,gr7
156         movgs           gr7,psr
157         movsg           psr,gr7
158         srli            gr7,#24,gr7
159         bar
160
161         lddi            @(gr8,#__FPMEDIA_MSR(0)),gr4
162
163         movgs           gr4,msr0
164         movgs           gr5,msr1
165
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
172
173         mwtacc          fr16,acc0
174         mwtacc          fr17,acc1
175         mwtacc          fr18,acc2
176         mwtacc          fr19,acc3
177         mwtaccg         fr20,accg0
178         mwtaccg         fr21,accg1
179         mwtaccg         fr22,accg2
180         mwtaccg         fr23,accg3
181
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
187 __restore_acc_cont:
188
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
193
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:
211
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
229
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
234
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:
252
253         lddi            @(gr8,#__FPMEDIA_FNER(0)),gr4
254         movsg           fner0,gr4
255         movsg           fner1,gr5
256         or.p            gr9,gr9,gr8
257         bralr
258
259         # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
260 __restore_acc_fr451:
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
267
268         mwtacc          fr16,acc8
269         mwtacc          fr17,acc9
270         mwtacc          fr18,acc10
271         mwtacc          fr19,acc11
272         mwtaccg         fr20,accg8
273         mwtaccg         fr21,accg9
274         mwtaccg         fr22,accg10
275         mwtaccg         fr23,accg11
276         bra             __restore_acc_cont
277
278         # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
279 __restore_acc_fr555:
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
286
287         mnop.p
288         mwtacc          fr16,acc4
289         mnop.p
290         mwtacc          fr17,acc5
291         mnop.p
292         mwtacc          fr18,acc6
293         mnop.p
294         mwtacc          fr19,acc7
295         mnop.p
296         mwtaccg         fr20,accg4
297         mnop.p
298         mwtaccg         fr21,accg5
299         mnop.p
300         mwtaccg         fr22,accg6
301         mnop.p
302         mwtaccg         fr23,accg7
303
304         ldi             @(gr8,#__FPMEDIA_FSR(0)),gr4
305         movgs           gr4,fsr0
306
307         bra             __restore_acc_cont
308
309
310 ###############################################################################
311 #
312 # save extra general regs and FP/Media regs
313 # - void save_user_regs(struct user_context *target)
314 #
315 ###############################################################################
316         .globl          save_user_regs
317 save_user_regs:
318         movsg           hsr0,gr6
319         ori             gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
320         movgs           gr6,hsr0
321         movsg           hsr0,gr6
322
323         movsg           psr,gr7
324         ori             gr7,#PSR_EF|PSR_EM,gr7
325         movgs           gr7,psr
326         movsg           psr,gr7
327         srli            gr7,#24,gr7
328         bar
329
330         movsg           fner0,gr4
331         movsg           fner1,gr5
332         stdi.p          gr4,@(gr8,#__FPMEDIA_FNER(0))
333
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
338
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:
356
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))
374
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
379
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:
397
398         mrdacc          acc0 ,fr4
399         mrdacc          acc1 ,fr5
400
401         stdfi.p         fr4 ,@(gr8,#__FPMEDIA_ACC(0))
402
403         mrdacc          acc2 ,fr6
404         mrdacc          acc3 ,fr7
405
406         stdfi.p         fr6 ,@(gr8,#__FPMEDIA_ACC(2))
407
408         mrdaccg         accg0,fr4
409         stbfi.p         fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
410
411         mrdaccg         accg1,fr5
412         stbfi.p         fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
413
414         mrdaccg         accg2,fr6
415         stbfi.p         fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
416
417         mrdaccg         accg3,fr7
418         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
419
420         movsg           msr0 ,gr4
421         movsg           msr1 ,gr5
422
423         stdi            gr4 ,@(gr8,#__FPMEDIA_MSR(0))
424
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
430 __save_acc_cont:
431
432         lddfi           @(gr8,#__FPMEDIA_FR(4)),fr4
433         lddfi.p         @(gr8,#__FPMEDIA_FR(6)),fr6
434         bralr
435
436         # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
437 __save_acc_fr451:
438         mrdacc          acc8 ,fr4
439         mrdacc          acc9 ,fr5
440
441         stdfi.p         fr4 ,@(gr8,#__FPMEDIA_ACC(4))
442
443         mrdacc          acc10,fr6
444         mrdacc          acc11,fr7
445
446         stdfi.p         fr6 ,@(gr8,#__FPMEDIA_ACC(6))
447
448         mrdaccg         accg8,fr4
449         stbfi.p         fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
450
451         mrdaccg         accg9,fr5
452         stbfi.p         fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
453
454         mrdaccg         accg10,fr6
455         stbfi.p         fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
456
457         mrdaccg         accg11,fr7
458         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
459         bra             __save_acc_cont
460
461         # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
462 __save_acc_fr555:
463         mnop.p
464         mrdacc          acc4 ,fr4
465         mnop.p
466         mrdacc          acc5 ,fr5
467
468         stdfi           fr4 ,@(gr8,#__FPMEDIA_ACC(4))
469
470         mnop.p
471         mrdacc          acc6 ,fr6
472         mnop.p
473         mrdacc          acc7 ,fr7
474
475         stdfi           fr6 ,@(gr8,#__FPMEDIA_ACC(6))
476
477         mnop.p
478         mrdaccg         accg4,fr4
479         stbfi           fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
480
481         mnop.p
482         mrdaccg         accg5,fr5
483         stbfi           fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
484
485         mnop.p
486         mrdaccg         accg6,fr6
487         stbfi           fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
488
489         mnop.p
490         mrdaccg         accg7,fr7
491         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
492
493         movsg           fsr0 ,gr4
494         sti             gr4 ,@(gr8,#__FPMEDIA_FSR(0))
495         bra             __save_acc_cont