root/arch/mips/kernel/resume.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /*
   2  *  linux/kernel/mips/sys_call.S
   3  *
   4  *  Copyright (C) 1994, 1995 Waldorf Electronics
   5  *  written by Ralf Baechle
   6  */
   7 
   8 /*
   9  * sys_call.S  contains the system-call and fault low-level handling routines.
  10  * This also contains the timer-interrupt handler, as well as all interrupts
  11  * and faults that can result in a task-switch.
  12  */
  13 
  14 #include <asm/regdef.h>
  15 #include <asm/processor.h>
  16 #include <asm/mipsregs.h>
  17 #include <asm/mipsconfig.h>
  18 
  19 /*
  20  * These are offsets into the task-struct.
  21  */
  22 state           =  0
  23 counter         =  4
  24 priority        =  8
  25 signal          = 12
  26 blocked         = 16
  27 flags           = 20
  28 errno           = 24                    #/* MIPS OK */
  29 exec_domain     = 60                    #/* ??? */
  30 
  31 ENOSYS          = 38
  32 
  33 /*
  34  * Code necessary to switch tasks on an Linux/MIPS machine.
  35  */
  36 MODE_ALIAS      =       0x0016                  # uncachable
  37 
  38                 .text
  39                 .set    noreorder
  40                 .set    at
  41 
  42                 .globl  _resume
  43 _resume:
  44                 /*
  45                  * current task's task_struct
  46                  */
  47                 lui     t5,%hi(_current)
  48                 lw      t0,%lo(_current)(t5)
  49 
  50                 /*
  51                  * Save status register
  52                  */
  53                 mfc0    t1,CP0_STATUS
  54                 addu    t0,a1                   # Add tss offset
  55                 sw      t1,TOFF_CP0_STATUS(t0)
  56 
  57                 /*
  58                  * Disable interrupts
  59                  */
  60                 ori     t2,t1,0x1f
  61                 xori    t2,0x1e
  62                 mtc0    t2,CP0_STATUS
  63 
  64                 /*
  65                  * Save non-scratch registers
  66                  * All other registers have been saved on the kernel stack
  67                  */
  68                 sw      s0,TOFF_REG16(t0)
  69                 sw      s1,TOFF_REG17(t0)
  70                 sw      s2,TOFF_REG18(t0)
  71                 sw      s3,TOFF_REG19(t0)
  72                 sw      s4,TOFF_REG20(t0)
  73                 sw      s5,TOFF_REG21(t0)
  74                 sw      s6,TOFF_REG22(t0)
  75                 sw      s7,TOFF_REG23(t0)
  76                 sw      gp,TOFF_REG28(t0)
  77                 sw      sp,TOFF_REG29(t0)
  78                 sw      fp,TOFF_REG30(t0)
  79                 sw      ra,TOFF_REG31(t0)
  80 
  81                 /*
  82                  * Save floating point state
  83                  */
  84                 srl     t2,t1,29
  85                 andi    t2,1
  86                 beqz    t2,2f
  87                 srl     t2,t1,26
  88                 andi    t2,1
  89                 beqz    t2,1f
  90                 sdc1    $f0,(TOFF_FPU+0)(t0)    # delay slot
  91                 /*
  92                  * Store the 16 odd double precision registers
  93                  */
  94                 sdc1    $f1,(TOFF_FPU+8)(t0)
  95                 sdc1    $f3,(TOFF_FPU+24)(t0)
  96                 sdc1    $f5,(TOFF_FPU+40)(t0)
  97                 sdc1    $f7,(TOFF_FPU+56)(t0)
  98                 sdc1    $f9,(TOFF_FPU+72)(t0)
  99                 sdc1    $f11,(TOFF_FPU+88)(t0)
 100                 sdc1    $f13,(TOFF_FPU+104)(t0)
 101                 sdc1    $f15,(TOFF_FPU+120)(t0)
 102                 sdc1    $f17,(TOFF_FPU+136)(t0)
 103                 sdc1    $f19,(TOFF_FPU+152)(t0)
 104                 sdc1    $f21,(TOFF_FPU+168)(t0)
 105                 sdc1    $f23,(TOFF_FPU+184)(t0)
 106                 sdc1    $f25,(TOFF_FPU+200)(t0)
 107                 sdc1    $f27,(TOFF_FPU+216)(t0)
 108                 sdc1    $f29,(TOFF_FPU+232)(t0)
 109                 sdc1    $f31,(TOFF_FPU+248)(t0)
 110 
 111                 /*
 112                  * Store the 16 even double precision registers
 113                  */
 114 1:              cfc1    t1,$31
 115                 sdc1    $f2,(TOFF_FPU+16)(t0)
 116                 sdc1    $f4,(TOFF_FPU+32)(t0)
 117                 sdc1    $f6,(TOFF_FPU+48)(t0)
 118                 sdc1    $f8,(TOFF_FPU+64)(t0)
 119                 sdc1    $f10,(TOFF_FPU+80)(t0)
 120                 sdc1    $f12,(TOFF_FPU+96)(t0)
 121                 sdc1    $f14,(TOFF_FPU+112)(t0)
 122                 sdc1    $f16,(TOFF_FPU+128)(t0)
 123                 sdc1    $f18,(TOFF_FPU+144)(t0)
 124                 sdc1    $f20,(TOFF_FPU+160)(t0)
 125                 sdc1    $f22,(TOFF_FPU+176)(t0)
 126                 sdc1    $f24,(TOFF_FPU+192)(t0)
 127                 sdc1    $f26,(TOFF_FPU+208)(t0)
 128                 sdc1    $f28,(TOFF_FPU+224)(t0)
 129                 sdc1    $f30,(TOFF_FPU+240)(t0)
 130                 sw      t1,(TOFF_FPU+256)(t0)
 131 
 132                 /*
 133                  * Switch current task
 134                  */
 135 2:              sw      a0,%lo(_current)(t5)
 136                 addu    a0,a1                   # Add tss offset
 137 
 138                 /*
 139                  * Switch address space
 140                  */
 141 
 142                 /*
 143                  * (Choose new ASID for process)
 144                  */
 145 
 146                 /*
 147                  * Switch the root pointer
 148                  */
 149                 lw      t0,TOFF_PG_DIR(a0)
 150                 la      t1,TLB_ROOT
 151                 mtc0    t1,CP0_ENTRYHI
 152                 mtc0    zero,CP0_INDEX
 153                 srl     t0,6
 154                 ori     t0,MODE_ALIAS
 155                 mtc0    t0,CP0_ENTRYLO0
 156                 mtc0    zero,CP0_ENTRYLO1
 157                 tlbwi
 158 
 159                 /*
 160                  * Flush tlb (probably not needed)
 161                  * (Doesn't clobber a0-a3)
 162                  */
 163                 jal     _tlbflush
 164                 nop                                     # delay slot
 165 
 166                 lw      a2,TOFF_CP0_STATUS(a0)
 167 
 168                 /*
 169                  * Restore fpu state:
 170                  *  - cp0 status register bits
 171                  *  - fp gp registers
 172                  *  - cp1 status/control register
 173                  */
 174                 ori     t1,a2,1                         # pipeline magic
 175                 xori    t1,1
 176                 mtc0    t1,CP0_STATUS
 177                 srl     t0,a2,29
 178                 andi    t0,1
 179                 beqz    t0,2f
 180                 srl     t0,a2,26
 181                 andi    t0,1
 182                 beqz    t0,1f
 183                 ldc1    $f0,(TOFF_FPU+0)(a0)    # delay slot
 184                 /*
 185                  * Restore the 16 odd double precision registers only
 186                  * when enabled in the cp0 status register.
 187                  */
 188                 ldc1    $f1,(TOFF_FPU+8)(a0)
 189                 ldc1    $f3,(TOFF_FPU+24)(a0)
 190                 ldc1    $f5,(TOFF_FPU+40)(a0)
 191                 ldc1    $f7,(TOFF_FPU+56)(a0)
 192                 ldc1    $f9,(TOFF_FPU+72)(a0)
 193                 ldc1    $f11,(TOFF_FPU+88)(a0)
 194                 ldc1    $f13,(TOFF_FPU+104)(a0)
 195                 ldc1    $f15,(TOFF_FPU+120)(a0)
 196                 ldc1    $f17,(TOFF_FPU+136)(a0)
 197                 ldc1    $f19,(TOFF_FPU+152)(a0)
 198                 ldc1    $f21,(TOFF_FPU+168)(a0)
 199                 ldc1    $f23,(TOFF_FPU+184)(a0)
 200                 ldc1    $f25,(TOFF_FPU+200)(a0)
 201                 ldc1    $f27,(TOFF_FPU+216)(a0)
 202                 ldc1    $f29,(TOFF_FPU+232)(a0)
 203                 ldc1    $f31,(TOFF_FPU+248)(a0)
 204 
 205                 /*
 206                  * Restore the 16 even double precision registers always
 207                  * when cp1 was enabled in the cp0 status register.
 208                  */
 209 1:              lw      t0,(TOFF_FPU+256)(a0)
 210                 ldc1    $f2,(TOFF_FPU+16)(a0)
 211                 ldc1    $f4,(TOFF_FPU+32)(a0)
 212                 ldc1    $f6,(TOFF_FPU+48)(a0)
 213                 ldc1    $f8,(TOFF_FPU+64)(a0)
 214                 ldc1    $f10,(TOFF_FPU+80)(a0)
 215                 ldc1    $f12,(TOFF_FPU+96)(a0)
 216                 ldc1    $f14,(TOFF_FPU+112)(a0)
 217                 ldc1    $f16,(TOFF_FPU+128)(a0)
 218                 ldc1    $f18,(TOFF_FPU+144)(a0)
 219                 ldc1    $f20,(TOFF_FPU+160)(a0)
 220                 ldc1    $f22,(TOFF_FPU+176)(a0)
 221                 ldc1    $f24,(TOFF_FPU+192)(a0)
 222                 ldc1    $f26,(TOFF_FPU+208)(a0)
 223                 ldc1    $f28,(TOFF_FPU+224)(a0)
 224                 ldc1    $f30,(TOFF_FPU+240)(a0)
 225                 ctc1    t0,$31
 226 
 227                 /*
 228                  * Restore non-scratch registers
 229                  */
 230 2:              lw      s0,TOFF_REG16(a0)
 231                 lw      s1,TOFF_REG17(a0)
 232                 lw      s2,TOFF_REG18(a0)
 233                 lw      s3,TOFF_REG19(a0)
 234                 lw      s4,TOFF_REG20(a0)
 235                 lw      s5,TOFF_REG21(a0)
 236                 lw      s6,TOFF_REG22(a0)
 237                 lw      s7,TOFF_REG23(a0)
 238                 lw      gp,TOFF_REG28(a0)
 239                 lw      sp,TOFF_REG29(a0)
 240                 lw      fp,TOFF_REG30(a0)
 241                 lw      ra,TOFF_REG31(a0)
 242 
 243                 /*
 244                  * Restore status register
 245                  */
 246                 lw      t0,TOFF_KSP(a0)
 247                 sw      t0,_kernelsp
 248 
 249                 jr      ra
 250                 mtc0    a2,CP0_STATUS                   # delay slot

/* [previous][next][first][last][top][bottom][index][help] */