swtch.S revision 232449
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 232449 2012-03-03 08:19:18Z jmallett $ 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_compat.h" 59#include "opt_cputype.h" 60#include <sys/syscall.h> 61#include <machine/asm.h> 62#include <machine/cpu.h> 63#include <machine/cpuregs.h> 64#include <machine/regnum.h> 65#include <machine/pte.h> 66 67#include "assym.s" 68 69 .set noreorder # Noreorder is default style! 70 71#define SAVE_U_PCB_REG(reg, offs, base) \ 72 REG_S reg, U_PCB_REGS + (SZREG * offs) (base) 73 74#define RESTORE_U_PCB_REG(reg, offs, base) \ 75 REG_L reg, U_PCB_REGS + (SZREG * offs) (base) 76 77#define SAVE_U_PCB_FPREG(reg, offs, base) \ 78 FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 79 80#define RESTORE_U_PCB_FPREG(reg, offs, base) \ 81 FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 82 83#define SAVE_U_PCB_FPSR(reg, offs, base) \ 84 REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 85 86#define RESTORE_U_PCB_FPSR(reg, offs, base) \ 87 REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base) 88 89#define SAVE_U_PCB_CONTEXT(reg, offs, base) \ 90 REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base) 91 92#define RESTORE_U_PCB_CONTEXT(reg, offs, base) \ 93 REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base) 94 95 96/* 97 * Setup for and return to user. 98 */ 99LEAF(fork_trampoline) 100 move a0,s0 101 move a1,s1 102 jal _C_LABEL(fork_exit) 103 move a2,s2 #BDSlot 104 105 DO_AST 106 107 mfc0 v0, MIPS_COP_0_STATUS 108 and v0, ~(MIPS_SR_INT_IE) 109 mtc0 v0, MIPS_COP_0_STATUS # disable interrupts 110 COP0_SYNC 111/* 112 * The use of k1 for storing the PCB pointer must be done only 113 * after interrupts are disabled. Otherwise it will get overwritten 114 * by the interrupt code. 115 */ 116 .set noat 117 GET_CPU_PCPU(k1) 118 PTR_L k1, PC_CURPCB(k1) 119 120 RESTORE_U_PCB_REG(t0, MULLO, k1) 121 RESTORE_U_PCB_REG(t1, MULHI, k1) 122 mtlo t0 123 mthi t1 124 RESTORE_U_PCB_REG(a0, PC, k1) 125 RESTORE_U_PCB_REG(AT, AST, k1) 126 RESTORE_U_PCB_REG(v0, V0, k1) 127 MTC0 a0, MIPS_COP_0_EXC_PC # set return address 128 129 RESTORE_U_PCB_REG(v1, V1, k1) 130 RESTORE_U_PCB_REG(a0, A0, k1) 131 RESTORE_U_PCB_REG(a1, A1, k1) 132 RESTORE_U_PCB_REG(a2, A2, k1) 133 RESTORE_U_PCB_REG(a3, A3, k1) 134 RESTORE_U_PCB_REG(t0, T0, k1) 135 RESTORE_U_PCB_REG(t1, T1, k1) 136 RESTORE_U_PCB_REG(t2, T2, k1) 137 RESTORE_U_PCB_REG(t3, T3, k1) 138 RESTORE_U_PCB_REG(ta0, TA0, k1) 139 RESTORE_U_PCB_REG(ta1, TA1, k1) 140 RESTORE_U_PCB_REG(ta2, TA2, k1) 141 RESTORE_U_PCB_REG(ta3, TA3, k1) 142 RESTORE_U_PCB_REG(s0, S0, k1) 143 RESTORE_U_PCB_REG(s1, S1, k1) 144 RESTORE_U_PCB_REG(s2, S2, k1) 145 RESTORE_U_PCB_REG(s3, S3, k1) 146 RESTORE_U_PCB_REG(s4, S4, k1) 147 RESTORE_U_PCB_REG(s5, S5, k1) 148 RESTORE_U_PCB_REG(s6, S6, k1) 149 RESTORE_U_PCB_REG(s7, S7, k1) 150 RESTORE_U_PCB_REG(t8, T8, k1) 151 RESTORE_U_PCB_REG(t9, T9, k1) 152 RESTORE_U_PCB_REG(k0, SR, k1) 153 RESTORE_U_PCB_REG(gp, GP, k1) 154 RESTORE_U_PCB_REG(s8, S8, k1) 155 RESTORE_U_PCB_REG(ra, RA, k1) 156 RESTORE_U_PCB_REG(sp, SP, k1) 157 li k1, ~MIPS_SR_INT_MASK 158 and k0, k0, k1 159 mfc0 k1, MIPS_COP_0_STATUS 160 and k1, k1, MIPS_SR_INT_MASK 161 or k0, k0, k1 162 mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...) 163 HAZARD_DELAY 164 sync 165 eret 166 .set at 167END(fork_trampoline) 168 169/* 170 * Update pcb, saving current processor state. 171 * Note: this only works if pcbp != curproc's pcb since 172 * cpu_switch() will copy over pcb_context. 173 * 174 * savectx(struct pcb *pcbp); 175 */ 176LEAF(savectx) 177 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) 178 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 179 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 180 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 181 mfc0 v0, MIPS_COP_0_STATUS 182 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 183 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 184 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 185 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 186 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) 187 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 188 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) 189 SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0) 190 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 191 192 move v0, ra /* save 'ra' before we trash it */ 193 jal 1f 194 nop 1951: 196 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) 197 move ra, v0 /* restore 'ra' before returning */ 198 199 j ra 200 move v0, zero 201END(savectx) 202 203NON_LEAF(cpu_throw, CALLFRAME_SIZ, ra) 204 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register 205 nop 206 nop 207 and a3, t0, ~(MIPS_SR_INT_IE) 208 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts 209 ITLBNOPFIX 210 j mips_sw1 # We're not interested in old 211 # thread's context, so jump 212 # right to action 213 nop # BDSLOT 214END(cpu_throw) 215 216/* 217 * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx); 218 * a0 - old 219 * a1 - new 220 * a2 - mtx 221 * Find the highest priority process and resume it. 222 */ 223NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra) 224 mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register 225 nop 226 nop 227 and a3, t0, ~(MIPS_SR_INT_IE) 228 mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts 229 ITLBNOPFIX 230 beqz a0, mips_sw1 231 move a3, a0 232 PTR_L a0, TD_PCB(a0) # load PCB addr of curproc 233 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp 234 PTR_SUBU sp, sp, CALLFRAME_SIZ 235 REG_S ra, CALLFRAME_RA(sp) 236 .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ) 237 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()' 238 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 239 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 240 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 241 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 242 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 243 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 244 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 245 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 246 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address 247 SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register 248 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 249 jal getpc 250 nop 251getpc: 252 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) # save return address 253 254#ifdef CPU_CNMIPS 255 256 lw t2, TD_MDFLAGS(a3) # get md_flags 257 and t1, t2, MDTD_COP2USED 258 beqz t1, cop2_untouched 259 nop 260 261 /* Clear cop2used flag */ 262 and t2, t2, ~MDTD_COP2USED 263 sw t2, TD_MDFLAGS(a3) 264 265 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit 266 SAVE_U_PCB_CONTEXT(t2, PREG_SR, a0) # save status register 267 268 RESTORE_U_PCB_REG(t0, PS, a0) # get CPU status register 269 and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit 270 SAVE_U_PCB_REG(t2, PS, a0) # save stratus register 271 272 /* preserve a0..a3 */ 273 move s0, a0 274 move s1, a1 275 move s2, a2 276 move s3, a3 277 278 /* does kernel own COP2 context? */ 279 lw t1, TD_COP2OWNER(a3) # get md_cop2owner 280 beqz t1, userland_cop2 # 0 - it's userland context 281 nop 282 283 PTR_L a0, TD_COP2(a3) 284 beqz a0, no_cop2_context 285 nop 286 287 j do_cop2_save 288 nop 289 290userland_cop2: 291 292 PTR_L a0, TD_UCOP2(a3) 293 beqz a0, no_cop2_context 294 nop 295 296do_cop2_save: 297 jal octeon_cop2_save 298 nop 299 300no_cop2_context: 301 move a3, s3 302 move a2, s2 303 move a1, s1 304 move a0, s0 305 306cop2_untouched: 307#endif 308 309 PTR_S a2, TD_LOCK(a3) # Switchout td_lock 310 311mips_sw1: 312#if defined(SMP) && defined(SCHED_ULE) 313 PTR_LA t0, _C_LABEL(blocked_lock) 314blocked_loop: 315 PTR_L t1, TD_LOCK(a1) 316 beq t0, t1, blocked_loop 317 nop 318#endif 319 move s7, a1 # Store newthread 320/* 321 * Switch to new context. 322 */ 323 GET_CPU_PCPU(a3) 324 PTR_S a1, PC_CURTHREAD(a3) 325 PTR_L a2, TD_PCB(a1) 326 PTR_S a2, PC_CURPCB(a3) 327 PTR_L v0, TD_KSTACK(a1) 328#if defined(__mips_n64) 329 PTR_LI s0, MIPS_XKSEG_START 330#else 331 PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2, 332#endif 333 bltu v0, s0, sw2 # no need to insert in TLB. 334 PTE_L a1, TD_UPTE + 0(s7) # a1 = u. pte #0 335 PTE_L a2, TD_UPTE + PTESIZE(s7) # a2 = u. pte #1 336/* 337 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target 338 * USPACE is already in another place of TLB before that, and if so 339 * invalidate that TLB entry. 340 * NOTE: This is hard coded to UPAGES == 2. 341 * Also, there should be no TLB faults at this point. 342 */ 343 MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va 344 HAZARD_DELAY 345 tlbp # probe VPN 346 HAZARD_DELAY 347 mfc0 s0, MIPS_COP_0_TLB_INDEX 348 HAZARD_DELAY 349 350 PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry 351 bltz s0, entry0set 352 nop 353 sll s0, PAGE_SHIFT + 1 354 addu t1, s0 355 MTC0 t1, MIPS_COP_0_TLB_HI 356 PTE_MTC0 zero, MIPS_COP_0_TLB_LO0 357 PTE_MTC0 zero, MIPS_COP_0_TLB_LO1 358 HAZARD_DELAY 359 tlbwi 360 HAZARD_DELAY 361 MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again 362 363entry0set: 364/* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */ 365 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0 366 HAZARD_DELAY 367 PTE_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0] 368 HAZARD_DELAY 369 PTE_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1] 370 HAZARD_DELAY 371 tlbwi # set TLB entry #0 372 HAZARD_DELAY 373/* 374 * Now running on new u struct. 375 */ 376sw2: 377 PTR_L s0, TD_PCB(s7) 378 RESTORE_U_PCB_CONTEXT(sp, PREG_SP, s0) 379 PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer 380 jalr t1 # s7 = new proc pointer 381 move a0, s7 # BDSLOT 382/* 383 * Restore registers and return. 384 */ 385 move a0, s0 386 RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0) 387 RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context 388 RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0) 389 RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0) 390 RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0) 391 RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0) 392 RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0) 393 RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0) 394 RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0) 395 RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0) 396 RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0) 397 RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0) 398 399 mfc0 t0, MIPS_COP_0_STATUS 400 and t0, t0, MIPS_SR_INT_MASK 401 and v0, v0, ~MIPS_SR_INT_MASK 402 or v0, v0, t0 403 mtc0 v0, MIPS_COP_0_STATUS 404 ITLBNOPFIX 405 406 j ra 407 nop 408END(cpu_switch) 409 410/*---------------------------------------------------------------------------- 411 * 412 * MipsSwitchFPState -- 413 * 414 * Save the current state into 'from' and restore it from 'to'. 415 * 416 * MipsSwitchFPState(from, to) 417 * struct thread *from; 418 * struct trapframe *to; 419 * 420 * Results: 421 * None. 422 * 423 * Side effects: 424 * None. 425 * 426 *---------------------------------------------------------------------------- 427 */ 428LEAF(MipsSwitchFPState) 429 mfc0 t1, MIPS_COP_0_STATUS # Save old SR 430 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor 431 mtc0 t0, MIPS_COP_0_STATUS 432 ITLBNOPFIX 433 434 beq a0, zero, 1f # skip save if NULL pointer 435 nop 436/* 437 * First read out the status register to make sure that all FP operations 438 * have completed. 439 */ 440 PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc 441 cfc1 t0, MIPS_FPU_CSR # stall til FP done 442 cfc1 t0, MIPS_FPU_CSR # now get status 443 li t3, ~MIPS_SR_COP_1_BIT 444 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 445 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 446 and t2, t2, t3 # clear COP_1 enable bit 447 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 448/* 449 * Save the floating point registers. 450 */ 451 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 452 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 453 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 454 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 455 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 456 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 457 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 458 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 459 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 460 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 461 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 462 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 463 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 464 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 465 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 466 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 467 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 468 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 469 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 470 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 471 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 472 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 473 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 474 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 475 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 476 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 477 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 478 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 479 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 480 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 481 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 482 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 483 4841: 485/* 486 * Restore the floating point registers. 487 */ 488 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register 489 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1) 490 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1) 491 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1) 492 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1) 493 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1) 494 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1) 495 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1) 496 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1) 497 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1) 498 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1) 499 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1) 500 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1) 501 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1) 502 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1) 503 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1) 504 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1) 505 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1) 506 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1) 507 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1) 508 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1) 509 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1) 510 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1) 511 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1) 512 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1) 513 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1) 514 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1) 515 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1) 516 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1) 517 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1) 518 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1) 519 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1) 520 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1) 521 522 and t0, t0, ~MIPS_FPU_EXCEPTION_BITS 523 ctc1 t0, MIPS_FPU_CSR 524 nop 525 526 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register. 527 ITLBNOPFIX 528 j ra 529 nop 530END(MipsSwitchFPState) 531 532/*---------------------------------------------------------------------------- 533 * 534 * MipsSaveCurFPState -- 535 * 536 * Save the current floating point coprocessor state. 537 * 538 * MipsSaveCurFPState(td) 539 * struct thread *td; 540 * 541 * Results: 542 * None. 543 * 544 * Side effects: 545 * machFPCurProcPtr is cleared. 546 * 547 *---------------------------------------------------------------------------- 548 */ 549LEAF(MipsSaveCurFPState) 550 PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread 551 mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and 552 li t0, MIPS_SR_COP_1_BIT # enable the coprocessor 553 mtc0 t0, MIPS_COP_0_STATUS 554 ITLBNOPFIX 555 GET_CPU_PCPU(a1) 556 PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved 557/* 558 * First read out the status register to make sure that all FP operations 559 * have completed. 560 */ 561 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 562 li t3, ~MIPS_SR_COP_1_BIT 563 and t2, t2, t3 # clear COP_1 enable bit 564 cfc1 t0, MIPS_FPU_CSR # stall til FP done 565 cfc1 t0, MIPS_FPU_CSR # now get status 566 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 567 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 568/* 569 * Save the floating point registers. 570 */ 571 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 572 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 573 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 574 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 575 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 576 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 577 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 578 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 579 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 580 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 581 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 582 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 583 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 584 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 585 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 586 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 587 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 588 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 589 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 590 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 591 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 592 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 593 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 594 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 595 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 596 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 597 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 598 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 599 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 600 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 601 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 602 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 603 604 mtc0 t1, MIPS_COP_0_STATUS # Restore the status register. 605 ITLBNOPFIX 606 j ra 607 nop 608END(MipsSaveCurFPState) 609 610/* 611 * When starting init, call this to configure the process for user 612 * mode. This will be inherited by other processes. 613 */ 614LEAF_NOPROFILE(prepare_usermode) 615 j ra 616 nop 617END(prepare_usermode) 618 619 620/* 621 * This code is copied the user's stack for returning from signal handlers 622 * (see sendsig() and sigreturn()). We have to compute the address 623 * of the sigcontext struct for the sigreturn call. 624 */ 625 .globl _C_LABEL(sigcode) 626_C_LABEL(sigcode): 627 PTR_ADDU a0, sp, SIGF_UC # address of ucontext 628 li v0, SYS_sigreturn 629# sigreturn (ucp) 630 syscall 631 break 0 # just in case sigreturn fails 632 .globl _C_LABEL(esigcode) 633_C_LABEL(esigcode): 634 635 .data 636 .globl szsigcode 637szsigcode: 638 .long esigcode-sigcode 639 .text 640 641#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32) 642 .globl _C_LABEL(sigcode32) 643_C_LABEL(sigcode32): 644 addu a0, sp, SIGF32_UC # address of ucontext 645 li v0, SYS_sigreturn 646# sigreturn (ucp) 647 syscall 648 break 0 # just in case sigreturn fails 649 .globl _C_LABEL(esigcode32) 650_C_LABEL(esigcode32): 651 652 .data 653 .globl szsigcode32 654szsigcode32: 655 .long esigcode32-sigcode32 656 .text 657#endif 658