1 1.116 riastrad /* $NetBSD: locore_mips3.S,v 1.116 2023/02/23 14:56:00 riastradh Exp $ */ 2 1.2 castor 3 1.2 castor /* 4 1.2 castor * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) 5 1.2 castor * All rights reserved. 6 1.2 castor * 7 1.2 castor * Redistribution and use in source and binary forms, with or without 8 1.2 castor * modification, are permitted provided that the following conditions 9 1.2 castor * are met: 10 1.2 castor * 1. Redistributions of source code must retain the above copyright 11 1.2 castor * notice, this list of conditions and the following disclaimer. 12 1.2 castor * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 castor * notice, this list of conditions and the following disclaimer in the 14 1.2 castor * documentation and/or other materials provided with the distribution. 15 1.2 castor * 3. All advertising materials mentioning features or use of this software 16 1.2 castor * must display the following acknowledgement: 17 1.2 castor * This product includes software developed by Jonathan R. Stone for 18 1.2 castor * the NetBSD Project. 19 1.2 castor * 4. The name of the author may not be used to endorse or promote products 20 1.2 castor * derived from this software without specific prior written permission. 21 1.2 castor * 22 1.2 castor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 23 1.2 castor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.2 castor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.2 castor * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 26 1.2 castor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.2 castor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.2 castor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.2 castor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.2 castor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.2 castor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.2 castor * SUCH DAMAGE. 33 1.2 castor */ 34 1.2 castor 35 1.2 castor /* 36 1.2 castor * Copyright (c) 1992, 1993 37 1.2 castor * The Regents of the University of California. All rights reserved. 38 1.2 castor * 39 1.2 castor * This code is derived from software contributed to Berkeley by 40 1.2 castor * Digital Equipment Corporation and Ralph Campbell. 41 1.2 castor * 42 1.2 castor * Redistribution and use in source and binary forms, with or without 43 1.2 castor * modification, are permitted provided that the following conditions 44 1.2 castor * are met: 45 1.2 castor * 1. Redistributions of source code must retain the above copyright 46 1.2 castor * notice, this list of conditions and the following disclaimer. 47 1.2 castor * 2. Redistributions in binary form must reproduce the above copyright 48 1.2 castor * notice, this list of conditions and the following disclaimer in the 49 1.2 castor * documentation and/or other materials provided with the distribution. 50 1.86 agc * 3. Neither the name of the University nor the names of its contributors 51 1.2 castor * may be used to endorse or promote products derived from this software 52 1.2 castor * without specific prior written permission. 53 1.2 castor * 54 1.2 castor * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 1.2 castor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 1.2 castor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 1.2 castor * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 1.2 castor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 1.2 castor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 1.2 castor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 1.2 castor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 1.2 castor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 1.2 castor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 1.2 castor * SUCH DAMAGE. 65 1.2 castor * 66 1.2 castor * Copyright (C) 1989 Digital Equipment Corporation. 67 1.2 castor * Permission to use, copy, modify, and distribute this software and 68 1.2 castor * its documentation for any purpose and without fee is hereby granted, 69 1.2 castor * provided that the above copyright notice appears in all copies. 70 1.2 castor * Digital Equipment Corporation makes no representations about the 71 1.2 castor * suitability of this software for any purpose. It is provided "as is" 72 1.2 castor * without express or implied warranty. 73 1.2 castor * 74 1.2 castor * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, 75 1.2 castor * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) 76 1.2 castor * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, 77 1.2 castor * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) 78 1.2 castor * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, 79 1.2 castor * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) 80 1.2 castor * 81 1.2 castor * @(#)locore.s 8.5 (Berkeley) 1/4/94 82 1.2 castor */ 83 1.29 soren #include "opt_cputype.h" 84 1.18 soren #include "opt_ddb.h" 85 1.82 simonb #include "opt_lockdebug.h" 86 1.97 matt #include "opt_multiprocessor.h" 87 1.68 lukem #include "opt_kgdb.h" 88 1.18 soren 89 1.18 soren #include <sys/cdefs.h> 90 1.100 matt #include <sys/endian.h> 91 1.18 soren 92 1.2 castor #include <mips/asm.h> 93 1.3 nisimura #include <mips/cpuregs.h> 94 1.2 castor 95 1.116 riastrad RCSID("$NetBSD: locore_mips3.S,v 1.116 2023/02/23 14:56:00 riastradh Exp $") 96 1.113 skrll 97 1.2 castor #include "assym.h" 98 1.2 castor 99 1.2 castor /* 100 1.2 castor * XXX We need a cleaner way of handling the instruction hazards of 101 1.2 castor * the various processors. Here are the relevant rules for the QED 52XX: 102 1.2 castor * tlbw[ri] -- two integer ops beforehand 103 1.2 castor * tlbr -- two integer ops beforehand 104 1.2 castor * tlbp -- two integer ops beforehand 105 1.2 castor * mtc0 [PageMask,EntryHi,Cp0] -- two integer ops afterwards 106 1.2 castor * changing JTLB -- two integer ops afterwards 107 1.32 soren * mtc0 [EPC,ErrorEPC,Status] -- two int ops afterwards before eret 108 1.2 castor * config.k0 -- five int ops before kseg0, ckseg0 memref 109 1.2 castor * 110 1.2 castor * For the IDT R4000, some hazards are: 111 1.2 castor * mtc0/mfc0 one integer op before and after 112 1.2 castor * tlbp -- one integer op afterwards 113 1.2 castor * Obvious solution is to take least common denominator. 114 1.2 castor */ 115 1.2 castor 116 1.2 castor /* 117 1.2 castor *============================================================================ 118 1.2 castor * 119 1.76 simonb * MIPS III ISA support, part 1: locore exception vectors. 120 1.76 simonb * The following code is copied to the vector locations to which 121 1.76 simonb * the CPU jumps in response to an exception or a TLB miss. 122 1.2 castor * 123 1.76 simonb *============================================================================ 124 1.2 castor */ 125 1.76 simonb .set noreorder 126 1.110 macallan #if (__mips < 3) || __mips_o32 127 1.76 simonb .set mips3 128 1.105 matt #endif 129 1.74 shin 130 1.99 matt #ifdef _LP64 131 1.99 matt #define _MFC0 dmfc0 132 1.99 matt #define _MTC0 dmtc0 133 1.99 matt #else 134 1.99 matt #define _MFC0 mfc0 135 1.99 matt #define _MTC0 mtc0 136 1.99 matt #endif 137 1.99 matt 138 1.74 shin .text 139 1.2 castor 140 1.2 castor /*---------------------------------------------------------------------------- 141 1.2 castor * 142 1.2 castor * mips3_wbflush -- 143 1.2 castor * 144 1.2 castor * Return when the write buffer is empty. 145 1.2 castor * 146 1.76 simonb * Common for all MIPS3 and greater ISAs 147 1.2 castor * 148 1.2 castor * Results: 149 1.2 castor * None. 150 1.2 castor * 151 1.2 castor * Side effects: 152 1.2 castor * None. 153 1.2 castor * 154 1.2 castor *---------------------------------------------------------------------------- 155 1.2 castor */ 156 1.2 castor LEAF(mips3_wbflush) 157 1.101 matt XLEAF(loongson2_wbflush) 158 1.76 simonb XLEAF(mips32_wbflush) 159 1.98 matt XLEAF(mips32r2_wbflush) 160 1.76 simonb XLEAF(mips64_wbflush) 161 1.98 matt XLEAF(mips64r2_wbflush) 162 1.2 castor nop 163 1.2 castor sync 164 1.102 matt jr ra 165 1.98 matt nop 166 1.2 castor END(mips3_wbflush) 167 1.2 castor 168 1.67 thorpej 169 1.67 thorpej /* 170 1.79 simonb * mips_wait_idle: 171 1.67 thorpej * 172 1.91 yamt * When no processes are on the runq, cpu_idle branches to 173 1.91 yamt * mips_wait_idle to save power. 174 1.67 thorpej */ 175 1.79 simonb LEAF(mips_wait_idle) 176 1.96 matt mfc0 v0, MIPS_COP_0_STATUS 177 1.97 matt andi v1, v0, MIPS_SR_INT_IE 178 1.107 matt #if __mips >= 32 179 1.107 matt teqi v1, 0 180 1.107 matt #else 181 1.97 matt beqz v1, 1f 182 1.98 matt nop 183 1.107 matt #endif 184 1.97 matt andi v1, v0, MIPS_INT_MASK 185 1.107 matt #if __mips >= 32 186 1.107 matt teqi v1, 0 187 1.107 matt #else 188 1.97 matt bnez v1, 2f 189 1.98 matt nop 190 1.97 matt 1: 191 1.97 matt move a1, v0 192 1.97 matt PANIC("mips_wait_idle: interrupts disabled status=%#x") 193 1.107 matt #endif 194 1.96 matt 195 1.97 matt 2: wait 196 1.67 thorpej nop 197 1.67 thorpej nop 198 1.67 thorpej nop 199 1.107 matt mfc0 v0, MIPS_COP_0_STATUS 200 1.107 matt andi v1, v0, MIPS_SR_INT_IE 201 1.107 matt #if __mips >= 32 202 1.107 matt teqi v1, 0 203 1.107 matt #else 204 1.107 matt beqz v1, 1b 205 1.107 matt nop 206 1.107 matt #endif 207 1.107 matt andi v1, v0, MIPS_INT_MASK 208 1.107 matt #if __mips >= 32 209 1.107 matt teqi v1, 0 210 1.107 matt #else 211 1.111 skrll beqz v1, 1b 212 1.107 matt nop 213 1.107 matt #endif 214 1.102 matt jr ra 215 1.98 matt nop 216 1.79 simonb END(mips_wait_idle) 217 1.76 simonb 218 1.2 castor /* 219 1.96 matt * uint32_t mips3_cp0_compare_read(void) 220 1.2 castor * 221 1.76 simonb * Return the current value of the CP0 Compare register. 222 1.2 castor */ 223 1.76 simonb LEAF(mips3_cp0_compare_read) 224 1.76 simonb mfc0 v0, MIPS_COP_0_COMPARE 225 1.102 matt jr ra 226 1.98 matt nop 227 1.76 simonb END(mips3_cp0_compare_read) 228 1.19 nisimura 229 1.22 nisimura /* 230 1.96 matt * void mips3_cp0_compare_write(uint32_t) 231 1.22 nisimura * 232 1.76 simonb * Set the value of the CP0 Compare register. 233 1.22 nisimura */ 234 1.76 simonb LEAF(mips3_cp0_compare_write) 235 1.76 simonb mtc0 a0, MIPS_COP_0_COMPARE 236 1.98 matt JR_HB_RA 237 1.76 simonb END(mips3_cp0_compare_write) 238 1.76 simonb 239 1.22 nisimura /* 240 1.96 matt * uint32_t mips3_cp0_config_read(void) 241 1.22 nisimura * 242 1.76 simonb * Return the current value of the CP0 Config register. 243 1.22 nisimura */ 244 1.76 simonb LEAF(mips3_cp0_config_read) 245 1.76 simonb mfc0 v0, MIPS_COP_0_CONFIG 246 1.102 matt jr ra 247 1.98 matt nop 248 1.76 simonb END(mips3_cp0_config_read) 249 1.22 nisimura 250 1.22 nisimura /* 251 1.96 matt * void mips3_cp0_config_write(uint32_t) 252 1.22 nisimura * 253 1.76 simonb * Set the value of the CP0 Config register. 254 1.22 nisimura */ 255 1.76 simonb LEAF(mips3_cp0_config_write) 256 1.76 simonb mtc0 a0, MIPS_COP_0_CONFIG 257 1.98 matt JR_HB_RA 258 1.76 simonb END(mips3_cp0_config_write) 259 1.57 cgd 260 1.98 matt #if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 261 1.98 matt .set push 262 1.106 matt #ifdef __mips_o32 263 1.106 matt .set mips32 264 1.106 matt #else 265 1.99 matt .set mips64 266 1.99 matt #endif 267 1.57 cgd /* 268 1.96 matt * uint32_t mipsNN_cp0_config1_read(void) 269 1.57 cgd * 270 1.76 simonb * Return the current value of the CP0 Config (Select 1) register. 271 1.57 cgd */ 272 1.76 simonb LEAF(mipsNN_cp0_config1_read) 273 1.76 simonb mfc0 v0, MIPS_COP_0_CONFIG, 1 274 1.102 matt jr ra 275 1.98 matt nop 276 1.76 simonb END(mipsNN_cp0_config1_read) 277 1.36 soren 278 1.57 cgd /* 279 1.96 matt * uint32_t mipsNN_cp0_config1_write(uint32_t) 280 1.2 castor * 281 1.98 matt * Set the current value of the CP0 Config (Select 1) register. 282 1.2 castor */ 283 1.76 simonb LEAF(mipsNN_cp0_config1_write) 284 1.76 simonb mtc0 v0, MIPS_COP_0_CONFIG, 1 285 1.98 matt JR_HB_RA 286 1.76 simonb END(mipsNN_cp0_config1_write) 287 1.2 castor 288 1.57 cgd /* 289 1.96 matt * uint32_t mipsNN_cp0_config2_read(void) 290 1.2 castor * 291 1.76 simonb * Return the current value of the CP0 Config (Select 2) register. 292 1.57 cgd */ 293 1.76 simonb LEAF(mipsNN_cp0_config2_read) 294 1.76 simonb mfc0 v0, MIPS_COP_0_CONFIG, 2 295 1.102 matt jr ra 296 1.98 matt nop 297 1.76 simonb END(mipsNN_cp0_config2_read) 298 1.57 cgd 299 1.57 cgd /* 300 1.96 matt * uint32_t mipsNN_cp0_config3_read(void) 301 1.2 castor * 302 1.76 simonb * Return the current value of the CP0 Config (Select 3) register. 303 1.2 castor */ 304 1.76 simonb LEAF(mipsNN_cp0_config3_read) 305 1.76 simonb mfc0 v0, MIPS_COP_0_CONFIG, 3 306 1.102 matt jr ra 307 1.98 matt nop 308 1.76 simonb END(mipsNN_cp0_config3_read) 309 1.98 matt 310 1.99 matt /* 311 1.112 matt * uint32_t mipsNN_cp0_config4_read(void) 312 1.112 matt * 313 1.112 matt * Return the current value of the CP0 Config (Select 4) register. 314 1.112 matt */ 315 1.112 matt LEAF(mipsNN_cp0_config4_read) 316 1.112 matt mfc0 v0, MIPS_COP_0_CONFIG, 4 317 1.112 matt jr ra 318 1.112 matt nop 319 1.112 matt END(mipsNN_cp0_config4_read) 320 1.112 matt 321 1.112 matt /* 322 1.112 matt * uint32_t mipsNN_cp0_config5_read(void) 323 1.112 matt * 324 1.112 matt * Return the current value of the CP0 Config (Select 5) register. 325 1.112 matt */ 326 1.112 matt LEAF(mipsNN_cp0_config5_read) 327 1.112 matt mfc0 v0, MIPS_COP_0_CONFIG, 5 328 1.112 matt jr ra 329 1.112 matt nop 330 1.112 matt END(mipsNN_cp0_config5_read) 331 1.112 matt 332 1.112 matt /* 333 1.112 matt * uint32_t mipsNN_cp0_config6_read(void) 334 1.112 matt * 335 1.112 matt * Return the current value of the CP0 Config (Select 6) register. 336 1.112 matt */ 337 1.112 matt LEAF(mipsNN_cp0_config6_read) 338 1.112 matt mfc0 v0, MIPS_COP_0_CONFIG, 6 339 1.112 matt jr ra 340 1.112 matt nop 341 1.112 matt END(mipsNN_cp0_config6_read) 342 1.112 matt 343 1.112 matt /* 344 1.112 matt * uint32_t mipsNN_cp0_config7_read(void) 345 1.112 matt * 346 1.112 matt * Return the current value of the CP0 Config (Select 7) register. 347 1.112 matt */ 348 1.112 matt LEAF(mipsNN_cp0_config7_read) 349 1.112 matt mfc0 v0, MIPS_COP_0_CONFIG, 7 350 1.112 matt jr ra 351 1.112 matt nop 352 1.112 matt END(mipsNN_cp0_config7_read) 353 1.112 matt 354 1.112 matt /* 355 1.99 matt * uintptr_t mipsNN_cp0_watchlo_read(u_int sel) 356 1.99 matt * 357 1.99 matt * Return the current value of the selected CP0 Watchlo register. 358 1.99 matt */ 359 1.99 matt LEAF(mipsNN_cp0_watchlo_read) 360 1.99 matt sll a0, 2 361 1.99 matt PTR_LA t9, 1f 362 1.99 matt PTR_ADDU t9, a0 363 1.99 matt jr t9 364 1.99 matt nop 365 1.99 matt 1: 366 1.99 matt jr ra 367 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 0 368 1.99 matt jr ra 369 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 1 370 1.99 matt jr ra 371 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 2 372 1.99 matt jr ra 373 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 3 374 1.99 matt jr ra 375 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 4 376 1.99 matt jr ra 377 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 5 378 1.99 matt jr ra 379 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 6 380 1.99 matt jr ra 381 1.99 matt _MFC0 v0, MIPS_COP_0_WATCH_LO, 7 382 1.99 matt END(mipsNN_cp0_watchlo_read) 383 1.99 matt 384 1.99 matt /* 385 1.99 matt * void mipsNN_cp0_watchlo_write(u_int sel, uintptr_t val) 386 1.99 matt * 387 1.99 matt * Set the current value of the selected CP0 WatchLo register. 388 1.99 matt */ 389 1.99 matt LEAF(mipsNN_cp0_watchlo_write) 390 1.99 matt sll a0, 2 391 1.99 matt PTR_LA t9, 1f 392 1.99 matt PTR_ADDU t9, a0 393 1.99 matt jr t9 394 1.99 matt nop 395 1.99 matt 1: 396 1.99 matt jr ra 397 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 0 398 1.99 matt jr ra 399 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 1 400 1.99 matt jr ra 401 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 2 402 1.99 matt jr ra 403 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 3 404 1.99 matt jr ra 405 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 4 406 1.99 matt jr ra 407 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 5 408 1.99 matt jr ra 409 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 6 410 1.99 matt jr ra 411 1.99 matt _MTC0 a1, MIPS_COP_0_WATCH_LO, 7 412 1.99 matt END(mipsNN_cp0_watchlo_write) 413 1.99 matt 414 1.99 matt /* 415 1.99 matt * uint32_t mipsNN_cp0_watchhi_read(u_int sel) 416 1.99 matt * 417 1.99 matt * Return the current value of the selected CP0 WatchHi register. 418 1.99 matt */ 419 1.99 matt LEAF(mipsNN_cp0_watchhi_read) 420 1.99 matt sll a0, 2 421 1.99 matt PTR_LA t9, 1f 422 1.99 matt PTR_ADDU t9, a0 423 1.99 matt jr t9 424 1.99 matt nop 425 1.99 matt 1: 426 1.99 matt jr ra 427 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 0 428 1.99 matt jr ra 429 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 1 430 1.99 matt jr ra 431 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 2 432 1.99 matt jr ra 433 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 3 434 1.99 matt jr ra 435 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 4 436 1.99 matt jr ra 437 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 5 438 1.99 matt jr ra 439 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 6 440 1.99 matt jr ra 441 1.99 matt mfc0 v0, MIPS_COP_0_WATCH_HI, 7 442 1.99 matt END(mipsNN_cp0_watchhi_read) 443 1.99 matt 444 1.99 matt /* 445 1.99 matt * void mipsNN_cp0_watchhi_write(u_int sel, uint32_t val) 446 1.99 matt * 447 1.99 matt * Set the current value of the selected CP0 WatchHi register. 448 1.99 matt */ 449 1.99 matt LEAF(mipsNN_cp0_watchhi_write) 450 1.99 matt sll a0, 2 451 1.99 matt PTR_LA t9, 1f 452 1.99 matt PTR_ADDU t9, a0 453 1.99 matt jr t9 454 1.99 matt nop 455 1.99 matt 1: 456 1.99 matt jr ra 457 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 0 458 1.99 matt jr ra 459 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 1 460 1.99 matt jr ra 461 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 2 462 1.99 matt jr ra 463 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 3 464 1.99 matt jr ra 465 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 4 466 1.99 matt jr ra 467 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 5 468 1.99 matt jr ra 469 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 6 470 1.99 matt jr ra 471 1.99 matt mtc0 a1, MIPS_COP_0_WATCH_HI, 7 472 1.99 matt END(mipsNN_cp0_watchhi_write) 473 1.99 matt 474 1.103 matt /* 475 1.103 matt * void mipsNN_cp0_ebase_read(void *); 476 1.103 matt * Get the value of the CP0 EBASE (PRID, select 1) register. 477 1.103 matt */ 478 1.103 matt LEAF(mipsNN_cp0_ebase_read) 479 1.103 matt jr ra 480 1.108 matt mfc0 v0, MIPS_COP_0_EBASE 481 1.103 matt END(mipsNN_cp0_ebase_read) 482 1.103 matt 483 1.103 matt /* 484 1.103 matt * void mipsNN_cp0_ebase_write(void *); 485 1.103 matt * Set the value of the CP0 EBASE (PRID, select 1) register. 486 1.103 matt */ 487 1.103 matt LEAF(mipsNN_cp0_ebase_write) 488 1.103 matt and v0, v0, 0x1ff 489 1.103 matt xor v0, v0, a0 490 1.103 matt jr ra 491 1.108 matt mtc0 v0, MIPS_COP_0_EBASE 492 1.103 matt END(mipsNN_cp0_ebase_write) 493 1.103 matt 494 1.98 matt #if (MIPS32R2 + MIPS64R2) > 0 495 1.98 matt /* 496 1.115 simonb * uint32_t mipsNN_cp0_rdhwr_cpunum(void); 497 1.115 simonb * Set the value of the CP0 HWRENA register. 498 1.115 simonb */ 499 1.115 simonb LEAF(mipsNN_cp0_rdhwr_cpunum) 500 1.115 simonb .set push 501 1.115 simonb #ifdef __mips_o32 502 1.115 simonb .set mips32r2 503 1.115 simonb #else 504 1.115 simonb .set mips64r2 505 1.115 simonb #endif 506 1.115 simonb jr ra 507 1.115 simonb rdhwr v0, MIPS_HWR_CPUNUM 508 1.115 simonb .set pop 509 1.115 simonb END(mipsNN_cp0_rdhwr_cpunum) 510 1.115 simonb 511 1.115 simonb /* 512 1.108 matt * void mipsNN_cp0_hwrena_write(void *); 513 1.108 matt * Set the value of the CP0 HWRENA register. 514 1.98 matt */ 515 1.98 matt LEAF(mipsNN_cp0_hwrena_write) 516 1.102 matt jr ra 517 1.99 matt mtc0 a0, MIPS_COP_0_HWRENA 518 1.98 matt END(mipsNN_cp0_hwrena_write) 519 1.98 matt 520 1.98 matt /* 521 1.98 matt * void mipsNN_cp0_userlocal_write(void *); 522 1.98 matt * Set the value of the CP0 USERLOCAL (TLB_CONTEXT, select 2) register. 523 1.98 matt */ 524 1.98 matt LEAF(mipsNN_cp0_userlocal_write) 525 1.102 matt jr ra 526 1.108 matt _MTC0 a0, MIPS_COP_0_USERLOCAL 527 1.98 matt END(mipsNN_cp0_userlocal_write) 528 1.98 matt #endif /* (MIPS32R2 + MIPS64R2) > 0 */ 529 1.98 matt .set pop 530 1.98 matt #endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */ 531 1.2 castor 532 1.2 castor /* 533 1.96 matt * uint32_t mips3_cp0_count_read(void) 534 1.2 castor * 535 1.57 cgd * Return the current value of the CP0 Count register. 536 1.2 castor */ 537 1.57 cgd LEAF(mips3_cp0_count_read) 538 1.57 cgd mfc0 v0, MIPS_COP_0_COUNT 539 1.102 matt jr ra 540 1.98 matt nop 541 1.57 cgd END(mips3_cp0_count_read) 542 1.97 matt WEAK_ALIAS(cpu_counter32, mips3_cp0_count_read) 543 1.2 castor 544 1.2 castor /* 545 1.96 matt * void mips3_cp0_count_write(uint32_t) 546 1.2 castor * 547 1.57 cgd * Set the value of the CP0 Count register. 548 1.2 castor */ 549 1.57 cgd LEAF(mips3_cp0_count_write) 550 1.57 cgd mtc0 a0, MIPS_COP_0_COUNT 551 1.98 matt JR_HB_RA 552 1.57 cgd END(mips3_cp0_count_write) 553 1.57 cgd 554 1.57 cgd /* 555 1.96 matt * uint32_t mips3_cp0_wired_read(void) 556 1.57 cgd * 557 1.57 cgd * Return the current value of the CP0 Wired register. 558 1.57 cgd */ 559 1.57 cgd LEAF(mips3_cp0_wired_read) 560 1.57 cgd mfc0 v0, MIPS_COP_0_TLB_WIRED 561 1.102 matt jr ra 562 1.98 matt nop 563 1.57 cgd END(mips3_cp0_wired_read) 564 1.2 castor 565 1.57 cgd /* 566 1.96 matt * void mips3_cp0_wired_write(uint32_t) 567 1.57 cgd * 568 1.57 cgd * Set the value of the CP0 Wired register. 569 1.57 cgd */ 570 1.57 cgd LEAF(mips3_cp0_wired_write) 571 1.57 cgd mtc0 a0, MIPS_COP_0_TLB_WIRED 572 1.98 matt JR_HB_RA 573 1.57 cgd END(mips3_cp0_wired_write) 574 1.55 cgd 575 1.87 tsutsui /* 576 1.96 matt * void mips3_cp0_pg_mask_write(uint32_t) 577 1.87 tsutsui * 578 1.87 tsutsui * Set the value of the CP0 PG_MASK register. 579 1.87 tsutsui */ 580 1.87 tsutsui LEAF(mips3_cp0_pg_mask_write) 581 1.87 tsutsui mtc0 a0, MIPS_COP_0_TLB_PG_MASK 582 1.98 matt JR_HB_RA 583 1.87 tsutsui END(mips3_cp0_pg_mask_write) 584 1.87 tsutsui 585 1.106 matt #if __mips != 32 586 1.55 cgd LEAF(mips3_ld) 587 1.96 matt #if defined(__mips_o32) 588 1.112 matt #if (MIPS64R2) > 0 589 1.112 matt di t0 590 1.112 matt #else 591 1.92 uebayasi mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts 592 1.55 cgd and t1, t0, ~(MIPS_SR_INT_IE) 593 1.55 cgd mtc0 t1, MIPS_COP_0_STATUS 594 1.112 matt #endif 595 1.71 uch COP0_SYNC 596 1.55 cgd 597 1.55 cgd ld v0, 0(a0) 598 1.55 cgd #if _BYTE_ORDER == _BIG_ENDIAN 599 1.76 simonb dsll v1, v0, 32 600 1.76 simonb dsra v1, v1, 32 # low word in v1 601 1.55 cgd #else 602 1.55 cgd dsra v1, v0, 32 # high word in v1 603 1.76 simonb dsll v0, v0, 32 604 1.112 matt #endif 605 1.76 simonb dsra v0, v0, 32 # low word in v0 606 1.55 cgd 607 1.55 cgd mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 608 1.98 matt JR_HB_RA 609 1.96 matt #else /* !__mips_o32 */ 610 1.98 matt jr ra 611 1.112 matt ld v0, 0(a0) 612 1.96 matt #endif /* !__mips_o32 */ 613 1.55 cgd END(mips3_ld) 614 1.55 cgd 615 1.55 cgd LEAF(mips3_sd) 616 1.96 matt #if defined(__mips_o32) 617 1.112 matt #if (MIPS64R2) > 0 618 1.112 matt di t0 619 1.112 matt #else 620 1.92 uebayasi mfc0 t0, MIPS_COP_0_STATUS # turn off interrupts 621 1.55 cgd and t1, t0, ~(MIPS_SR_INT_IE) 622 1.55 cgd mtc0 t1, MIPS_COP_0_STATUS 623 1.112 matt #endif 624 1.71 uch COP0_SYNC 625 1.55 cgd 626 1.112 matt dsll a2, a2, 32 # high word in a2 627 1.55 cgd #if _BYTE_ORDER == _BIG_ENDIAN 628 1.55 cgd dsll a3, a3, 32 # low word in a3 629 1.55 cgd dsrl a3, a3, 32 630 1.55 cgd #else 631 1.55 cgd dsrl a2, a2, 32 632 1.55 cgd dsll a3, a3, 32 # high word in a3 633 1.55 cgd #endif 634 1.55 cgd or a1, a2, a3 635 1.55 cgd sd a1, 0(a0) 636 1.55 cgd 637 1.55 cgd mtc0 t0, MIPS_COP_0_STATUS # restore intr status. 638 1.98 matt JR_HB_RA 639 1.96 matt #else /* !__mips_o32 */ 640 1.98 matt jr ra 641 1.112 matt sd a1, 0(a0) 642 1.96 matt #endif /* !__mips_o32 */ 643 1.55 cgd END(mips3_sd) 644 1.2 castor 645 1.2 castor /* 646 1.76 simonb * int badaddr64(uint64_t addr, int len) 647 1.76 simonb * See if access to addr with a len type instruction causes a machine check. 648 1.76 simonb * len is length of access in bytes (can be 1, 2, 4, or 8). 649 1.76 simonb */ 650 1.76 simonb LEAF(badaddr64) 651 1.96 matt PTR_L v1, L_PCB(MIPS_CURLWP) 652 1.96 matt PTR_LA v0, _C_LABEL(baderr64) 653 1.76 simonb 654 1.112 matt #ifdef __mips_o32 655 1.76 simonb /* Enable KX */ 656 1.76 simonb mfc0 t0, MIPS_COP_0_STATUS 657 1.76 simonb or t1, t0, MIPS3_SR_KX 658 1.97 matt and t2, t0, MIPS_SR_INT_IE # disable interrupts 659 1.97 matt xor t1, t2 660 1.76 simonb mtc0 t1, MIPS_COP_0_STATUS 661 1.84 simonb COP0_SYNC 662 1.2 castor 663 1.97 matt #ifdef __MIPSEB__ 664 1.97 matt dsll a0, a0, 32 # MSW 665 1.97 matt dsll a1, a1, 32 # LSW 666 1.97 matt dsrl a1, a1, 32 667 1.97 matt #else 668 1.97 matt dsll a1, a1, 32 # MSW 669 1.97 matt dsll a0, a0, 32 # LSW 670 1.97 matt dsrl a0, a0, 32 671 1.97 matt #endif 672 1.97 matt or a0, a1 # combine 673 1.97 matt move a1, a2 # move up length argument 674 1.97 matt #endif /* __mips_o32 */ 675 1.97 matt 676 1.96 matt bne a1, 1, 2f 677 1.98 matt PTR_S v0, PCB_ONFAULT(v1) 678 1.76 simonb b 9f 679 1.97 matt lbu v0, (a0) 680 1.76 simonb 2: 681 1.96 matt bne a1, 2, 4f 682 1.98 matt nop 683 1.76 simonb b 9f 684 1.97 matt lhu v0, (a0) 685 1.76 simonb 4: 686 1.96 matt bne a1, 4, 8f 687 1.98 matt nop 688 1.76 simonb b 9f 689 1.97 matt INT_L v0, (a0) 690 1.76 simonb 8: 691 1.96 matt REG_L v0, (a0) 692 1.76 simonb 9: 693 1.97 matt sync 694 1.112 matt #ifdef __mips_o32 695 1.76 simonb mtc0 t0, MIPS_COP_0_STATUS # Restore KX 696 1.84 simonb COP0_SYNC 697 1.112 matt #endif 698 1.96 matt PTR_S zero, PCB_ONFAULT(v1) 699 1.102 matt jr ra 700 1.97 matt move v0, zero # made it w/o errors 701 1.76 simonb END(badaddr64) 702 1.76 simonb 703 1.76 simonb LEAF(baderr64) 704 1.112 matt #ifdef __mips_o32 705 1.76 simonb mtc0 t0, MIPS_COP_0_STATUS # Restore KX 706 1.84 simonb COP0_SYNC 707 1.112 matt #endif 708 1.96 matt PTR_S zero, PCB_ONFAULT(v1) 709 1.102 matt jr ra 710 1.96 matt li v0, -1 711 1.76 simonb END(baderr64) 712 1.97 matt 713 1.97 matt /* 714 1.97 matt * uint64_t mips3_cp0_tlb_entry_hi_probe(void); 715 1.97 matt * 716 1.97 matt * Write 1s to the VPN and ASID fields of Entry_Hi0 to see how many VA bits 717 1.97 matt * and ASID bits are implemented. Assumes that interrupts are disabled. 718 1.97 matt */ 719 1.97 matt LEAF(mips3_cp0_tlb_entry_hi_probe) 720 1.97 matt dmfc0 t0, MIPS_COP_0_TLB_HI 721 1.97 matt li v0, -1 /* all 1s */ 722 1.105 matt #if defined(__mips_isa_rev) && __mips_isa_rev >= 2 723 1.105 matt dinsu v0, zero, 62, 2 724 1.105 matt #else 725 1.97 matt dsll v0, v0, 2 /* except the top 2 */ 726 1.97 matt dsrl v0, v0, 2 727 1.105 matt #endif 728 1.97 matt dmtc0 v0, MIPS_COP_0_TLB_HI 729 1.97 matt COP0_SYNC 730 1.97 matt dmfc0 v0, MIPS_COP_0_TLB_HI 731 1.97 matt dmtc0 t0, MIPS_COP_0_TLB_HI 732 1.97 matt COP0_SYNC 733 1.97 matt nop 734 1.97 matt #ifdef __mips_o32 735 1.97 matt nop 736 1.97 matt #if BYTE_ORDER == BIG_ENDIAN 737 1.97 matt srl v1, v0, 0 738 1.97 matt dsra v0, v0, 32 739 1.76 simonb #endif 740 1.97 matt #if BYTE_ORDER == LITTLE_ENDIAN 741 1.97 matt dsra v1, v0, 32 742 1.97 matt srl v0, v0, 0 743 1.97 matt #endif 744 1.97 matt #endif /* __mips_o32 */ 745 1.102 matt jr ra 746 1.97 matt nop 747 1.97 matt END(mips3_cp0_tlb_entry_hi_probe) 748 1.112 matt #endif /* __mips != 32 */ 749 1.97 matt 750 1.97 matt /* 751 1.97 matt * uint64_t mips3_cp0_tlb_entry_lo_probe(void); 752 1.97 matt * 753 1.97 matt * Write 1s to the PFN field of Entry_Lo0 to see how many 754 1.97 matt * PA bits are implemented. Assumes that interrupts are disabled. 755 1.97 matt */ 756 1.97 matt LEAF(mips3_cp0_tlb_entry_lo_probe) 757 1.97 matt dmfc0 t0, MIPS_COP_0_TLB_LO0 758 1.97 matt li v0, -64 /* all 1s except low 6 bits */ 759 1.97 matt dmtc0 v0, MIPS_COP_0_TLB_LO0 760 1.97 matt COP0_SYNC 761 1.97 matt dmfc0 v0, MIPS_COP_0_TLB_LO0 762 1.97 matt dmtc0 t0, MIPS_COP_0_TLB_LO0 763 1.97 matt COP0_SYNC 764 1.97 matt #ifdef __mips_o32 765 1.97 matt #if BYTE_ORDER == BIG_ENDIAN 766 1.97 matt srl v1, v0, 0 767 1.97 matt dsra v0, v0, 32 768 1.97 matt #endif 769 1.97 matt #if BYTE_ORDER == LITTLE_ENDIAN 770 1.97 matt dsra v1, v0, 32 771 1.97 matt srl v0, v0, 0 772 1.97 matt #endif 773 1.97 matt #endif /* __mips_o32 */ 774 1.102 matt jr ra 775 1.97 matt nop 776 1.97 matt END(mips3_cp0_tlb_entry_lo_probe) 777 1.97 matt 778 1.97 matt /* 779 1.97 matt * uint32_t mips3_cp0_tlb_page_mask_probe(void); 780 1.97 matt * 781 1.97 matt * Write 1s to the RPN field of Entry_Lo0 to see how many PA bits are implemented. 782 1.97 matt * Assumes that interrupts are disabled. 783 1.97 matt */ 784 1.97 matt LEAF(mips3_cp0_tlb_page_mask_probe) 785 1.97 matt mfc0 t0, MIPS_COP_0_TLB_PG_MASK 786 1.97 matt lui v0, 0xffff 787 1.97 matt srl v0, v0, 3 788 1.97 matt mtc0 v0, MIPS_COP_0_TLB_PG_MASK 789 1.97 matt COP0_SYNC 790 1.97 matt mfc0 v0, MIPS_COP_0_TLB_PG_MASK 791 1.97 matt mtc0 t0, MIPS_COP_0_TLB_PG_MASK 792 1.98 matt JR_HB_RA 793 1.97 matt END(mips3_cp0_tlb_page_mask_probe) 794 1.97 matt 795 1.97 matt #ifdef MULTIPROCESSOR 796 1.97 matt /* 797 1.103 matt * MD code calls/jumps to this with the pointer to this CPU's cpu_info in a1, 798 1.103 matt * sp set to ci->ci_data.cpu_idlelwp->l_md.md_utf. gp will be overridden so 799 1.97 matt * 0 can be supplied if needed. (This happens to match what CFE wants) 800 1.97 matt */ 801 1.97 matt NESTED_NOPROFILE(cpu_trampoline, 0, ra) 802 1.97 matt /* 803 1.97 matt * We act as the idle lwp so make it CURLWP. When know 804 1.97 matt * that the cpu_info is a KSEG0 address. 805 1.97 matt */ 806 1.97 matt move a0, a1 807 1.103 matt // Loop until idlelwp is filled in. 808 1.103 matt 1: PTR_L MIPS_CURLWP, CPU_INFO_IDLELWP(a0) 809 1.97 matt nop 810 1.103 matt beqz MIPS_CURLWP, 1b 811 1.103 matt nop 812 1.116 riastrad /* 813 1.116 riastrad * No membar needed because we're not switching from a 814 1.116 riastrad * previous lwp, and the idle lwp we're switching to can't be 815 1.116 riastrad * holding locks already; see cpu_switchto. 816 1.116 riastrad */ 817 1.97 matt PTR_S MIPS_CURLWP, CPU_INFO_CURLWP(a0) 818 1.97 matt 819 1.97 matt #ifdef _LP64 820 1.97 matt li v0, MIPS_SR_KX | MIPS_SR_UX # allow 64bit addressing 821 1.112 matt #elif defined(__mips_n32) 822 1.112 matt li v0, MIPS_SR_KX # allow 64bit kernel addressing 823 1.97 matt #else 824 1.97 matt li v0, 0 825 1.97 matt #endif 826 1.97 matt mtc0 v0, MIPS_COP_0_STATUS # reset to known state 827 1.97 matt COP0_SYNC 828 1.97 matt 829 1.104 matt PTR_L sp, L_MD_UTF(MIPS_CURLWP) # fetch KSP 830 1.104 matt 831 1.97 matt /* 832 1.97 matt * Indicate that no one has called us. 833 1.97 matt */ 834 1.97 matt move ra, zero 835 1.97 matt REG_S ra, CALLFRAME_RA(sp) 836 1.97 matt 837 1.97 matt #ifdef __GP_SUPPORT__ 838 1.97 matt /* 839 1.97 matt * New execution constant needs GP to be loaded. 840 1.97 matt */ 841 1.97 matt PTR_LA gp, _C_LABEL(_gp) 842 1.97 matt #endif 843 1.97 matt 844 1.104 matt #if 0 845 1.104 matt LONG_L t0, CPU_INFO_FLAGS(a0) 846 1.104 matt or t0, t0, CPUF_PRESENT 847 1.104 matt LONG_S t0, CPU_INFO_FLAGS(a0) 848 1.104 matt sync 849 1.104 matt #endif 850 1.104 matt 851 1.97 matt /* 852 1.97 matt * and off we go. 853 1.97 matt */ 854 1.97 matt j _C_LABEL(cpu_hatch) # does everything 855 1.97 matt nop 856 1.97 matt END(cpu_trampoline) 857 1.97 matt #endif /* MULTIPROCESSOR */ 858