1 /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */ 2 /*- 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Digital Equipment Corporation and Ralph Campbell. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Copyright (C) 1989 Digital Equipment Corporation. 34 * Permission to use, copy, modify, and distribute this software and 35 * its documentation for any purpose and without fee is hereby granted, 36 * provided that the above copyright notice appears in all copies. 37 * Digital Equipment Corporation makes no representations about the 38 * suitability of this software for any purpose. It is provided "as is" 39 * without express or implied warranty. 40 * 41 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 42 * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 43 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 44 * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 45 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 46 * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 47 * 48 * from: @(#)locore.s 8.5 (Berkeley) 1/4/94 49 * JNPR: tlb.S,v 1.1.4.2 2007/09/10 09:02:05 girish 50 * $FreeBSD: releng/8.1/sys/mips/mips/tlb.S 178172 2008-04-13 07:27:37Z imp $ 51 */ 52 53 /* 54 * Contains code that is the first executed at boot time plus 55 * assembly language support routines. 56 */ 57 58 #include "opt_cputype.h" 59 60 #include 61 #include 62 #include 63 #include 64 #include 65 66 #include "assym.s" 67 68 #if defined(ISA_MIPS32) 69 #undef WITH_64BIT_CP0 70 #elif defined(ISA_MIPS64) 71 #define WITH_64BIT_CP0 72 #elif defined(ISA_MIPS3) 73 #define WITH_64BIT_CP0 74 #else 75 #error "Please write the code for this ISA" 76 #endif 77 78 #ifdef WITH_64BIT_CP0 79 #define _SLL dsll 80 #define _SRL dsrl 81 #define _MFC0 dmfc0 82 #define _MTC0 dmtc0 83 #define WIRED_SHIFT 34 84 #define PAGE_SHIFT 34 85 #else 86 #define _SLL sll 87 #define _SRL srl 88 #define _MFC0 mfc0 89 #define _MTC0 mtc0 90 #define WIRED_SHIFT 2 91 #define PAGE_SHIFT 2 92 #endif 93 .set noreorder # Noreorder is default style! 94 #if defined(ISA_MIPS32) 95 .set mips32 96 #elif defined(ISA_MIPS64) 97 .set mips64 98 #elif defined(ISA_MIPS3) 99 .set mips3 100 #endif 101 102 #define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; 103 104 /* 105 * FREEBSD_DEVELOPERS_FIXME 106 * Some MIPS CPU may need delays using nops between executing CP0 Instructions 107 */ 108 #define MIPS_CPU_NOP_DELAY nop;nop;nop;nop; 109 110 /*-------------------------------------------------------------------------- 111 * 112 * Mips_TLBWriteIndexed(unsigned index, tlb *tlb); 113 * 114 * Write the given entry into the TLB at the given index. 115 * 116 * Results: 117 * None. 118 * 119 * Side effects: 120 * TLB entry set. 121 * 122 *-------------------------------------------------------------------------- 123 */ 124 LEAF(Mips_TLBWriteIndexed) 125 mfc0 v1, COP_0_STATUS_REG # Save the status register. 126 mtc0 zero, COP_0_STATUS_REG # Disable interrupts 127 ITLBNOPFIX 128 lw a2, 8(a1) 129 lw a3, 12(a1) 130 _MFC0 t0, COP_0_TLB_HI # Save the current PID. 131 132 _MTC0 a2, COP_0_TLB_LO0 # Set up entry low0. 133 _MTC0 a3, COP_0_TLB_LO1 # Set up entry low1. 134 lw a2, 0(a1) 135 lw a3, 4(a1) 136 mtc0 a0, COP_0_TLB_INDEX # Set the index. 137 _MTC0 a2, COP_0_TLB_PG_MASK # Set up entry mask. 138 _MTC0 a3, COP_0_TLB_HI # Set up entry high. 139 MIPS_CPU_NOP_DELAY 140 tlbwi # Write the TLB 141 MIPS_CPU_NOP_DELAY 142 143 _MTC0 t0, COP_0_TLB_HI # Restore the PID. 144 nop 145 _MTC0 zero, COP_0_TLB_PG_MASK # Default mask value. 146 mtc0 v1, COP_0_STATUS_REG # Restore the status register 147 ITLBNOPFIX 148 j ra 149 nop 150 END(Mips_TLBWriteIndexed) 151 152 /*-------------------------------------------------------------------------- 153 * 154 * Mips_SetPID(int pid); 155 * 156 * Write the given pid into the TLB pid reg. 157 * 158 * Results: 159 * None. 160 * 161 * Side effects: 162 * PID set in the entry hi register. 163 * 164 *-------------------------------------------------------------------------- 165 */ 166 LEAF(Mips_SetPID) 167 _MTC0 a0, COP_0_TLB_HI # Write the hi reg value 168 nop # required for QED5230 169 nop # required for QED5230 170 j ra 171 nop 172 END(Mips_SetPID) 173 174 /*-------------------------------------------------------------------------- 175 * 176 * Mips_SetWIRED(int wired); 177 * 178 * Write the given value into the TLB wired reg. 179 * 180 * Results: 181 * None. 182 * 183 * Side effects: 184 * WIRED set in the wired register. 185 * 186 *-------------------------------------------------------------------------- 187 */ 188 LEAF(Mips_SetWIRED) 189 mtc0 a0, COP_0_TLB_WIRED 190 j ra 191 nop 192 END(Mips_SetWIRED) 193 194 /*-------------------------------------------------------------------------- 195 * 196 * Mips_GetWIRED(void); 197 * 198 * Get the value from the TLB wired reg. 199 * 200 * Results: 201 * Value of wired reg. 202 * 203 * Side effects: 204 * None. 205 * 206 *-------------------------------------------------------------------------- 207 */ 208 LEAF(Mips_GetWIRED) 209 mfc0 v0, COP_0_TLB_WIRED 210 j ra 211 nop 212 END(Mips_GetWIRED) 213 214 /*-------------------------------------------------------------------------- 215 * 216 * Mips_TLBFlush(tlbsize); 217 * 218 * Flush the "random" entries from the TLB. 219 * Uses "wired" register to determine what register to start with. 220 * Arg "tlbsize" is the number of entries to flush. 221 * 222 * Results: 223 * None. 224 * 225 * Side effects: 226 * The TLB is flushed. 227 * 228 *-------------------------------------------------------------------------- 229 */ 230 LEAF(Mips_TLBFlush) 231 mfc0 v1, COP_0_STATUS_REG # Save the status register. 232 mtc0 zero, COP_0_STATUS_REG # Disable interrupts 233 ITLBNOPFIX 234 mfc0 t1, COP_0_TLB_WIRED 235 li v0, MIPS_KSEG3_START + 0x0fff0000 # invalid address 236 _MFC0 t0, COP_0_TLB_HI # Save the PID 237 238 _MTC0 v0, COP_0_TLB_HI # Mark entry high as invalid 239 _MTC0 zero, COP_0_TLB_LO0 # Zero out low entry0. 240 _MTC0 zero, COP_0_TLB_LO1 # Zero out low entry1. 241 mtc0 zero, COP_0_TLB_PG_MASK # Zero out mask entry. 242 /* 243 * Align the starting value (t1) and the upper bound (a0). 244 */ 245 1: 246 mtc0 t1, COP_0_TLB_INDEX # Set the index register. 247 ITLBNOPFIX 248 _MTC0 t0, COP_0_TLB_HI # Restore the PID 249 addu t1, t1, 1 # Increment index. 250 addu t0, t0, 8 * 1024 251 MIPS_CPU_NOP_DELAY 252 tlbwi # Write the TLB entry. 253 MIPS_CPU_NOP_DELAY 254 bne t1, a0, 1b 255 nop 256 257 _MTC0 t0, COP_0_TLB_HI # Restore the PID 258 mtc0 v1, COP_0_STATUS_REG # Restore the status register 259 ITLBNOPFIX 260 j ra 261 nop 262 END(Mips_TLBFlush) 263 264 265 /*-------------------------------------------------------------------------- 266 * 267 * Mips_TLBFlushAddr(unsigned TLBhi); 268 * 269 * Flush any TLB entries for the given address and TLB PID. 270 * 271 * Results: 272 * None. 273 * 274 * Side effects: 275 * The process's page is flushed from the TLB. 276 * 277 *-------------------------------------------------------------------------- 278 */ 279 LEAF(Mips_TLBFlushAddr) 280 mfc0 v1, COP_0_STATUS_REG # Save the status register. 281 mtc0 zero, COP_0_STATUS_REG # Disable interrupts 282 ITLBNOPFIX 283 li v0, (PTE_HVPN | PTE_ASID) 284 and a0, a0, v0 # Make shure valid hi value. 285 _MFC0 t0, COP_0_TLB_HI # Get current PID 286 mfc0 t3, COP_0_TLB_PG_MASK # Save current pgMask 287 _MTC0 a0, COP_0_TLB_HI # look for addr & PID 288 MIPS_CPU_NOP_DELAY 289 tlbp # Probe for the entry. 290 MIPS_CPU_NOP_DELAY 291 mfc0 v0, COP_0_TLB_INDEX # See what we got 292 li t1, MIPS_KSEG0_START + 0x0fff0000 293 bltz v0, 1f # index < 0 => !found 294 nop 295 # Load invalid entry, each TLB entry should have it's own bogus 296 # address calculated by following expression: 297 # MIPS_KSEG0_START + 0x0fff0000 + 2 * i * PAGE_SIZE; 298 # One bogus value for every TLB entry might cause MCHECK exception 299 sll v0, PAGE_SHIFT + 1 300 addu t1, v0 301 _MTC0 t1, COP_0_TLB_HI # Mark entry high as invalid 302 303 _MTC0 zero, COP_0_TLB_LO0 # Zero out low entry. 304 _MTC0 zero, COP_0_TLB_LO1 # Zero out low entry. 305 MIPS_CPU_NOP_DELAY 306 tlbwi 307 MIPS_CPU_NOP_DELAY 308 1: 309 _MTC0 t0, COP_0_TLB_HI # restore PID 310 mtc0 t3, COP_0_TLB_PG_MASK # Restore pgMask 311 mtc0 v1, COP_0_STATUS_REG # Restore the status register 312 ITLBNOPFIX 313 j ra 314 nop 315 END(Mips_TLBFlushAddr) 316 317 /*-------------------------------------------------------------------------- 318 * 319 * Mips_TLBUpdate(unsigned virpageadr, lowregx); 320 * 321 * Update the TLB if highreg is found; otherwise, enter the data. 322 * 323 * Results: 324 * < 0 if loaded >= 0 if updated. 325 * 326 * Side effects: 327 * None. 328 * 329 *-------------------------------------------------------------------------- 330 */ 331 LEAF(Mips_TLBUpdate) 332 mfc0 v1, COP_0_STATUS_REG # Save the status register. 333 mtc0 zero, COP_0_STATUS_REG # Disable interrupts 334 ITLBNOPFIX 335 and t1, a0, 0x1000 # t1 = Even/Odd flag 336 li v0, (PTE_HVPN | PTE_ASID) 337 and a0, a0, v0 338 _MFC0 t0, COP_0_TLB_HI # Save current PID 339 _MTC0 a0, COP_0_TLB_HI # Init high reg 340 and a2, a1, PTE_G # Copy global bit 341 MIPS_CPU_NOP_DELAY 342 tlbp # Probe for the entry. 343 _SLL a1, a1, WIRED_SHIFT 344 _SRL a1, a1, WIRED_SHIFT 345 nop 346 mfc0 v0, COP_0_TLB_INDEX # See what we got 347 bne t1, zero, 2f # Decide even odd 348 # EVEN 349 nop 350 bltz v0, 1f # index < 0 => !found 351 MIPS_CPU_NOP_DELAY 352 353 tlbr # update, read entry first 354 MIPS_CPU_NOP_DELAY 355 _MTC0 a1, COP_0_TLB_LO0 # init low reg0. 356 MIPS_CPU_NOP_DELAY 357 tlbwi # update slot found 358 b 4f 359 nop 360 1: 361 mtc0 zero, COP_0_TLB_PG_MASK # init mask. 362 _MTC0 a0, COP_0_TLB_HI # init high reg. 363 _MTC0 a1, COP_0_TLB_LO0 # init low reg0. 364 _MTC0 a2, COP_0_TLB_LO1 # init low reg1. 365 MIPS_CPU_NOP_DELAY 366 tlbwr # enter into a random slot 367 MIPS_CPU_NOP_DELAY 368 b 4f 369 nop 370 # ODD 371 2: 372 nop 373 bltz v0, 3f # index < 0 => !found 374 MIPS_CPU_NOP_DELAY 375 376 tlbr # read the entry first 377 MIPS_CPU_NOP_DELAY 378 _MTC0 a1, COP_0_TLB_LO1 # init low reg1. 379 MIPS_CPU_NOP_DELAY 380 tlbwi # update slot found 381 MIPS_CPU_NOP_DELAY 382 b 4f 383 nop 384 3: 385 mtc0 zero, COP_0_TLB_PG_MASK # init mask. 386 _MTC0 a0, COP_0_TLB_HI # init high reg. 387 _MTC0 a2, COP_0_TLB_LO0 # init low reg0. 388 _MTC0 a1, COP_0_TLB_LO1 # init low reg1. 389 MIPS_CPU_NOP_DELAY 390 tlbwr # enter into a random slot 391 392 4: # Make shure pipeline 393 MIPS_CPU_NOP_DELAY 394 _MTC0 t0, COP_0_TLB_HI # restore PID 395 mtc0 v1, COP_0_STATUS_REG # Restore the status register 396 ITLBNOPFIX 397 j ra 398 nop 399 END(Mips_TLBUpdate) 400 401 /*-------------------------------------------------------------------------- 402 * 403 * Mips_TLBRead(unsigned entry, struct tlb *tlb); 404 * 405 * Read the TLB entry. 406 * 407 * Results: 408 * None. 409 * 410 * Side effects: 411 * tlb will contain the TLB entry found. 412 * 413 *-------------------------------------------------------------------------- 414 */ 415 LEAF(Mips_TLBRead) 416 mfc0 v1, COP_0_STATUS_REG # Save the status register. 417 mtc0 zero, COP_0_STATUS_REG # Disable interrupts 418 ITLBNOPFIX 419 _MFC0 t0, COP_0_TLB_HI # Get current PID 420 421 mtc0 a0, COP_0_TLB_INDEX # Set the index register 422 MIPS_CPU_NOP_DELAY 423 tlbr # Read from the TLB 424 MIPS_CPU_NOP_DELAY 425 mfc0 t2, COP_0_TLB_PG_MASK # fetch the hi entry 426 _MFC0 t3, COP_0_TLB_HI # fetch the hi entry 427 _MFC0 t4, COP_0_TLB_LO0 # See what we got 428 _MFC0 t5, COP_0_TLB_LO1 # See what we got 429 _MTC0 t0, COP_0_TLB_HI # restore PID 430 MIPS_CPU_NOP_DELAY 431 mtc0 v1, COP_0_STATUS_REG # Restore the status register 432 ITLBNOPFIX 433 sw t2, 0(a1) 434 sw t3, 4(a1) 435 sw t4, 8(a1) 436 j ra 437 sw t5, 12(a1) 438 END(Mips_TLBRead) 439 440 /*-------------------------------------------------------------------------- 441 * 442 * Mips_TLBGetPID(void); 443 * 444 * Results: 445 * Returns the current TLB pid reg. 446 * 447 * Side effects: 448 * None. 449 * 450 *-------------------------------------------------------------------------- 451 */ 452 LEAF(Mips_TLBGetPID) 453 _MFC0 v0, COP_0_TLB_HI # get PID 454 j ra 455 and v0, v0, VMTLB_PID # mask off PID 456 END(Mips_TLBGetPID) 457 458 459 460 /*-------------------------------------------------------------------------- 461 * 462 * void mips_TBIAP(int sizeofTLB); 463 * 464 * Invalidate TLB entries belong to per process user spaces while 465 * leaving entries for kernel space marked global intact. 466 * 467 *-------------------------------------------------------------------------- 468 */ 469 LEAF(mips_TBIAP) 470 mfc0 v1, COP_0_STATUS_REG # save status register 471 mtc0 zero, COP_0_STATUS_REG # disable interrupts 472 473 _MFC0 t4, COP_0_TLB_HI # Get current PID 474 move t2, a0 475 mfc0 t1, COP_0_TLB_WIRED 476 li v0, MIPS_KSEG0_START + 0x0fff0000 # invalid address 477 mfc0 t3, COP_0_TLB_PG_MASK # save current pgMask 478 479 # do {} while (t1 < t2) 480 1: 481 mtc0 t1, COP_0_TLB_INDEX # set index 482 MIPS_CPU_NOP_DELAY 483 tlbr # obtain an entry 484 MIPS_CPU_NOP_DELAY 485 _MFC0 a0, COP_0_TLB_LO1 486 and a0, a0, PTE_G # check to see it has G bit 487 bnez a0, 2f 488 nop 489 490 _MTC0 v0, COP_0_TLB_HI # make entryHi invalid 491 _MTC0 zero, COP_0_TLB_LO0 # zero out entryLo0 492 _MTC0 zero, COP_0_TLB_LO1 # zero out entryLo1 493 mtc0 zero, COP_0_TLB_PG_MASK # zero out mask entry 494 MIPS_CPU_NOP_DELAY 495 tlbwi # invalidate the TLB entry 496 2: 497 addu t1, t1, 1 498 addu v0, 1 << (PAGE_SHIFT + 1) 499 bne t1, t2, 1b 500 nop 501 502 _MTC0 t4, COP_0_TLB_HI # restore PID 503 mtc0 t3, COP_0_TLB_PG_MASK # restore pgMask 504 MIPS_CPU_NOP_DELAY 505 mtc0 v1, COP_0_STATUS_REG # restore status register 506 j ra # new ASID will be set soon 507 nop 508 .set mips2 509 END(mips_TBIAP)