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 
  63                 /*
  64                  * Save fs (may be pointing to kernel memory)
  65                  */
  66                 lui     t4,%hi(_segment_fs)
  67                 lw      t3,%lo(_segment_fs)(t4)
  68                 mtc0    t2,CP0_STATUS
  69                 sw      t3,TOFF_FS(t0)
  70 
  71                 /*
  72                  * Save non-scratch registers
  73                  * All other registers have been saved on the kernel stack
  74                  */
  75                 sw      s0,TOFF_REG16(t0)
  76                 sw      s1,TOFF_REG17(t0)
  77                 sw      s2,TOFF_REG18(t0)
  78                 sw      s3,TOFF_REG19(t0)
  79                 sw      s4,TOFF_REG20(t0)
  80                 sw      s5,TOFF_REG21(t0)
  81                 sw      s6,TOFF_REG22(t0)
  82                 sw      s7,TOFF_REG23(t0)
  83                 sw      gp,TOFF_REG28(t0)
  84                 sw      sp,TOFF_REG29(t0)
  85                 sw      fp,TOFF_REG30(t0)
  86                 sw      ra,TOFF_REG31(t0)
  87 
  88                 /*
  89                  * Save floating point state
  90                  */
  91                 srl     t2,t1,29
  92                 andi    t2,1
  93                 beqz    t2,2f
  94                 srl     t2,t1,26
  95                 andi    t2,1
  96                 beqz    t2,1f
  97                 sdc1    $f0,(TOFF_FPU+0)(t0)    # delay slot
  98                 /*
  99                  * Store the 16 odd double precision registers
 100                  */
 101                 sdc1    $f1,(TOFF_FPU+8)(t0)
 102                 sdc1    $f3,(TOFF_FPU+24)(t0)
 103                 sdc1    $f5,(TOFF_FPU+40)(t0)
 104                 sdc1    $f7,(TOFF_FPU+56)(t0)
 105                 sdc1    $f9,(TOFF_FPU+72)(t0)
 106                 sdc1    $f11,(TOFF_FPU+88)(t0)
 107                 sdc1    $f13,(TOFF_FPU+104)(t0)
 108                 sdc1    $f15,(TOFF_FPU+120)(t0)
 109                 sdc1    $f17,(TOFF_FPU+136)(t0)
 110                 sdc1    $f19,(TOFF_FPU+152)(t0)
 111                 sdc1    $f21,(TOFF_FPU+168)(t0)
 112                 sdc1    $f23,(TOFF_FPU+184)(t0)
 113                 sdc1    $f25,(TOFF_FPU+200)(t0)
 114                 sdc1    $f27,(TOFF_FPU+216)(t0)
 115                 sdc1    $f29,(TOFF_FPU+232)(t0)
 116                 sdc1    $f31,(TOFF_FPU+248)(t0)
 117 
 118                 /*
 119                  * Store the 16 even double precision registers
 120                  */
 121 1:              cfc1    t1,$31
 122                 sdc1    $f2,(TOFF_FPU+16)(t0)
 123                 sdc1    $f4,(TOFF_FPU+32)(t0)
 124                 sdc1    $f6,(TOFF_FPU+48)(t0)
 125                 sdc1    $f8,(TOFF_FPU+64)(t0)
 126                 sdc1    $f10,(TOFF_FPU+80)(t0)
 127                 sdc1    $f12,(TOFF_FPU+96)(t0)
 128                 sdc1    $f14,(TOFF_FPU+112)(t0)
 129                 sdc1    $f16,(TOFF_FPU+128)(t0)
 130                 sdc1    $f18,(TOFF_FPU+144)(t0)
 131                 sdc1    $f20,(TOFF_FPU+160)(t0)
 132                 sdc1    $f22,(TOFF_FPU+176)(t0)
 133                 sdc1    $f24,(TOFF_FPU+192)(t0)
 134                 sdc1    $f26,(TOFF_FPU+208)(t0)
 135                 sdc1    $f28,(TOFF_FPU+224)(t0)
 136                 sdc1    $f30,(TOFF_FPU+240)(t0)
 137                 sw      t1,(TOFF_FPU+256)(t0)
 138 
 139                 /*
 140                  * Switch current task
 141                  */
 142 2:              sw      a0,%lo(_current)(t5)
 143                 addu    a0,a1                   # Add tss offset
 144 
 145                 /*
 146                  * Switch address space
 147                  */
 148 
 149                 /*
 150                  * (Choose new ASID for process)
 151                  */
 152 
 153                 /*
 154                  * Switch the root pointer
 155                  */
 156                 lw      t0,TOFF_PG_DIR(a0)
 157                 la      t1,TLB_ROOT
 158                 mtc0    t1,CP0_ENTRYHI
 159                 mtc0    zero,CP0_INDEX
 160                 srl     t0,6
 161                 ori     t0,MODE_ALIAS
 162                 mtc0    t0,CP0_ENTRYLO0
 163                 mtc0    zero,CP0_ENTRYLO1
 164                 tlbwi
 165 
 166                 /*
 167                  * Flush tlb (probably not needed)
 168                  * (Doesn't clobber a0-a3)
 169                  */
 170                 jal     _tlbflush
 171                 nop                                     # delay slot
 172 
 173                 lw      a2,TOFF_CP0_STATUS(a0)
 174 
 175                 /*
 176                  * Restore fpu state:
 177                  *  - cp0 status register bits
 178                  *  - fp gp registers
 179                  *  - cp1 status/control register
 180                  */
 181                 ori     t1,a2,1                         # pipeline magic
 182                 xori    t1,1
 183                 mtc0    t1,CP0_STATUS
 184                 srl     t0,a2,29
 185                 andi    t0,1
 186                 beqz    t0,2f
 187                 srl     t0,a2,26
 188                 andi    t0,1
 189                 beqz    t0,1f
 190                 ldc1    $f0,(TOFF_FPU+0)(a0)    # delay slot
 191                 /*
 192                  * Restore the 16 odd double precision registers only
 193                  * when enabled in the cp0 status register.
 194                  */
 195                 ldc1    $f1,(TOFF_FPU+8)(a0)
 196                 ldc1    $f3,(TOFF_FPU+24)(a0)
 197                 ldc1    $f5,(TOFF_FPU+40)(a0)
 198                 ldc1    $f7,(TOFF_FPU+56)(a0)
 199                 ldc1    $f9,(TOFF_FPU+72)(a0)
 200                 ldc1    $f11,(TOFF_FPU+88)(a0)
 201                 ldc1    $f13,(TOFF_FPU+104)(a0)
 202                 ldc1    $f15,(TOFF_FPU+120)(a0)
 203                 ldc1    $f17,(TOFF_FPU+136)(a0)
 204                 ldc1    $f19,(TOFF_FPU+152)(a0)
 205                 ldc1    $f21,(TOFF_FPU+168)(a0)
 206                 ldc1    $f23,(TOFF_FPU+184)(a0)
 207                 ldc1    $f25,(TOFF_FPU+200)(a0)
 208                 ldc1    $f27,(TOFF_FPU+216)(a0)
 209                 ldc1    $f29,(TOFF_FPU+232)(a0)
 210                 ldc1    $f31,(TOFF_FPU+248)(a0)
 211 
 212                 /*
 213                  * Restore the 16 even double precision registers always
 214                  * when cp1 was enabled in the cp0 status register.
 215                  */
 216 1:              lw      t0,(TOFF_FPU+256)(a0)
 217                 ldc1    $f2,(TOFF_FPU+16)(a0)
 218                 ldc1    $f4,(TOFF_FPU+32)(a0)
 219                 ldc1    $f6,(TOFF_FPU+48)(a0)
 220                 ldc1    $f8,(TOFF_FPU+64)(a0)
 221                 ldc1    $f10,(TOFF_FPU+80)(a0)
 222                 ldc1    $f12,(TOFF_FPU+96)(a0)
 223                 ldc1    $f14,(TOFF_FPU+112)(a0)
 224                 ldc1    $f16,(TOFF_FPU+128)(a0)
 225                 ldc1    $f18,(TOFF_FPU+144)(a0)
 226                 ldc1    $f20,(TOFF_FPU+160)(a0)
 227                 ldc1    $f22,(TOFF_FPU+176)(a0)
 228                 ldc1    $f24,(TOFF_FPU+192)(a0)
 229                 ldc1    $f26,(TOFF_FPU+208)(a0)
 230                 ldc1    $f28,(TOFF_FPU+224)(a0)
 231                 ldc1    $f30,(TOFF_FPU+240)(a0)
 232                 ctc1    t0,$31
 233 
 234                 /*
 235                  * Restore non-scratch registers
 236                  */
 237 2:              lw      s0,TOFF_REG16(a0)
 238                 lw      s1,TOFF_REG17(a0)
 239                 lw      s2,TOFF_REG18(a0)
 240                 lw      s3,TOFF_REG19(a0)
 241                 lw      s4,TOFF_REG20(a0)
 242                 lw      s5,TOFF_REG21(a0)
 243                 lw      s6,TOFF_REG22(a0)
 244                 lw      s7,TOFF_REG23(a0)
 245                 lw      gp,TOFF_REG28(a0)
 246                 lw      sp,TOFF_REG29(a0)
 247                 lw      fp,TOFF_REG30(a0)
 248                 lw      ra,TOFF_REG31(a0)
 249 
 250                 /*
 251                  * Restore fs segment pointer
 252                  * Restore status register
 253                  */
 254                 lw      t0,TOFF_FS(a0)
 255                 lw      t1,TOFF_KSP(a0)
 256                 sw      t0,%lo(_segment_fs)(t4)
 257                 sw      t1,_kernelsp
 258 
 259                 jr      ra
 260                 mtc0    a2,CP0_STATUS                   # delay slot
 261 

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