1/* $NetBSD: locore_mips3.S,v 1.84 2002/11/08 00:49:32 simonb 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#include "opt_lockdebug.h" 90#include "opt_kgdb.h" 91 92#include <sys/cdefs.h> 93 94#include <mips/asm.h> 95#include <mips/cpuregs.h> 96#include <machine/param.h> 97#include <machine/endian.h> 98 99#include "assym.h" 100 101/* 102 * XXX We need a cleaner way of handling the instruction hazards of 103 * the various processors. Here are the relevant rules for the QED 52XX: 104 * tlbw[ri] -- two integer ops beforehand 105 * tlbr -- two integer ops beforehand 106 * tlbp -- two integer ops beforehand 107 * mtc0 [PageMask,EntryHi,Cp0] -- two integer ops afterwards 108 * changing JTLB -- two integer ops afterwards 109 * mtc0 [EPC,ErrorEPC,Status] -- two int ops afterwards before eret 110 * config.k0 -- five int ops before kseg0, ckseg0 memref 111 * 112 * For the IDT R4000, some hazards are: 113 * mtc0/mfc0 one integer op before and after 114 * tlbp -- one integer op afterwards 115 * Obvious solution is to take least common denominator. 116 * 117 * For the Toshiba R5900, TX79: 118 * mtc0 following sync.p 119 * tlbw[ri], tlbp following sync.p or eret 120 * for those CPU, define COP0_SYNC as sync.p 121 */ 122 123/* 124 *============================================================================ 125 * 126 * MIPS III ISA support, part 1: locore exception vectors. 127 * The following code is copied to the vector locations to which 128 * the CPU jumps in response to an exception or a TLB miss. 129 * 130 *============================================================================ 131 */ 132 .set noreorder 133 .set mips3 134 135 .text 136 137/*---------------------------------------------------------------------------- 138 * 139 * mips3_wbflush -- 140 * 141 * Return when the write buffer is empty. 142 * 143 * Common for all MIPS3 and greater ISAs 144 * 145 * Results: 146 * None. 147 * 148 * Side effects: 149 * None. 150 * 151 *---------------------------------------------------------------------------- 152 */ 153LEAF(mips3_wbflush) 154XLEAF(mips5900_wbflush) 155XLEAF(mips32_wbflush) 156XLEAF(mips64_wbflush) 157 nop 158 sync 159 j ra 160 nop 161END(mips3_wbflush) 162 163 164/* XXX simonb: ugg, another ugly #ifdef check... */ 165#if (defined(MIPS3) && !defined(MIPS3_5900)) || defined(MIPS32) || defined(MIPS64) 166/* 167 * mips_wait_idle: 168 * 169 * When no processes are on the runq, cpu_switch branches to 170 * idle to wait for something to come ready. 171 * 172 * NOTE: This is really part of cpu_switch(), but defined here 173 * for kernel profiling. 174 * 175 * This version takes advantage of power-saving features on 176 * the QED RM52xx family of CPUs, and MIPS32 & MIPS64 CPUs. 177 */ 178LEAF(mips_wait_idle) 179 sw zero, _C_LABEL(curproc) # set curproc NULL for stats 180#if defined(LOCKDEBUG) 181 jal _C_LABEL(sched_unlock_idle) # release sched_lock 182 nop 183#endif 184 li t0, (MIPS_INT_MASK | MIPS_SR_INT_IE) 185 DYNAMIC_STATUS_MASK(t0,t1) # machine dependent masking 186 mtc0 t0, MIPS_COP_0_STATUS # enable all interrupts 187 COP0_SYNC 188 nop 189 190 /* Try to zero some free pages. */ 191 lw t0, _C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO 192 nop 193 beq t0, zero, 1f 194 nop 195 jal _C_LABEL(uvm_pageidlezero) 196 nop 1971: 198#ifdef MIPS_DYNAMIC_STATUS_MASK 199 # Do this again since the mask may have changed. 200 li t3, (MIPS_INT_MASK | MIPS_SR_INT_IE) 201 DYNAMIC_STATUS_MASK(t3,t1) # machine dependent masking 202 mtc0 t3, MIPS_COP_0_STATUS # enable all interrupts 203 COP0_SYNC 204 nop 205#endif 206 lw t0, _C_LABEL(sched_whichqs) # look for non-empty queue 207 bne t0, zero, 1f 208 nop 209 wait 210 nop 211 nop 212 nop 213 b 1b 214 nop 2151: 216#if defined(LOCKDEBUG) 217 mtc0 zero, MIPS_COP_0_STATUS # disable all interrupts 218 COP0_SYNC 219 nop 220 nop 221 nop 222 nop 223 jal _C_LABEL(sched_lock_idle) # acquire sched_lock 224 nop 225 la ra, cpu_switch_queuescan 226 j ra 227 nop 228#else 229 mtc0 zero, MIPS_COP_0_STATUS # disable all interrupts 230 COP0_SYNC 231 nop 232 nop 233 nop 234 la ra, cpu_switch_queuescan 235 j ra 236 nop 237#endif 238END(mips_wait_idle) 239#endif /* (MIPS3 && !MIPS3_5900) || MIPS32 || MIPS64 */ 240 241/* 242 * u_int32_t mips3_cp0_compare_read(void) 243 * 244 * Return the current value of the CP0 Compare register. 245 */ 246LEAF(mips3_cp0_compare_read) 247 mfc0 v0, MIPS_COP_0_COMPARE 248 j ra 249 nop 250END(mips3_cp0_compare_read) 251 252/* 253 * void mips3_cp0_compare_write(u_int32_t) 254 * 255 * Set the value of the CP0 Compare register. 256 */ 257LEAF(mips3_cp0_compare_write) 258 mtc0 a0, MIPS_COP_0_COMPARE 259 COP0_SYNC 260 nop 261 nop 262 j ra 263 nop 264END(mips3_cp0_compare_write) 265 266/* 267 * u_int32_t mips3_cp0_config_read(void) 268 * 269 * Return the current value of the CP0 Config register. 270 */ 271LEAF(mips3_cp0_config_read) 272 mfc0 v0, MIPS_COP_0_CONFIG 273 j ra 274 nop 275END(mips3_cp0_config_read) 276 277/* 278 * void mips3_cp0_config_write(u_int32_t) 279 * 280 * Set the value of the CP0 Config register. 281 */ 282LEAF(mips3_cp0_config_write) 283 mtc0 a0, MIPS_COP_0_CONFIG 284 COP0_SYNC 285 nop 286 nop 287 j ra 288 nop 289END(mips3_cp0_config_write) 290 291#if defined(MIPS32) || defined(MIPS64) 292/* 293 * u_int32_t mipsNN_cp0_config1_read(void) 294 * 295 * Return the current value of the CP0 Config (Select 1) register. 296 */ 297LEAF(mipsNN_cp0_config1_read) 298 .set push 299 .set mips32 300 mfc0 v0, MIPS_COP_0_CONFIG, 1 301 j ra 302 nop 303 .set pop 304END(mipsNN_cp0_config1_read) 305 306/* 307 * u_int32_t mipsNN_cp0_config1_write(u_int32_t) 308 * 309 * Return the current value of the CP0 Config (Select 1) register. 310 */ 311LEAF(mipsNN_cp0_config1_write) 312 .set push 313 .set mips32 314 mtc0 v0, MIPS_COP_0_CONFIG, 1 315 nop 316 j ra 317 nop 318 .set pop 319END(mipsNN_cp0_config1_write) 320 321/* 322 * u_int32_t mipsNN_cp0_config2_read(void) 323 * 324 * Return the current value of the CP0 Config (Select 2) register. 325 */ 326LEAF(mipsNN_cp0_config2_read) 327 .set push 328 .set mips32 329 mfc0 v0, MIPS_COP_0_CONFIG, 2 330 j ra 331 nop 332 .set pop 333END(mipsNN_cp0_config2_read) 334 335/* 336 * u_int32_t mipsNN_cp0_config3_read(void) 337 * 338 * Return the current value of the CP0 Config (Select 3) register. 339 */ 340LEAF(mipsNN_cp0_config3_read) 341 .set push 342 .set mips32 343 mfc0 v0, MIPS_COP_0_CONFIG, 3 344 j ra 345 nop 346 .set pop 347END(mipsNN_cp0_config3_read) 348#endif /* MIPS32 || MIPS64 */ 349 350/* 351 * u_int32_t mips3_cp0_count_read(void) 352 * 353 * Return the current value of the CP0 Count register. 354 */ 355LEAF(mips3_cp0_count_read) 356 mfc0 v0, MIPS_COP_0_COUNT 357 j ra 358 nop 359END(mips3_cp0_count_read) 360 361/* 362 * void mips3_cp0_count_write(u_int32_t) 363 * 364 * Set the value of the CP0 Count register. 365 */ 366LEAF(mips3_cp0_count_write) 367 mtc0 a0, MIPS_COP_0_COUNT 368 COP0_SYNC 369 nop 370 nop 371 j ra 372 nop 373END(mips3_cp0_count_write) 374 375/* 376 * u_int32_t mips3_cp0_wired_read(void) 377 * 378 * Return the current value of the CP0 Wired register. 379 */ 380LEAF(mips3_cp0_wired_read) 381 mfc0 v0, MIPS_COP_0_TLB_WIRED 382 j ra 383 nop 384END(mips3_cp0_wired_read) 385 386/* 387 * void mips3_cp0_wired_write(u_int32_t) 388 * 389 * Set the value of the CP0 Wired register. 390 */ 391LEAF(mips3_cp0_wired_write) 392 mtc0 a0, MIPS_COP_0_TLB_WIRED 393 COP0_SYNC 394 nop 395 nop 396 j ra 397 nop 398END(mips3_cp0_wired_write) 399 400#if defined(_MIPS_BSD_API) && \ 401 (_MIPS_BSD_API == _MIPS_BSD_API_N32 || _MIPS_BSD_API == _MIPS_BSD_API_LP64) 402#error mips3_ld and mips3_sd should be adjusted for N32 or LP64 403#endif 404 405LEAF(mips3_ld) 406#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32 407 mfc0 t0, MIPS_COP_0_STATUS # turn of interrupts 408 and t1, t0, ~(MIPS_SR_INT_IE) 409 mtc0 t1, MIPS_COP_0_STATUS 410 COP0_SYNC 411 nop 412 nop 413 nop 414#endif 415 416 ld v0, 0(a0) 417#if _BYTE_ORDER == _BIG_ENDIAN 418 dsll v1, v0, 32 419 dsra v1, v1, 32 # low word in v1 420 dsra v0, v0, 32 # high word in v0 421#else 422 dsra v1, v0, 32 # high word in v1 423 dsll v0, v0, 32 424 dsra v0, v0, 32 # low word in v0 425#endif 426 427#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32 428 mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 429 COP0_SYNC 430 nop 431#endif 432 433 jr ra 434 nop 435END(mips3_ld) 436 437LEAF(mips3_sd) 438#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32 439 mfc0 t0, MIPS_COP_0_STATUS # turn of interrupts 440 and t1, t0, ~(MIPS_SR_INT_IE) 441 mtc0 t1, MIPS_COP_0_STATUS 442 COP0_SYNC 443 nop 444 nop 445 nop 446#endif 447 448 # NOTE: a1 is padding! 449 450#if _BYTE_ORDER == _BIG_ENDIAN 451 dsll a2, a2, 32 # high word in a2 452 dsll a3, a3, 32 # low word in a3 453 dsrl a3, a3, 32 454#else 455 dsll a2, a2, 32 # low word in a2 456 dsrl a2, a2, 32 457 dsll a3, a3, 32 # high word in a3 458#endif 459 or a1, a2, a3 460 sd a1, 0(a0) 461 462#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32 463 mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 464 COP0_SYNC 465 nop 466#endif 467 468 jr ra 469 nop 470END(mips3_sd) 471 472/* 473 * int badaddr64(uint64_t addr, int len) 474 * See if access to addr with a len type instruction causes a machine check. 475 * len is length of access in bytes (can be 1, 2, 4, or 8). 476 */ 477#if defined(_MIPS_BSD_API) && _MIPS_BSD_API != _MIPS_BSD_API_LP32 478LEAF(badaddr64) 479 lw v1, _C_LABEL(curpcb) 480 la v0, _C_LABEL(baderr64) 481 482 /* Enable KX */ 483 mfc0 t0, MIPS_COP_0_STATUS 484 or t1, t0, MIPS3_SR_KX 485 mtc0 t1, MIPS_COP_0_STATUS 486 COP0_SYNC 487 488#if _BYTE_ORDER == _BIG_ENDIAN 489 dsll a0, a0, 32 # high word in a0 490 dsll a1, a1, 32 # low word in a1 491 dsrl a1, a1, 32 492#else 493 dsll a0, a0, 32 # low word in a2 494 dsrl a0, a0, 32 495 dsll a1, a1, 32 # high word in a3 496#endif 497 or a0, a0, a1 498 499 bne a2, 1, 2f 500 sw v0, U_PCB_ONFAULT(v1) 501 b 9f 502 lbu v0, (a0) 5032: 504 bne a2, 2, 4f 505 nop 506 b 9f 507 lhu v0, (a0) 5084: 509 bne a2, 4, 8f 510 nop 511 b 9f 512 lw v0, (a0) 5138: 514 ld v0, (a0) 5159: 516 mtc0 t0, MIPS_COP_0_STATUS # Restore KX 517 COP0_SYNC 518 sw zero, U_PCB_ONFAULT(v1) 519 j ra 520 move v0, zero # made it w/o errors 521END(badaddr64) 522 523LEAF(baderr64) 524 mtc0 t0, MIPS_COP_0_STATUS # Restore KX 525 COP0_SYNC 526 sw zero, U_PCB_ONFAULT(v1) 527 j ra 528 li v0, -1 529END(baderr64) 530#endif 531