swtch.S revision 210096
1/* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */ 2/*- 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Digital Equipment Corporation and Ralph Campbell. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Copyright (C) 1989 Digital Equipment Corporation. 34 * Permission to use, copy, modify, and distribute this software and 35 * its documentation for any purpose and without fee is hereby granted, 36 * provided that the above copyright notice appears in all copies. 37 * Digital Equipment Corporation makes no representations about the 38 * suitability of this software for any purpose. It is provided "as is" 39 * without express or implied warranty. 40 * 41 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 42 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 43 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 44 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 45 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 46 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 47 * 48 * from: @(#)locore.s 8.5 (Berkeley) 1/4/94 49 * JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish 50 * $FreeBSD: head/sys/mips/mips/swtch.S 210096 2010-07-15 01:47:47Z imp $ 51 */ 52 53/* 54 * Contains code that is the first executed at boot time plus 55 * assembly language support routines. 56 */ 57 58#include "opt_cputype.h" 59#include <sys/syscall.h> 60#include <machine/asm.h> 61#include <machine/cpu.h> 62#include <machine/cpuregs.h> 63#include <machine/regnum.h> 64#include <machine/pte.h> 65 66#include "assym.s" 67 68 .set noreorder # Noreorder is default style! 69 70/* 71 * FREEBSD_DEVELOPERS_FIXME 72 * Some MIPS CPU may need delays using nops between executing CP0 Instructions 73 */ 74 75#if 1 76#define HAZARD_DELAY nop ; nop ; nop ; nop 77#else 78#define HAZARD_DELAY 79#endif 80 81#define SAVE_U_PCB_REG(reg, offs, base) \ 82 REG_S reg, U_PCB_REGS + (SZREG * offs) (base) 83 84#define RESTORE_U_PCB_REG(reg, offs, base) \ 85 REG_L reg, U_PCB_REGS + (SZREG * offs) (base) 86 87#define SAVE_U_PCB_FPREG(reg, offs, base) \ 88 FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 89 90#define RESTORE_U_PCB_FPREG(reg, offs, base) \ 91 FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 92 93#define SAVE_U_PCB_FPSR(reg, offs, base) \ 94 REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 95 96#define RESTORE_U_PCB_FPSR(reg, offs, base) \ 97 REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 98 99#define SAVE_U_PCB_CONTEXT(reg, offs, base) \ 100 REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base) 101 102#define RESTORE_U_PCB_CONTEXT(reg, offs, base) \ 103 REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base) 104 105#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; 106 107/* 108 * Setup for and return to user. 109 */ 110LEAF(fork_trampoline) 111 move a0,s0 112 move a1,s1 113 jal _C_LABEL(fork_exit) 114 move a2,s2 #BDSlot 115 116 DO_AST 117 118 mfc0 v0, MIPS_COP_0_STATUS 119 and v0, ~(MIPS_SR_INT_IE) 120 mtc0 v0, MIPS_COP_0_STATUS # disable interrupts 121 COP0_SYNC 122/* 123 * The use of k1 for storing the PCB pointer must be done only 124 * after interrupts are disabled. Otherwise it will get overwritten 125 * by the interrupt code. 126 */ 127 .set noat 128 GET_CPU_PCPU(k1) 129 PTR_L k1, PC_CURPCB(k1) 130 131 RESTORE_U_PCB_REG(t0, MULLO, k1) 132 RESTORE_U_PCB_REG(t1, MULHI, k1) 133 mtlo t0 134 mthi t1 135 RESTORE_U_PCB_REG(a0, PC, k1) 136 RESTORE_U_PCB_REG(AT, AST, k1) 137 RESTORE_U_PCB_REG(v0, V0, k1) 138 MTC0 a0, MIPS_COP_0_EXC_PC # set return address 139 140 RESTORE_U_PCB_REG(v1, V1, k1) 141 RESTORE_U_PCB_REG(a0, A0, k1) 142 RESTORE_U_PCB_REG(a1, A1, k1) 143 RESTORE_U_PCB_REG(a2, A2, k1) 144 RESTORE_U_PCB_REG(a3, A3, k1) 145 RESTORE_U_PCB_REG(t0, T0, k1) 146 RESTORE_U_PCB_REG(t1, T1, k1) 147 RESTORE_U_PCB_REG(t2, T2, k1) 148 RESTORE_U_PCB_REG(t3, T3, k1) 149 RESTORE_U_PCB_REG(ta0, TA0, k1) 150 RESTORE_U_PCB_REG(ta1, TA1, k1) 151 RESTORE_U_PCB_REG(ta2, TA2, k1) 152 RESTORE_U_PCB_REG(ta3, TA3, k1) 153 RESTORE_U_PCB_REG(s0, S0, k1) 154 RESTORE_U_PCB_REG(s1, S1, k1) 155 RESTORE_U_PCB_REG(s2, S2, k1) 156 RESTORE_U_PCB_REG(s3, S3, k1) 157 RESTORE_U_PCB_REG(s4, S4, k1) 158 RESTORE_U_PCB_REG(s5, S5, k1) 159 RESTORE_U_PCB_REG(s6, S6, k1) 160 RESTORE_U_PCB_REG(s7, S7, k1) 161 RESTORE_U_PCB_REG(t8, T8, k1) 162 RESTORE_U_PCB_REG(t9, T9, k1) 163 RESTORE_U_PCB_REG(k0, SR, k1) 164 RESTORE_U_PCB_REG(gp, GP, k1) 165 RESTORE_U_PCB_REG(s8, S8, k1) 166 RESTORE_U_PCB_REG(ra, RA, k1) 167 RESTORE_U_PCB_REG(sp, SP, k1) 168 li k1, ~MIPS_SR_INT_MASK 169 and k0, k0, k1 170 mfc0 k1, MIPS_COP_0_STATUS 171 and k1, k1, MIPS_SR_INT_MASK 172 or k0, k0, k1 173 mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...) 174 HAZARD_DELAY 175 sync 176 eret 177 .set at 178END(fork_trampoline) 179 180/* 181 * Update pcb, saving current processor state. 182 * Note: this only works if pcbp != curproc's pcb since 183 * cpu_switch() will copy over pcb_context. 184 * 185 * savectx(struct pcb *pcbp); 186 */ 187LEAF(savectx) 188 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) 189 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 190 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 191 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 192 mfc0 v0, MIPS_COP_0_STATUS 193 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 194 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 195 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 196 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 197 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) 198 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 199 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) 200 SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0) 201 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 202 203 move v0, ra /* save 'ra' before we trash it */ 204 jal 1f 205 nop 2061: 207 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) 208 move ra, v0 /* restore 'ra' before returning */ 209 210 /* 211 * FREEBSD_DEVELOPERS_FIXME: 212 * In case there are CPU-specific registers that need 213 * to be saved with the other registers do so here. 214 */ 215 j ra 216 move v0, zero 217END(savectx) 218 219NON_LEAF(cpu_throw, CALLFRAME_SIZ, ra) 220 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register 221 nop 222 nop 223 and a3, t0, ~(MIPS_SR_INT_IE) 224 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts 225 ITLBNOPFIX 226 j mips_sw1 # We're not interested in old 227 # thread's context, so jump 228 # right to action 229 nop # BDSLOT 230END(cpu_throw) 231 232/* 233 * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx); 234 * a0 - old 235 * a1 - new 236 * a2 - mtx 237 * Find the highest priority process and resume it. 238 */ 239NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra) 240 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register 241 nop 242 nop 243 and a3, t0, ~(MIPS_SR_INT_IE) 244 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts 245 ITLBNOPFIX 246 beqz a0, mips_sw1 247 move a3, a0 248 PTR_L a0, TD_PCB(a0) # load PCB addr of curproc 249 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp 250 PTR_SUBU sp, sp, CALLFRAME_SIZ 251 REG_S ra, CALLFRAME_RA(sp) 252 .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 253 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()' 254 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 255 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 256 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 257 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 258 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 259 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 260 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 261 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 262 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address 263 SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register 264 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 265 jal getpc 266 nop 267getpc: 268 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) # save return address 269 /* 270 * FREEBSD_DEVELOPERS_FIXME: 271 * In case there are CPU-specific registers that need 272 * to be saved with the other registers do so here. 273 */ 274 275 PTR_S a2, TD_LOCK(a3) # Switchout td_lock 276 277mips_sw1: 278#if defined(SMP) && defined(SCHED_ULE) 279 PTR_LA t0, _C_LABEL(blocked_lock) 280blocked_loop: 281 PTR_L t1, TD_LOCK(a1) 282 beq t0, t1, blocked_loop 283 nop 284#endif 285 move s7, a1 # Store newthread 286/* 287 * Switch to new context. 288 */ 289 GET_CPU_PCPU(a3) 290 PTR_S a1, PC_CURTHREAD(a3) 291 PTR_L a2, TD_PCB(a1) 292 PTR_S a2, PC_CURPCB(a3) 293 PTR_L v0, TD_KSTACK(a1) 294#if !defined(__mips_n64) 295 PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2, 296 bltu v0, s0, sw2 # no need to insert in TLB. 297#endif 298 lw a1, TD_UPTE + 0(s7) # a1 = u. pte #0 299 lw a2, TD_UPTE + 4(s7) # a2 = u. pte #1 300/* 301 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target 302 * USPACE is already in another place of TLB before that, and if so 303 * invalidate that TLB entry. 304 * NOTE: This is hard coded to UPAGES == 2. 305 * Also, there should be no TLB faults at this point. 306 */ 307 MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va 308 HAZARD_DELAY 309 tlbp # probe VPN 310 HAZARD_DELAY 311 mfc0 s0, MIPS_COP_0_TLB_INDEX 312 HAZARD_DELAY 313 314 PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry 315 bltz s0, entry0set 316 nop 317 sll s0, PAGE_SHIFT + 1 318 addu t1, s0 319 MTC0 t1, MIPS_COP_0_TLB_HI 320 mtc0 zero, MIPS_COP_0_TLB_LO0 321 mtc0 zero, MIPS_COP_0_TLB_LO1 322 HAZARD_DELAY 323 tlbwi 324 HAZARD_DELAY 325 MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again 326 327entry0set: 328/* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */ 329 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0 330 HAZARD_DELAY 331 mtc0 a1, MIPS_COP_0_TLB_LO0 # upte[0] 332 HAZARD_DELAY 333 mtc0 a2, MIPS_COP_0_TLB_LO1 # upte[1] 334 HAZARD_DELAY 335 tlbwi # set TLB entry #0 336 HAZARD_DELAY 337/* 338 * Now running on new u struct. 339 */ 340sw2: 341 PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer 342 jalr t1 # s7 = new proc pointer 343 move a0, s7 # BDSLOT 344/* 345 * Restore registers and return. 346 */ 347 PTR_L a0, TD_PCB(s7) 348 RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0) 349 RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context 350 RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0) 351 RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0) 352 RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0) 353 RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0) 354 RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0) 355 RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0) 356 RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0) 357 RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0) 358 RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0) 359 RESTORE_U_PCB_CONTEXT(sp, PREG_SP, a0) 360 RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0) 361 /* 362 * FREEBSD_DEVELOPERS_FIXME: 363 * In case there are CPU-specific registers that need 364 * to be restored with the other registers do so here. 365 */ 366 mfc0 t0, MIPS_COP_0_STATUS 367 and t0, t0, MIPS_SR_INT_MASK 368 and v0, v0, ~MIPS_SR_INT_MASK 369 or v0, v0, t0 370 mtc0 v0, MIPS_COP_0_STATUS 371 ITLBNOPFIX 372 373 j ra 374 nop 375END(cpu_switch) 376 377/*---------------------------------------------------------------------------- 378 * 379 * MipsSwitchFPState -- 380 * 381 * Save the current state into 'from' and restore it from 'to'. 382 * 383 * MipsSwitchFPState(from, to) 384 * struct thread *from; 385 * struct trapframe *to; 386 * 387 * Results: 388 * None. 389 * 390 * Side effects: 391 * None. 392 * 393 *---------------------------------------------------------------------------- 394 */ 395LEAF(MipsSwitchFPState) 396 mfc0 t1, MIPS_COP_0_STATUS # Save old SR 397 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor 398 mtc0 t0, MIPS_COP_0_STATUS 399 ITLBNOPFIX 400 401 beq a0, zero, 1f # skip save if NULL pointer 402 nop 403/* 404 * First read out the status register to make sure that all FP operations 405 * have completed. 406 */ 407 PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc 408 cfc1 t0, MIPS_FPU_CSR # stall til FP done 409 cfc1 t0, MIPS_FPU_CSR # now get status 410 li t3, ~MIPS_SR_COP_1_BIT 411 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 412 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 413 and t2, t2, t3 # clear COP_1 enable bit 414 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 415/* 416 * Save the floating point registers. 417 */ 418 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 419 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 420 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 421 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 422 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 423 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 424 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 425 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 426 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 427 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 428 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 429 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 430 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 431 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 432 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 433 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 434 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 435 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 436 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 437 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 438 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 439 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 440 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 441 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 442 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 443 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 444 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 445 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 446 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 447 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 448 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 449 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 450 4511: 452/* 453 * Restore the floating point registers. 454 */ 455 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register 456 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1) 457 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1) 458 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1) 459 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1) 460 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1) 461 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1) 462 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1) 463 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1) 464 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1) 465 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1) 466 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1) 467 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1) 468 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1) 469 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1) 470 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1) 471 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1) 472 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1) 473 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1) 474 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1) 475 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1) 476 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1) 477 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1) 478 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1) 479 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1) 480 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1) 481 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1) 482 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1) 483 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1) 484 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1) 485 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1) 486 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1) 487 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1) 488 489 and t0, t0, ~MIPS_FPU_EXCEPTION_BITS 490 ctc1 t0, MIPS_FPU_CSR 491 nop 492 493 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register. 494 ITLBNOPFIX 495 j ra 496 nop 497END(MipsSwitchFPState) 498 499/*---------------------------------------------------------------------------- 500 * 501 * MipsSaveCurFPState -- 502 * 503 * Save the current floating point coprocessor state. 504 * 505 * MipsSaveCurFPState(td) 506 * struct thread *td; 507 * 508 * Results: 509 * None. 510 * 511 * Side effects: 512 * machFPCurProcPtr is cleared. 513 * 514 *---------------------------------------------------------------------------- 515 */ 516LEAF(MipsSaveCurFPState) 517 PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread 518 mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and 519 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor 520 mtc0 t0, MIPS_COP_0_STATUS 521 ITLBNOPFIX 522 GET_CPU_PCPU(a1) 523 PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved 524/* 525 * First read out the status register to make sure that all FP operations 526 * have completed. 527 */ 528 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 529 li t3, ~MIPS_SR_COP_1_BIT 530 and t2, t2, t3 # clear COP_1 enable bit 531 cfc1 t0, MIPS_FPU_CSR # stall til FP done 532 cfc1 t0, MIPS_FPU_CSR # now get status 533 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 534 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 535/* 536 * Save the floating point registers. 537 */ 538 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 539 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 540 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 541 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 542 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 543 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 544 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 545 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 546 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 547 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 548 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 549 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 550 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 551 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 552 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 553 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 554 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 555 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 556 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 557 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 558 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 559 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 560 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 561 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 562 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 563 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 564 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 565 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 566 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 567 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 568 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 569 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 570 571 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register. 572 ITLBNOPFIX 573 j ra 574 nop 575END(MipsSaveCurFPState) 576 577/* 578 * When starting init, call this to configure the process for user 579 * mode. This will be inherited by other processes. 580 */ 581LEAF_NOPROFILE(prepare_usermode) 582 j ra 583 nop 584END(prepare_usermode) 585 586 587/* 588 * This code is copied the user's stack for returning from signal handlers 589 * (see sendsig() and sigreturn()). We have to compute the address 590 * of the sigcontext struct for the sigreturn call. 591 */ 592 .globl _C_LABEL(sigcode) 593_C_LABEL(sigcode): 594 addu a0, sp, SIGF_UC # address of ucontext 595 li v0, SYS_sigreturn 596# sigreturn (ucp) 597 syscall 598 break 0 # just in case sigreturn fails 599 .globl _C_LABEL(esigcode) 600_C_LABEL(esigcode): 601 602 .data 603 .globl szsigcode 604szsigcode: 605 .long esigcode-sigcode 606 .text 607