1 /* $NetBSD: locore.s,v 1.210 2026/06/13 15:28:08 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 /*- 38 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, 39 * Michael L. Finch, Bradley A. Grantham, and 40 * Lawrence A. Kesteloot 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the Alice Group. 54 * 4. The names of the Alice Group or any of its members may not be used 55 * to endorse or promote products derived from this software without 56 * specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 67 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 * 69 */ 70 71 /* 72 * from: Utah $Hdr: locore.s 1.58 91/04/22$ 73 * 74 * @(#)locore.s 7.11 (Berkeley) 5/9/91 75 */ 76 77 #include "opt_compat_netbsd.h" 78 #include "opt_compat_sunos.h" 79 #include "opt_ddb.h" 80 #include "opt_fpu_emulate.h" 81 #include "opt_kgdb.h" 82 #include "opt_lockdebug.h" 83 #include "opt_fpsp.h" 84 #include "opt_m68k_arch.h" 85 86 #include "assym.h" 87 88 #include <machine/asm.h> 89 #include <machine/trap.h> 90 91 /* 92 * This is for kvm_mkdb, and should be the address of the beginning 93 * of the kernel text segment (not necessarily the same as kernbase). 94 */ 95 .text 96 GLOBAL(kernel_text) 97 98 #include <mac68k/mac68k/vectors.s> 99 #include <mac68k/mac68k/macglobals.s> 100 101 /* 102 * Initialization 103 */ 104 105 .data 106 | Scratch memory. Careful when messing with these... 107 ASLOCAL(longscratch) 108 .long 0 109 ASLOCAL(longscratch2) 110 .long 0 111 ASLOCAL(pte_tmp) | for get_pte() 112 .long 0 113 GLOBAL(macos_crp1) 114 .long 0 115 GLOBAL(macos_crp2) 116 .long 0 117 GLOBAL(macos_tc) 118 .long 0 119 GLOBAL(macos_tt0) 120 .long 0 121 GLOBAL(macos_tt1) 122 .long 0 123 GLOBAL(bletch) 124 .long 0 125 126 BSS(esym,4) 127 128 ASENTRY_NOPROFILE(start) 129 movw #PSL_HIGHIPL,%sr | no interrupts. ever. 130 lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack 131 132 movl #CACHE_OFF,%d0 133 movc %d0,%cacr | clear and disable on-chip cache(s) 134 135 /* Initialize source/destination control registers for movs */ 136 movql #FC_USERD,%d0 | user space 137 movc %d0,%sfc | as source 138 movc %d0,%dfc | and destination of transfers 139 140 /* 141 * Some parameters provided by MacOS 142 * 143 * LAK: This section is the new way to pass information from the booter 144 * to the kernel. At A1 there is an environment variable which has 145 * a bunch of stuff in ascii format, "VAR=value\0VAR=value\0\0". 146 */ 147 movl %a1,%sp@- | Address of buffer 148 movl %d4,%sp@- | Some flags... (mostly not used) 149 jbsr _C_LABEL(getenvvars) | Parse the environment buffer 150 addql #8,%sp 151 152 /* Determine MMU/MPU from what we can test empirically */ 153 movl #0x200,%d0 | data freeze bit 154 movc %d0,%cacr | only exists on 68030 155 movc %cacr,%d0 | read it back 156 tstl %d0 | zero? 157 jeq Lnot68030 | yes, we have 68020/68040/68060 158 159 movl #CACHE_OFF,%d0 | disable and clear both caches 160 movc %d0,%cacr 161 lea _C_LABEL(mmutype),%a0 | no, we have 68030 162 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU 163 lea _C_LABEL(cputype),%a0 164 movl #CPU_68030,%a0@ | and 68030 MPU 165 jra Lstart1 166 167 Lnot68030: 168 bset #31,%d0 | data cache enable bit 169 movc %d0,%cacr | only exists on 68040/68060 170 movc %cacr,%d0 | read it back 171 tstl %d0 | zero? 172 beq Lis68020 | yes, we have 68020 173 174 movql #CACHE40_OFF,%d0 | now turn it back off 175 movc %d0,%cacr | before we access any data 176 .word 0xf4f8 | cpusha bc ;push and invalidate caches 177 bset #30,%d0 | data cache no allocate mode bit 178 movc %d0,%cacr | only exists on 68060 179 movc %cacr,%d0 | read it back 180 tstl %d0 | zero? 181 jeq Lis68040 | yes, we have 68040 182 lea _C_LABEL(mmutype),%a0 | no, we have 68060 183 movl #MMU_68040,%a0@ | with a 68040 compatible MMU 184 lea _C_LABEL(cputype),%a0 185 movl #CPU_68060,%a0@ | and a 68060 CPU 186 187 | Mac OS may be running with 060 FPU disabled. Check if we have 188 | one and re-enable it. Assume superscalar execution and loadstore 189 | bypass are already enabled if required. 190 | XXXJRT revisit this maybe? 191 .word 0x4e7a,0x1808 | movc pcr,d1 192 cmpw #0x0430,%d1 | check ID word 193 jne Lstart1 | no FPU? go to start 194 swap %d1 195 bclr #1,%d1 | ... and switch it on. 196 .word 0x4e7b,0x1808 | movc d1,pcr 197 jra Lstart1 198 Lis68040: 199 lea _C_LABEL(mmutype),%a0 200 movl #MMU_68040,%a0@ | Reflect 68040 MMU 201 lea _C_LABEL(cputype),%a0 202 movl #CPU_68040,%a0@ | and 68040 MPU 203 jra Lstart1 204 205 Lis68020: 206 movl #CACHE_OFF,%d0 | disable and clear cache 207 movc %d0,%cacr 208 lea _C_LABEL(mmutype),%a0 | Must be 68020+68851 209 movl #MMU_68851,%a0@ | Reflect 68851 PMMU 210 lea _C_LABEL(cputype),%a0 211 movl #CPU_68020,%a0@ | and 68020 MPU 212 213 Lstart1: 214 jbsr _C_LABEL(setmachdep) | Set some machine-dep stuff 215 jbsr _C_LABEL(consinit) | XXX Should only be if graybar on 216 217 /* 218 * Figure out MacOS mappings and bootstrap NetBSD 219 */ 220 lea _C_LABEL(macos_tc),%a0 | get current %TC 221 cmpl #MMU_68040,_C_LABEL(mmutype) | check to see if 68040 222 jeq Lget040TC 223 224 pmove %tc,%a0@ 225 jra Lstart3 226 227 Lget040TC: 228 #if 0 229 movl _C_LABEL(current_mac_model),%a1 | if an AV Mac, save current 230 cmpl #MACH_CLASSAV,%a1@(CPUINFO_CLASS) | %TC so internal video will 231 jne LnotAV | get configured 232 #endif 233 .long 0x4e7a0003 | movc %tc,%d0 234 jra LsaveTC 235 LnotAV: 236 movql #0,%d0 | otherwise, 237 .long 0x4e7b0003 | movc %d0,%tc ;Disable MMU 238 LsaveTC: 239 movl %d0,%a0@ 240 241 Lstart3: 242 movl %a0@,%sp@- | get Mac OS mapping, relocate video, 243 jbsr _C_LABEL(bootstrap_mac68k) | bootstrap pmap, et al. 244 addql #4,%sp 245 246 /* 247 * nextpa is returned in %d0. We need to squirrel that 248 * away in a callee-saved regstier for use later, after 249 * the MMU is enabled. 250 */ 251 movl %d0, %d7 252 253 /* NOTE: %d7 is now off-limits!! */ 254 255 /* 256 * Set up the vector table, and race to get the MMU 257 * enabled. 258 * 259 * XXX Should move vec_init() call to Lloaddone, like other 260 * XXX m68k platforms do. 261 */ 262 jbsr _C_LABEL(vec_init) 263 264 movl _C_LABEL(Sysseg_pa),%a1 | system segment table PA 265 cmpl #MMU_68040,_C_LABEL(mmutype) 266 jne Lenablepre040MMU | if not 040, skip 267 268 movql #0,%d0 269 .long 0x4e7b0003 | movc %d0,%tc ;Disable MMU 270 .long 0x4e7b0004 | movc %d0,%itt0 ;Disable itt0 271 .long 0x4e7b0005 | movc %d0,%itt1 ;Disable itt1 272 .long 0x4e7b0006 | movc %d0,%dtt0 ;Disable dtt0 273 .long 0x4e7b0007 | movc %d0,%dtt1 ;Disable dtt1 274 movl %a1,%d1 275 .word 0xf518 | pflusha 276 .long 0x4e7b1807 | movc %d1,%srp 277 278 #if defined(DJMEMCMAX) 279 movl %a3,%sp@- 280 cmpl #MACH_MACC610,_C_LABEL(machineid) 281 jeq Ldjmemc610 282 cmpl #MACH_MACQ610,_C_LABEL(machineid) 283 jeq Ldjmemc610 284 cmpl #MACH_MACC650,_C_LABEL(machineid) 285 jeq Ldjmemccfg 286 cmpl #MACH_MACQ650,_C_LABEL(machineid) 287 jeq Ldjmemccfg 288 cmpl #MACH_MACQ800,_C_LABEL(machineid) 289 jeq Ldjmemccfg 290 291 jra Lnodjmemc 292 293 Ldjmemccfg: 294 movl #0x50f0e00c,%a0 295 movl %a0@,%d0 | determine where RAM SIMMs start 296 andl #0x000000FF,%d0 297 addl #0x10,%d0 | bank 3 start 298 addl #0x10,%d0 | bank 4 start 299 300 movl #0x50f0e014,%a0 301 movl %d0,%a0@+ | bank 4 302 addl #0x10,%d0 303 movl %d0,%a0@+ | bank 5 304 addl #0x10,%d0 305 306 movl %d0,%a0@+ | bank 6 307 addl #0x10,%d0 308 movl %d0,%a0@+ | bank 7 309 addl #0x10,%d0 310 movl %d0,%a0@+ | bank 8 311 addl #0x10,%d0 312 movl %d0,%a0@+ | bank 9 313 addl #0x10,%d0 314 jra Ldjmemctop 315 316 Ldjmemc610: 317 movl #0x50f0e00c,%a0 318 movl %a0@,%d0 | determine where RAM SIMMs start 319 andl #0x000000FF,%d0 320 addl #0x10,%d0 | bank 3 start 321 322 movl #0x50f0e014,%a0 323 movl %d0,%a0@+ | bank 4 324 addl #0x10,%d0 325 movl %d0,%a0@+ | bank 5 326 movl %d0,%a0@+ | bank 6 327 addl #0x10,%d0 328 movl %d0,%a0@+ | bank 7 329 movl %d0,%a0@+ | bank 8 330 addl #0x10,%d0 331 movl %d0,%a0@+ | bank 9 332 333 Ldjmemctop: 334 movl #0x50F0E02C,%a0 335 movl %d0,%a0@ | memtop 336 337 | preserve ~512KB beyond 4MB just in case 338 movl #0x400000,%a0 339 movl #0x9000000,%a2 340 movl #0xFFFF,%d0 341 L1stbankcopy1: 342 movl %a0@+,%a2@+ 343 dbra %d0,L1stbankcopy1 344 movl #0xFFFF,%d0 345 L1stbankcopy2: 346 movl %a0@+,%a2@+ 347 dbra %d0,L1stbankcopy2 348 349 lea _ASM_LABEL(Lsetup1stbank),%a0 350 movl #0x8800000,%a2 | Pick a location that should be in bank 4 351 movl #0x64,%d0 352 Ldjcopy: 353 movl %a0@+,%a2@+ 354 dbra %d0,Ldjcopy 355 356 movl #0x8800000,%a0 357 lea _ASM_LABEL(Ldjmemcdone),%a2 358 jmp %a0@ 359 360 Lsetup1stbank: 361 | now configure banks 2 & 3 362 movl #0x50f0e00c,%a0 363 movl %a0@,%d0 | determine where RAM SIMMs start 364 andl #0x000000FF,%d0 365 movl %d0,%a0@+ 366 addl #0x10,%d0 | bank 3 start 367 movl %d0,%a0@ 368 369 | and return to where we came from. 370 jmp %a2@ 371 372 Ldjmemcdone: 373 movl #0x400000,%a2 374 movl #0x9000000,%a0 375 movl #0xFFFF,%d0 376 Lcopyback1: 377 movl %a0@+,%a2@+ 378 dbra %d0,Lcopyback1 379 movl #0xFFFF,%d0 380 Lcopyback2: 381 movl %a0@+,%a2@+ 382 dbra %d0,Lcopyback2 383 384 Lnodjmemc: 385 movl %sp@+,%a3 386 #endif 387 388 movl #MMU40_TCR_BITS,%d0 389 .long 0x4e7b0003 | movc %d0,%tc ;Enable MMU 390 movl #CACHE40_ON,%d0 391 #ifdef M68060 392 cmpl #CPU_68060,_C_LABEL(cputype) 393 jne Lcacheon 394 movl #CACHE60_ON,%d0 395 #endif 396 Lcacheon: 397 movc %d0,%cacr | turn on both caches 398 jra Lloaddone 399 400 Lenablepre040MMU: 401 tstl _C_LABEL(mmutype) | TTx instructions will break 68851 402 jgt LnokillTT 403 404 lea _ASM_LABEL(longscratch),%a0 | disable TTx registers on 68030 405 movl #0,%a0@ 406 .long 0xf0100800 | movl %a0@,%tt0 407 .long 0xf0100c00 | movl %a0@,%tt1 408 409 LnokillTT: 410 #if defined(M68020) || defined(M68030) 411 lea _C_LABEL(protorp),%a0 412 movl %a1,%a0@(4) | segtable address 413 pmove %a0@,%srp | load the supervisor root pointer 414 pflusha 415 lea _ASM_LABEL(longscratch),%a2 416 movl #MMU51_TCR_BITS,%a2@ | value to load %TC with 417 pmove %a2@,%tc | load it 418 #endif /* M68020 || M68030 */ 419 420 /* 421 * Should be running mapped from this point on 422 */ 423 Lloaddone: 424 lea _ASM_LABEL(tmpstk),%sp | temporary stack 425 426 /* phase 2 of pmap setup, returns lwp0 SP in %a0 */ 427 jbsr _C_LABEL(pmap_bootstrap2) 428 movl %a0,%sp | now running on lwp0's stack 429 movl #0,%a6 | terminate the stack back trace 430 431 /* flush TLB and turn on caches */ 432 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/060? 433 jeq Ltbia040 | yes, cache already on 434 pflusha 435 movl #CACHE_ON,%d0 436 movc %d0,%cacr | clear cache(s) 437 #ifdef __notyet__ 438 tstl _C_LABEL(ectype) 439 jeq Lnocache0 440 | Enable external cache here 441 #endif 442 jra Lnocache0 443 444 Ltbia040: 445 .word 0xf518 | pflusha 446 447 Lnocache0: 448 movl %d7,%sp@- | push nextpa saved above 449 jbsr _C_LABEL(machine_init) | additional pre-main initialization 450 addql #4,%sp 451 jra _C_LABEL(main) | main() (never returns) 452 453 /* 454 * Use common m68k bus error and address error handlers. 455 */ 456 .data 457 GLOBAL(mac68k_a2_fromfault) 458 .long 0 459 GLOBAL(m68k_fault_addr) 460 .long 0 461 462 /* 463 * Interrupt handlers. 464 * 465 * Most 68k-based Macintosh computers 466 * 467 * Level 0: Spurious: ignored 468 * Level 1: VIA1 (clock, ADB) 469 * Level 2: VIA2 (NuBus, SCSI) 470 * Level 3: 471 * Level 4: Serial (SCC) 472 * Level 5: 473 * Level 6: 474 * Level 7: Non-maskable: parity errors, RESET button 475 * 476 * On the Q700, Q900 and Q950 in "A/UX mode": this should become: 477 * 478 * Level 0: Spurious: ignored 479 * Level 1: Software 480 * Level 2: VIA2 (except ethernet, sound) 481 * Level 3: Ethernet 482 * Level 4: Serial (SCC) 483 * Level 5: Sound 484 * Level 6: VIA1 485 * Level 7: NMIs: parity errors, RESET button, YANCC error 486 * 487 * On the 660AV and 840AV: 488 * 489 * Level 0: Spurious: ignored 490 * Level 1: VIA1 (clock, ADB) 491 * Level 2: VIA2 (NuBus, SCSI) 492 * Level 3: PSC device interrupt 493 * Level 4: PSC DMA and serial 494 * Level 5: ??? 495 * Level 6: ??? 496 * Level 7: NMIs: parity errors?, RESET button 497 */ 498 499 ENTRY_NOPROFILE(spurintr) 500 addql #1,_C_LABEL(intrcnt)+0 501 INTERRUPT_SAVEREG 502 CPUINFO_INCREMENT(CI_NINTR) 503 INTERRUPT_RESTOREREG 504 jra _ASM_LABEL(rei) 505 506 ENTRY_NOPROFILE(intrhand) 507 INTERRUPT_SAVEREG 508 jbsr _C_LABEL(intr_dispatch) | call dispatch routine 509 INTERRUPT_RESTOREREG 510 jra _ASM_LABEL(rei) | all done 511 512 ENTRY_NOPROFILE(lev7intr) 513 addql #1,_C_LABEL(intrcnt)+16 514 clrl %sp@- | pad %SR to longword 515 moveml #0xFFFF,%sp@- | save registers 516 movl %usp,%a0 | and save 517 movl %a0,%sp@(FR_SP) | the user stack pointer 518 jbsr _C_LABEL(nmihand) | call handler 519 movl %sp@(FR_SP),%a0 | restore 520 movl %a0,%usp | %USP 521 moveml %sp@+,#0x7FFF | and remaining registers 522 addql #8,%sp | pop SSP and align word 523 jra _ASM_LABEL(rei) 524 525 /* 526 * We could tweak rtclock_intr and gain 12 cycles on the 020 and 030 by 527 * saving the status register directly to the stack, but this would lose 528 * badly on the 040. Aligning the stack takes 10 more cycles than this 529 * code does, so it's a good compromise. 530 * 531 * A pointer to the clockframe is passed as an argument in the usual 532 * fashion. 533 */ 534 ENTRY_NOPROFILE(rtclock_intr) 535 movl %sp@(4),%a1 | stash pointer to clockframe 536 movl %d2,%sp@- | save %d2 537 movw %sr,%d2 | save SPL 538 | raise SPL to splclock() 539 movw _C_LABEL(ipl2psl_table)+IPL_CLOCK*2,%sr 540 movl %a1,%sp@- | push pointer to clockframe 541 jbsr _C_LABEL(hardclock) | call generic clock int routine 542 addql #4,%sp | pop param 543 jbsr _C_LABEL(mrg_VBLQueue) | give programs in the VBLqueue a chance 544 addql #1,_C_LABEL(intrcnt)+32 | record a clock interrupt 545 INTERRUPT_SAVEREG 546 CPUINFO_INCREMENT(CI_NINTR) 547 INTERRUPT_RESTOREREG 548 movw %d2,%sr | restore SPL 549 movl %sp@+,%d2 | restore %d2 550 rts | go back from whence we came 551 552 /* 553 * delay() - delay for a specified number of microseconds 554 * _delay() - calibrator helper for delay() 555 * 556 * Notice that delay_factor is scaled up by a factor of 128 to avoid loss 557 * of precision for small delays. As a result of this we need to avoid 558 * overflow. 559 * 560 * The branch target for the loops must be aligned on a half-line (8-byte) 561 * boundary to minimize cache effects. This guarantees both that there 562 * will be no prefetch stalls due to cache line burst operations and that 563 * the loops will run from a single cache half-line. 564 */ 565 .align 8 | align to half-line boundary 566 | (use nop instructions if necessary!) 567 ALTENTRY(_delay, _delay) 568 ENTRY(delay) 569 movl %sp@(4),%d0 | get microseconds to delay 570 cmpl #0x40000,%d0 | is it a "large" delay? 571 bls .Ldelayshort | no, normal calculation 572 movql #0x7f,%d1 | adjust for scaled multiplier (to 573 addl %d1,%d0 | avoid overflow) 574 lsrl #7,%d0 575 mulul _C_LABEL(delay_factor),%d0 | calculate number of loop iterations 576 bra .Ldelaysetup | go do it! 577 .Ldelayshort: 578 mulul _C_LABEL(delay_factor),%d0 | calculate number of loop iterations 579 lsrl #7,%d0 | adjust for scaled multiplier 580 .Ldelaysetup: 581 jeq .Ldelayexit | bail out if nothing to do 582 movql #0,%d1 | put bits 15-0 in %d1 for the 583 movw %d0,%d1 | inner loop, and move bits 584 movw #0,%d0 | 31-16 to the low-order word 585 subql #1,%d1 | of %d0 for the outer loop 586 swap %d0 587 .Ldelay: 588 tstl _C_LABEL(delay_flag) | this never changes for delay()! 589 dbeq %d1,.Ldelay | (used only for timing purposes) 590 dbeq %d0,.Ldelay 591 addqw #1,%d1 | adjust end count and 592 swap %d0 | return the longword result 593 orl %d1,%d0 594 .Ldelayexit: 595 rts 596 597 /* 598 * Handle the nitty-gritty of rebooting the machine. 599 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 600 * Note that we must be running in an address range that is mapped one-to-one 601 * logical to physical so that the PC is still valid immediately after the MMU 602 * is turned off. We have conveniently mapped the last page of physical 603 * memory this way. 604 */ 605 ENTRY_NOPROFILE(doboot) 606 #if defined(M68040) || defined(M68060) 607 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/060? 608 jeq Lnocache5 | yes, skip 609 #endif 610 movl #CACHE_OFF,%d0 611 movc %d0,%cacr | disable on-chip cache(s) 612 Lnocache5: 613 movl _C_LABEL(last_page),%a0 | last page of physical memory 614 lea Lbootcode,%a1 | start of boot code 615 lea Lebootcode,%a3 | end of boot code 616 Lbootcopy: 617 movw %a1@+,%a0@+ | copy a word 618 cmpl %a3,%a1 | done yet? 619 jcs Lbootcopy | no, keep going 620 #if defined(M68040) || defined(M68060) 621 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/060? 622 jne LmotommuE | no, skip 623 .word 0xf4f8 | cpusha bc 624 LmotommuE: 625 #endif 626 movl _C_LABEL(last_page),%a0 627 jmp %a0@ | jump to last page 628 629 Lbootcode: 630 lea %a0@(0x800),%sp | physical %SP in case of NMI 631 movl _C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase 632 633 #if defined(M68040) || defined(M68060) 634 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/060? 635 jne LmotommuF | no, skip 636 movl #0,%d0 637 movc %d0,%cacr | caches off 638 .long 0x4e7b0003 | movc %d0,%tc (disable MMU) 639 jra Ldoboot1 640 LmotommuF: 641 #endif 642 lea _ASM_LABEL(longscratch),%a3 643 movl #0,%a3@ | value for pmove to %TC (turn off MMU) 644 pmove %a3@,%tc | disable MMU 645 646 Ldoboot1: 647 lea %a1@(0x90),%a1 | offset of ROM reset routine 648 jmp %a1@ | and jump to ROM to reset machine 649 Lebootcode: 650 651 /* 652 * u_long plpar060(void *addr, u_int fc); 653 * 654 * plpar060() uses the new plpar instruction to resolve a physical address to 655 * the associated logical address when MMU is enabled. Used by get_physical(). 656 * zzj apr-9-2026 657 */ 658 ENTRY_NOPROFILE(plpar060) 659 #if defined(M68060) 660 .long 0x4e7a0003 | movc %tc,%d0 661 andw #0x8000,%d0 662 jeq 2f | MMU is disabled 663 664 movc %dfc,%d1 | Save %dfc 665 movl %sp@(8),%d0 | Set FC for plpar 666 movc %d0,%dfc 667 668 movec %vbr,%a1 | get vbr 669 addq.l #8,%a1 | access error vector 670 lea _ASM_LABEL(L060mmuerr),%a0 | temporary handler address 671 move.l %a1@,%d0 | save old handler into %d0 672 move.l %a0,%a1@ | install temp handler 673 674 movl %sp@(4),%a0 | logical address to look up 675 676 .word 0xf5c8 | plpar %a0@ 677 move.l %d0,%a1@ | restore original handler 678 679 movl %a0,%d0 | return address in %d0 680 movc %d1,%dfc | Restore %dfc 681 rts 682 683 L060mmuerr: | plpa will throw an access error (vect $8) on failure 684 movl #-1, %a0 | return failure 685 addq.l #2,2(%sp) | advance %pc past plpar insn 686 rte 687 2: 688 #endif 689 movl #-1,%d0 | return failure 690 rts 691 692 /* 693 * u_long ptest040(void *addr, u_int fc); 694 * 695 * ptest040() does an 040 PTESTR (addr) and returns the 040 MMUSR iff 696 * translation is enabled. This allows us to find the physical address 697 * corresponding to a MacOS logical address for get_physical(). 698 * sar 01-oct-1996 699 */ 700 ENTRY_NOPROFILE(ptest040) 701 #if defined(M68040) 702 .long 0x4e7a0003 | movc %tc,%d0 703 andw #0x8000,%d0 704 jeq Lget_phys1 | MMU is disabled 705 movc %dfc,%d1 | Save %DFC 706 movl %sp@(8),%d0 | Set FC for ptestr 707 movc %d0,%dfc 708 movl %sp@(4),%a0 | logical address to look up 709 .word 0xf568 | ptestr (%a0) 710 .long 0x4e7a0805 | movc %mmusr,%d0 711 movc %d1,%dfc | Restore %DFC 712 rts 713 Lget_phys1: 714 #endif 715 movql #0,%d0 | return failure 716 rts 717 718 /* 719 * LAK: (7/24/94) This routine was added so that the 720 * C routine that runs at startup can figure out how MacOS 721 * had mapped memory. We want to keep the same mapping so 722 * that when we set our MMU pointer, the PC doesn't point 723 * in the middle of nowhere. 724 * 725 * long get_pte(void *addr, unsigned long pte[2], unsigned short *psr) 726 * 727 * Takes "addr" and looks it up in the current MMU pages. Puts 728 * the PTE of that address in "pte" and the result of the 729 * search in "psr". "pte" should be 2 longs in case it is 730 * a long-format entry. 731 * 732 * One possible problem here is that setting the TT register 733 * may screw something up if we access user data space in a 734 * called function or in an interrupt service routine. 735 * 736 * Returns -1 on error, 0 if pte is a short-format pte, or 737 * 1 if pte is a long-format pte. 738 * 739 * Be sure to only call this routine if the MMU is enabled. This 740 * routine is probably more general than it needs to be -- it 741 * could simply return the physical address (replacing 742 * get_physical() in machdep). 743 * 744 * "gas" does not understand the %tt0 register, so we must hand- 745 * assemble the instructions. 746 */ 747 ENTRY_NOPROFILE(get_pte) 748 subql #4,%sp | make temporary space 749 750 lea _ASM_LABEL(longscratch),%a0 751 movl #MAC68K_TT_GET_PTE,%a0@ | See pmap.h 752 .long 0xf0100800 | pmove %a0@,%tt0 753 754 movl %sp@(8),%a0 | logical address to look up 755 movl #0,%a1 | clear in case of failure 756 ptestr #FC_USERD,%a0@,#7,%a1 | search for logical address 757 pmove %psr,%sp@ | store processor status register 758 movw %sp@,%d1 759 movl %sp@(16),%a0 | where to store the %psr 760 movw %d1,%a0@ | send back to caller 761 andw #0xc400,%d1 | if bus error, exceeded limit, or invalid 762 jne get_pte_fail1 | leave now 763 tstl %a1 | check address we got back 764 jeq get_pte_fail2 | if 0, then was not set -- fail 765 766 movl %a1,%d0 767 movl %d0,_ASM_LABEL(pte_tmp) | save for later 768 769 | send first long back to user 770 movl %sp@(12),%a0 | address of where to put pte 771 movsl %a1@,%d0 | 772 movl %d0,%a0@ | first long 773 774 andl #3,%d0 | dt bits of pte 775 cmpl #1,%d0 | should be 1 if page descriptor 776 jne get_pte_fail3 | if not, get out now 777 778 movl %sp@(16),%a0 | addr of stored %psr 779 movw %a0@,%d0 | get %psr again 780 andw #7,%d0 | number of levels it found 781 addw #-1,%d0 | find previous level 782 movl %sp@(8),%a0 | logical address to look up 783 movl #0,%a1 | clear in case of failure 784 785 cmpl #0,%d0 786 jeq pte_level_zero 787 cmpl #1,%d0 788 jeq pte_level_one 789 cmpl #2,%d0 790 jeq pte_level_two 791 cmpl #3,%d0 792 jeq pte_level_three 793 cmpl #4,%d0 794 jeq pte_level_four 795 cmpl #5,%d0 796 jeq pte_level_five 797 cmpl #6,%d0 798 jeq pte_level_six 799 jra get_pte_fail4 | really should have been one of these... 800 801 pte_level_zero: 802 | must get CRP to get length of entries at first level 803 lea _ASM_LABEL(longscratch),%a0 | space for two longs 804 pmove %crp,%a0@ | save root pointer 805 movl %a0@,%d0 | load high long 806 jra pte_got_parent 807 pte_level_one: 808 ptestr #FC_USERD,%a0@,#1,%a1 | search for logical address 809 pmove %psr,%sp@ | store processor status register 810 movw %sp@,%d1 811 jra pte_got_it 812 pte_level_two: 813 ptestr #FC_USERD,%a0@,#2,%a1 | search for logical address 814 pmove %psr,%sp@ | store processor status register 815 movw %sp@,%d1 816 jra pte_got_it 817 pte_level_three: 818 ptestr #FC_USERD,%a0@,#3,%a1 | search for logical address 819 pmove %psr,%sp@ | store processor status register 820 movw %sp@,%d1 821 jra pte_got_it 822 pte_level_four: 823 ptestr #FC_USERD,%a0@,#4,%a1 | search for logical address 824 pmove %psr,%sp@ | store processor status register 825 movw %sp@,%d1 826 jra pte_got_it 827 pte_level_five: 828 ptestr #FC_USERD,%a0@,#5,%a1 | search for logical address 829 pmove %psr,%sp@ | store processor status register 830 movw %sp@,%d1 831 jra pte_got_it 832 pte_level_six: 833 ptestr #FC_USERD,%a0@,#6,%a1 | search for logical address 834 pmove %psr,%sp@ | store processor status register 835 movw %sp@,%d1 836 837 pte_got_it: 838 andw #0xc400,%d1 | if bus error, exceeded limit, or invalid 839 jne get_pte_fail5 | leave now 840 tstl %a1 | check address we got back 841 jeq get_pte_fail6 | if 0, then was not set -- fail 842 843 movsl %a1@,%d0 | get pte of parent 844 movl %d0,_C_LABEL(macos_tt0) | XXX for later analysis (kill me) 845 pte_got_parent: 846 andl #3,%d0 | dt bits of pte 847 cmpl #2,%d0 | child is short-format descriptor 848 jeq short_format 849 cmpl #3,%d0 | child is long-format descriptor 850 jne get_pte_fail7 851 852 | long_format -- we must go back, change the tt, and get the 853 | second long. The reason we didn't do this in the first place 854 | is that the first long might have been the last long of RAM. 855 856 movl _ASM_LABEL(pte_tmp),%a1 | get address of our original pte 857 addql #4,%a1 | address of ite second long 858 859 | send second long back to user 860 movl %sp@(12),%a0 | address of where to put pte 861 movsl %a1@,%d0 | 862 movl %d0,%a0@(4) | write in second long 863 864 movql #1,%d0 | return long-format 865 jra get_pte_success 866 867 short_format: 868 movql #0,%d0 | return short-format 869 jra get_pte_success 870 871 get_pte_fail: 872 movql #-1,%d0 | return failure 873 874 get_pte_success: 875 lea _ASM_LABEL(longscratch),%a0 | disable tt 876 movl #0,%a0@ 877 .long 0xf0100800 | pmove %a0@,%tt0 878 879 addql #4,%sp | return temporary space 880 rts 881 882 get_pte_fail1: 883 jbsr _C_LABEL(printstar) 884 jra get_pte_fail 885 get_pte_fail2: 886 jbsr _C_LABEL(printstar) 887 jbsr _C_LABEL(printstar) 888 jra get_pte_fail 889 get_pte_fail3: 890 jbsr _C_LABEL(printstar) 891 jbsr _C_LABEL(printstar) 892 jbsr _C_LABEL(printstar) 893 jra get_pte_fail 894 get_pte_fail4: 895 jbsr _C_LABEL(printstar) 896 jbsr _C_LABEL(printstar) 897 jbsr _C_LABEL(printstar) 898 jbsr _C_LABEL(printstar) 899 jra get_pte_fail 900 get_pte_fail5: 901 jbsr _C_LABEL(printstar) 902 jbsr _C_LABEL(printstar) 903 jbsr _C_LABEL(printstar) 904 jbsr _C_LABEL(printstar) 905 jbsr _C_LABEL(printstar) 906 jra get_pte_fail 907 get_pte_fail6: 908 jbsr _C_LABEL(printstar) 909 jbsr _C_LABEL(printstar) 910 jbsr _C_LABEL(printstar) 911 jbsr _C_LABEL(printstar) 912 jbsr _C_LABEL(printstar) 913 jbsr _C_LABEL(printstar) 914 jra get_pte_fail 915 get_pte_fail7: 916 jbsr _C_LABEL(printstar) 917 jbsr _C_LABEL(printstar) 918 jbsr _C_LABEL(printstar) 919 jbsr _C_LABEL(printstar) 920 jbsr _C_LABEL(printstar) 921 jbsr _C_LABEL(printstar) 922 jbsr _C_LABEL(printstar) 923 jra get_pte_fail 924 get_pte_fail8: 925 jbsr _C_LABEL(printstar) 926 jbsr _C_LABEL(printstar) 927 jbsr _C_LABEL(printstar) 928 jbsr _C_LABEL(printstar) 929 jbsr _C_LABEL(printstar) 930 jbsr _C_LABEL(printstar) 931 jbsr _C_LABEL(printstar) 932 jbsr _C_LABEL(printstar) 933 jra get_pte_fail 934 get_pte_fail9: 935 jbsr _C_LABEL(printstar) 936 jbsr _C_LABEL(printstar) 937 jbsr _C_LABEL(printstar) 938 jbsr _C_LABEL(printstar) 939 jbsr _C_LABEL(printstar) 940 jbsr _C_LABEL(printstar) 941 jbsr _C_LABEL(printstar) 942 jbsr _C_LABEL(printstar) 943 jbsr _C_LABEL(printstar) 944 jra get_pte_fail 945 get_pte_fail10: 946 jbsr _C_LABEL(printstar) 947 jbsr _C_LABEL(printstar) 948 jbsr _C_LABEL(printstar) 949 jbsr _C_LABEL(printstar) 950 jbsr _C_LABEL(printstar) 951 jbsr _C_LABEL(printstar) 952 jbsr _C_LABEL(printstar) 953 jbsr _C_LABEL(printstar) 954 jbsr _C_LABEL(printstar) 955 jbsr _C_LABEL(printstar) 956 jra get_pte_fail 957 958 /* 959 * Misc. global variables. 960 */ 961 .data 962 GLOBAL(sanity_check) 963 .long 0x18621862 | this is our stack overflow checker. 964 965 .space 4 * PAGE_SIZE 966 .align 4 967 ASGLOBAL(tmpstk) 968 969 GLOBAL(machineid) 970 .long 0 | default to 320 971 972 GLOBAL(mmutype) 973 .long MMU_68851 | default to 68851 PMMU 974 975 GLOBAL(cputype) 976 .long CPU_68020 | default to 68020 CPU 977 978 #ifdef __notyet__ 979 GLOBAL(ectype) 980 .long EC_NONE | external cache type, default to none 981 #endif 982 983 GLOBAL(intiolimit) 984 .long 0 | KVA of end of internal IO space 985 986 GLOBAL(load_addr) 987 .long 0 | Physical address of kernel 988 989 ASLOCAL(lastpage) 990 .long 0 | LAK: to store the addr of last page in mem 991 992 GLOBAL(MacOSROMBase) 993 .long 0x40800000 994 GLOBAL(mac68k_vrsrc_cnt) 995 .long 0 996 GLOBAL(mac68k_vrsrc_vec) 997 .word 0, 0, 0, 0, 0, 0 998 999 #ifdef DEBUG 1000 ASGLOBAL(fulltflush) 1001 .long 0 1002 1003 ASGLOBAL(fullcflush) 1004 .long 0 1005 #endif 1006 1007 /* interrupt counters -- leave some space for overriding the names */ 1008 1009 GLOBAL(intrnames) 1010 .asciz "spur " 1011 .asciz "via1 " 1012 .asciz "via2 " 1013 .asciz "unused1 " 1014 .asciz "scc " 1015 .asciz "unused2 " 1016 .asciz "unused3 " 1017 .asciz "nmi " 1018 .asciz "clock " 1019 GLOBAL(eintrnames) 1020 .even 1021 1022 GLOBAL(intrcnt) 1023 .long 0,0,0,0,0,0,0,0,0 1024 GLOBAL(eintrcnt) 1025