1/* $NetBSD: locore_mips1.S,v 1.55 2002/11/12 14:00:41 nisimura Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Digital Equipment Corporation and Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permited provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * Copyright (C) 1989 Digital Equipment Corporation. 39 * Permission to use, copy, modify, and distribute this software and 40 * its documentation for any purpose and without fee is hereby granted, 41 * provided that the above copyright notice appears in all copies. 42 * Digital Equipment Corporation makes no representations about the 43 * suitability of this software for any purpose. It is provided "as is" 44 * without express or implied warranty. 45 * 46 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 47 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 48 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 49 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 50 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 51 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 52 * 53 * @(#)locore.s 8.5 (Berkeley) 1/4/94 54 */ 55#include "opt_cputype.h" 56#include "opt_ddb.h" 57#include "opt_kgdb.h" 58 59#include <sys/cdefs.h> 60 61#include <mips/asm.h> 62#include <mips/cpuregs.h> 63#include <machine/param.h> 64 65#include "assym.h" 66 67 .set noreorder 68 .text 69 70EXPORT(mips1_exceptionentry_start) 71 72/* 73 * mips1_UTLBMiss 74 * 75 * A reference is made (in either kernel or user mode) to a page in 76 * kuseg that has no matching TLB entry. This routine is copied down 77 * at 0x80000000 and total length must be less than 32 instructions. 78 * No pc relative jump instruction is allowed. 79 */ 80VECTOR(mips1_UTLBMiss, unknown) 81 .set noat 82 mfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 83 lw k1, _C_LABEL(segbase) # get the current segment table 84 bltz k0, 1f # R3000 chip bug 85 srl k0, k0, SEGSHIFT # compute segment table index 86 sll k0, k0, 2 87 addu k1, k1, k0 88 mfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address 89 lw k1, 0(k1) # get pointer to segment map 90 srl k0, k0, PGSHIFT - 2 # compute segment map index 91 and k0, k0, (NPTEPG - 1) << 2 92 beq k1, zero, 2f # invalid segment map 93 addu k1, k1, k0 # index into segment map 94 lw k0, 0(k1) # get page PTE 95 nop 96 beq k0, zero, 2f # dont load invalid entries 97 mtc0 k0, MIPS_COP_0_TLB_LOW 98 nop 99 tlbwr # update TLB 1001: 101 mfc0 k1, MIPS_COP_0_EXC_PC # get return address 102 nop 103 j k1 104 rfe 1052: 106 j mips1_SlowFault # handle the rest 107 nop 108 .set at 109VECTOR_END(mips1_UTLBMiss) 110 111 112/* 113 * mips1_exception 114 * 115 * Handles any exceptions other than reset and UTLB miss. This routine 116 * is copied down at 0x80000080 and total length must be less than 32 117 * instructions. No pc relative jump instruction is allowed. 118 */ 119VECTOR(mips1_exception, unknown) 120/* 121 * Find out what mode we came from and jump to the proper handler. 122 */ 123 .set noat 124 mfc0 k0, MIPS_COP_0_STATUS # get the status register 125 mfc0 k1, MIPS_COP_0_CAUSE # get the cause register 126 and k0, k0, MIPS1_SR_KU_PREV # test for user mode 127 sll k0, k0, 4 # shift user bit for cause index 128 and k1, k1, MIPS1_CR_EXC_CODE # mask out the cause bits 129 or k1, k1, k0 # change index to user table 1301: 131 la k0, mips1_excpt_sw # get base of the jump table 132 addu k0, k0, k1 # get the address of the 133 # function entry. Note that 134 # the cause is already 135 # shifted left by 2 bits so 136 # we dont have to shift 137 lw k0, 0(k0) # get the function address 138 nop 139 j k0 # jump to the function 140 nop 141 .set at 142VECTOR_END(mips1_exception) 143 144 145/* 146 * mips1_SlowFault 147 * 148 * UTLBMiss handler could not find out a TLB entry for the user process. 149 * Dispatch a general case exception handler. 150 */ 151mips1_SlowFault: 152 .set noat 153 mfc0 k1, MIPS_COP_0_STATUS 154 la k0, _C_LABEL(mips1_KernGenException) 155 and k1, k1, MIPS1_SR_KU_PREV 156 beq k1, zero, 1f 157 nop 158 la k0, _C_LABEL(mips1_UserGenException) 1591: j k0 160 nop 161 .set at 162 163/* 164 * mips1_KernGenException 165 * 166 * Handle an exception during kernel mode. 167 * Build trapframe on stack to hold interrupted kernel context, then 168 * call trap() to process the condition. 169 * 170 * trapframe is now pointed by 5th arg { 171 * register_t cf_args[4 + 1]; 172 * register_t cf_pad; 173 * register_t cf_sp; 174 * register_t cf_ra; 175 * mips_reg_t tf_regs[17]; - trapframe begins here 176 * mips_reg_t tf_sr; - 177 * mips_reg_t tf_mullo; - 178 * mips_reg_t tf_mulhi; - 179 * register_t tf_epc; - may be changed by trap() call 180 * }; 181 */ 182NESTED_NOPROFILE(mips1_KernGenException, KERNFRAME_SIZ, ra) 183 .set noat 184 .mask 0x80000000, -4 185#if defined(DDB) || defined(KGDB) 186 la k0, _C_LABEL(kdbaux) 187 sw s0, SF_REG_S0(k0) 188 sw s1, SF_REG_S1(k0) 189 sw s2, SF_REG_S2(k0) 190 sw s3, SF_REG_S3(k0) 191 sw s4, SF_REG_S4(k0) 192 sw s5, SF_REG_S5(k0) 193 sw s6, SF_REG_S6(k0) 194 sw s7, SF_REG_S7(k0) 195 sw sp, SF_REG_SP(k0) 196 sw s8, SF_REG_S8(k0) 197 sw gp, SF_REG_RA(k0) 198#endif 199/* 200 * Save the relevant kernel registers onto the stack. 201 * We don't need to save s0 - s8, sp and gp because 202 * the compiler does it for us. 203 */ 204 subu sp, sp, KERNFRAME_SIZ 205 sw AT, TF_BASE+TF_REG_AST(sp) 206 sw v0, TF_BASE+TF_REG_V0(sp) 207 sw v1, TF_BASE+TF_REG_V1(sp) 208 mflo v0 209 mfhi v1 210 sw a0, TF_BASE+TF_REG_A0(sp) 211 sw a1, TF_BASE+TF_REG_A1(sp) 212 sw a2, TF_BASE+TF_REG_A2(sp) 213 sw a3, TF_BASE+TF_REG_A3(sp) 214 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 215 sw t0, TF_BASE+TF_REG_T0(sp) 216 sw t1, TF_BASE+TF_REG_T1(sp) 217 sw t2, TF_BASE+TF_REG_T2(sp) 218 sw t3, TF_BASE+TF_REG_T3(sp) 219 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 220 sw t4, TF_BASE+TF_REG_T4(sp) 221 sw t5, TF_BASE+TF_REG_T5(sp) 222 sw t6, TF_BASE+TF_REG_T6(sp) 223 sw t7, TF_BASE+TF_REG_T7(sp) 224 mfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address 225 sw t8, TF_BASE+TF_REG_T8(sp) 226 sw t9, TF_BASE+TF_REG_T9(sp) 227 sw ra, TF_BASE+TF_REG_RA(sp) 228 sw a0, TF_BASE+TF_REG_SR(sp) 229 mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC 230 sw v0, TF_BASE+TF_REG_MULLO(sp) 231 sw v1, TF_BASE+TF_REG_MULHI(sp) 232 sw a3, TF_BASE+TF_REG_EPC(sp) 233 addu v0, sp, TF_BASE 234 sw v0, KERNFRAME_ARG5(sp) # 5th arg is p. to trapframe 235/* 236 * Call the trap handler. 237 */ 238#if defined(DDB) || defined(DEBUG) || defined(KGDB) 239 addu v0, sp, KERNFRAME_SIZ 240 sw v0, KERNFRAME_SP(sp) 241#endif 242 jal _C_LABEL(trap) 243 sw a3, KERNFRAME_RA(sp) # for debugging 244 245/* 246 * Restore registers and return from the exception. 247 */ 248 lw a0, TF_BASE+TF_REG_SR(sp) 249 lw t0, TF_BASE+TF_REG_MULLO(sp) 250 lw t1, TF_BASE+TF_REG_MULHI(sp) 251 mtc0 a0, MIPS_COP_0_STATUS 252 mtlo t0 253 mthi t1 254 lw k0, TF_BASE+TF_REG_EPC(sp) 255 lw AT, TF_BASE+TF_REG_AST(sp) 256 lw v0, TF_BASE+TF_REG_V0(sp) 257 lw v1, TF_BASE+TF_REG_V1(sp) 258 lw a0, TF_BASE+TF_REG_A0(sp) 259 lw a1, TF_BASE+TF_REG_A1(sp) 260 lw a2, TF_BASE+TF_REG_A2(sp) 261 lw a3, TF_BASE+TF_REG_A3(sp) 262 lw t0, TF_BASE+TF_REG_T0(sp) 263 lw t1, TF_BASE+TF_REG_T1(sp) 264 lw t2, TF_BASE+TF_REG_T2(sp) 265 lw t3, TF_BASE+TF_REG_T3(sp) 266 lw t4, TF_BASE+TF_REG_T4(sp) 267 lw t5, TF_BASE+TF_REG_T5(sp) 268 lw t6, TF_BASE+TF_REG_T6(sp) 269 lw t7, TF_BASE+TF_REG_T7(sp) 270 lw t8, TF_BASE+TF_REG_T8(sp) 271 lw t9, TF_BASE+TF_REG_T9(sp) 272 lw ra, TF_BASE+TF_REG_RA(sp) 273 addu sp, sp, KERNFRAME_SIZ 274#ifdef DDBnotyet 275 la k1, _C_LABEL(kdbaux) 276 lw s0, SF_REG_S0(k1) 277 lw s1, SF_REG_S1(k1) 278 lw s2, SF_REG_S2(k1) 279 lw s3, SF_REG_S3(k1) 280 lw s4, SF_REG_S4(k1) 281 lw s5, SF_REG_S5(k1) 282 lw s6, SF_REG_S6(k1) 283 lw s7, SF_REG_S7(k1) 284 lw sp, SF_REG_SP(k1) 285 lw s8, SF_REG_S8(k1) 286 lw gp, SF_REG_RA(k1) 287#endif 288 j k0 # return to interrupted point 289 rfe 290 .set at 291END(mips1_KernGenException) 292 293/* 294 * mips1_UserGenException 295 * 296 * Handle an exception during user mode. 297 * Save user context atop of kernel stack, then call trap() to process 298 * the condition. The context can be manipulated alternatively via 299 * curproc->p_md.md_regs. 300 */ 301NESTED_NOPROFILE(mips1_UserGenException, CALLFRAME_SIZ, ra) 302 .set noat 303 .mask 0x80000000, -4 304/* 305 * Save all the registers but the kernel temporaries onto stack. 306 */ 307 lw k1, _C_LABEL(curpcb) 308 nop 309 addu k1, k1, USPACE - FRAME_SIZ 310 sw AT, FRAME_AST(k1) 311 sw v0, FRAME_V0(k1) 312 sw v1, FRAME_V1(k1) 313 mflo v0 314 sw a0, FRAME_A0(k1) 315 sw a1, FRAME_A1(k1) 316 sw a2, FRAME_A2(k1) 317 sw a3, FRAME_A3(k1) 318 mfhi v1 319 sw t0, FRAME_T0(k1) 320 sw t1, FRAME_T1(k1) 321 sw t2, FRAME_T2(k1) 322 sw t3, FRAME_T3(k1) 323 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 324 sw t4, FRAME_T4(k1) 325 sw t5, FRAME_T5(k1) 326 sw t6, FRAME_T6(k1) 327 sw t7, FRAME_T7(k1) 328 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 329 sw s0, FRAME_S0(k1) 330 sw s1, FRAME_S1(k1) 331 sw s2, FRAME_S2(k1) 332 sw s3, FRAME_S3(k1) 333 mfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address 334 sw s4, FRAME_S4(k1) 335 sw s5, FRAME_S5(k1) 336 sw s6, FRAME_S6(k1) 337 sw s7, FRAME_S7(k1) 338 mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC 339 sw t8, FRAME_T8(k1) 340 sw t9, FRAME_T9(k1) 341 sw gp, FRAME_GP(k1) 342 sw sp, FRAME_SP(k1) 343 sw s8, FRAME_S8(k1) 344 sw ra, FRAME_RA(k1) 345 sw a0, FRAME_SR(k1) 346 sw v0, FRAME_MULLO(k1) 347 sw v1, FRAME_MULHI(k1) 348 sw a3, FRAME_EPC(k1) 349 addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP 350#ifdef __GP_SUPPORT__ 351 la gp, _C_LABEL(_gp) # switch to kernel GP 352#endif 353 .set at 354 and t0, a0, ~MIPS_SR_COP_1_BIT # turn off the FPU 355 .set noat 356#if defined(DDB) || defined(DEBUG) || defined(KGDB) 357 move ra, a3 358 sw ra, CALLFRAME_RA(sp) 359#endif 360/* 361 * Call the exception handler. 362 */ 363 jal _C_LABEL(trap) 364 mtc0 t0, MIPS_COP_0_STATUS 365/* 366 * Check pending asynchronous traps. 367 */ 368 lw t0, _C_LABEL(curproc) # t0 = curproc 369 nop 370 lw t0, P_MD_ASTPENDING(t0) # any pending ast? 371 nop 372 beq t0, zero, 1f # if no, skip ast processing 373 nop 374/* 375 * We have pending asynchronous traps; all the state is already saved. 376 */ 377 jal _C_LABEL(ast) 378 lw a0, CALLFRAME_SIZ + FRAME_EPC(sp) 3791: 380 la ra, _C_LABEL(mips1_xcpt_return) 381 j ra # pretend function return 382 nop 383 .set at 384END(mips1_UserGenException) 385 386/* 387 * mips1_SystemCall 388 * 389 * Save user context atop of kernel stack, then call syscall() to process 390 * the condition. The context can be manipulated alternatively via 391 * curproc->p_md.md_regs. 392 */ 393NESTED_NOPROFILE(mips1_SystemCall, CALLFRAME_SIZ, ra) 394 .set noat 395 .mask 0x80000000, -4 396/* 397 * Save all the registers but kernel temporaries onto stack. 398 */ 399 lw k1, _C_LABEL(curpcb) 400 nop 401 addu k1, k1, USPACE - FRAME_SIZ 402 #sw AT, FRAME_AST(k1) 403 .set at 404 sw v0, FRAME_V0(k1) # syscall # 405 sw v1, FRAME_V1(k1) # used by syscall() 406 mflo v0 407 sw a0, FRAME_A0(k1) 408 sw a1, FRAME_A1(k1) 409 sw a2, FRAME_A2(k1) 410 sw a3, FRAME_A3(k1) 411 lw a0, _C_LABEL(curproc) # 1st arg is curproc 412 mfhi v1 413 #sw t0, FRAME_T0(k1) # no need to save temp regs 414 #sw t1, FRAME_T1(k1) 415 #sw t2, FRAME_T2(k1) 416 #sw t3, FRAME_T3(k1) 417 mfc0 a1, MIPS_COP_0_STATUS # 2nd arg is STATUS 418 #sw t4, FRAME_T4(k1) 419 #sw t5, FRAME_T5(k1) 420 #sw t6, FRAME_T6(k1) 421 sw t7, FRAME_T7(k1) 422 mfc0 a2, MIPS_COP_0_CAUSE # 3rd arg is CAUSE 423 sw s0, FRAME_S0(k1) 424 sw s1, FRAME_S1(k1) 425 sw s2, FRAME_S2(k1) 426 sw s3, FRAME_S3(k1) 427 mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC 428 sw s4, FRAME_S4(k1) 429 sw s5, FRAME_S5(k1) 430 sw s6, FRAME_S6(k1) 431 sw s7, FRAME_S7(k1) 432 #sw t8, FRAME_T8(k1) 433 #sw t9, FRAME_T9(k1) 434 sw gp, FRAME_GP(k1) 435 sw sp, FRAME_SP(k1) 436 sw s8, FRAME_S8(k1) 437 sw ra, FRAME_RA(k1) 438 sw a1, FRAME_SR(k1) 439 sw v0, FRAME_MULLO(k1) 440 sw v1, FRAME_MULHI(k1) 441 sw a3, FRAME_EPC(k1) 442 addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP 443#ifdef __GP_SUPPORT__ 444 la gp, _C_LABEL(_gp) # switch to kernel GP 445#endif 446#if defined(DDB) || defined(DEBUG) || defined(KGDB) 447 move ra, a3 448 sw ra, CALLFRAME_RA(sp) 449#endif 450 lw t1, P_MD_SYSCALL(a0) # t1 = syscall 451 ori t0, a1, MIPS_SR_INT_IE # turn on IEc, enable intr. 452 and t0, t0, ~MIPS_SR_COP_1_BIT # turn off FPU 453/* 454 * Call the system call handler. 455 */ 456 jal t1 457 mtc0 t0, MIPS_COP_0_STATUS 458/* 459 * Check pending asynchronous traps. 460 */ 461 lw t0, _C_LABEL(curproc) # t0 = curproc 462 nop 463 lw t0, P_MD_ASTPENDING(t0) # any pending ast? 464 nop 465 beq t0, zero, 1f 466 nop 467/* 468 * We have pending asynchronous traps; all the state is already saved. 469 */ 470 jal _C_LABEL(ast) 471 lw a0, CALLFRAME_SIZ + FRAME_EPC(sp) 4721: 473 la ra, _C_LABEL(mips1_xcpt_return) 474 j ra # pretend function return 475 nop 476END(mips1_SystemCall) 477 478/* 479 * mips1_KernIntr 480 * 481 * Handle an interrupt from kernel mode. 482 * Build kernframe on stack to hold interrupted kernel context, then 483 * call cpu_intr() to process it. 484 * 485 */ 486NESTED_NOPROFILE(mips1_KernIntr, KERNFRAME_SIZ, ra) 487 .set noat 488 .mask 0x80000000, (CALLFRAME_RA - KERNFRAME_SIZ) 489 subu sp, sp, KERNFRAME_SIZ 490/* 491 * Save the relevant kernel registers onto the stack. 492 * We don't need to save s0 - s8 and sp because 493 * the compiler does it for us. 494 */ 495 sw AT, TF_BASE+TF_REG_AST(sp) 496 sw v0, TF_BASE+TF_REG_V0(sp) 497 sw v1, TF_BASE+TF_REG_V1(sp) 498 mflo v0 499 mfhi v1 500 sw a0, TF_BASE+TF_REG_A0(sp) 501 sw a1, TF_BASE+TF_REG_A1(sp) 502 sw a2, TF_BASE+TF_REG_A2(sp) 503 sw a3, TF_BASE+TF_REG_A3(sp) 504 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 505 sw t0, TF_BASE+TF_REG_T0(sp) 506 sw t1, TF_BASE+TF_REG_T1(sp) 507 sw t2, TF_BASE+TF_REG_T2(sp) 508 sw t3, TF_BASE+TF_REG_T3(sp) 509 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 510 sw t4, TF_BASE+TF_REG_T4(sp) 511 sw t5, TF_BASE+TF_REG_T5(sp) 512 sw t6, TF_BASE+TF_REG_T6(sp) 513 sw t7, TF_BASE+TF_REG_T7(sp) 514 mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is exception PC 515 sw t8, TF_BASE+TF_REG_T8(sp) 516 sw t9, TF_BASE+TF_REG_T9(sp) 517 sw ra, TF_BASE+TF_REG_RA(sp) 518 sw a0, TF_BASE+TF_REG_SR(sp) 519 and a3, a0, a1 # 4th is STATUS & CAUSE 520 sw v0, TF_BASE+TF_REG_MULLO(sp) 521 sw v1, TF_BASE+TF_REG_MULHI(sp) 522 sw a2, TF_BASE+TF_REG_EPC(sp) 523#if defined(DDB) || defined(DEBUG) || defined(KGDB) 524 move ra, a2 525 sw ra, KERNFRAME_RA(sp) # for debugging 526#endif 527/* 528 * Call the interrupt handler. 529 */ 530 jal _C_LABEL(cpu_intr) 531 nop 532/* 533 * Restore registers and return from the interrupt. 534 */ 535 lw a0, TF_BASE+TF_REG_SR(sp) 536 lw t0, TF_BASE+TF_REG_MULLO(sp) 537 lw t1, TF_BASE+TF_REG_MULHI(sp) 538 mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts 539 mtlo t0 540 mthi t1 541 lw k0, TF_BASE+TF_REG_EPC(sp) # restore exception PC 542 lw AT, TF_BASE+TF_REG_AST(sp) 543 lw v0, TF_BASE+TF_REG_V0(sp) 544 lw v1, TF_BASE+TF_REG_V1(sp) 545 lw a0, TF_BASE+TF_REG_A0(sp) 546 lw a1, TF_BASE+TF_REG_A1(sp) 547 lw a2, TF_BASE+TF_REG_A2(sp) 548 lw a3, TF_BASE+TF_REG_A3(sp) 549 lw t0, TF_BASE+TF_REG_T0(sp) 550 lw t1, TF_BASE+TF_REG_T1(sp) 551 lw t2, TF_BASE+TF_REG_T2(sp) 552 lw t3, TF_BASE+TF_REG_T3(sp) 553 lw t4, TF_BASE+TF_REG_T4(sp) 554 lw t5, TF_BASE+TF_REG_T5(sp) 555 lw t6, TF_BASE+TF_REG_T6(sp) 556 lw t7, TF_BASE+TF_REG_T7(sp) 557 lw t8, TF_BASE+TF_REG_T8(sp) 558 lw t9, TF_BASE+TF_REG_T9(sp) 559 lw ra, TF_BASE+TF_REG_RA(sp) 560 addu sp, sp, KERNFRAME_SIZ # restore kernel SP 561 j k0 # return to interrupted point 562 rfe 563 .set at 564END(mips1_KernIntr) 565 566/*---------------------------------------------------------------------------- 567 * XXX this comment block should be updated XXX 568 * mips1_UserIntr -- 569 * 570 * Handle an interrupt from user mode. 571 * Note: we save minimal state in the u.u_pcb struct and use the standard 572 * kernel stack since there has to be a u page if we came from user mode. 573 * If there is a pending software interrupt, then save the remaining state 574 * and call softintr(). This is all because if we call switch() inside 575 * cpu_intr(), not all the user registers have been saved in u.u_pcb. 576 * 577 * Results: 578 * None. 579 * 580 * Side effects: 581 * None. 582 * 583 *---------------------------------------------------------------------------- 584 */ 585NESTED_NOPROFILE(mips1_UserIntr, CALLFRAME_SIZ, ra) 586 .set noat 587 .mask 0x80000000, -4 588/* 589 * Save the relevant user registers onto the stack. 590 * We don't need to save s0 - s8 because the compiler does it for us. 591 */ 592 lw k1, _C_LABEL(curpcb) 593 nop 594 addu k1, k1, USPACE - FRAME_SIZ 595 sw AT, FRAME_AST(k1) 596 sw v0, FRAME_V0(k1) 597 sw v1, FRAME_V1(k1) 598 mflo v0 599 sw a0, FRAME_A0(k1) 600 sw a1, FRAME_A1(k1) 601 sw a2, FRAME_A2(k1) 602 sw a3, FRAME_A3(k1) 603 mfhi v1 604 sw t0, FRAME_T0(k1) 605 sw t1, FRAME_T1(k1) 606 sw t2, FRAME_T2(k1) 607 sw t3, FRAME_T3(k1) 608 mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS 609 sw t4, FRAME_T4(k1) 610 sw t5, FRAME_T5(k1) 611 sw t6, FRAME_T6(k1) 612 sw t7, FRAME_T7(k1) 613 mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE 614 sw t8, FRAME_T8(k1) 615 sw t9, FRAME_T9(k1) 616 sw gp, FRAME_GP(k1) 617 sw sp, FRAME_SP(k1) 618 mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is exception PC 619 sw ra, FRAME_RA(k1) 620 sw a0, FRAME_SR(k1) 621 sw v0, FRAME_MULLO(k1) 622 sw v1, FRAME_MULHI(k1) 623 and a3, a0, a1 # 4th is STATUS & CAUSE 624 sw a2, FRAME_EPC(k1) 625 addu sp, k1, -CALLFRAME_SIZ # switch to kernel SP 626#ifdef __GP_SUPPORT__ 627 la gp, _C_LABEL(_gp) # switch to kernel GP 628#endif 629 .set at 630 and t0, a0, ~MIPS_SR_COP_1_BIT # turn off the FPU 631 .set noat 632#if defined(DDB) || defined(DEBUG) || defined(KGDB) 633 move ra, a2 634 sw ra, CALLFRAME_RA(sp) # for debugging 635#endif 636/* 637 * Call the interrupt handler. 638 */ 639 jal _C_LABEL(cpu_intr) 640 mtc0 t0, MIPS_COP_0_STATUS 641/* 642 * Check pending asynchoronous traps. 643 */ 644 lw v0, _C_LABEL(curproc) # v0 = curproc 645 addu a1, sp, CALLFRAME_SIZ 646 lw a0, FRAME_SR(a1) 647 lw v0, P_MD_ASTPENDING(v0) # any pending ast? 648 mtc0 a0, MIPS_COP_0_STATUS # restore SR, disable intrs 649 beq v0, zero, 1f # if no, skip ast processing 650 nop # -delay slot- 651/* 652 * We have pending asynchronous traps; save remaining user state in stack. 653 */ 654 sw s0, FRAME_S0(a1) 655 sw s1, FRAME_S1(a1) 656 sw s2, FRAME_S2(a1) 657 sw s3, FRAME_S3(a1) 658 sw s4, FRAME_S4(a1) 659 sw s5, FRAME_S5(a1) 660 sw s6, FRAME_S6(a1) 661 sw s7, FRAME_S7(a1) 662 sw s8, FRAME_S8(a1) 663 664 lw a0, FRAME_EPC(a1) # argument is interrupted PC 665 li t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE 666 jal _C_LABEL(ast) 667 mtc0 t0, MIPS_COP_0_STATUS # enable interrupts (spl0) 668 669 addu a1, sp, CALLFRAME_SIZ 670 lw a0, FRAME_SR(a1) 671 lw s0, FRAME_S0(a1) 672 mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts 673 lw s1, FRAME_S1(a1) 674 lw s2, FRAME_S2(a1) 675 lw s3, FRAME_S3(a1) 676 lw s4, FRAME_S4(a1) 677 lw s5, FRAME_S5(a1) 678 lw s6, FRAME_S6(a1) 679 lw s7, FRAME_S7(a1) 680 lw s8, FRAME_S8(a1) 6811: 682 lw v0, FRAME_MULLO(a1) 683 lw v1, FRAME_MULHI(a1) 684 mtlo v0 685 mthi v1 686 move k1, a1 687 lw k0, FRAME_EPC(k1) # exception PC 688 lw AT, FRAME_AST(k1) 689 lw v0, FRAME_V0(k1) 690 lw v1, FRAME_V1(k1) 691 lw a0, FRAME_A0(k1) 692 lw a1, FRAME_A1(k1) 693 lw a2, FRAME_A2(k1) 694 lw a3, FRAME_A3(k1) 695 lw t0, FRAME_T0(k1) 696 lw t1, FRAME_T1(k1) 697 lw t2, FRAME_T2(k1) 698 lw t3, FRAME_T3(k1) 699 lw t4, FRAME_T4(k1) 700 lw t5, FRAME_T5(k1) 701 lw t6, FRAME_T6(k1) 702 lw t7, FRAME_T7(k1) 703 lw t8, FRAME_T8(k1) 704 lw t9, FRAME_T9(k1) 705 lw gp, FRAME_GP(k1) 706 lw sp, FRAME_SP(k1) 707 lw ra, FRAME_RA(k1) 708 j k0 # return to interrupted point 709 rfe 710 .set at 711END(mips1_UserIntr) 712 713/* 714 * Mark where code entreed from exception hander jumptable 715 * ends, for stack traceback code. 716 */ 717 718 .globl _C_LABEL(mips1_exceptionentry_end) 719_C_LABEL(mips1_exceptionentry_end): 720 721 722#if 0 723/*---------------------------------------------------------------------------- 724 * 725 * mips1_TLBModException -- 726 * 727 * Handle a TLB modified exception. 728 * The BaddVAddr, Context, and EntryHi registers contain the failed 729 * virtual address. 730 * 731 * Results: 732 * None. 733 * 734 * Side effects: 735 * None. 736 * 737 *---------------------------------------------------------------------------- 738 */ 739LEAF_NOPROFILE(mips1_TLBModException) 740 .set noat 741 tlbp # find the TLB entry 742 mfc0 k0, MIPS_COP_0_TLB_LOW # get the physical address 743 mfc0 k1, MIPS_COP_0_TLB_INDEX # check to be sure its valid 744 or k0, k0, MIPS1_TLB_DIRTY_BIT # update TLB 745 blt k1, zero, 4f # not found!!! 746 mtc0 k0, MIPS_COP_0_TLB_LOW 747 li k1, MIPS_KSEG0_START 748 subu k0, k0, k1 749 srl k0, k0, MIPS1_TLB_PHYS_PAGE_SHIFT 750 la k1, pmap_attributes 751 addu k0, k0, k1 752 lbu k1, 0(k0) # fetch old value 753 nop 754 or k1, k1, 1 # set modified bit 755 sb k1, 0(k0) # save new value 756 mfc0 k0, MIPS_COP_0_EXC_PC # get return address 757 nop 758 j k0 759 rfe 7604: 761 break 0 # panic 762 .set at 763END(mips1_TLBModException) 764#endif 765 766/*---------------------------------------------------------------------------- 767 * 768 * mips1_TLBMissException -- 769 * 770 * Handle a TLB miss exception from kernel mode. 771 * The BaddVAddr, Context, and EntryHi registers contain the failed 772 * virtual address. 773 * 774 * Results: 775 * None. 776 * 777 * Side effects: 778 * None. 779 * 780 *---------------------------------------------------------------------------- 781 */ 782LEAF_NOPROFILE(mips1_TLBMissException) 783 .set noat 784 mfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address 785 li k1, VM_MIN_KERNEL_ADDRESS # compute index 786 subu k0, k0, k1 787 lw k1, _C_LABEL(Sysmapsize) # index within range? 788 srl k0, k0, PGSHIFT 789 sltu k1, k0, k1 790 beq k1, zero, outofworld # No. falling beyond... 791 nop 792 lw k1, _C_LABEL(Sysmap) 793 sll k0, k0, 2 # compute offset from index 794 addu k1, k1, k0 795 lw k0, 0(k1) # get PTE entry 796 mfc0 k1, MIPS_COP_0_EXC_PC # get return address 797 mtc0 k0, MIPS_COP_0_TLB_LOW # save PTE entry 798 and k0, k0, MIPS1_PG_V # check for valid entry 799 beq k0, zero, _C_LABEL(mips1_KernGenException) # PTE invalid 800 nop 801 tlbwr # update TLB 802 j k1 803 rfe 804 805outofworld: 806 /* Ensure we have a valid sp so panic has a chance */ 807 move a1, sp 808 la sp, start # set sp to a valid place 809 PANIC("TLB out of universe: ksp was %p") 810 .set at 811END(mips1_TLBMissException) 812 813 814/*-------------------------------------------------------------------------- 815 * 816 * mips1_SetPID -- 817 * 818 * Write the given pid into the TLB pid reg. 819 * 820 * mips1_SetPID(pid) 821 * int pid; 822 * 823 * Results: 824 * None. 825 * 826 * Side effects: 827 * PID set in the entry hi register. 828 * 829 *-------------------------------------------------------------------------- 830 */ 831LEAF(mips1_SetPID) 832 sll a0, a0, MIPS1_TLB_PID_SHIFT # put PID in right spot 833 mtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value 834 j ra 835 nop 836END(mips1_SetPID) 837 838 839/*-------------------------------------------------------------------------- 840 * 841 * mips1_TLBUpdate -- 842 * 843 * Update the TLB if highreg is found; otherwise, enter the data. 844 * 845 * mips1_TLBUpdate(highreg, lowreg) 846 * unsigned highreg, lowreg; 847 * 848 * Results: 849 * None. 850 * 851 * Side effects: 852 * None. 853 * 854 *-------------------------------------------------------------------------- 855 */ 856LEAF(mips1_TLBUpdate) 857 mfc0 v1, MIPS_COP_0_STATUS # save the status register 858 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 859 nop 860 mfc0 t0, MIPS_COP_0_TLB_HI # save current PID 861 nop 862 mtc0 a0, MIPS_COP_0_TLB_HI # set entryhi 863 nop 864 tlbp # probe the existence 865 mfc0 v0, MIPS_COP_0_TLB_INDEX # see what we got 866 mtc0 a1, MIPS_COP_0_TLB_LOW # set new entrylo 867 bgez v0, 2f # index < 0 => !found 868 nop 869 b 3f 870 tlbwr # add vicitimizing another 8712: 872 tlbwi # update the existing one 8733: 874 mtc0 t0, MIPS_COP_0_TLB_HI # restore current PID 875 j ra 876 mtc0 v1, MIPS_COP_0_STATUS 877END(mips1_TLBUpdate) 878 879/*-------------------------------------------------------------------------- 880 * 881 * mips1_TLBRead -- 882 * 883 * Read the TLB entry. 884 * 885 * mips1_TLBRead(entry, tlb) 886 * unsigned entry; 887 * struct mips1_tlb *tlb; 888 * 889 * Results: 890 * Returns MIPS1 TLB HI/LO in a pair. 891 * 892 *-------------------------------------------------------------------------- 893 */ 894LEAF(mips1_TLBRead) 895 mfc0 v1, MIPS_COP_0_STATUS # Save the status register. 896 mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts 897 mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID 898 899 sll a0, a0, MIPS1_TLB_INDEX_SHIFT 900 mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register 901 nop 902 tlbr # Read from the TLB 903 mfc0 t2, MIPS_COP_0_TLB_HI # fetch the hi entry 904 mfc0 t3, MIPS_COP_0_TLB_LOW # fetch the low entry 905 sw t2, 0(a1) 906 sw t3, 4(a1) 907 908 mtc0 t0, MIPS_COP_0_TLB_HI # restore PID 909 j ra 910 mtc0 v1, MIPS_COP_0_STATUS # Restore the status register 911END(mips1_TLBRead) 912 913/*---------------------------------------------------------------------------- 914 * 915 * R3000 cache sizing and flushing code. 916 * 917 *---------------------------------------------------------------------------- 918 */ 919#ifndef ENABLE_MIPS_TX3900 920/* 921 * void mips1_wbflush(void) 922 * 923 * Drain processor's write buffer, normally used to ensure any I/O 924 * register write operations are done before subsequent manipulations. 925 * 926 * Some hardware implementations have a WB chip independent from CPU 927 * core, and CU0 (Coprocessor Usability #0) bit of CP0 status register 928 * is wired to indicate writebuffer condition. This code does busy-loop 929 * while CU0 bit indicates false condition. 930 * 931 * For other hardwares which have the writebuffer logic is implemented 932 * in a system controller ASIC chip, wbflush operation would done 933 * differently. 934 */ 935LEAF(mips1_wbflush) 936 nop 937 nop 938 nop 939 nop 9401: bc0f 1b 941 nop 942 j ra 943 nop 944END(mips1_wbflush) 945#else /* !ENABLE_MIPS_TX3900 */ 946/* 947 * The differences between R3900 and R3000. 948 * 1. Cache system 949 * Physical-index physical-tag 950 * fixed line-size 951 * refil-size 4/8/16/32 words (set in config register) 952 * TX3912 953 * Write-through 954 * I-cache 4KB/16B direct mapped (256line) 955 * D-cache 1KB/4B 2-way sa (128line) 956 * Cache snoop 957 * TX3922 958 * Write-through/write-back (set in config register) 959 * I-cache 16KB/16B 2-way sa 960 * D-cache 8KB/16B 2-way sa 961 * Cache snoop 962 * 963 * 2. Coprocessor1 964 * 2.1 cache operation. 965 * R3900 uses MIPSIII cache op like method. 966 * 2.2 R3900 specific CP0 register. 967 * (mips/include/r3900regs.h overrides cpuregs.h) 968 * 2.3 # of TLB entries 969 * TX3912 32 entries 970 * TX3922 64 entries 971 * 972 * 3. System address map 973 * kseg2 0xff000000-0xfffeffff is reserved. 974 * (mips/include/vmparam.h) 975 * 976 * + If defined both MIPS1 and ENABLE_MIPS_TX3900, it generates kernel for 977 * R3900. If defined MIPS1 only, No R3900 feature include. 978 * + R3920 core has write-back mode. but it is always disabled in NetBSD. 979 */ 980 981LEAF_NOPROFILE(tx3900_cp0_config_read) 982 mfc0 v0, R3900_COP_0_CONFIG 983 j ra 984 nop 985END(tx3900_cp0_config_read) 986 987LEAF(mips1_wbflush) 988 sync 989 j ra 990 nop 991END(mips1_wbflush) 992#endif /* !ENABLE_MIPS_TX3900 */ 993 994/* 995 * mips1_proc_trampoline 996 * 997 * Special arrangement for a process about to go user mode right after 998 * fork() system call. When the first CPU tick is scheduled to the 999 * forked child, it starts running from here. Then, a service function 1000 * is called with one argument supplied to complete final preparations, 1001 * and the process returns to user mode as if the fork() system call is 1002 * handled in a normal way. No need to save any registers although this 1003 * calls another. 1004 */ 1005LEAF(mips1_proc_trampoline) 1006 addu sp, sp, -CALLFRAME_SIZ 1007 jal ra, s0 1008 move a0, s1 1009 .set noat 1010XLEAF(mips1_xcpt_return) 1011 addu a1, sp, CALLFRAME_SIZ # a1 points exception frame 1012 lw a0, FRAME_SR(a1) 1013 lw t0, FRAME_MULLO(a1) 1014 lw t1, FRAME_MULHI(a1) 1015 mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts 1016 mtlo t0 1017 mthi t1 1018 nop 1019 move k1, a1 1020 lw k0, FRAME_EPC(k1) 1021 lw AT, FRAME_AST(k1) 1022 lw v0, FRAME_V0(k1) 1023 lw v1, FRAME_V1(k1) 1024 lw a0, FRAME_A0(k1) 1025 lw a1, FRAME_A1(k1) 1026 lw a2, FRAME_A2(k1) 1027 lw a3, FRAME_A3(k1) 1028 lw t0, FRAME_T0(k1) 1029 lw t1, FRAME_T1(k1) 1030 lw t2, FRAME_T2(k1) 1031 lw t3, FRAME_T3(k1) 1032 lw t4, FRAME_T4(k1) 1033 lw t5, FRAME_T5(k1) 1034 lw t6, FRAME_T6(k1) 1035 lw t7, FRAME_T7(k1) 1036 lw s0, FRAME_S0(k1) 1037 lw s1, FRAME_S1(k1) 1038 lw s2, FRAME_S2(k1) 1039 lw s3, FRAME_S3(k1) 1040 lw s4, FRAME_S4(k1) 1041 lw s5, FRAME_S5(k1) 1042 lw s6, FRAME_S6(k1) 1043 lw s7, FRAME_S7(k1) 1044 lw t8, FRAME_T8(k1) 1045 lw t9, FRAME_T9(k1) 1046 lw gp, FRAME_GP(k1) 1047 lw s8, FRAME_S8(k1) 1048 lw ra, FRAME_RA(k1) 1049 lw sp, FRAME_SP(k1) 1050 nop 1051 j k0 1052 rfe 1053 .set at 1054END(mips1_proc_trampoline) 1055 1056/* 1057 * void mips1_cpu_switch_resume(struct proc *newproc) 1058 * 1059 * Wiredown the USPACE of newproc with TLB entry#0 and #1. Check 1060 * if target USPACE is already refered by any TLB entry before 1061 * doing that, and make sure TBIS(them) in the case. 1062 */ 1063LEAF_NOPROFILE(mips1_cpu_switch_resume) 1064 lw a1, P_MD_UPTE_0(a0) # a1 = upte[0] 1065 lw a2, P_MD_UPTE_1(a0) # a2 = upte[1] 1066 lw s0, P_ADDR(a0) # va = p->p_addr 1067 li s2, MIPS_KSEG2_START 1068 blt s0, s2, resume 1069 nop 1070 1071 mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va 1072 nop 1073 tlbp # probe 1st VPN 1074 mfc0 s1, MIPS_COP_0_TLB_INDEX 1075 nop 1076 bltz s1, entry0set 1077 li s1, MIPS_KSEG0_START # found, then 1078 mtc0 s1, MIPS_COP_0_TLB_HI 1079 mtc0 zero, MIPS_COP_0_TLB_LOW 1080 nop 1081 tlbwi # TBIS(va) 1082 nop 1083 mtc0 s0, MIPS_COP_0_TLB_HI # set 1st VPN again 1084entry0set: 1085 mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB index #0 1086 ori a1, a1, MIPS1_PG_G 1087 mtc0 a1, MIPS_COP_0_TLB_LOW # 1st PFN w/ PG_G 1088 nop 1089 tlbwi # set TLB entry #0 1090 1091 addu s0, s0, NBPG 1092 mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va+NBPG 1093 nop 1094 tlbp # probe 2nd VPN 1095 mfc0 s1, MIPS_COP_0_TLB_INDEX 1096 nop 1097 bltz s1, entry1set 1098 li s1, MIPS_KSEG0_START # found, then 1099 mtc0 s1, MIPS_COP_0_TLB_HI 1100 mtc0 zero, MIPS_COP_0_TLB_LOW 1101 nop 1102 tlbwi # TBIS(va+NBPG) 1103 nop 1104 mtc0 s0, MIPS_COP_0_TLB_HI # set 2nd VPN again 1105entry1set: 1106 li s1, 1 << MIPS1_TLB_INDEX_SHIFT 1107 mtc0 s1, MIPS_COP_0_TLB_INDEX # TLB index #1 1108 ori a2, a2, MIPS1_PG_G 1109 mtc0 a2, MIPS_COP_0_TLB_LOW # 2nd PFN w/ PG_G 1110 nop 1111 tlbwi # set TLB entry #1 1112 1113resume: 1114 j ra 1115 nop 1116 END(mips1_cpu_switch_resume) 1117 1118/* 1119 * void mips1_TBIS(vaddr_t va) 1120 * 1121 * Invalidate a TLB entry for given virtual address if found in TLB. 1122 */ 1123LEAF(mips1_TBIS) 1124 mfc0 v1, MIPS_COP_0_STATUS # save status register 1125 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 1126 mfc0 t0, MIPS_COP_0_TLB_HI # save current PID 1127 nop 1128 1129 mtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID 1130 nop 1131 tlbp # probe the entry in question 1132 mfc0 a0, MIPS_COP_0_TLB_INDEX # see what we got 1133 li t1, MIPS_KSEG0_START # load invalid address 1134 bltz a0, 1f # index < 0 then skip 1135 mtc0 t1, MIPS_COP_0_TLB_HI # make entryHi invalid 1136 mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo 1137 nop 1138 tlbwi 11391: 1140 mtc0 t0, MIPS_COP_0_TLB_HI # restore PID 1141 j ra 1142 mtc0 v1, MIPS_COP_0_STATUS # restore the status register 1143 END(mips1_TBIS) 1144 1145/* 1146 * void mips1_TBIAP(int sizeofTLB) 1147 * 1148 * Invalidate TLB entries belong to per process user spaces while 1149 * leaving entries for kernel space marked global intact. 1150 */ 1151LEAF(mips1_TBIAP) 1152 mfc0 v1, MIPS_COP_0_STATUS # save status register 1153 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 1154 1155 li t1, MIPS1_TLB_FIRST_RAND_ENTRY << MIPS1_TLB_INDEX_SHIFT 1156 sll t2, a0, MIPS1_TLB_INDEX_SHIFT 1157 li v0, MIPS_KSEG0_START # invalid address 1158 1159 # do {} while (t1 < t2) 11601: 1161 mtc0 t1, MIPS_COP_0_TLB_INDEX # set index 1162 nop 1163 tlbr # obtain an entry 1164 mfc0 a0, MIPS_COP_0_TLB_LOW 1165 nop 1166 and a0, a0, MIPS1_PG_G # check to see it has G bit 1167 bnez a0, 2f 1168 nop 1169 mtc0 v0, MIPS_COP_0_TLB_HI # make entryHi invalid 1170 mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo 1171 nop 1172 tlbwi # invalidate the TLB entry 11732: 1174 addu t1, t1, 1 << MIPS1_TLB_INDEX_SHIFT # increment index 1175 bne t1, t2, 1b 1176 nop 1177 1178 j ra # new TLBpid will be set soon 1179 mtc0 v1, MIPS_COP_0_STATUS # restore status register 1180 END(mips1_TBIAP) 1181 1182/* 1183 * void mips1_TBIA(int sizeofTLB) 1184 * 1185 * Invalidate TLB entirely. 1186 */ 1187LEAF(mips1_TBIA) 1188 mfc0 v1, MIPS_COP_0_STATUS # save the status register. 1189 mtc0 zero, MIPS_COP_0_STATUS # disable interrupts 1190 1191 li t1, MIPS_KSEG0_START 1192 mtc0 t1, MIPS_COP_0_TLB_HI # make entryHi invalid 1193 mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo 1194 1195 move t1, zero 1196 sll a0, a0, MIPS1_TLB_INDEX_SHIFT 1197 1198 # do {} while (t1 < a0) 11991: 1200 mtc0 t1, MIPS_COP_0_TLB_INDEX # set TLBindex 1201 addu t1, t1, 1 << MIPS1_TLB_INDEX_SHIFT # increment index 1202 bne t1, a0, 1b 1203 tlbwi # invalidate the entry 1204 1205 j ra 1206 mtc0 v1, MIPS_COP_0_STATUS # restore status register 1207 END(mips1_TBIA) 1208 1209 .data 1210 1211 .globl _C_LABEL(mips1_locoresw) 1212_C_LABEL(mips1_locoresw): 1213 .word _C_LABEL(mips1_cpu_switch_resume) 1214 .word _C_LABEL(mips1_proc_trampoline) 1215 .word _C_LABEL(mips_idle) 1216 1217mips1_excpt_sw: 1218 #### 1219 #### The kernel exception handlers. 1220 #### 1221 .word _C_LABEL(mips1_KernIntr) # 0 external interrupt 1222 .word _C_LABEL(mips1_KernGenException) # 1 TLB modification 1223 .word _C_LABEL(mips1_TLBMissException) # 2 TLB miss (LW/I-fetch) 1224 .word _C_LABEL(mips1_TLBMissException) # 3 TLB miss (SW) 1225 .word _C_LABEL(mips1_KernGenException) # 4 address error (LW/I-fetch) 1226 .word _C_LABEL(mips1_KernGenException) # 5 address error (SW) 1227 .word _C_LABEL(mips1_KernGenException) # 6 bus error (I-fetch) 1228 .word _C_LABEL(mips1_KernGenException) # 7 bus error (load or store) 1229 .word _C_LABEL(mips1_KernGenException) # 8 system call 1230 .word _C_LABEL(mips1_KernGenException) # 9 breakpoint 1231 .word _C_LABEL(mips1_KernGenException) # 10 reserved instruction 1232 .word _C_LABEL(mips1_KernGenException) # 11 coprocessor unusable 1233 .word _C_LABEL(mips1_KernGenException) # 12 arithmetic overflow 1234 .word _C_LABEL(mips1_KernGenException) # 13 r3k reserved 1235 .word _C_LABEL(mips1_KernGenException) # 14 r3k reserved 1236 .word _C_LABEL(mips1_KernGenException) # 15 r3k reserved 1237 .word _C_LABEL(mips1_KernGenException) # 16 never happens w/ MIPS1 1238 .word _C_LABEL(mips1_KernGenException) # 17 never happens w/ MIPS1 1239 .word _C_LABEL(mips1_KernGenException) # 18 never happens w/ MIPS1 1240 .word _C_LABEL(mips1_KernGenException) # 19 never happens w/ MIPS1 1241 .word _C_LABEL(mips1_KernGenException) # 20 never happens w/ MIPS1 1242 .word _C_LABEL(mips1_KernGenException) # 21 never happens w/ MIPS1 1243 .word _C_LABEL(mips1_KernGenException) # 22 never happens w/ MIPS1 1244 .word _C_LABEL(mips1_KernGenException) # 23 never happens w/ MIPS1 1245 .word _C_LABEL(mips1_KernGenException) # 24 never happens w/ MIPS1 1246 .word _C_LABEL(mips1_KernGenException) # 25 never happens w/ MIPS1 1247 .word _C_LABEL(mips1_KernGenException) # 26 never happens w/ MIPS1 1248 .word _C_LABEL(mips1_KernGenException) # 27 never happens w/ MIPS1 1249 .word _C_LABEL(mips1_KernGenException) # 28 never happens w/ MIPS1 1250 .word _C_LABEL(mips1_KernGenException) # 29 never happens w/ MIPS1 1251 .word _C_LABEL(mips1_KernGenException) # 30 never happens w/ MIPS1 1252 .word _C_LABEL(mips1_KernGenException) # 31 never happens w/ MIPS1 1253 ##### 1254 ##### The user exception handlers. 1255 ##### 1256 .word _C_LABEL(mips1_UserIntr) # 0 1257 .word _C_LABEL(mips1_UserGenException) # 1 1258 .word _C_LABEL(mips1_UserGenException) # 2 1259 .word _C_LABEL(mips1_UserGenException) # 3 1260 .word _C_LABEL(mips1_UserGenException) # 4 1261 .word _C_LABEL(mips1_UserGenException) # 5 1262 .word _C_LABEL(mips1_UserGenException) # 6 1263 .word _C_LABEL(mips1_UserGenException) # 7 1264 .word _C_LABEL(mips1_SystemCall) # 8 1265 .word _C_LABEL(mips1_UserGenException) # 9 1266 .word _C_LABEL(mips1_UserGenException) # 10 1267 .word _C_LABEL(mips1_UserGenException) # 11 1268 .word _C_LABEL(mips1_UserGenException) # 12 1269 .word _C_LABEL(mips1_UserGenException) # 13 1270 .word _C_LABEL(mips1_UserGenException) # 14 1271 .word _C_LABEL(mips1_UserGenException) # 15 1272 .word _C_LABEL(mips1_UserGenException) # 16 1273 .word _C_LABEL(mips1_UserGenException) # 17 1274 .word _C_LABEL(mips1_UserGenException) # 18 1275 .word _C_LABEL(mips1_UserGenException) # 19 1276 .word _C_LABEL(mips1_UserGenException) # 20 1277 .word _C_LABEL(mips1_UserGenException) # 21 1278 .word _C_LABEL(mips1_UserGenException) # 22 1279 .word _C_LABEL(mips1_UserGenException) # 23 1280 .word _C_LABEL(mips1_UserGenException) # 24 1281 .word _C_LABEL(mips1_UserGenException) # 25 1282 .word _C_LABEL(mips1_UserGenException) # 26 1283 .word _C_LABEL(mips1_UserGenException) # 27 1284 .word _C_LABEL(mips1_UserGenException) # 28 1285 .word _C_LABEL(mips1_UserGenException) # 29 1286 .word _C_LABEL(mips1_UserGenException) # 20 1287 .word _C_LABEL(mips1_UserGenException) # 31 1288