locore_mips3.S revision 1.46
1/* $NetBSD: locore_mips3.S,v 1.46 2000/09/06 06:33:42 jeffs Exp $ */ 2 3/* 4 * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jonathan R. Stone for 18 * the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35/* 36 * Copyright (c) 1992, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * Digital Equipment Corporation and Ralph Campbell. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * Copyright (C) 1989 Digital Equipment Corporation. 71 * Permission to use, copy, modify, and distribute this software and 72 * its documentation for any purpose and without fee is hereby granted, 73 * provided that the above copyright notice appears in all copies. 74 * Digital Equipment Corporation makes no representations about the 75 * suitability of this software for any purpose. It is provided "as is" 76 * without express or implied warranty. 77 * 78 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 79 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 80 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 81 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 82 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 83 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 84 * 85 * @(#)locore.s 8.5 (Berkeley) 1/4/94 86 */ 87#include "opt_cputype.h" 88#include "opt_ddb.h" 89 90#include <sys/cdefs.h> 91 92#include <mips/asm.h> 93#include <mips/cpuregs.h> 94#include <machine/param.h> 95#include <machine/endian.h> 96 97#include "assym.h" 98 99/* 100 * XXX We need a cleaner way of handling the instruction hazards of 101 * the various processors. Here are the relevant rules for the QED 52XX: 102 * tlbw[ri] -- two integer ops beforehand 103 * tlbr -- two integer ops beforehand 104 * tlbp -- two integer ops beforehand 105 * mtc0 [PageMask,EntryHi,Cp0] -- two integer ops afterwards 106 * changing JTLB -- two integer ops afterwards 107 * mtc0 [EPC,ErrorEPC,Status] -- two int ops afterwards before eret 108 * config.k0 -- five int ops before kseg0, ckseg0 memref 109 * 110 * For the IDT R4000, some hazards are: 111 * mtc0/mfc0 one integer op before and after 112 * tlbp -- one integer op afterwards 113 * Obvious solution is to take least common denominator. 114 */ 115 116/* 117 * XXX mips/include 118 */ 119#define C_IINV_I 0x00 120#define C_IWBINV_D 0x01 121#define C_IINV_SI 0x02 122#define C_IWBINV_SD 0x03 123 124#define C_ILDTAG_I 0x04 125#define C_ILDTAG_D 0x05 126#define C_ILDTAG_SI 0x06 127#define C_ILDTAG_SD 0x07 128 129#define C_HINV_I 0x10 130#define C_HINV_D 0x11 131#define C_HINV_SI 0x12 132#define C_HINV_SD 0x13 133 134#define C_HWBINV_D 0x15 135#define C_HWBINV_SD 0x17 136 137#define C_HSETV_SI 0x1e 138#define C_HSETV_SD 0x1f 139 140/* 141 *============================================================================ 142 * 143 * MIPS III ISA support, part 1: locore exception vectors. 144 * The following code is copied to the vector locations to which 145 * the CPU jumps in response to an exception or a TLB miss. 146 * 147 *============================================================================ 148 */ 149 .set noreorder 150 .set mips3 151 .text 152 153/* 154 *---------------------------------------------------------------------------- 155 * 156 * mips3_TLBMiss -- 157 * 158 * Vector code for the TLB-miss exception vector 0x80000000 159 * on an r4000. 160 * 161 * This code is copied to the TLB exception vector address to 162 * handle TLB translation misses. 163 * NOTE: This code should be relocatable and max 32 instructions!!! 164 * 165 * Don't check for invalid pte's here. We load them as well and 166 * let the processor trap to load the correct value after service. 167 * 168 * NOTE: This relies on a non-standard use of the XContext register. The 169 * upper 32 bits of the XContext register is loaded with the 32-bit address 170 * of the user PT segment table. This eliminatees the need to load the 171 * address of the segment table from memory on each miss. 172 * Also, the BadVAddr register contains the virtual address that caused the 173 * TLBmiss - the 32-bit address is signed extended to 64 bits in the BadVAddr 174 * register, so the upper 32 bits will be the same as bit 31 of the virtual 175 * address and is used to check for a user or kernel address. 176 * 177 *---------------------------------------------------------------------------- 178 */ 179VECTOR(mips3_TLBMiss, unknown) 180 .set noat 181 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 182 dmfc0 k1, MIPS_COP_0_TLB_XCONTEXT 183 bltz k0, 4f # Kernel address (KSEG) if bit 31 set 184 srl k0, k0, SEGSHIFT - 2 # compute segment table index 185 and k0, k0, 0x7fc # index of segment table 186 dsra k1, k1, 32 # Tricky -- The lower bit is 187 # actually part of KSU but we must 188 # be a user address 189 add k1, k0, k1 190 lw k1, 0(k1) 191 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 192 beq k1, zero, 5f # invalid segment map 193 srl k0, k0, PGSHIFT - 2 # compute segment map index 194 and k0, k0, ((NPTEPG/2) - 1) << 3 195 addu k1, k1, k0 # index into segment map 196 ld k0, 0(k1) # load both 32 bit pte's at once 1973: dsll k1, k0, 34 # Clear soft wired, ro bits 198 dsrl k1, k1, 34 199#if BYTE_ORDER == BIG_ENDIAN 200 dmtc0 k1, MIPS_COP_0_TLB_LO1 201 dsll k0, k0, 2 202 dsrl k0, k0, 34 203 dmtc0 k0, MIPS_COP_0_TLB_LO0 204#else 205 dmtc0 k1, MIPS_COP_0_TLB_LO0 206 dsll k0, k0, 2 207 dsrl k0, k0, 34 208 dmtc0 k0, MIPS_COP_0_TLB_LO1 209#endif 210 nop 211 nop # required for QED5230 212 tlbwr # update TLB 213 nop 214 eret 2154: 216 j _C_LABEL(mips3_TLBMissException) 217 nop 2185: 219 j mips3_SlowFault 220 nop 221VECTOR_END(mips3_TLBMiss) 222 223/* 224 * mips3_XTLBMiss routine 225 * 226 * Vector code for the TLB-miss exception vector 0x80000080 on an r4000. 227 * 228 * This code is copied to the XTLB exception vector address to 229 * handle TLB translation misses while in 64-bit mode. 230 * NOTE: This code should be relocatable and max 32 instructions!!! 231 * 232 * Note that we do not support the full size of the PTEs, relying 233 * on appropriate truncation/sign extension. 234 * 235 * Don't check for invalid pte's here. We load them as well and 236 * let the processor trap to load the correct value after service. 237 * 238 * NOTE: This also relies on a non-standard use of the XContext register. The 239 * upper 32 bits of the XContext register is loaded with the 32-bit address 240 * of the user PT segment table. This eliminatees the need to load the 241 * address of the segment table from memory on each miss. The 32-bit address 242 * is shifted to form the 64-bit address, and will be a KSEG0 compatibility 243 * mode address (tricky!). 244 * Bit 63 in the BadVAddr register will be 0 for a user address, 1 for 245 * a kernel address. 246 */ 247VECTOR(mips3_XTLBMiss, unknown) 248 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 249 dmfc0 k1, MIPS_COP_0_TLB_XCONTEXT 250 bltz k0, 4f # Kernel address if bit 63 set. 251 srl k0, k0, SEGSHIFT - 2 # compute segment table index 252 and k0, k0, 0x7fc # index of segment table 253 dsra k1, k1, 32 # Tricky -- The lower bit is 254 # actually part of KSU but we must 255 # be a user address 256 add k1, k0, k1 257 lw k1, 0(k1) 258 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 259 beq k1, zero, 5f # invalid segment map 260 srl k0, k0, PGSHIFT - 2 # compute segment map index 261 and k0, k0, ((NPTEPG/2) - 1) << 3 262 addu k1, k1, k0 # index into segment map 263 ld k0, 0(k1) # load both 32 bit pte's at once 2643: dsll k1, k0, 34 # Clear soft wired, ro bits 265 dsrl k1, k1, 34 266#if BYTE_ORDER == _BIG_ENDIAN 267 dmtc0 k1, MIPS_COP_0_TLB_LO1 268 dsll k0, k0, 2 269 dsrl k0, k0, 34 270 dmtc0 k0, MIPS_COP_0_TLB_LO0 271#else 272 dmtc0 k1, MIPS_COP_0_TLB_LO0 273 dsll k0, k0, 2 274 dsrl k0, k0, 34 275 dmtc0 k0, MIPS_COP_0_TLB_LO1 276#endif 277 nop 278 nop # required for QED5230 279 tlbwr # update TLB 280 nop 281 eret 2824: 283 j mips3_TLBMissException 284 nop 2855: 286 j mips3_SlowFault 287 nop 288VECTOR_END(mips3_XTLBMiss) 289 290 .set at 291 292/* 293 *---------------------------------------------------------------------------- 294 * 295 * mips3_exception -- 296 * 297 * Vector code for the general exception vector 0x80000180 298 * on an r4000 or r4400. 299 * 300 * This code is copied to the general exception vector address to 301 * handle all exceptions except RESET and TLBMiss. 302 * NOTE: This code must be relocatable!!! 303 *---------------------------------------------------------------------------- 304 */ 305VECTOR(mips3_exception, unknown) 306/* 307 * Find out what mode we came from and jump to the proper handler. 308 */ 309 .set noat 310 mfc0 k0, MIPS_COP_0_STATUS # get the status register 311 mfc0 k1, MIPS_COP_0_CAUSE # get the cause register 312 and k0, k0, MIPS3_SR_KSU_USER # test for user mode 313 # sneaky but the bits are 314 # with us........ 315 sll k0, k0, 3 # shift user bit for cause index 316 and k1, k1, MIPS3_CR_EXC_CODE # mask out the cause bits. 317 or k1, k1, k0 # change index to user table 3181: 319 la k0, _C_LABEL(mips3_excpt_sw) # get base of the jump table 320 addu k0, k0, k1 # get the address of the 321 # function entry. Note that 322 # the cause is already 323 # shifted left by 2 bits so 324 # we dont have to shift. 325 lw k0, 0(k0) # get the function address 326 #nop # -slip- 327 j k0 # jump to the function 328 nop 329 .set at 330VECTOR_END(mips3_exception) 331 332 333/*---------------------------------------------------------------------------- 334 * 335 * mips3_SlowFault -- 336 * 337 * Alternate entry point into the mips3_UserGenException or 338 * or mips3_user_Kern_exception, when the ULTB miss handler couldn't 339 * find a TLB entry. 340 * 341 * Find out what mode we came from and call the appropriate handler. 342 * 343 *---------------------------------------------------------------------------- 344 */ 345 346/* 347 * We couldn't find a TLB entry. 348 * Find out what mode we came from and call the appropriate handler. 349 */ 350mips3_SlowFault: 351 .set noat 352 mfc0 k0, MIPS_COP_0_STATUS 353 nop 354 and k0, k0, MIPS3_SR_KSU_USER 355 bne k0, zero, _C_LABEL(mips3_UserGenException) 356 nop 357 .set at 358/* 359 * Fall though ... 360 */ 361 362/* 363 * mips3_KernGenException 364 * 365 * Handle an exception from kernel mode. 366 * Build trapframe on stack to hold interrupted kernel context, then 367 * call trap() to process the condition. 368 * 369 * trapframe is pointed to by the 5th arg 370 * and a dummy sixth argument is used to avoid alignment problems 371 * { 372 * register_t cf_args[4 + 1]; 373 * register_t cf_pad; (for 8 word alignment) 374 * register_t cf_sp; 375 * register_t cf_ra; 376 * mips_reg_t kf_regs[17]; - trapframe begins here 377 * mips_reg_t kf_sr; - 378 * mips_reg_t kf_mullo; - 379 * mips_reg_t kf_mulhi; - 380 * mips_reg_t kf_epc; - may be changed by trap() call 381 * }; 382 */ 383NESTED_NOPROFILE(mips3_KernGenException, KERNFRAME_SIZ, ra) 384 .set noat 385 .mask 0x80000000, -4 386#if defined(DDB) || defined(KGDB) 387 la k0, _C_LABEL(kdbaux) 388 REG_S s0, SF_REG_S0(k0) 389 REG_S s1, SF_REG_S1(k0) 390 REG_S s2, SF_REG_S2(k0) 391 REG_S s3, SF_REG_S3(k0) 392 REG_S s4, SF_REG_S4(k0) 393 REG_S s5, SF_REG_S5(k0) 394 REG_S s6, SF_REG_S6(k0) 395 REG_S s7, SF_REG_S7(k0) 396 REG_S sp, SF_REG_SP(k0) 397 REG_S s8, SF_REG_S8(k0) 398 REG_S gp, SF_REG_RA(k0) 399#endif 400/* 401 * Save the relevant kernel registers onto the stack. 402 * We don't need to save s0 - s8, sp and gp because 403 * the compiler does it for us. 404 */ 405 subu sp, sp, KERNFRAME_SIZ 406 REG_S AT, TF_BASE+TF_REG_AST(sp) 407 REG_S v0, TF_BASE+TF_REG_V0(sp) 408 REG_S v1, TF_BASE+TF_REG_V1(sp) 409 mflo v0 410 mfhi v1 411 REG_S a0, TF_BASE+TF_REG_A0(sp) 412 REG_S a1, TF_BASE+TF_REG_A1(sp) 413 REG_S a2, TF_BASE+TF_REG_A2(sp) 414 REG_S a3, TF_BASE+TF_REG_A3(sp) 415 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 416 REG_S t0, TF_BASE+TF_REG_T0(sp) 417 REG_S t1, TF_BASE+TF_REG_T1(sp) 418 REG_S t2, TF_BASE+TF_REG_T2(sp) 419 REG_S t3, TF_BASE+TF_REG_T3(sp) 420 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 421 REG_S t4, TF_BASE+TF_REG_T4(sp) 422 REG_S t5, TF_BASE+TF_REG_T5(sp) 423 REG_S t6, TF_BASE+TF_REG_T6(sp) 424 REG_S t7, TF_BASE+TF_REG_T7(sp) 425 mfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address 426 REG_S t8, TF_BASE+TF_REG_T8(sp) 427 REG_S t9, TF_BASE+TF_REG_T9(sp) 428 REG_S ra, TF_BASE+TF_REG_RA(sp) 429 REG_S a0, TF_BASE+TF_REG_SR(sp) 430 mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC 431 REG_S v0, TF_BASE+TF_REG_MULLO(sp) 432 REG_S v1, TF_BASE+TF_REG_MULHI(sp) 433 REG_S a3, TF_BASE+TF_REG_EPC(sp) 434 addu v0, sp, TF_BASE 435 sw v0, KERNFRAME_ARG5(sp) # 5th arg is p. to trapframe 436/* 437 * Call the trap handler. 438 */ 439#if defined(DDB) || defined(DEBUG) || defined(KGDB) 440 addu v0, sp, KERNFRAME_SIZ 441 sw v0, KERNFRAME_SP(sp) 442#endif 443 mtc0 zero, MIPS_COP_0_STATUS # Set kernel no error level 444 nop 445 nop 446 nop 447 jal _C_LABEL(trap) # 448 sw a3, KERNFRAME_RA(sp) # for debugging 449 450/* 451 * Restore registers and return from the exception. 452 */ 453 mtc0 zero, MIPS_COP_0_STATUS # Make sure int disabled 454 nop # 3 nop delay 455 nop 456 nop 457 REG_L a0, TF_BASE+TF_REG_SR(sp) # ??? why differs ??? 458 REG_L t0, TF_BASE+TF_REG_MULLO(sp) 459 REG_L t1, TF_BASE+TF_REG_MULHI(sp) 460 REG_L k0, TF_BASE+TF_REG_EPC(sp) # might be changed inside trap 461 mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs 462 mtlo t0 463 mthi t1 464 dmtc0 k0, MIPS_COP_0_EXC_PC # set return address 465 REG_L AT, TF_BASE+TF_REG_AST(sp) 466 REG_L v0, TF_BASE+TF_REG_V0(sp) 467 REG_L v1, TF_BASE+TF_REG_V1(sp) 468 REG_L a0, TF_BASE+TF_REG_A0(sp) 469 REG_L a1, TF_BASE+TF_REG_A1(sp) 470 REG_L a2, TF_BASE+TF_REG_A2(sp) 471 REG_L a3, TF_BASE+TF_REG_A3(sp) 472 REG_L t0, TF_BASE+TF_REG_T0(sp) 473 REG_L t1, TF_BASE+TF_REG_T1(sp) 474 REG_L t2, TF_BASE+TF_REG_T2(sp) 475 REG_L t3, TF_BASE+TF_REG_T3(sp) 476 REG_L t4, TF_BASE+TF_REG_T4(sp) 477 REG_L t5, TF_BASE+TF_REG_T5(sp) 478 REG_L t6, TF_BASE+TF_REG_T6(sp) 479 REG_L t7, TF_BASE+TF_REG_T7(sp) 480 REG_L t8, TF_BASE+TF_REG_T8(sp) 481 REG_L t9, TF_BASE+TF_REG_T9(sp) 482 REG_L ra, TF_BASE+TF_REG_RA(sp) 483 addu sp, sp, KERNFRAME_SIZ 484#ifdef DDBnotyet 485 la k0, _C_LABEL(kdbaux) 486 REG_L s0, SF_REG_S0(k0) 487 REG_L s1, SF_REG_S1(k0) 488 REG_L s2, SF_REG_S2(k0) 489 REG_L s3, SF_REG_S3(k0) 490 REG_L s4, SF_REG_S4(k0) 491 REG_L s5, SF_REG_S5(k0) 492 REG_L s6, SF_REG_S6(k0) 493 REG_L s7, SF_REG_S7(k0) 494 REG_L sp, SF_REG_SP(k0) 495 REG_L s8, SF_REG_S8(k0) 496 REG_L gp, SF_REG_RA(k0) 497#endif 498 eret # return to interrupted point 499 .set at 500END(mips3_KernGenException) 501 502/* 503 * mips3_UserGenException 504 * 505 * Handle an exception from user mode. 506 * Save user context atop the kernel stack, then call trap() to process 507 * the condition. The context can be manipulated alternatively via 508 * curproc->p_md.md_regs. 509 */ 510NESTED_NOPROFILE(mips3_UserGenException, CALLFRAME_SIZ, ra) 511 .set noat 512 .mask 0x80000000, -4 513/* 514 * Save all of the registers except for the kernel temporaries in u_pcb. 515 */ 516 lw k1, _C_LABEL(curpcb) 517 #nop # -slip- 518 addu k1, k1, USPACE - FRAME_SIZ 519 REG_S AT, FRAME_AST(k1) 520 REG_S v0, FRAME_V0(k1) 521 REG_S v1, FRAME_V1(k1) 522 mflo v0 523 REG_S a0, FRAME_A0(k1) 524 REG_S a1, FRAME_A1(k1) 525 REG_S a2, FRAME_A2(k1) 526 REG_S a3, FRAME_A3(k1) 527 mfhi v1 528 REG_S t0, FRAME_T0(k1) 529 REG_S t1, FRAME_T1(k1) 530 REG_S t2, FRAME_T2(k1) 531 REG_S t3, FRAME_T3(k1) 532 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 533 REG_S t4, FRAME_T4(k1) 534 REG_S t5, FRAME_T5(k1) 535 REG_S t6, FRAME_T6(k1) 536 REG_S t7, FRAME_T7(k1) 537 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 538 REG_S s0, FRAME_S0(k1) 539 REG_S s1, FRAME_S1(k1) 540 REG_S s2, FRAME_S2(k1) 541 REG_S s3, FRAME_S3(k1) 542 dmfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address 543 REG_S s4, FRAME_S4(k1) 544 REG_S s5, FRAME_S5(k1) 545 REG_S s6, FRAME_S6(k1) 546 REG_S s7, FRAME_S7(k1) 547 dmfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC 548 REG_S t8, FRAME_T8(k1) 549 REG_S t9, FRAME_T9(k1) 550 REG_S gp, FRAME_GP(k1) 551 REG_S sp, FRAME_SP(k1) 552 REG_S s8, FRAME_S8(k1) 553 REG_S ra, FRAME_RA(k1) 554 REG_S a0, FRAME_SR(k1) 555 REG_S v0, FRAME_MULLO(k1) 556 REG_S v1, FRAME_MULHI(k1) 557 REG_S a3, FRAME_EPC(k1) 558 addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP 559#ifdef __GP_SUPPORT__ 560 la gp, _C_LABEL(_gp) # switch to kernel GP 561#endif 562/* 563 * Turn off fpu and enter kernel mode 564 */ 565 .set at 566 and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE) 567 .set noat 568/* 569 * Call the trap handler. 570 */ 571 mtc0 t0, MIPS_COP_0_STATUS 572 jal _C_LABEL(trap) 573 sw a3, CALLFRAME_SIZ-4(sp) # for debugging 574/* 575 * Restore user registers and return. 576 * First disable interrupts and set exception level. 577 */ 578 mtc0 zero, MIPS_COP_0_STATUS # disable interrupt 579 nop # 3 clock delay before 580 nop # exceptions blocked 581 nop # for R4X 582 li v0, MIPS_SR_EXL 583 mtc0 v0, MIPS_COP_0_STATUS # set exception level 584 nop # 3 nop delay 585 nop 586 nop 587 addu a1, sp, CALLFRAME_SIZ 588 # REG_L a0, FRAME_SR(a1) 589 REG_L t0, FRAME_MULLO(a1) 590 REG_L t1, FRAME_MULHI(a1) 591 REG_L v0, FRAME_EPC(a1) 592 # mtc0 a0, MIPS_COP_0_STATUS # still exception level 593 mtlo t0 594 mthi t1 595 dmtc0 v0, MIPS_COP_0_EXC_PC # set return address 596 597 move k1, a1 598 REG_L AT, FRAME_AST(k1) 599 REG_L v0, FRAME_V0(k1) 600 REG_L v1, FRAME_V1(k1) 601 REG_L a0, FRAME_A0(k1) 602 REG_L a1, FRAME_A1(k1) 603 REG_L a2, FRAME_A2(k1) 604 REG_L a3, FRAME_A3(k1) 605 REG_L t0, FRAME_T0(k1) 606 REG_L t1, FRAME_T1(k1) 607 REG_L t2, FRAME_T2(k1) 608 REG_L t3, FRAME_T3(k1) 609 REG_L t4, FRAME_T4(k1) 610 REG_L t5, FRAME_T5(k1) 611 REG_L t6, FRAME_T6(k1) 612 REG_L t7, FRAME_T7(k1) 613 REG_L s0, FRAME_S0(k1) 614 REG_L s1, FRAME_S1(k1) 615 REG_L s2, FRAME_S2(k1) 616 REG_L s3, FRAME_S3(k1) 617 REG_L s4, FRAME_S4(k1) 618 REG_L s5, FRAME_S5(k1) 619 REG_L s6, FRAME_S6(k1) 620 REG_L s7, FRAME_S7(k1) 621 REG_L t8, FRAME_T8(k1) 622 REG_L t9, FRAME_T9(k1) 623 REG_L k0, FRAME_SR(k1) 624 DYNAMIC_STATUS_MASK(k0,ra) # machine dependent masking 625 REG_L gp, FRAME_GP(k1) 626 REG_L sp, FRAME_SP(k1) 627 REG_L s8, FRAME_S8(k1) 628 REG_L ra, FRAME_RA(k1) 629 mtc0 k0, MIPS_COP_0_STATUS # restore status 630 nop 631 nop 632 eret # return to interrupted point 633 .set at 634END(mips3_UserGenException) 635 636/* 637 * mips3_SystemCall 638 * 639 * Save user context in u_pcb, then call syscall() to process a system call. 640 * The context can be manipulated alternatively via curproc->p_md.md_regs; 641 */ 642NESTED_NOPROFILE(mips3_SystemCall, CALLFRAME_SIZ, ra) 643 .set noat 644 .mask 0x80000000, -4 645 lw k1, _C_LABEL(curpcb) 646 #nop # -slip- 647 addu k1, k1, USPACE - FRAME_SIZ 648 REG_S AT, FRAME_AST(k1) 649 REG_S v0, FRAME_V0(k1) 650 REG_S v1, FRAME_V1(k1) 651 mflo v0 652 REG_S a0, FRAME_A0(k1) 653 REG_S a1, FRAME_A1(k1) 654 REG_S a2, FRAME_A2(k1) 655 REG_S a3, FRAME_A3(k1) 656 mfhi v1 657 REG_S t0, FRAME_T0(k1) 658 REG_S t1, FRAME_T1(k1) 659 REG_S t2, FRAME_T2(k1) 660 REG_S t3, FRAME_T3(k1) 661 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 662 REG_S t4, FRAME_T4(k1) 663 REG_S t5, FRAME_T5(k1) 664 REG_S t6, FRAME_T6(k1) 665 REG_S t7, FRAME_T7(k1) 666 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 667 REG_S s0, FRAME_S0(k1) 668 REG_S s1, FRAME_S1(k1) 669 REG_S s2, FRAME_S2(k1) 670 REG_S s3, FRAME_S3(k1) 671 mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC 672 REG_S s4, FRAME_S4(k1) 673 REG_S s5, FRAME_S5(k1) 674 REG_S s6, FRAME_S6(k1) 675 REG_S s7, FRAME_S7(k1) 676 REG_S t8, FRAME_T8(k1) 677 REG_S t9, FRAME_T9(k1) 678 REG_S gp, FRAME_GP(k1) 679 REG_S sp, FRAME_SP(k1) 680 REG_S s8, FRAME_S8(k1) 681 REG_S ra, FRAME_RA(k1) 682 REG_S a0, FRAME_SR(k1) 683 REG_S v0, FRAME_MULLO(k1) 684 REG_S v1, FRAME_MULHI(k1) 685 REG_S a2, FRAME_EPC(k1) 686 addu sp, k1, -CALLFRAME_SIZ 687#ifdef __GP_SUPPORT__ 688 la gp, _C_LABEL(_gp) # switch to kernel GP 689#endif 690/* 691 * Turn off fpu and enter kernel mode 692 */ 693 .set at 694 and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE) 695 .set noat 696#if defined(DDB) || defined(DEBUG) || defined(KGDB) 697 move ra, a2 698 sw ra, CALLFRAME_RA(sp) 699#endif 700/* 701 * Call the system call handler. 702 */ 703 mtc0 t0, MIPS_COP_0_STATUS 704 jal _C_LABEL(syscall) 705 nop 706/* 707 * Restore user registers and return. 708 * First disable interrupts and set exception level. 709 */ 710 mtc0 zero, MIPS_COP_0_STATUS # disable int 711 nop # 3 op delay 712 nop 713 nop 714 715 li v0, MIPS_SR_EXL 716 mtc0 v0, MIPS_COP_0_STATUS # set exception level 717 nop # 3 op delay 718 nop 719 nop 720/* 721 * Restore user registers and return. 722 */ 723 addu a1, sp, CALLFRAME_SIZ 724 # REG_L a0, FRAME_SR(a1) 725 REG_L t0, FRAME_MULLO(a1) 726 REG_L t1, FRAME_MULHI(a1) 727 REG_L v0, FRAME_EPC(a1) # might be changed in syscall 728 # mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts 729 mtlo t0 730 mthi t1 731 dmtc0 v0, MIPS_COP_0_EXC_PC # set return address 732 move k1, a1 733 REG_L AT, FRAME_AST(k1) 734 REG_L v0, FRAME_V0(k1) 735 REG_L v1, FRAME_V1(k1) 736 REG_L a0, FRAME_A0(k1) 737 REG_L a1, FRAME_A1(k1) 738 REG_L a2, FRAME_A2(k1) 739 REG_L a3, FRAME_A3(k1) 740 REG_L t0, FRAME_T0(k1) 741 REG_L t1, FRAME_T1(k1) 742 REG_L t2, FRAME_T2(k1) 743 REG_L t3, FRAME_T3(k1) 744 REG_L t4, FRAME_T4(k1) 745 REG_L t5, FRAME_T5(k1) 746 REG_L t6, FRAME_T6(k1) 747 REG_L t7, FRAME_T7(k1) 748 REG_L s0, FRAME_S0(k1) 749 REG_L s1, FRAME_S1(k1) 750 REG_L s2, FRAME_S2(k1) 751 REG_L s3, FRAME_S3(k1) 752 REG_L s4, FRAME_S4(k1) 753 REG_L s5, FRAME_S5(k1) 754 REG_L s6, FRAME_S6(k1) 755 REG_L s7, FRAME_S7(k1) 756 REG_L t8, FRAME_T8(k1) 757 REG_L t9, FRAME_T9(k1) 758 REG_L k0, FRAME_SR(k1) 759 DYNAMIC_STATUS_MASK(k0,ra) # machine dependent masking 760 REG_L gp, FRAME_GP(k1) 761 REG_L sp, FRAME_SP(k1) 762 REG_L s8, FRAME_S8(k1) 763 REG_L ra, FRAME_RA(k1) 764 mtc0 k0, MIPS_COP_0_STATUS 765 nop # 3 nops before eret 766 nop 767 nop 768 eret # return to syscall point 769 .set at 770END(mips3_SystemCall) 771 772/* 773 * mips3_KernIntr 774 * 775 * Handle an interrupt from kernel mode. 776 * Build intrframe on stack to hold interrupted kernel context, then 777 * call cpu_intr() to process it. 778 * 779 */ 780NESTED_NOPROFILE(mips3_KernIntr, KERNFRAME_SIZ, ra) 781 .set noat 782 .mask 0x80000000, -4 783 subu sp, sp, KERNFRAME_SIZ 784/* 785 * Save the relevant kernel registers onto the stack. 786 * We don't need to save s0 - s8, sp and gp because 787 * the compiler does it for us. 788 */ 789 REG_S AT, TF_BASE+TF_REG_AST(sp) 790 REG_S v0, TF_BASE+TF_REG_V0(sp) 791 REG_S v1, TF_BASE+TF_REG_V1(sp) 792 mflo v0 793 mfhi v1 794 REG_S a0, TF_BASE+TF_REG_A0(sp) 795 REG_S a1, TF_BASE+TF_REG_A1(sp) 796 REG_S a2, TF_BASE+TF_REG_A2(sp) 797 REG_S a3, TF_BASE+TF_REG_A3(sp) 798 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 799 REG_S t0, TF_BASE+TF_REG_T0(sp) 800 REG_S t1, TF_BASE+TF_REG_T1(sp) 801 REG_S t2, TF_BASE+TF_REG_T2(sp) 802 REG_S t3, TF_BASE+TF_REG_T3(sp) 803 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 804 REG_S t4, TF_BASE+TF_REG_T4(sp) 805 REG_S t5, TF_BASE+TF_REG_T5(sp) 806 REG_S t6, TF_BASE+TF_REG_T6(sp) 807 REG_S t7, TF_BASE+TF_REG_T7(sp) 808 mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is exception PC 809 REG_S t8, TF_BASE+TF_REG_T8(sp) 810 REG_S t9, TF_BASE+TF_REG_T9(sp) 811 REG_S ra, TF_BASE+TF_REG_RA(sp) 812 REG_S a0, TF_BASE+TF_REG_SR(sp) 813 REG_S v0, TF_BASE+TF_REG_MULLO(sp) 814 REG_S v1, TF_BASE+TF_REG_MULHI(sp) 815 REG_S a2, TF_BASE+TF_REG_EPC(sp) 816/* 817 * Call the interrupt handler. 818 */ 819#if defined(DDB) || defined(DEBUG) || defined(KGDB) 820 move ra, a2 821 sw ra, KERNFRAME_RA(sp) # for debugging 822#endif 823 mtc0 zero, MIPS_COP_0_STATUS # Reset exl, trap possible. 824 jal _C_LABEL(cpu_intr) 825 and a3, a0, a1 # 4th is STATUS & CAUSE 826/* 827 * Restore registers and return from the interrupt. 828 */ 829 mtc0 zero, MIPS_COP_0_STATUS # Disable interrupt 830 nop 831 nop 832 nop 833 REG_L a0, TF_BASE+TF_REG_SR(sp) # ??? why differs ??? 834 DYNAMIC_STATUS_MASK(a0,t0) # machine dependent masking 835 REG_L t0, TF_BASE+TF_REG_MULLO(sp) 836 REG_L t1, TF_BASE+TF_REG_MULHI(sp) 837 REG_L v0, TF_BASE+TF_REG_EPC(sp) 838 mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs 839 mtlo t0 840 mthi t1 841 dmtc0 v0, MIPS_COP_0_EXC_PC # set return address 842 843 REG_L AT, TF_BASE+TF_REG_AST(sp) 844 REG_L v0, TF_BASE+TF_REG_V0(sp) 845 REG_L v1, TF_BASE+TF_REG_V1(sp) 846 REG_L a0, TF_BASE+TF_REG_A0(sp) 847 REG_L a1, TF_BASE+TF_REG_A1(sp) 848 REG_L a2, TF_BASE+TF_REG_A2(sp) 849 REG_L a3, TF_BASE+TF_REG_A3(sp) 850 REG_L t0, TF_BASE+TF_REG_T0(sp) 851 REG_L t1, TF_BASE+TF_REG_T1(sp) 852 REG_L t2, TF_BASE+TF_REG_T2(sp) 853 REG_L t3, TF_BASE+TF_REG_T3(sp) 854 REG_L t4, TF_BASE+TF_REG_T4(sp) 855 REG_L t5, TF_BASE+TF_REG_T5(sp) 856 REG_L t6, TF_BASE+TF_REG_T6(sp) 857 REG_L t7, TF_BASE+TF_REG_T7(sp) 858 REG_L t8, TF_BASE+TF_REG_T8(sp) 859 REG_L t9, TF_BASE+TF_REG_T9(sp) 860 REG_L ra, TF_BASE+TF_REG_RA(sp) 861 addu sp, sp, KERNFRAME_SIZ # restore kernel SP 862 eret # return to interrupted point 863 .set at 864END(mips3_KernIntr) 865 866/*---------------------------------------------------------------------------- 867 * XXX this comment block should be updated XXX 868 * mips3_UserIntr -- 869 * 870 * Handle an interrupt from user mode. 871 * Note: we save minimal state in the u.u_pcb struct and use the standard 872 * kernel stack since there has to be a u page if we came from user mode. 873 * If there is a pending software interrupt, then save the remaining state 874 * and call softintr(). This is all because if we call switch() inside 875 * cpu_intr(), not all the user registers have been saved in u.u_pcb. 876 * 877 * Results: 878 * None. 879 * 880 * Side effects: 881 * None. 882 * 883 *---------------------------------------------------------------------------- 884 */ 885NESTED_NOPROFILE(mips3_UserIntr, CALLFRAME_SIZ, ra) 886 .set noat 887 .mask 0x80000000, -4 888/* 889 * Save the relevant user registers into the u_pcb. 890 * We don't need to save s0 - s8 because the compiler does it for us. 891 */ 892 lw k1, _C_LABEL(curpcb) 893 #nop # -slip- 894 addu k1, k1, USPACE - FRAME_SIZ 895 REG_S AT, FRAME_AST(k1) 896 REG_S v0, FRAME_V0(k1) 897 REG_S v1, FRAME_V1(k1) 898 mflo v0 899 REG_S a0, FRAME_A0(k1) 900 REG_S a1, FRAME_A1(k1) 901 REG_S a2, FRAME_A2(k1) 902 REG_S a3, FRAME_A3(k1) 903 mfhi v1 904 REG_S t0, FRAME_T0(k1) 905 REG_S t1, FRAME_T1(k1) 906 REG_S t2, FRAME_T2(k1) 907 REG_S t3, FRAME_T3(k1) 908 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 909 REG_S t4, FRAME_T4(k1) 910 REG_S t5, FRAME_T5(k1) 911 REG_S t6, FRAME_T6(k1) 912 REG_S t7, FRAME_T7(k1) 913 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 914 REG_S t8, FRAME_T8(k1) 915 REG_S t9, FRAME_T9(k1) 916 REG_S gp, FRAME_GP(k1) 917 REG_S sp, FRAME_SP(k1) 918 mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC 919 REG_S ra, FRAME_RA(k1) 920 REG_S a0, FRAME_SR(k1) 921 REG_S v0, FRAME_MULLO(k1) 922 REG_S v1, FRAME_MULHI(k1) 923 REG_S a2, FRAME_EPC(k1) 924 addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP 925#ifdef __GP_SUPPORT__ 926 la gp, _C_LABEL(_gp) # switch to kernel GP 927#endif 928/* 929 * Turn off fpu and enter kernel mode 930 */ 931 .set at 932 and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS_SR_KSU_MASK) 933 .set noat 934#if defined(DDB) || defined(DEBUG) || defined(KGDB) 935 move ra, a2 936 sw ra, CALLFRAME_RA(sp) 937#endif 938/* 939 * Call the interrupt handler. 940 */ 941 mtc0 t0, MIPS_COP_0_STATUS 942 jal _C_LABEL(cpu_intr) 943 and a3, a0, a1 # 4th is STATUS & CAUSE 944/* 945 * Restore registers and return from the interrupt. 946 */ 947 nop 948 mtc0 zero, MIPS_COP_0_STATUS 949 nop # 3 nop hazard 950 nop 951 nop 952 li v0, MIPS_SR_EXL 953 mtc0 v0, MIPS_COP_0_STATUS # set exception level bit. 954 nop # 3 nop hazard 955 nop 956 nop 957 addu a1, sp, CALLFRAME_SIZ 958 # REG_L a0, FRAME_SR(a1) 959 lw v0, _C_LABEL(astpending) # any pending ast? 960 nop # ??? 961 # mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs 962/* 963 * Check pending asynchronous traps. 964 */ 965 beq v0, zero, 1f # if no, skip ast processing 966 nop # -delay slot- 967/* 968 * We have pending asynchronous traps; save remaining user state in u_pcb. 969 */ 970 REG_S s0, FRAME_S0(a1) 971 REG_S s1, FRAME_S1(a1) 972 REG_S s2, FRAME_S2(a1) 973 REG_S s3, FRAME_S3(a1) 974 REG_S s4, FRAME_S4(a1) 975 REG_S s5, FRAME_S5(a1) 976 REG_S s6, FRAME_S6(a1) 977 REG_S s7, FRAME_S7(a1) 978 REG_S s8, FRAME_S8(a1) 979 980 REG_L a0, FRAME_EPC(a1) # argument is interrupted PC 981 li t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE 982 DYNAMIC_STATUS_MASK(t0,t1) # machine dependent masking 983 jal _C_LABEL(ast) 984 mtc0 t0, MIPS_COP_0_STATUS # enable interrupts (spl0) 985 986/* 987 * Restore user registers and return. NOTE: interrupts are enabled. 988 */ 989 mtc0 zero, MIPS_COP_0_STATUS 990 nop # 3 nop delay 991 nop 992 nop 993 li v0, MIPS_SR_EXL 994 mtc0 v0, MIPS_COP_0_STATUS # set exception level bit. 995 nop # 3 nop delay 996 nop 997 nop 998 999 addu a1, sp, CALLFRAME_SIZ 1000 # REG_L a0, FRAME_SR(a1) 1001 REG_L s0, FRAME_S0(a1) 1002 REG_L s1, FRAME_S1(a1) 1003 REG_L s2, FRAME_S2(a1) 1004 REG_L s3, FRAME_S3(a1) 1005 REG_L s4, FRAME_S4(a1) 1006 REG_L s5, FRAME_S5(a1) 1007 REG_L s6, FRAME_S6(a1) 1008 REG_L s7, FRAME_S7(a1) 1009 REG_L s8, FRAME_S8(a1) 1010 # mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts 1011 10121: 1013 REG_L t0, FRAME_MULLO(a1) 1014 REG_L t1, FRAME_MULHI(a1) 1015 REG_L v0, FRAME_EPC(a1) 1016 mtlo t0 1017 mthi t1 1018 dmtc0 v0, MIPS_COP_0_EXC_PC # set return address 1019 nop # ??? how much delay ??? 1020 nop 1021 1022 move k1, a1 1023 REG_L AT, FRAME_AST(k1) 1024 REG_L v0, FRAME_V0(k1) 1025 REG_L v1, FRAME_V1(k1) 1026 REG_L a0, FRAME_A0(k1) 1027 REG_L a1, FRAME_A1(k1) 1028 REG_L a2, FRAME_A2(k1) 1029 REG_L a3, FRAME_A3(k1) 1030 REG_L t0, FRAME_T0(k1) 1031 REG_L t1, FRAME_T1(k1) 1032 REG_L t2, FRAME_T2(k1) 1033 REG_L t3, FRAME_T3(k1) 1034 REG_L t4, FRAME_T4(k1) 1035 REG_L t5, FRAME_T5(k1) 1036 REG_L t6, FRAME_T6(k1) 1037 REG_L t7, FRAME_T7(k1) 1038 REG_L t8, FRAME_T8(k1) 1039 REG_L t9, FRAME_T9(k1) 1040 REG_L k0, FRAME_SR(k1) 1041 DYNAMIC_STATUS_MASK(k0,ra) # machine dependent masking 1042 REG_L gp, FRAME_GP(k1) 1043 REG_L sp, FRAME_SP(k1) 1044 REG_L ra, FRAME_RA(k1) 1045 mtc0 k0, MIPS_COP_0_STATUS # restore the SR 1046 nop # required for QED 5230 1047 nop 1048 eret # return to interrupted point 1049 .set at 1050END(mips3_UserIntr) 1051 1052 1053/*---------------------------------------------------------------------------- 1054 * 1055 * R4000 TLB exception handlers 1056 * 1057 *---------------------------------------------------------------------------- 1058 */ 1059 1060 1061/*---------------------------------------------------------------------------- 1062 * 1063 * mips3_TLBInvalidException -- 1064 * 1065 * Handle a TLB invalid exception from kernel mode in kernel space. 1066 * The BaddVAddr, Context, and EntryHi registers contain the failed 1067 * virtual address. 1068 * 1069 * The case of wired TLB entries is special. The wired TLB entries 1070 * are used to keep the u area TLB's valid. The PTE entries for these 1071 * do not have MIPS3_PG_G set; the kernel instead relies 1072 * on the switch_resume function to set these bits. 1073 * 1074 * To preserve this situation, we set PG_G bits on the "other" TLB entries 1075 * when they are wired. 1076 * 1077 * Results: 1078 * None. 1079 * 1080 * Side effects: 1081 * None. 1082 * 1083 *---------------------------------------------------------------------------- 1084 */ 1085LEAF_NOPROFILE(mips3_TLBInvalidException) 1086 .set noat 1087 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address 1088 li k1, VM_MIN_KERNEL_ADDRESS # compute index 1089 bgez k0, _C_LABEL(mips3_KernGenException) # full trap processing 1090 subu k0, k0, k1 1091 lw k1, _C_LABEL(Sysmapsize) # index within range? 1092 srl k0, k0, PGSHIFT 1093 sltu k1, k0, k1 1094 beq k1, zero, outofworld # No. Failing beyond. . . 1095 lw k1, _C_LABEL(Sysmap) 1096 1097 sll k0, k0, 2 # compute offset from index 1098 addu k1, k1, k0 1099 tlbp # Probe the invalid entry 1100 and k0, k0, 4 # check even/odd page 1101 nop # required for QED 5230 1102 bne k0, zero, KernTLBIOdd 1103 nop 1104 1105 mfc0 k0, MIPS_COP_0_TLB_INDEX 1106 nop 1107 bltz k0, outofworld # ASSERT(TLB entry exists) 1108 lw k0, 0(k1) # get PTE entry 1109 1110 dsll k0, k0, 34 # get rid of "wired" bit 1111 dsrl k0, k0, 34 1112 dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry 1113 and k0, k0, MIPS3_PG_V # check for valid entry 1114 nop # required for QED5230 1115 beq k0, zero, _C_LABEL(mips3_KernGenException) # PTE invalid 1116 lw k0, 4(k1) # get odd PTE entry 1117 dsll k0, k0, 34 1118 mfc0 k1, MIPS_COP_0_TLB_INDEX 1119 dsrl k0, k0, 34 1120 sltiu k1, k1, MIPS3_TLB_WIRED_UPAGES # Luckily this is MIPS3_PG_G 1121 or k1, k1, k0 1122 dmtc0 k0, MIPS_COP_0_TLB_LO1 # load PTE entry 1123 nop 1124 nop # required for QED5230 1125 tlbwi # write TLB 1126 nop 1127 nop 1128 nop 1129 nop 1130 nop 1131 eret 1132 1133KernTLBIOdd: 1134 mfc0 k0, MIPS_COP_0_TLB_INDEX 1135 nop 1136 bltz k0, outofworld # assert(TLB Entry exists) 1137 lw k0, 0(k1) # get PTE entry 1138 1139 dsll k0, k0, 34 # get rid of wired bit 1140 dsrl k0, k0, 34 1141 dmtc0 k0, MIPS_COP_0_TLB_LO1 # save PTE entry 1142 and k0, k0, MIPS3_PG_V # check for valid entry 1143 nop # required for QED5230 1144 beq k0, zero, _C_LABEL(mips3_KernGenException) # PTE invalid 1145 lw k0, -4(k1) # get even PTE entry 1146 dsll k0, k0, 34 1147 mfc0 k1, MIPS_COP_0_TLB_INDEX 1148 dsrl k0, k0, 34 1149 sltiu k1, k1, MIPS3_TLB_WIRED_UPAGES # Luckily this is MIPS3_PG_G 1150 or k1, k1, k0 1151 dmtc0 k0, MIPS_COP_0_TLB_LO0 # save PTE entry 1152 nop 1153 nop # required for QED5230 1154 tlbwi # update TLB 1155 nop 1156 nop 1157 nop 1158 nop 1159 nop 1160 eret 1161END(mips3_TLBInvalidException) 1162 1163/*---------------------------------------------------------------------------- 1164 * 1165 * mips3_TLBMissException -- 1166 * 1167 * Handle a TLB miss exception from kernel mode in kernel space. 1168 * The BaddVAddr, Context, and EntryHi registers contain the failed 1169 * virtual address. 1170 * 1171 * Results: 1172 * None. 1173 * 1174 * Side effects: 1175 * None. 1176 * 1177 *---------------------------------------------------------------------------- 1178 */ 1179LEAF_NOPROFILE(mips3_TLBMissException) 1180 .set noat 1181 dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address 1182 li k1, VM_MIN_KERNEL_ADDRESS # compute index 1183 subu k0, k0, k1 1184 lw k1, _C_LABEL(Sysmapsize) # index within range? 1185 srl k0, k0, PGSHIFT 1186 sltu k1, k0, k1 1187#ifdef newsmips 1188 /* news5000 has ROM work area at 0xfff00000. */ 1189 bne k1, zero, 1f 1190 nop 1191 j checkromwork 11921: 1193#else 1194 beq k1, zero, outofworld # No. Failing beyond. . . 1195#endif 1196 lw k1, _C_LABEL(Sysmap) 1197 srl k0, k0, 1 1198 sll k0, k0, 3 # compute offset from index 1199 addu k1, k1, k0 1200 lw k0, 0(k1) # get PTE entry 1201 lw k1, 4(k1) # get odd PTE entry 1202 dsll k0, k0, 34 # get rid of "wired" bit 1203 dsrl k0, k0, 34 1204 dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry 1205 dsll k1, k1, 34 1206 dsrl k1, k1, 34 1207 dmtc0 k1, MIPS_COP_0_TLB_LO1 # load PTE entry 1208 nop 1209 nop # required for QED5230 1210 tlbwr # write TLB 1211 nop 1212 nop 1213 nop 1214 nop 1215 nop 1216 eret 1217 1218outofworld: 1219 /* Ensure we have a valid sp so panic has a chance */ 1220 la a0, 9f # string 1221 la t0,_C_LABEL(panic) 1222 dmfc0 a2, MIPS_COP_0_EXC_PC 1223 move a1, sp 1224 sll k0, k0, PGSHIFT 1225 dmtc0 t0, MIPS_COP_0_EXC_PC # return to panic 1226 li k1, VM_MIN_KERNEL_ADDRESS 1227 addu a3, k0, k1 1228 la sp, start # set sp to a valid place 1229 eret 1230 1231 MSG("TLB out of universe: ksp %p epc %p vaddr %p") 1232 1233 .set at 1234END(mips3_TLBMissException) 1235 1236/* 1237 * Mark where code entered from exception hander jumptable 1238 * ends, for stack traceback code. 1239 */ 1240 1241 .globl _C_LABEL(mips3_exceptionentry_end) 1242_C_LABEL(mips3_exceptionentry_end): 1243 1244/*-------------------------------------------------------------------------- 1245 * 1246 * mips3_SetPID -- 1247 * 1248 * Write the given pid into the TLB pid reg. 1249 * 1250 * mips3_SetPID(pid) 1251 * int pid; 1252 * 1253 * Results: 1254 * None. 1255 * 1256 * Side effects: 1257 * PID set in the entry hi register. 1258 * 1259 *-------------------------------------------------------------------------- 1260 */ 1261LEAF(mips3_SetPID) 1262 dmtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value 1263 nop # required for QED5230 1264 nop # required for QED5230 1265 j ra 1266 nop 1267END(mips3_SetPID) 1268 1269/*-------------------------------------------------------------------------- 1270 * 1271 * mips3_SetWIRED -- 1272 * 1273 * Write the given value into the TLB wired reg. 1274 * 1275 * mips3_SetWIRED(wired) 1276 * int wired; 1277 * 1278 * Results: 1279 * None. 1280 * 1281 * Side effects: 1282 * WIRED set in the wired register. 1283 * 1284 *-------------------------------------------------------------------------- 1285 */ 1286LEAF(mips3_SetWIRED) 1287 mtc0 a0, MIPS_COP_0_TLB_WIRED 1288 nop # required for 5230 1289 nop # required for 5230 1290 j ra 1291 nop 1292END(mips3_SetWIRED) 1293 1294/*-------------------------------------------------------------------------- 1295 * 1296 * mips3_GetWIRED -- 1297 * 1298 * Get the value from the TLB wired reg. 1299 * 1300 * mips3_GetWIRED(void) 1301 * 1302 * Results: 1303 * Value of wired reg. 1304 * 1305 * Side effects: 1306 * None. 1307 * 1308 *-------------------------------------------------------------------------- 1309 */ 1310LEAF(mips3_GetWIRED) 1311 mfc0 v0, MIPS_COP_0_TLB_WIRED 1312 j ra 1313 nop 1314END(mips3_GetWIRED) 1315 1316/*-------------------------------------------------------------------------- 1317 * 1318 * mips3_TLBUpdate -- 1319 * 1320 * Update the TLB if highreg is found; otherwise, enter the data. 1321 * 1322 * mips3_TLBUpdate(virpageadr, lowregx) 1323 * unsigned virpageadr, lowregx; 1324 * 1325 * Results: 1326 * < 0 if loaded >= 0 if updated. 1327 * 1328 * Side effects: 1329 * None. 1330 * 1331 *-------------------------------------------------------------------------- 1332 */ 1333LEAF(mips3_TLBUpdate) 1334 mfc0 v1, MIPS_COP_0_STATUS # Save the status register. 1335 mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts 1336 and t1, a0, MIPS3_PG_ODDPG # t1 = Even/Odd flag 1337 li v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID) 1338 and a0, a0, v0 1339 dmfc0 t0, MIPS_COP_0_TLB_HI # Save current PID 1340 dmtc0 a0, MIPS_COP_0_TLB_HI # Init high reg 1341 and a2, a1, MIPS3_PG_G # Copy global bit 1342 nop 1343 nop 1344 tlbp # Probe for the entry. 1345 dsll a1, a1, 34 1346 dsrl a1, a1, 34 1347 bne t1, zero, 2f # Decide even odd 1348 mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got 1349# EVEN 1350 nop 1351 bltz v0, 1f # index < 0 => !found 1352 nop 1353 nop # required for QED5230 1354 1355 tlbr # update, read entry first 1356 nop 1357 nop 1358 nop 1359 dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. 1360 nop 1361 nop # required for QED5230 1362 tlbwi # update slot found 1363 nop # required for QED5230 1364 nop # required for QED5230 1365 b 4f 1366 nop 13671: 1368#ifdef MIPS3_4100 /* VR4100 core */ 1369 lw v0, _C_LABEL(default_pg_mask) # default_pg_mask declared 1370 mtc0 v0, MIPS_COP_0_TLB_PG_MASK # in mips_machdep.c 1371#else 1372 mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. 1373#endif 1374 dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. 1375 dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. 1376 dmtc0 a2, MIPS_COP_0_TLB_LO1 # init low reg1. 1377 nop 1378 nop # required for QED5230 1379 tlbwr # enter into a random slot 1380 nop # required for QED5230 1381 nop # required for QED5230 1382 b 4f 1383 nop 1384# ODD 13852: 1386 nop 1387 bltz v0, 3f # index < 0 => !found 1388 nop 1389 nop # required for QED5230 1390 1391 tlbr # read the entry first 1392 nop 1393 nop 1394 nop 1395 dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. 1396 nop 1397 nop # required for QED5230 1398 tlbwi # update slot found 1399 nop # required for QED5230 1400 nop # required for QED5230 1401 b 4f 1402 nop 14033: 1404#ifdef MIPS3_4100 /* VR4100 core */ 1405 lw v0, _C_LABEL(default_pg_mask) # default_pg_mask declared 1406 mtc0 v0, MIPS_COP_0_TLB_PG_MASK # in mips_machdep.c 1407#else 1408 mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. 1409#endif 1410 dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. 1411 dmtc0 a2, MIPS_COP_0_TLB_LO0 # init low reg0. 1412 dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. 1413 nop 1414 nop # required for QED5230 1415 tlbwr # enter into a random slot 1416 14174: # Make shure pipeline 1418 nop # advances before we 1419 nop # uses the tlb. 1420 nop 1421 nop 1422 dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID 1423 nop # required for QED5230 1424 nop # required for QED5230 1425 j ra 1426 mtc0 v1, MIPS_COP_0_STATUS # Restore the status register 1427END(mips3_TLBUpdate) 1428 1429/*-------------------------------------------------------------------------- 1430 * 1431 * mips3_TLBRead -- 1432 * 1433 * Read the TLB entry. 1434 * 1435 * mips3_TLBRead(entry, tlb) 1436 * unsigned entry; 1437 * struct tlb *tlb; 1438 * 1439 * Results: 1440 * None. 1441 * 1442 * Side effects: 1443 * tlb will contain the TLB entry found. 1444 * 1445 *-------------------------------------------------------------------------- 1446 */ 1447LEAF(mips3_TLBRead) 1448 mfc0 v1, MIPS_COP_0_STATUS # Save the status register. 1449 mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts 1450 nop 1451 mfc0 t6, MIPS_COP_0_TLB_PG_MASK # save current pgMask 1452 nop 1453 dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID 1454 1455 mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register 1456 nop 1457 nop # required for QED5230 1458 tlbr # Read from the TLB 1459 nop 1460 nop 1461 nop 1462 mfc0 t2, MIPS_COP_0_TLB_PG_MASK # fetch the pgMask 1463 dmfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry 1464 dmfc0 t4, MIPS_COP_0_TLB_LO0 # See what we got 1465 dmfc0 t5, MIPS_COP_0_TLB_LO1 # See what we got 1466 dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID 1467 mtc0 t6, MIPS_COP_0_TLB_PG_MASK # restore pgMask 1468 nop 1469 nop 1470 nop # wait for PID active 1471 mtc0 v1, MIPS_COP_0_STATUS # Restore the status register 1472 nop 1473 sw t2, 0(a1) 1474 sw t3, 4(a1) 1475 sw t4, 8(a1) 1476 j ra 1477 sw t5, 12(a1) 1478END(mips3_TLBRead) 1479 1480/*---------------------------------------------------------------------------- 1481 * 1482 * mips3_FlushCache -- 1483 * 1484 * Flush the caches. Assumes a line size of 16 bytes for speed. 1485 * 1486 * Results: 1487 * None. 1488 * 1489 * Side effects: 1490 * The contents of the caches is flushed. 1491 * 1492 *---------------------------------------------------------------------------- 1493 */ 1494LEAF(mips3_FlushCache) 1495 lw t1, mips_L1ICacheSize 1496 lw t2, mips_L1DCacheSize 1497 # lw t3, mips_L1ICacheLSize 1498 # lw t4, mips_L1DCacheLSize 1499/* 1500 * Flush the instruction cache. 1501 */ 1502 li t0, MIPS_KSEG0_START 1503 addu t1, t0, t1 # End address 1504 subu t1, t1, 128 15051: 1506 cache C_IINV_I, 0(t0) 1507 cache C_IINV_I, 16(t0) 1508 cache C_IINV_I, 32(t0) 1509 cache C_IINV_I, 48(t0) 1510 cache C_IINV_I, 64(t0) 1511 cache C_IINV_I, 80(t0) 1512 cache C_IINV_I, 96(t0) 1513 cache C_IINV_I, 112(t0) 1514 bne t0, t1, 1b 1515 addu t0, t0, 128 1516 1517/* 1518 * Flush the data cache. 1519 */ 1520 li t0, MIPS_KSEG0_START 1521 addu t1, t0, t2 # End address 1522 subu t1, t1, 128 15231: 1524 cache C_IWBINV_D, 0(t0) 1525 cache C_IWBINV_D, 16(t0) 1526 cache C_IWBINV_D, 32(t0) 1527 cache C_IWBINV_D, 48(t0) 1528 cache C_IWBINV_D, 64(t0) 1529 cache C_IWBINV_D, 80(t0) 1530 cache C_IWBINV_D, 96(t0) 1531 cache C_IWBINV_D, 112(t0) 1532 bne t0, t1, 1b 1533 addu t0, t0, 128 1534 1535 lw t2, mips_L2CacheSize 1536 beq t2, zero, 2f 1537 nop 1538 li t0, MIPS_KSEG0_START 1539 addu t1, t0, t2 1540 subu t1, t1, 128 15411: 1542 cache C_IWBINV_SD, 0(t0) 1543 cache C_IWBINV_SD, 32(t0) 1544 cache C_IWBINV_SD, 64(t0) 1545 cache C_IWBINV_SD, 96(t0) 1546 bne t0, t1, 1b 1547 addu t0, t0, 128 15482: 1549 j ra 1550 nop 1551END(mips3_FlushCache) 1552 1553/*---------------------------------------------------------------------------- 1554 * 1555 * mips3_FlushICache -- 1556 * 1557 * void mips3_FlushICache(addr, len) 1558 * vaddr_t addr; vsize_t len; 1559 * 1560 * Flush instruction cache for range of addr to addr + len - 1. 1561 * The address is reduced to a kseg0 index. 1562 * Assumes a cache line size of 16 bytes for speed. 1563 * 1564 * Results: 1565 * None. 1566 * 1567 * Side effects: 1568 * The contents of the cache is flushed. 1569 * Must not touch v0. 1570 * 1571 *---------------------------------------------------------------------------- 1572 */ 1573LEAF(mips3_FlushICache) 1574 lw a2, mips_L1ICacheSize 1575 addu a2, -1 1576 and a0, a0, a2 # get index into primary cache 1577 addu a1, 127 # Align 1578 li a2, MIPS_KSEG0_START 1579 addu a0, a0, a2 1580 srl a1, a1, 7 # Number of unrolled loops 15811: 1582 cache C_IINV_I, 0(a0) 1583 cache C_IINV_I, 16(a0) 1584 cache C_IINV_I, 32(a0) 1585 cache C_IINV_I, 48(a0) 1586 cache C_IINV_I, 64(a0) 1587 cache C_IINV_I, 80(a0) 1588 cache C_IINV_I, 96(a0) 1589 cache C_IINV_I, 112(a0) 1590 addu a1, -1 1591 bne a1, zero, 1b 1592 addu a0, 128 1593 1594 j ra 1595 nop 1596END(mips3_FlushICache) 1597 1598/*---------------------------------------------------------------------------- 1599 * 1600 * mips3_FlushDCache -- 1601 * 1602 * void mips3_FlushDCache(addr, len) 1603 * vaddr_t addr; vsize_t len; 1604 * 1605 * Flush data cache for index range of addr to addr + len - 1. 1606 * The address is reduced to a kseg0 index. 1607 * 1608 * Results: 1609 * None. 1610 * 1611 * Side effects: 1612 * The contents of the cache is written back to primary memory. 1613 * The cache line is invalidated. 1614 * 1615 *---------------------------------------------------------------------------- 1616 */ 1617LEAF(mips3_FlushDCache) 1618 lw a2, mips_L1DCacheSize 1619 addu a2, -1 1620 move t0, a0 # copy start address 1621 and a0, a0, a2 # get index into primary cache 1622 addu a1, 127 # Align 1623 li a2, MIPS_KSEG0_START 1624 addu a0, a0, a2 1625 addu a1, a1, a0 1626 and a0, a0, -128 1627 subu a1, a1, a0 1628 srl a1, a1, 7 # Compute number of cache lines 1629 move t1, a1 # copy length 16301: 1631 cache C_IWBINV_D, 0(a0) 1632 cache C_IWBINV_D, 16(a0) 1633 cache C_IWBINV_D, 32(a0) 1634 cache C_IWBINV_D, 48(a0) 1635 cache C_IWBINV_D, 64(a0) 1636 cache C_IWBINV_D, 80(a0) 1637 cache C_IWBINV_D, 96(a0) 1638 cache C_IWBINV_D, 112(a0) 1639 addu a1, -1 1640 bne a1, zero, 1b 1641 addu a0, 128 1642 1643 lw a2, mips_L2CacheSize 1644 beq a2, zero, 2f # no secondary cache 1645 addu a2, -1 1646 and t0,t0,a2 # secondary cache index 1647 li a0, MIPS_KSEG0_START 1648 addu a0, a0, t0 # reduce to kseg0 address 16491: 1650 cache C_IWBINV_SD, 0(a0) 1651 cache C_IWBINV_SD, 32(a0) 1652 cache C_IWBINV_SD, 64(a0) 1653 cache C_IWBINV_SD, 96(a0) 1654 addu t1, -1 1655 bne t1, zero, 1b 1656 addu a0, 128 16572: 1658 1659 j ra 1660 nop 1661END(mips3_FlushDCache) 1662 1663/*---------------------------------------------------------------------------- 1664 * 1665 * mips3_HitFlushDCache -- 1666 * 1667 * void mips3_HitFlushDCache(addr, len) 1668 * vaddr_t addr, len; 1669 * 1670 * Flush data cache for range of addr to addr + len - 1. 1671 * The address can be any valid virtual address as long 1672 * as no TLB invalid traps occur. Only lines with matching 1673 * addr is flushed. 1674 * 1675 * Results: 1676 * None. 1677 * 1678 * Side effects: 1679 * The contents of the cache is written back to primary memory. 1680 * The cache line is invalidated. 1681 * 1682 *---------------------------------------------------------------------------- 1683 */ 1684LEAF(mips3_HitFlushDCache) 1685 beq a1, zero, 2f 1686 addu a1, 127 # Align 1687 addu a1, a1, a0 1688 and a0, a0, -128 1689 subu a1, a1, a0 1690 srl a1, a1, 7 # Compute number of cache lines 16911: 1692 cache C_HWBINV_D, 0(a0) 1693 cache C_HWBINV_D, 16(a0) 1694 cache C_HWBINV_D, 32(a0) 1695 cache C_HWBINV_D, 48(a0) 1696 cache C_HWBINV_D, 64(a0) 1697 cache C_HWBINV_D, 80(a0) 1698 cache C_HWBINV_D, 96(a0) 1699 cache C_HWBINV_D, 112(a0) 1700#if 1 1701 cache C_HWBINV_SD, 0(a0) 1702 cache C_HWBINV_SD, 32(a0) 1703 cache C_HWBINV_SD, 64(a0) 1704 cache C_HWBINV_SD, 96(a0) 1705#endif 1706 addu a1, -1 1707 bne a1, zero, 1b 1708 addu a0, 128 1709 17102: 1711 j ra 1712 nop 1713END(mips3_HitFlushDCache) 1714 1715/*---------------------------------------------------------------------------- 1716 * 1717 * mips3_InvalidateDCache -- 1718 * 1719 * void mips3_InvalidateDCache(addr, len) 1720 * vaddr_t addr, len; 1721 * 1722 * Flush data cache for range of addr to addr + len - 1. 1723 * The address can be any valid address as long as no TLB misses occur. 1724 * (Be sure to use cached K0SEG kernel addresses or mapped addresses) 1725 * Results: 1726 * None. 1727 * 1728 * Side effects: 1729 * The cache line is invalidated. 1730 * 1731 *---------------------------------------------------------------------------- 1732 */ 1733LEAF(mips3_InvalidateDCache) 1734 addu a1, a1, a0 # compute ending address 17351: 1736 cache C_HINV_SD, 0(a0) 1737 addu a0, a0, 4 1738 bne a0, a1, 1b 1739 cache C_HINV_D,-4(a0) 1740 1741 j ra 1742 nop 1743END(mips3_InvalidateDCache) 1744 1745/*---------------------------------------------------------------------------- 1746 * 1747 * mips3_FlushCache_2way -- 1748 * 1749 * Flush the caches. Assumes a line size of 32 bytes for speed. 1750 * 1751 * Results: 1752 * None. 1753 * 1754 * Side effects: 1755 * The contents of the caches is flushed. 1756 * 1757 *---------------------------------------------------------------------------- 1758 */ 1759LEAF(mips3_FlushCache_2way) 1760 lw t1, mips_L1ICacheSize 1761 lw t2, mips_L1DCacheSize 1762 1763 /* 1764 * Flush the instruction cache. 1765 */ 1766 li t0, MIPS_KSEG0_START 1767 srl t1, 1 # Two way set assoc 1768 or t3, t1, t0 # Second way address 1769 addu t1, t0, t1 # End address 17701: 1771 cache C_IINV_I, 0(t0) 1772 cache C_IINV_I, 0(t3) 1773 cache C_IINV_I, 32(t0) 1774 cache C_IINV_I, 32(t3) 1775 cache C_IINV_I, 64(t0) 1776 cache C_IINV_I, 64(t3) 1777 cache C_IINV_I, 96(t0) 1778 addu t0, t0, 128 1779 cache C_IINV_I, 96(t3) 1780 bne t0, t1, 1b 1781 addu t3, t3, 128 # Branch delay slot 1782 1783 /* 1784 * Flush the data cache. 1785 */ 1786 li t0, MIPS_KSEG0_START 1787 srl t2, 1 # Two way set assoc 1788 or t3, t2, t0 # Second way address 1789 addu t1, t0, t2 # End address 17901: 1791 cache C_IWBINV_D, 0(t0) 1792 cache C_IWBINV_D, 0(t3) 1793 cache C_IWBINV_D, 32(t0) 1794 cache C_IWBINV_D, 32(t3) 1795 cache C_IWBINV_D, 64(t0) 1796 cache C_IWBINV_D, 64(t3) 1797 cache C_IWBINV_D, 96(t0) 1798 addu t0, t0, 128 1799 cache C_IWBINV_D, 96(t3) 1800 bne t0, t1, 1b 1801 addu t3, t3, 128 # Branch delay slot 1802 1803 lw t2, mips_L2CacheSize 1804 beq t2, zero, 2f 1805 nop 1806 li t0, MIPS_KSEG0_START 1807 addu t1, t0, t2 1808 subu t1, t1, 128 18091: 1810 cache C_IWBINV_SD, 0(t0) 1811 cache C_IWBINV_SD, 32(t0) 1812 cache C_IWBINV_SD, 64(t0) 1813 cache C_IWBINV_SD, 96(t0) 1814 bne t0, t1, 1b 1815 addu t0, t0, 128 18162: 1817 j ra 1818 nop 1819END(mips3_FlushCache_2way) 1820 1821/*---------------------------------------------------------------------------- 1822 * 1823 * mips3_FlushICache_2way -- 1824 * 1825 * void mips3_FlushICache_2way(addr, len) 1826 * vaddr_t addr; vsize_t len; 1827 * 1828 * Flush instruction cache for range of addr to addr + len - 1. 1829 * The address can be any valid address so long as no TLB misses occur. 1830 * 1831 * Assumes a cache line size of 32 bytes for speed. 1832 * 1833 * Addr should be a KSEG0 address, but it can be called with a KUSEG 1834 * address. To handle flushing both ways here we | in KSEG0 to avoid 1835 * invalid TLB misses. With a virtually indexed cache this does the 1836 * correct thing. 1837 * 1838 * Results: 1839 * None. 1840 * 1841 * Side effects: 1842 * The contents of the cache is flushed. 1843 * Must not touch v0. 1844 * 1845 *---------------------------------------------------------------------------- 1846 */ 1847LEAF(mips3_FlushICache_2way) 1848 lw t0, mips_L1ICacheSize 1849 li t1, MIPS_KSEG0_START 1850 addu a1, 127 # Align (I $ inval of partials is ok) 1851 srl t0,1 # Two way set assoc offset 1852 addu t2, t0, -1 # Cache index mask 1853 and a0, a0, t2 # Only keep index bits (avoid KSEG2, way 0) 1854 or a0, a0, t1 # Make KSEG0 1855 srl a1, a1, 7 # Number of unrolled loops 1856 or t0, t0, a0 # Way 1 index offset. 18571: 1858 cache C_IINV_I, 0(a0) 1859 cache C_IINV_I, 0(t0) # other way 1860 cache C_IINV_I, 32(a0) 1861 cache C_IINV_I, 32(t0) # other way 1862 addu a1, -1 1863 cache C_IINV_I, 64(a0) 1864 cache C_IINV_I, 64(t0) # other way 1865 cache C_IINV_I, 96(a0) 1866 addu a0, 128 1867 cache C_IINV_I, 96(t0) # other way 1868 bgt a1, zero, 1b 1869 addu t0, 128 # Branch delay slot 1870 1871 j ra 1872 nop 1873END(mips3_FlushICache_2way) 1874 1875/*---------------------------------------------------------------------------- 1876 * 1877 * mips3_FlushDCache_2way -- 1878 * 1879 * void mips3_FlushDCache_2way(paddr_t addr, len) 1880 * 1881 * Flush data cache for index range of addr to addr + len - 1. 1882 * The address is reduced to a kseg0 index. 1883 * 1884 * Results: 1885 * None. 1886 * 1887 * Side effects: 1888 * The contents of the cache is written back to primary memory. 1889 * The cache line is invalidated. 1890 * 1891 *---------------------------------------------------------------------------- 1892 */ 1893LEAF(mips3_FlushDCache_2way) 1894 lw a2, mips_L1DCacheSize 1895 srl a3, a2, 1 # two way set associative cache 1896 addu a2, a3, -1 # offset mask 1897 and a0, a0, a2 # get index into primary cache 1898 addu a1, a1, a0 # add offset to length 1899 and a0, a0, -128 # block align address 1900 subu a1, a1, a0 # subtract aligned offset -> inc len by align 1901 addu a1, 127 # tail align length 1902 li a2, MIPS_KSEG0_START 1903 addu a0, a0, a2 # K0(vindex) 1904 addu a3, a0, a3 # second set of two way cache 1905 srl a1, a1, 7 # Compute number of cache blocks 19061: 1907 cache C_IWBINV_D, 0(a0) 1908 cache C_IWBINV_D, 0(a3) # second way 1909 cache C_IWBINV_D, 32(a0) 1910 cache C_IWBINV_D, 32(a3) 1911 addu a1, -1 1912 cache C_IWBINV_D, 64(a0) 1913 cache C_IWBINV_D, 64(a3) 1914 cache C_IWBINV_D, 96(a0) 1915 cache C_IWBINV_D, 96(a3) 1916 addu a0, 128 1917 bgtz a1, 1b 1918 addu a3, 128 # Branch delay slot 1919 1920 j ra 1921 nop 1922END(mips3_FlushDCache_2way) 1923 1924/*---------------------------------------------------------------------------- 1925 * 1926 * mips3_HitFlushDCache_2way -- 1927 * 1928 * void mips3_HitFlushDCache_2way(addr, len) 1929 * vaddr_t addr, len; 1930 * 1931 * Flush data cache for range of addr to addr + len - 1. 1932 * The address can be any valid virtual address as long 1933 * as no TLB invalid traps occur. Only lines with matching 1934 * addr is flushed. 1935 * 1936 * Assumes a cache line size of 32 bytes for speed. 1937 * Does not currently support a second level cache. 1938 * 1939 * Other MIPS code does 128B per loop. W/o a secondary 1940 * cache, I think it's better to just operate on what 1941 * cache lines were asked to be cleared in the hit case. 1942 * 1943 * Results: 1944 * None. 1945 * 1946 * Side effects: 1947 * The contents of the cache is written back to primary memory. 1948 * The cache line is invalidated. 1949 * 1950 *---------------------------------------------------------------------------- 1951 */ 1952LEAF(mips3_HitFlushDCache_2way) 1953 beq a1, zero, 2f 1954 addu a1, 31 # Branch delay slot; align length 1955 and a0, a0, -32 1956 srl a1, a1, 5 # Compute number of cache lines 19571: 1958 addu a1, -1 1959 cache C_HWBINV_D,0(a0) 1960 bne a1, zero, 1b 1961 addu a0, 32 # Branch delay slot 19622: 1963 j ra 1964 nop 1965END(mips3_HitFlushDCache_2way) 1966 1967/*---------------------------------------------------------------------------- 1968 * 1969 * mips3_InvalidateDCache_2way -- 1970 * 1971 * void mips3_InvalidateDCache_2way(addr, len) 1972 * vaddr_t addr, len; 1973 * 1974 * Flush data cache for range of addr to addr + len - 1. 1975 * The address can be any valid address as long as no TLB misses occur. 1976 * (Be sure to use cached K0SEG kernel addresses or mapped addresses) 1977 * 1978 * Caller must be sure the whole cache line is to be invalidated, and 1979 * the call does not corrupt bordering data. 1980 * 1981 * Does not currently support a second level cache. 1982 * 1983 * Results: 1984 * None. 1985 * 1986 * Side effects: 1987 * The cache line is invalidated. 1988 * 1989 *---------------------------------------------------------------------------- 1990 */ 1991LEAF(mips3_InvalidateDCache_2way) 1992 addu a1, a1, a0 # compute ending address 19931: 1994 cache C_HINV_D,0(a0) 1995 addu a0, a0, 32 1996 bltu a0, a1, 1b 1997 nop # Branch delay slot 1998 1999 j ra 2000 nop 2001END(mips3_InvalidateDCache_2way) 2002 2003/*---------------------------------------------------------------------------- 2004 * 2005 * mips3_VCED -- 2006 * 2007 * Handle virtual coherency exceptions. 2008 * Called directly from the mips3 execption-table code. 2009 * only k0, k1 are avaiable on entry 2010 * 2011 * Results: 2012 * None. 2013 * 2014 * Side effects: 2015 * Remaps the conflicting address as uncached and returns 2016 * from the execption. 2017 * 2018 * NB: cannot be profiled, all registers are user registers on entry. 2019 * 2020 *---------------------------------------------------------------------------- 2021 */ 2022LEAF_NOPROFILE(mips3_VCED) 2023XLEAF(mips3_VCEI) /* XXXX */ 2024 .set noat 2025 move k0, AT 2026 .set at 2027 sw k0, vce_saveat 2028 mfc0 k0, MIPS_COP_0_BAD_VADDR # fault addr. 2029 nop 2030 nop 2031 and k0, -16 2032 sw k0, vce_savek0 # save virtual address 2033 cache C_IWBINV_D, 0(k0) # writeback primary line 2034 nop 2035 nop 2036 cache C_ILDTAG_SD, 0(k0) # read L2Cache tag 2037 and k0, PGOFSET 2038 mfc0 k1, MIPS_COP_0_TAG_LO 2039 and k1, 0x00000380 # VIndex[9..7] 2040 sll k1, k1, 5 # [14..12] <--- 2041 or k0, k0, k1 2042 or k0, MIPS_KSEG0_START # physical K0SEG address 2043 lw k1, _C_LABEL(mips_L2CacheLSize) 2044 beq k1, zero, 2f # XXX needed? 2045 subu k1, zero, k1 2046 and k0, k0, k1 # align to L2CacheLSize 20471: 2048 cache C_IWBINV_D, 0(k0) # flush 32 bytes 2049 cache C_IWBINV_D, 16(k0) 2050 addu k1, 32 2051 bltz k1, 1b 2052 addu k0, 32 20532: 2054 lw k0, vce_savek0 # get original address 2055 cache C_HSETV_SD, 0(k0) 2056 nop 2057#ifdef DEBUG 2058 mfc0 k1, MIPS_COP_0_EXC_PC 2059 sw k0, VCE_vaddr 2060 sw k1, VCE_epc 2061 la k1, VCE_count # count number of exceptions 2062 srl k0, k0, 26 # position upper 4 bits of VA 2063 and k0, k0, 0x3c # mask it off 2064 add k1, k0 # get address of count table 2065 lw k0, 0(k1) 2066 addu k0, 1 2067 sw k0, 0(k1) 2068#endif 2069 lw k0, vce_saveat 2070 .set noat 2071 move AT, k0 2072 .set at 2073 eret 2074 .align 3 # needs to be aligned? 2075vce_saveat: 2076 .word 0 2077 .word 0 2078vce_savek0: 2079 .word 0 2080 .word 0 2081 .globl _C_LABEL(VCE_count) 2082_C_LABEL(VCE_count): 2083 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 2084 .globl _C_LABEL(VCE_epc) 2085_C_LABEL(VCE_epc): 2086 .word 0 2087 .globl _C_LABEL(VCE_vaddr) 2088_C_LABEL(VCE_vaddr): 2089 .word 0 2090END(mips3_VCED) 2091 2092/*---------------------------------------------------------------------------- 2093 * 2094 * mips3_wbflush -- 2095 * 2096 * Return when the write buffer is empty. 2097 * 2098 * mips3_wbflush() 2099 * 2100 * Results: 2101 * None. 2102 * 2103 * Side effects: 2104 * None. 2105 * 2106 *---------------------------------------------------------------------------- 2107 */ 2108LEAF(mips3_wbflush) 2109 nop 2110 sync 2111 j ra 2112 nop 2113END(mips3_wbflush) 2114 2115/* 2116 * mips3_proc_trampoline() 2117 * 2118 * Arrange for a function to be invoked neatly, after a cpu_switch(). 2119 * Call the service function with one argument, specified by the s0 2120 * and s1 respectively. There is no need register save operation. 2121 */ 2122LEAF(mips3_proc_trampoline) 2123 jal ra, s0 2124 move a0, s1 2125 .set noat 2126 li a0, MIPS_SR_EXL # set exception level 2127 mtc0 a0, MIPS_COP_0_STATUS 2128 nop 2129 nop 2130 addu a1, sp, CALLFRAME_SIZ 2131 # REG_L a0, FRAME_SR(a1) 2132 REG_L t0, FRAME_MULLO(a1) 2133 REG_L t1, FRAME_MULHI(a1) 2134 REG_L v0, FRAME_EPC(a1) 2135 mtlo t0 2136 mthi t1 2137 dmtc0 v0, MIPS_COP_0_EXC_PC 2138 nop 2139 move k1, a1 2140 REG_L AT, FRAME_AST(k1) 2141 REG_L v0, FRAME_V0(k1) 2142 REG_L v1, FRAME_V1(k1) 2143 REG_L a0, FRAME_A0(k1) 2144 REG_L a1, FRAME_A1(k1) 2145 REG_L a2, FRAME_A2(k1) 2146 REG_L a3, FRAME_A3(k1) 2147 REG_L t0, FRAME_T0(k1) 2148 REG_L t1, FRAME_T1(k1) 2149 REG_L t2, FRAME_T2(k1) 2150 REG_L t3, FRAME_T3(k1) 2151 REG_L t4, FRAME_T4(k1) 2152 REG_L t5, FRAME_T5(k1) 2153 REG_L t6, FRAME_T6(k1) 2154 REG_L t7, FRAME_T7(k1) 2155 REG_L s0, FRAME_S0(k1) 2156 REG_L s1, FRAME_S1(k1) 2157 REG_L s2, FRAME_S2(k1) 2158 REG_L s3, FRAME_S3(k1) 2159 REG_L s4, FRAME_S4(k1) 2160 REG_L s5, FRAME_S5(k1) 2161 REG_L s6, FRAME_S6(k1) 2162 REG_L s7, FRAME_S7(k1) 2163 REG_L t8, FRAME_T8(k1) 2164 REG_L t9, FRAME_T9(k1) 2165 REG_L k0, FRAME_SR(k1) 2166 DYNAMIC_STATUS_MASK(k0,sp) # machine dependent masking 2167 REG_L gp, FRAME_GP(k1) 2168 REG_L s8, FRAME_S8(k1) 2169 REG_L ra, FRAME_RA(k1) 2170 REG_L sp, FRAME_SP(k1) 2171 mtc0 k0, MIPS_COP_0_STATUS 2172 nop 2173 nop 2174 eret 2175 .set at 2176END(mips3_proc_trampoline) 2177 2178/* 2179 * void mips3_cpu_switch_resume(struct proc *newproc) 2180 * 2181 * Wiredown the USPACE of newproc with TLB entry#0, and possibly #1 2182 * if necessary. Check whether target USPACE is already refered by 2183 * some TLB entry(s) before that, and make sure TBIS(them) in the 2184 * case. 2185 */ 2186LEAF_NOPROFILE(mips3_cpu_switch_resume) 2187 lw a1, P_MD_UPTE_0(a0) # a1 = upte[0] 2188 lw a2, P_MD_UPTE_1(a0) # a2 = upte[1] 2189 lw v0, P_ADDR(a0) # va = p->p_addr 2190 li s0, MIPS_KSEG2_START 2191 blt v0, s0, resume 2192 nop 2193 2194 and s0, v0, MIPS3_PG_ODDPG 2195 beq s0, zero, entry0 2196 nop 2197 2198 # p_addr starts on an odd page, need to set up 2 TLB entries 2199 addu v0, v0, MIPS3_PG_ODDPG 2200 dmtc0 v0, MIPS_COP_0_TLB_HI # VPN = va 2201 nop 2202 nop 2203 tlbp # probe VPN 2204 nop 2205 nop 2206 mfc0 s0, MIPS_COP_0_TLB_INDEX 2207 nop 2208 bltz s0, entry1set 2209 li s0, MIPS_KSEG0_START 2210 dmtc0 s0, MIPS_COP_0_TLB_HI 2211 dmtc0 zero, MIPS_COP_0_TLB_LO0 2212 dmtc0 zero, MIPS_COP_0_TLB_LO1 2213 nop 2214 nop 2215 tlbwi 2216 nop 2217 nop 2218 dmtc0 v0, MIPS_COP_0_TLB_HI # set VPN again 2219entry1set: 2220 li s0, 1 2221 mtc0 s0, MIPS_COP_0_TLB_INDEX # TLB entry #1 2222 or a2, MIPS3_PG_G 2223 dmtc0 a2, MIPS_COP_0_TLB_LO0 # lo0: upte[1] | PG_G 2224 li a2, MIPS3_PG_G 2225 dmtc0 a2, MIPS_COP_0_TLB_LO1 # lo1: none | PG_G 2226 nop 2227 nop 2228 tlbwi # set TLB entry #1 2229 #nop 2230 #nop 2231 move a2, a1 # lo0: none 2232 move a1, zero # lo1: u_pte[0] 2233 addu v0, v0, -NBPG * 2 # backup to odd page mapping 2234 2235entry0: 2236 dmtc0 v0, MIPS_COP_0_TLB_HI # VPN = va 2237 nop 2238 nop 2239 tlbp # probe VPN 2240 nop 2241 nop 2242 mfc0 s0, MIPS_COP_0_TLB_INDEX 2243 nop 2244 bltz s0, entry0set 2245 li s0, MIPS_KSEG0_START 2246 dmtc0 s0, MIPS_COP_0_TLB_HI 2247 dmtc0 zero, MIPS_COP_0_TLB_LO0 2248 dmtc0 zero, MIPS_COP_0_TLB_LO1 2249 nop 2250 nop 2251 tlbwi 2252 nop 2253 nop 2254 dmtc0 v0, MIPS_COP_0_TLB_HI # set VPN again 2255entry0set: 2256 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0 2257 or a1, MIPS3_PG_G 2258 dmtc0 a1, MIPS_COP_0_TLB_LO0 # upte[0] | PG_G 2259 or a2, MIPS3_PG_G 2260 dmtc0 a2, MIPS_COP_0_TLB_LO1 # upte[1] | PG_G 2261 nop 2262 nop 2263 tlbwi # set TLB entry #0 2264 nop 2265 nop 2266 2267resume: 2268 j ra 2269 nop 2270 END(mips3_cpu_switch_resume) 2271 2272/* 2273 * void mips3_TBIS(vaddr_t va) 2274 * 2275 * Invalidate a TLB entry which has the given vaddr and ASID if found. 2276 */ 2277LEAF_NOPROFILE(mips3_TBIS) 2278 mfc0 v1, MIPS_COP_0_STATUS # save status register 2279 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 2280 2281 li v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID) 2282 dmfc0 t0, MIPS_COP_0_TLB_HI # save current ASID 2283 mfc0 t3, MIPS_COP_0_TLB_PG_MASK # save current pgMask 2284 and a0, a0, v0 # make sure valid entryHi 2285 dmtc0 a0, MIPS_COP_0_TLB_HI # look for the vaddr & ASID 2286 nop 2287 nop 2288 tlbp # probe the entry in question 2289 nop 2290 nop 2291 mfc0 v0, MIPS_COP_0_TLB_INDEX # see what we got 2292 #nop # -slip- 2293 #nop # -slip- 2294 bltz v0, 1f # index < 0 then skip 2295 li t1, MIPS_KSEG0_START # invalid address 2296 dmtc0 t1, MIPS_COP_0_TLB_HI # make entryHi invalid 2297 dmtc0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0 2298 dmtc0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1 2299 mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out pageMask 2300 nop 2301 nop 2302 tlbwi 2303 nop 2304 nop 23051: 2306 dmtc0 t0, MIPS_COP_0_TLB_HI # restore current ASID 2307 mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask 2308 nop 2309 nop 2310 j ra 2311 mtc0 v1, MIPS_COP_0_STATUS # restore status register 2312 END(mips3_TBIS) 2313 2314/* 2315 * void mips3_TBIAP(int sizeofTLB) 2316 * 2317 * Invalidate TLB entries belong to per process user spaces while 2318 * leaving entries for kernel space marked global intact. 2319 */ 2320LEAF_NOPROFILE(mips3_TBIAP) 2321 mfc0 v1, MIPS_COP_0_STATUS # save status register 2322 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 2323 2324 move t2, a0 2325 mfc0 t1, MIPS_COP_0_TLB_WIRED 2326 li v0, MIPS_KSEG0_START # invalid address 2327 mfc0 t3, MIPS_COP_0_TLB_PG_MASK # save current pgMask 2328 2329 # do {} while (t1 < t2) 23301: 2331 mtc0 t1, MIPS_COP_0_TLB_INDEX # set index 2332 nop 2333 nop 2334 tlbr # obtain an entry 2335 dmfc0 a0, MIPS_COP_0_TLB_LO1 2336 #nop # -slip- 2337 #nop # -slip- 2338 and a0, a0, MIPS3_PG_G # check to see it has G bit 2339 bnez a0, 2f 2340 nop 2341 2342 dmtc0 v0, MIPS_COP_0_TLB_HI # make entryHi invalid 2343 dmtc0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0 2344 dmtc0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1 2345 mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out mask entry 2346 nop 2347 nop 2348 tlbwi # invalidate the TLB entry 2349 #nop 2350 #nop 23512: 2352 addu t1, t1, 1 2353 bne t1, t2, 1b 2354 nop 2355 2356 mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask 2357 nop 2358 nop 2359 j ra # new ASID will be set soon 2360 mtc0 v1, MIPS_COP_0_STATUS # restore status register 2361 END(mips3_TBIAP) 2362 2363/* 2364 * void mips3_TBIA(int sizeofTLB) 2365 * 2366 * Invalidate all of non-wired TLB entries. 2367 */ 2368LEAF_NOPROFILE(mips3_TBIA) 2369 mfc0 v1, MIPS_COP_0_STATUS # save status register 2370 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 2371 2372 li v0, MIPS_KSEG0_START # invalid address 2373 dmfc0 t0, MIPS_COP_0_TLB_HI # save current ASID 2374 mfc0 t1, MIPS_COP_0_TLB_WIRED 2375 mfc0 t2, MIPS_COP_0_TLB_PG_MASK # save current pgMask 2376 2377 dmtc0 v0, MIPS_COP_0_TLB_HI # make entryHi invalid 2378 dmtc0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0 2379 dmtc0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1 2380 mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out pageMask 2381 2382 # do {} while (t1 < a0) 23831: 2384 mtc0 t1, MIPS_COP_0_TLB_INDEX # set TLBindex 2385 nop 2386 nop 2387 tlbwi # clear the entry 2388 #nop 2389 #nop 2390 addu t1, t1, 1 # increment index 2391 bne t1, a0, 1b 2392 nop 2393 2394 dmtc0 t0, MIPS_COP_0_TLB_HI # restore ASID 2395 mtc0 t2, MIPS_COP_0_TLB_PG_MASK # restore pgMask 2396 nop 2397 nop 2398 j ra 2399 mtc0 v1, MIPS_COP_0_STATUS # restore status register 2400 END(mips3_TBIA) 2401 2402LEAF(mips3_read_config) 2403 mfc0 v0, MIPS_COP_0_CONFIG 2404 nop 2405 j ra 2406 nop 2407END(mips3_read_config) 2408 2409LEAF(mips3_write_config) 2410 mtc0 a0, MIPS_COP_0_CONFIG 2411 nop 2412 nop 2413 j ra 2414 nop 2415END(mips3_write_config) 2416 2417/*---------------------------------------------------------------------------- 2418 * 2419 * mips3_cycle_count -- 2420 * 2421 * u_int32_t mips3_cycle_count(void) 2422 * 2423 * read 32-bit cycle-counter clock in coprocessor 0. 2424 * 2425 * Results: 2426 * returns 32-bit clock value, incremented automatically by CPU 2427 * at nominal cycle rate (i.e., half the maximum issue rate.) 2428 * 2429 * Side effects: 2430 * none. 2431 * 2432 *---------------------------------------------------------------------------- 2433 */ 2434LEAF(mips3_cycle_count) 2435 mfc0 v0, MIPS_COP_0_COUNT 2436 nop 2437 nop 2438 j ra 2439 nop 2440END(mips3_cycle_count) 2441 2442/*-------------------------------------------------------------------------- 2443 * 2444 * mips3_write_count -- 2445 * 2446 * Write the given value into the Compare reg 2447 * 2448 * mips3_write_count(count) 2449 * int count; 2450 * 2451 * Results: 2452 * None. 2453 * 2454 * Side effects: 2455 * 2456 * Sets the Count value in the CP0 register (9). 2457 * 2458 *-------------------------------------------------------------------------- 2459 */ 2460LEAF(mips3_write_count) 2461 mtc0 a0, MIPS_COP_0_COUNT # Write the Counter value 2462 j ra 2463 nop 2464END(mips3_write_count) 2465 2466/* 2467 * Read compare register. 2468 * 2469 * On mips3, generates a hardint 5 interrupt request is generated 2470 * each time the COUNT register increments past the COMPARE register. 2471 * 2472 * (The mips interrupt mask defintions currently leaves this interrupt 2473 * unconditionally masked out on mips3 CPUs.) 2474 */ 2475LEAF(mips3_read_compare) 2476 mfc0 v0, MIPS_COP_0_COMPARE 2477 nop 2478 j ra 2479 nop 2480END(mips3_read_compare) 2481 2482/* 2483 * Write value to compare register. 2484 * 2485 * Side Effects: 2486 * Clears interrupt request from cycle-counter clock. 2487 */ 2488LEAF(mips3_write_compare) 2489 mtc0 a0, MIPS_COP_0_COMPARE 2490 nop 2491 j ra 2492 nop 2493END(mips3_write_compare) 2494 2495LEAF(mips3_write_xcontext_upper) 2496 mfc0 v1, MIPS_COP_0_STATUS # save status register 2497 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 2498 nop 2499 nop 2500 nop 2501 dsll a0, 32 2502 dmtc0 a0, MIPS_COP_0_TLB_XCONTEXT # Store segment map for access 2503 nop 2504 nop 2505 j ra 2506 mtc0 v1, MIPS_COP_0_STATUS # restore status register 2507END(mips3_write_xcontext_upper) 2508 2509/* 2510 * Clear BEV bit if it was set. 2511 */ 2512LEAF(mips3_clearBEV) 2513 mfc0 v0, MIPS_COP_0_STATUS 2514 or v0, MIPS3_SR_DIAG_BEV 2515 xor v0, MIPS3_SR_DIAG_BEV 2516 mtc0 v0, MIPS_COP_0_STATUS 2517 j ra 2518 nop 2519 END(mips3_clearBEV) 2520 2521LEAF(mips3_FetchIcache) 2522 lw t1, mips_L1ICacheSize 2523 lw t2, mips_L1ICacheLSize 2524 li v0, 0 2525 li t0, MIPS_KSEG0_START 2526 addu t3, t1, t0 25271: 2528 cache C_ILDTAG_I, 0(t0) 2529 mfc0 t4, MIPS_COP_0_TAG_LO 2530 sw t4, 0(a0) 2531 addu a0, 4 2532 addu v0, 1 2533 addu t0, t2 2534 blt t0, t3, 1b 2535 nop 2536 j ra 2537 nop 2538END(mips3_FetchIcache) 2539 2540LEAF(mips3_FetchDcache) 2541 lw t1, mips_L1DCacheSize 2542 lw t2, mips_L1DCacheLSize 2543 li v0, 0 2544 li t0, MIPS_KSEG0_START 2545 addu t3, t1, t0 25461: 2547 cache C_ILDTAG_D, 0(t0) 2548 mfc0 t4, MIPS_COP_0_TAG_LO 2549 sw t4, 0(a0) 2550 addu a0, 4 2551 addu v0, 1 2552 addu t0, t2 2553 blt t0, t3, 1b 2554 nop 2555 j ra 2556 nop 2557END(mips3_FetchDcache) 2558 2559 2560/* 2561 * The variables below are used to communicate the cache handling 2562 * to higher-level software. 2563 */ 2564 .sdata 2565 2566 .globl _C_LABEL(mips3_L1TwoWayCache) 2567_C_LABEL(mips3_L1TwoWayCache): 2568 .word 0 2569 2570 .data 2571 2572 .globl _C_LABEL(mips3_locoresw) 2573_C_LABEL(mips3_locoresw): 2574 .word _C_LABEL(mips3_cpu_switch_resume) 2575 .word _C_LABEL(mips3_proc_trampoline) 2576 .word _C_LABEL(mips_idle) 2577 2578_C_LABEL(mips3_excpt_sw): 2579 #### 2580 #### The kernel exception handlers. 2581 #### 2582 .word _C_LABEL(mips3_KernIntr) # 0 external interrupt 2583 .word _C_LABEL(mips3_KernGenException) # 1 TLB modification 2584 .word _C_LABEL(mips3_TLBInvalidException) # 2 TLB miss (LW/I-fetch) 2585 .word _C_LABEL(mips3_TLBInvalidException) # 3 TLB miss (SW) 2586 .word _C_LABEL(mips3_KernGenException) # 4 address error (LW/I-fetch) 2587 .word _C_LABEL(mips3_KernGenException) # 5 address error (SW) 2588 .word _C_LABEL(mips3_KernGenException) # 6 bus error (I-fetch) 2589 .word _C_LABEL(mips3_KernGenException) # 7 bus error (load or store) 2590 .word _C_LABEL(mips3_KernGenException) # 8 system call 2591 .word _C_LABEL(mips3_KernGenException) # 9 breakpoint 2592 .word _C_LABEL(mips3_KernGenException) # 10 reserved instruction 2593 .word _C_LABEL(mips3_KernGenException) # 11 coprocessor unusable 2594 .word _C_LABEL(mips3_KernGenException) # 12 arithmetic overflow 2595 .word _C_LABEL(mips3_KernGenException) # 13 r4k trap exception 2596 .word _C_LABEL(mips3_VCEI) # 14 r4k virt coherence 2597 .word _C_LABEL(mips3_KernGenException) # 15 r4k FP exception 2598 .word _C_LABEL(mips3_KernGenException) # 16 reserved 2599 .word _C_LABEL(mips3_KernGenException) # 17 reserved 2600 .word _C_LABEL(mips3_KernGenException) # 18 reserved 2601 .word _C_LABEL(mips3_KernGenException) # 19 reserved 2602 .word _C_LABEL(mips3_KernGenException) # 20 reserved 2603 .word _C_LABEL(mips3_KernGenException) # 21 reserved 2604 .word _C_LABEL(mips3_KernGenException) # 22 reserved 2605 .word _C_LABEL(mips3_KernGenException) # 23 watch exception 2606 .word _C_LABEL(mips3_KernGenException) # 24 reserved 2607 .word _C_LABEL(mips3_KernGenException) # 25 reserved 2608 .word _C_LABEL(mips3_KernGenException) # 26 reserved 2609 .word _C_LABEL(mips3_KernGenException) # 27 reserved 2610 .word _C_LABEL(mips3_KernGenException) # 28 reserved 2611 .word _C_LABEL(mips3_KernGenException) # 29 reserved 2612 .word _C_LABEL(mips3_KernGenException) # 30 reserved 2613 .word _C_LABEL(mips3_VCED) # 31 v. coherence exception data 2614 ##### 2615 ##### The user exception handlers. 2616 ##### 2617 .word _C_LABEL(mips3_UserIntr) # 0 2618 .word _C_LABEL(mips3_UserGenException) # 1 2619 .word _C_LABEL(mips3_UserGenException) # 2 2620 .word _C_LABEL(mips3_UserGenException) # 3 2621 .word _C_LABEL(mips3_UserGenException) # 4 2622 .word _C_LABEL(mips3_UserGenException) # 5 2623 .word _C_LABEL(mips3_UserGenException) # 6 2624 .word _C_LABEL(mips3_UserGenException) # 7 2625 .word _C_LABEL(mips3_SystemCall) # 8 2626 .word _C_LABEL(mips3_UserGenException) # 9 2627 .word _C_LABEL(mips3_UserGenException) # 10 2628 .word _C_LABEL(mips3_UserGenException) # 11 2629 .word _C_LABEL(mips3_UserGenException) # 12 2630 .word _C_LABEL(mips3_UserGenException) # 13 2631 .word _C_LABEL(mips3_VCEI) # 14 2632 .word _C_LABEL(mips3_UserGenException) # 15 2633 .word _C_LABEL(mips3_UserGenException) # 16 2634 .word _C_LABEL(mips3_UserGenException) # 17 2635 .word _C_LABEL(mips3_UserGenException) # 18 2636 .word _C_LABEL(mips3_UserGenException) # 19 2637 .word _C_LABEL(mips3_UserGenException) # 20 2638 .word _C_LABEL(mips3_UserGenException) # 21 2639 .word _C_LABEL(mips3_UserGenException) # 22 2640 .word _C_LABEL(mips3_UserGenException) # 23 2641 .word _C_LABEL(mips3_UserGenException) # 24 2642 .word _C_LABEL(mips3_UserGenException) # 25 2643 .word _C_LABEL(mips3_UserGenException) # 26 2644 .word _C_LABEL(mips3_UserGenException) # 27 2645 .word _C_LABEL(mips3_UserGenException) # 28 2646 .word _C_LABEL(mips3_UserGenException) # 29 2647 .word _C_LABEL(mips3_UserGenException) # 20 2648 .word _C_LABEL(mips3_VCED) # 31 v. coherence exception data 2649