Back to home page

LXR

 
 

    


0001 ###############################################################################
0002 #
0003 # switch_to.S: context switch operation
0004 #
0005 # Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
0006 # Written by David Howells (dhowells@redhat.com)
0007 #
0008 # This program is free software; you can redistribute it and/or
0009 # modify it under the terms of the GNU General Public License
0010 # as published by the Free Software Foundation; either version
0011 # 2 of the License, or (at your option) any later version.
0012 #
0013 ###############################################################################
0014 
0015 #include <linux/linkage.h>
0016 #include <asm/thread_info.h>
0017 #include <asm/processor.h>
0018 #include <asm/registers.h>
0019 #include <asm/spr-regs.h>
0020 
0021 .macro LEDS val
0022     setlos      #~\val,gr27
0023     st      gr27,@(gr30,gr0)
0024     membar
0025     dcf     @(gr30,gr0)
0026 .endm
0027 
0028     .section    .sdata
0029     .balign     8
0030 
0031     # address of frame 0 (userspace) on current kernel stack
0032     .globl      __kernel_frame0_ptr
0033 __kernel_frame0_ptr:
0034     .long       init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
0035 
0036     # address of current task
0037     .globl      __kernel_current_task
0038 __kernel_current_task:
0039     .long       init_task
0040 
0041     .section    .text
0042     .balign     4
0043 
0044 ###############################################################################
0045 #
0046 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
0047 #                 struct thread_struct *next_thread,
0048 #                 struct task_struct *prev)
0049 #
0050 ###############################################################################
0051     .globl      __switch_to
0052 __switch_to:
0053     # save outgoing process's context
0054     sethi.p     %hi(__switch_back),gr13
0055     setlo       %lo(__switch_back),gr13
0056     movsg       lr,gr12
0057 
0058     stdi        gr28,@(gr8,#__THREAD_FRAME)
0059     sti     sp  ,@(gr8,#__THREAD_SP)
0060     sti     fp  ,@(gr8,#__THREAD_FP)
0061     stdi        gr12,@(gr8,#__THREAD_LR)
0062     stdi        gr16,@(gr8,#__THREAD_GR(16))
0063     stdi        gr18,@(gr8,#__THREAD_GR(18))
0064     stdi        gr20,@(gr8,#__THREAD_GR(20))
0065     stdi        gr22,@(gr8,#__THREAD_GR(22))
0066     stdi        gr24,@(gr8,#__THREAD_GR(24))
0067     stdi.p      gr26,@(gr8,#__THREAD_GR(26))
0068 
0069     or      gr8,gr8,gr22
0070     ldi.p       @(gr8,#__THREAD_USER),gr8
0071     call        save_user_regs
0072     or      gr22,gr22,gr8
0073     
0074     # retrieve the new context
0075     sethi.p     %hi(__kernel_frame0_ptr),gr6
0076     setlo       %lo(__kernel_frame0_ptr),gr6
0077     movsg       psr,gr4
0078 
0079     lddi.p      @(gr9,#__THREAD_FRAME),gr10
0080     or      gr10,gr10,gr27      ; save prev for the return value
0081 
0082     ldi     @(gr11,#4),gr19     ; get new_current->thread_info
0083 
0084     lddi        @(gr9,#__THREAD_SP),gr12
0085     ldi     @(gr9,#__THREAD_LR),gr14
0086     ldi     @(gr9,#__THREAD_PC),gr18
0087     ldi.p       @(gr9,#__THREAD_FRAME0),gr7
0088 
0089     # actually switch kernel contexts with ordinary exceptions disabled
0090     andi        gr4,#~PSR_ET,gr5
0091     movgs       gr5,psr
0092 
0093     or.p        gr10,gr0,gr28       ; set __frame
0094     or      gr11,gr0,gr29       ; set __current
0095     or.p        gr12,gr0,sp
0096     or      gr13,gr0,fp
0097     or      gr19,gr0,gr15       ; set __current_thread_info
0098 
0099     sti     gr7,@(gr6,#0)       ; set __kernel_frame0_ptr
0100     sti     gr29,@(gr6,#4)      ; set __kernel_current_task
0101 
0102     movgs       gr14,lr
0103     bar
0104 
0105     # jump to __switch_back or ret_from_fork as appropriate
0106     # - move prev to GR8
0107     movgs       gr4,psr
0108     jmpl.p      @(gr18,gr0)
0109     or      gr27,gr27,gr8
0110 
0111 ###############################################################################
0112 #
0113 # restore incoming process's context
0114 # - on entry:
0115 #   - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
0116 #   - GR8 will point to the outgoing task_struct
0117 #   - GR9 will point to the incoming thread_struct
0118 #
0119 ###############################################################################
0120 __switch_back:
0121     lddi        @(gr9,#__THREAD_GR(16)),gr16
0122     lddi        @(gr9,#__THREAD_GR(18)),gr18
0123     lddi        @(gr9,#__THREAD_GR(20)),gr20
0124     lddi        @(gr9,#__THREAD_GR(22)),gr22
0125     lddi        @(gr9,#__THREAD_GR(24)),gr24
0126     lddi        @(gr9,#__THREAD_GR(26)),gr26
0127 
0128     # fall through into restore_user_regs()
0129     ldi.p       @(gr9,#__THREAD_USER),gr8
0130     or      gr8,gr8,gr9
0131 
0132 ###############################################################################
0133 #
0134 # restore extra general regs and FP/Media regs
0135 # - void *restore_user_regs(const struct user_context *target, void *retval)
0136 # - on entry:
0137 #   - GR8 will point to the user context to swap in
0138 #   - GR9 will contain the value to be returned in GR8 (prev task on context switch)
0139 #
0140 ###############################################################################
0141     .globl      restore_user_regs
0142 restore_user_regs:
0143     movsg       hsr0,gr6
0144     ori     gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
0145     movgs       gr6,hsr0
0146     movsg       hsr0,gr6
0147 
0148     movsg       psr,gr7
0149     ori     gr7,#PSR_EF|PSR_EM,gr7
0150     movgs       gr7,psr
0151     movsg       psr,gr7
0152     srli        gr7,#24,gr7
0153     bar
0154 
0155     lddi        @(gr8,#__FPMEDIA_MSR(0)),gr4
0156 
0157     movgs       gr4,msr0
0158     movgs       gr5,msr1
0159 
0160     lddfi       @(gr8,#__FPMEDIA_ACC(0)),fr16
0161     lddfi       @(gr8,#__FPMEDIA_ACC(2)),fr18
0162     ldbfi       @(gr8,#__FPMEDIA_ACCG(0)),fr20
0163     ldbfi       @(gr8,#__FPMEDIA_ACCG(1)),fr21
0164     ldbfi       @(gr8,#__FPMEDIA_ACCG(2)),fr22
0165     ldbfi       @(gr8,#__FPMEDIA_ACCG(3)),fr23
0166 
0167     mwtacc      fr16,acc0
0168     mwtacc      fr17,acc1
0169     mwtacc      fr18,acc2
0170     mwtacc      fr19,acc3
0171     mwtaccg     fr20,accg0
0172     mwtaccg     fr21,accg1
0173     mwtaccg     fr22,accg2
0174     mwtaccg     fr23,accg3
0175 
0176     # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
0177     subicc.p    gr7,#0x50,gr0,icc0
0178     subicc      gr7,#0x31,gr0,icc1
0179     beq     icc0,#0,__restore_acc_fr451
0180     beq     icc1,#0,__restore_acc_fr555
0181 __restore_acc_cont:
0182 
0183     # some CPU's have GR32-GR63
0184     setlos      #HSR0_FRHE,gr4
0185     andcc       gr6,gr4,gr0,icc0
0186     beq     icc0,#1,__restore_skip_gr32_gr63
0187 
0188     lddi        @(gr8,#__INT_GR(32)),gr32
0189     lddi        @(gr8,#__INT_GR(34)),gr34
0190     lddi        @(gr8,#__INT_GR(36)),gr36
0191     lddi        @(gr8,#__INT_GR(38)),gr38
0192     lddi        @(gr8,#__INT_GR(40)),gr40
0193     lddi        @(gr8,#__INT_GR(42)),gr42
0194     lddi        @(gr8,#__INT_GR(44)),gr44
0195     lddi        @(gr8,#__INT_GR(46)),gr46
0196     lddi        @(gr8,#__INT_GR(48)),gr48
0197     lddi        @(gr8,#__INT_GR(50)),gr50
0198     lddi        @(gr8,#__INT_GR(52)),gr52
0199     lddi        @(gr8,#__INT_GR(54)),gr54
0200     lddi        @(gr8,#__INT_GR(56)),gr56
0201     lddi        @(gr8,#__INT_GR(58)),gr58
0202     lddi        @(gr8,#__INT_GR(60)),gr60
0203     lddi        @(gr8,#__INT_GR(62)),gr62
0204 __restore_skip_gr32_gr63:
0205 
0206     # all CPU's have FR0-FR31
0207     lddfi       @(gr8,#__FPMEDIA_FR( 0)),fr0
0208     lddfi       @(gr8,#__FPMEDIA_FR( 2)),fr2
0209     lddfi       @(gr8,#__FPMEDIA_FR( 4)),fr4
0210     lddfi       @(gr8,#__FPMEDIA_FR( 6)),fr6
0211     lddfi       @(gr8,#__FPMEDIA_FR( 8)),fr8
0212     lddfi       @(gr8,#__FPMEDIA_FR(10)),fr10
0213     lddfi       @(gr8,#__FPMEDIA_FR(12)),fr12
0214     lddfi       @(gr8,#__FPMEDIA_FR(14)),fr14
0215     lddfi       @(gr8,#__FPMEDIA_FR(16)),fr16
0216     lddfi       @(gr8,#__FPMEDIA_FR(18)),fr18
0217     lddfi       @(gr8,#__FPMEDIA_FR(20)),fr20
0218     lddfi       @(gr8,#__FPMEDIA_FR(22)),fr22
0219     lddfi       @(gr8,#__FPMEDIA_FR(24)),fr24
0220     lddfi       @(gr8,#__FPMEDIA_FR(26)),fr26
0221     lddfi       @(gr8,#__FPMEDIA_FR(28)),fr28
0222     lddfi.p     @(gr8,#__FPMEDIA_FR(30)),fr30
0223 
0224     # some CPU's have FR32-FR63
0225     setlos      #HSR0_FRHE,gr4
0226     andcc       gr6,gr4,gr0,icc0
0227     beq     icc0,#1,__restore_skip_fr32_fr63
0228 
0229     lddfi       @(gr8,#__FPMEDIA_FR(32)),fr32
0230     lddfi       @(gr8,#__FPMEDIA_FR(34)),fr34
0231     lddfi       @(gr8,#__FPMEDIA_FR(36)),fr36
0232     lddfi       @(gr8,#__FPMEDIA_FR(38)),fr38
0233     lddfi       @(gr8,#__FPMEDIA_FR(40)),fr40
0234     lddfi       @(gr8,#__FPMEDIA_FR(42)),fr42
0235     lddfi       @(gr8,#__FPMEDIA_FR(44)),fr44
0236     lddfi       @(gr8,#__FPMEDIA_FR(46)),fr46
0237     lddfi       @(gr8,#__FPMEDIA_FR(48)),fr48
0238     lddfi       @(gr8,#__FPMEDIA_FR(50)),fr50
0239     lddfi       @(gr8,#__FPMEDIA_FR(52)),fr52
0240     lddfi       @(gr8,#__FPMEDIA_FR(54)),fr54
0241     lddfi       @(gr8,#__FPMEDIA_FR(56)),fr56
0242     lddfi       @(gr8,#__FPMEDIA_FR(58)),fr58
0243     lddfi       @(gr8,#__FPMEDIA_FR(60)),fr60
0244     lddfi       @(gr8,#__FPMEDIA_FR(62)),fr62
0245 __restore_skip_fr32_fr63:
0246 
0247     lddi        @(gr8,#__FPMEDIA_FNER(0)),gr4
0248     movsg       fner0,gr4
0249     movsg       fner1,gr5
0250     or.p        gr9,gr9,gr8
0251     bralr
0252 
0253     # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
0254 __restore_acc_fr451:
0255     lddfi       @(gr8,#__FPMEDIA_ACC(4)),fr16
0256     lddfi       @(gr8,#__FPMEDIA_ACC(6)),fr18
0257     ldbfi       @(gr8,#__FPMEDIA_ACCG(4)),fr20
0258     ldbfi       @(gr8,#__FPMEDIA_ACCG(5)),fr21
0259     ldbfi       @(gr8,#__FPMEDIA_ACCG(6)),fr22
0260     ldbfi       @(gr8,#__FPMEDIA_ACCG(7)),fr23
0261 
0262     mwtacc      fr16,acc8
0263     mwtacc      fr17,acc9
0264     mwtacc      fr18,acc10
0265     mwtacc      fr19,acc11
0266     mwtaccg     fr20,accg8
0267     mwtaccg     fr21,accg9
0268     mwtaccg     fr22,accg10
0269     mwtaccg     fr23,accg11
0270     bra     __restore_acc_cont
0271 
0272     # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
0273 __restore_acc_fr555:
0274     lddfi       @(gr8,#__FPMEDIA_ACC(4)),fr16
0275     lddfi       @(gr8,#__FPMEDIA_ACC(6)),fr18
0276     ldbfi       @(gr8,#__FPMEDIA_ACCG(4)),fr20
0277     ldbfi       @(gr8,#__FPMEDIA_ACCG(5)),fr21
0278     ldbfi       @(gr8,#__FPMEDIA_ACCG(6)),fr22
0279     ldbfi       @(gr8,#__FPMEDIA_ACCG(7)),fr23
0280 
0281     mnop.p
0282     mwtacc      fr16,acc4
0283     mnop.p
0284     mwtacc      fr17,acc5
0285     mnop.p
0286     mwtacc      fr18,acc6
0287     mnop.p
0288     mwtacc      fr19,acc7
0289     mnop.p
0290     mwtaccg     fr20,accg4
0291     mnop.p
0292     mwtaccg     fr21,accg5
0293     mnop.p
0294     mwtaccg     fr22,accg6
0295     mnop.p
0296     mwtaccg     fr23,accg7
0297 
0298     ldi     @(gr8,#__FPMEDIA_FSR(0)),gr4
0299     movgs       gr4,fsr0
0300 
0301     bra     __restore_acc_cont
0302 
0303 
0304 ###############################################################################
0305 #
0306 # save extra general regs and FP/Media regs
0307 # - void save_user_regs(struct user_context *target)
0308 #
0309 ###############################################################################
0310     .globl      save_user_regs
0311 save_user_regs:
0312     movsg       hsr0,gr6
0313     ori     gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
0314     movgs       gr6,hsr0
0315     movsg       hsr0,gr6
0316 
0317     movsg       psr,gr7
0318     ori     gr7,#PSR_EF|PSR_EM,gr7
0319     movgs       gr7,psr
0320     movsg       psr,gr7
0321     srli        gr7,#24,gr7
0322     bar
0323 
0324     movsg       fner0,gr4
0325     movsg       fner1,gr5
0326     stdi.p      gr4,@(gr8,#__FPMEDIA_FNER(0))
0327 
0328     # some CPU's have GR32-GR63
0329     setlos      #HSR0_GRHE,gr4
0330     andcc       gr6,gr4,gr0,icc0
0331     beq     icc0,#1,__save_skip_gr32_gr63
0332 
0333     stdi        gr32,@(gr8,#__INT_GR(32))
0334     stdi        gr34,@(gr8,#__INT_GR(34))
0335     stdi        gr36,@(gr8,#__INT_GR(36))
0336     stdi        gr38,@(gr8,#__INT_GR(38))
0337     stdi        gr40,@(gr8,#__INT_GR(40))
0338     stdi        gr42,@(gr8,#__INT_GR(42))
0339     stdi        gr44,@(gr8,#__INT_GR(44))
0340     stdi        gr46,@(gr8,#__INT_GR(46))
0341     stdi        gr48,@(gr8,#__INT_GR(48))
0342     stdi        gr50,@(gr8,#__INT_GR(50))
0343     stdi        gr52,@(gr8,#__INT_GR(52))
0344     stdi        gr54,@(gr8,#__INT_GR(54))
0345     stdi        gr56,@(gr8,#__INT_GR(56))
0346     stdi        gr58,@(gr8,#__INT_GR(58))
0347     stdi        gr60,@(gr8,#__INT_GR(60))
0348     stdi        gr62,@(gr8,#__INT_GR(62))
0349 __save_skip_gr32_gr63:
0350 
0351     # all CPU's have FR0-FR31
0352     stdfi       fr0 ,@(gr8,#__FPMEDIA_FR( 0))
0353     stdfi       fr2 ,@(gr8,#__FPMEDIA_FR( 2))
0354     stdfi       fr4 ,@(gr8,#__FPMEDIA_FR( 4))
0355     stdfi       fr6 ,@(gr8,#__FPMEDIA_FR( 6))
0356     stdfi       fr8 ,@(gr8,#__FPMEDIA_FR( 8))
0357     stdfi       fr10,@(gr8,#__FPMEDIA_FR(10))
0358     stdfi       fr12,@(gr8,#__FPMEDIA_FR(12))
0359     stdfi       fr14,@(gr8,#__FPMEDIA_FR(14))
0360     stdfi       fr16,@(gr8,#__FPMEDIA_FR(16))
0361     stdfi       fr18,@(gr8,#__FPMEDIA_FR(18))
0362     stdfi       fr20,@(gr8,#__FPMEDIA_FR(20))
0363     stdfi       fr22,@(gr8,#__FPMEDIA_FR(22))
0364     stdfi       fr24,@(gr8,#__FPMEDIA_FR(24))
0365     stdfi       fr26,@(gr8,#__FPMEDIA_FR(26))
0366     stdfi       fr28,@(gr8,#__FPMEDIA_FR(28))
0367     stdfi.p     fr30,@(gr8,#__FPMEDIA_FR(30))
0368 
0369     # some CPU's have FR32-FR63
0370     setlos      #HSR0_FRHE,gr4
0371     andcc       gr6,gr4,gr0,icc0
0372     beq     icc0,#1,__save_skip_fr32_fr63
0373 
0374     stdfi       fr32,@(gr8,#__FPMEDIA_FR(32))
0375     stdfi       fr34,@(gr8,#__FPMEDIA_FR(34))
0376     stdfi       fr36,@(gr8,#__FPMEDIA_FR(36))
0377     stdfi       fr38,@(gr8,#__FPMEDIA_FR(38))
0378     stdfi       fr40,@(gr8,#__FPMEDIA_FR(40))
0379     stdfi       fr42,@(gr8,#__FPMEDIA_FR(42))
0380     stdfi       fr44,@(gr8,#__FPMEDIA_FR(44))
0381     stdfi       fr46,@(gr8,#__FPMEDIA_FR(46))
0382     stdfi       fr48,@(gr8,#__FPMEDIA_FR(48))
0383     stdfi       fr50,@(gr8,#__FPMEDIA_FR(50))
0384     stdfi       fr52,@(gr8,#__FPMEDIA_FR(52))
0385     stdfi       fr54,@(gr8,#__FPMEDIA_FR(54))
0386     stdfi       fr56,@(gr8,#__FPMEDIA_FR(56))
0387     stdfi       fr58,@(gr8,#__FPMEDIA_FR(58))
0388     stdfi       fr60,@(gr8,#__FPMEDIA_FR(60))
0389     stdfi       fr62,@(gr8,#__FPMEDIA_FR(62))
0390 __save_skip_fr32_fr63:
0391 
0392     mrdacc      acc0 ,fr4
0393     mrdacc      acc1 ,fr5
0394 
0395     stdfi.p     fr4 ,@(gr8,#__FPMEDIA_ACC(0))
0396 
0397     mrdacc      acc2 ,fr6
0398     mrdacc      acc3 ,fr7
0399 
0400     stdfi.p     fr6 ,@(gr8,#__FPMEDIA_ACC(2))
0401 
0402     mrdaccg     accg0,fr4
0403     stbfi.p     fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
0404 
0405     mrdaccg     accg1,fr5
0406     stbfi.p     fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
0407 
0408     mrdaccg     accg2,fr6
0409     stbfi.p     fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
0410 
0411     mrdaccg     accg3,fr7
0412     stbfi       fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
0413 
0414     movsg       msr0 ,gr4
0415     movsg       msr1 ,gr5
0416 
0417     stdi        gr4 ,@(gr8,#__FPMEDIA_MSR(0))
0418 
0419     # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
0420     subicc.p    gr7,#0x50,gr0,icc0
0421     subicc      gr7,#0x31,gr0,icc1
0422     beq     icc0,#0,__save_acc_fr451
0423     beq     icc1,#0,__save_acc_fr555
0424 __save_acc_cont:
0425 
0426     lddfi       @(gr8,#__FPMEDIA_FR(4)),fr4
0427     lddfi.p     @(gr8,#__FPMEDIA_FR(6)),fr6
0428     bralr
0429 
0430     # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
0431 __save_acc_fr451:
0432     mrdacc      acc8 ,fr4
0433     mrdacc      acc9 ,fr5
0434 
0435     stdfi.p     fr4 ,@(gr8,#__FPMEDIA_ACC(4))
0436 
0437     mrdacc      acc10,fr6
0438     mrdacc      acc11,fr7
0439 
0440     stdfi.p     fr6 ,@(gr8,#__FPMEDIA_ACC(6))
0441 
0442     mrdaccg     accg8,fr4
0443     stbfi.p     fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
0444 
0445     mrdaccg     accg9,fr5
0446     stbfi.p     fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
0447 
0448     mrdaccg     accg10,fr6
0449     stbfi.p     fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
0450 
0451     mrdaccg     accg11,fr7
0452     stbfi       fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
0453     bra     __save_acc_cont
0454 
0455     # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
0456 __save_acc_fr555:
0457     mnop.p
0458     mrdacc      acc4 ,fr4
0459     mnop.p
0460     mrdacc      acc5 ,fr5
0461 
0462     stdfi       fr4 ,@(gr8,#__FPMEDIA_ACC(4))
0463 
0464     mnop.p
0465     mrdacc      acc6 ,fr6
0466     mnop.p
0467     mrdacc      acc7 ,fr7
0468 
0469     stdfi       fr6 ,@(gr8,#__FPMEDIA_ACC(6))
0470 
0471     mnop.p
0472     mrdaccg     accg4,fr4
0473     stbfi       fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
0474 
0475     mnop.p
0476     mrdaccg     accg5,fr5
0477     stbfi       fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
0478 
0479     mnop.p
0480     mrdaccg     accg6,fr6
0481     stbfi       fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
0482 
0483     mnop.p
0484     mrdaccg     accg7,fr7
0485     stbfi       fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
0486 
0487     movsg       fsr0 ,gr4
0488     sti     gr4 ,@(gr8,#__FPMEDIA_FSR(0))
0489     bra     __save_acc_cont