1 /* $NetBSD: locore.s,v 1.209 2026/04/07 12:36:22 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 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 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 lea _C_LABEL(mmutype),%a0 178 movl #MMU_68040,%a0@ | Reflect 68040 MMU 179 lea _C_LABEL(cputype),%a0 180 movl #CPU_68040,%a0@ | and 68040 MPU 181 jra Lstart1 182 183 Lis68020: 184 movl #CACHE_OFF,%d0 | disable and clear cache 185 movc %d0,%cacr 186 lea _C_LABEL(mmutype),%a0 | Must be 68020+68851 187 movl #MMU_68851,%a0@ | Reflect 68851 PMMU 188 lea _C_LABEL(cputype),%a0 189 movl #CPU_68020,%a0@ | and 68020 MPU 190 191 Lstart1: 192 jbsr _C_LABEL(setmachdep) | Set some machine-dep stuff 193 jbsr _C_LABEL(consinit) | XXX Should only be if graybar on 194 195 /* 196 * Figure out MacOS mappings and bootstrap NetBSD 197 */ 198 lea _C_LABEL(macos_tc),%a0 | get current %TC 199 cmpl #MMU_68040,_C_LABEL(mmutype) | check to see if 68040 200 jeq Lget040TC 201 202 pmove %tc,%a0@ 203 jra Lstart3 204 205 Lget040TC: 206 #if 0 207 movl _C_LABEL(current_mac_model),%a1 | if an AV Mac, save current 208 cmpl #MACH_CLASSAV,%a1@(CPUINFO_CLASS) | %TC so internal video will 209 jne LnotAV | get configured 210 #endif 211 .long 0x4e7a0003 | movc %tc,%d0 212 jra LsaveTC 213 LnotAV: 214 movql #0,%d0 | otherwise, 215 .long 0x4e7b0003 | movc %d0,%tc ;Disable MMU 216 LsaveTC: 217 movl %d0,%a0@ 218 219 Lstart3: 220 movl %a0@,%sp@- | get Mac OS mapping, relocate video, 221 jbsr _C_LABEL(bootstrap_mac68k) | bootstrap pmap, et al. 222 addql #4,%sp 223 224 /* 225 * nextpa is returned in %d0. We need to squirrel that 226 * away in a callee-saved regstier for use later, after 227 * the MMU is enabled. 228 */ 229 movl %d0, %d7 230 231 /* NOTE: %d7 is now off-limits!! */ 232 233 /* 234 * Set up the vector table, and race to get the MMU 235 * enabled. 236 * 237 * XXX Should move vec_init() call to Lloaddone, like other 238 * XXX m68k platforms do. 239 */ 240 jbsr _C_LABEL(vec_init) 241 242 movl _C_LABEL(Sysseg_pa),%a1 | system segment table PA 243 cmpl #MMU_68040,_C_LABEL(mmutype) 244 jne Lenablepre040MMU | if not 040, skip 245 246 movql #0,%d0 247 .long 0x4e7b0003 | movc %d0,%tc ;Disable MMU 248 .long 0x4e7b0004 | movc %d0,%itt0 ;Disable itt0 249 .long 0x4e7b0005 | movc %d0,%itt1 ;Disable itt1 250 .long 0x4e7b0006 | movc %d0,%dtt0 ;Disable dtt0 251 .long 0x4e7b0007 | movc %d0,%dtt1 ;Disable dtt1 252 movl %a1,%d1 253 .word 0xf518 | pflusha 254 .long 0x4e7b1807 | movc %d1,%srp 255 256 #if defined(DJMEMCMAX) 257 movl %a3,%sp@- 258 cmpl #MACH_MACC610,_C_LABEL(machineid) 259 jeq Ldjmemc610 260 cmpl #MACH_MACQ610,_C_LABEL(machineid) 261 jeq Ldjmemc610 262 cmpl #MACH_MACC650,_C_LABEL(machineid) 263 jeq Ldjmemccfg 264 cmpl #MACH_MACQ650,_C_LABEL(machineid) 265 jeq Ldjmemccfg 266 cmpl #MACH_MACQ800,_C_LABEL(machineid) 267 jeq Ldjmemccfg 268 269 jra Lnodjmemc 270 271 Ldjmemccfg: 272 movl #0x50f0e00c,%a0 273 movl %a0@,%d0 | determine where RAM SIMMs start 274 andl #0x000000FF,%d0 275 addl #0x10,%d0 | bank 3 start 276 addl #0x10,%d0 | bank 4 start 277 278 movl #0x50f0e014,%a0 279 movl %d0,%a0@+ | bank 4 280 addl #0x10,%d0 281 movl %d0,%a0@+ | bank 5 282 addl #0x10,%d0 283 284 movl %d0,%a0@+ | bank 6 285 addl #0x10,%d0 286 movl %d0,%a0@+ | bank 7 287 addl #0x10,%d0 288 movl %d0,%a0@+ | bank 8 289 addl #0x10,%d0 290 movl %d0,%a0@+ | bank 9 291 addl #0x10,%d0 292 jra Ldjmemctop 293 294 Ldjmemc610: 295 movl #0x50f0e00c,%a0 296 movl %a0@,%d0 | determine where RAM SIMMs start 297 andl #0x000000FF,%d0 298 addl #0x10,%d0 | bank 3 start 299 300 movl #0x50f0e014,%a0 301 movl %d0,%a0@+ | bank 4 302 addl #0x10,%d0 303 movl %d0,%a0@+ | bank 5 304 movl %d0,%a0@+ | bank 6 305 addl #0x10,%d0 306 movl %d0,%a0@+ | bank 7 307 movl %d0,%a0@+ | bank 8 308 addl #0x10,%d0 309 movl %d0,%a0@+ | bank 9 310 311 Ldjmemctop: 312 movl #0x50F0E02C,%a0 313 movl %d0,%a0@ | memtop 314 315 | preserve ~512KB beyond 4MB just in case 316 movl #0x400000,%a0 317 movl #0x9000000,%a2 318 movl #0xFFFF,%d0 319 L1stbankcopy1: 320 movl %a0@+,%a2@+ 321 dbra %d0,L1stbankcopy1 322 movl #0xFFFF,%d0 323 L1stbankcopy2: 324 movl %a0@+,%a2@+ 325 dbra %d0,L1stbankcopy2 326 327 lea _ASM_LABEL(Lsetup1stbank),%a0 328 movl #0x8800000,%a2 | Pick a location that should be in bank 4 329 movl #0x64,%d0 330 Ldjcopy: 331 movl %a0@+,%a2@+ 332 dbra %d0,Ldjcopy 333 334 movl #0x8800000,%a0 335 lea _ASM_LABEL(Ldjmemcdone),%a2 336 jmp %a0@ 337 338 Lsetup1stbank: 339 | now configure banks 2 & 3 340 movl #0x50f0e00c,%a0 341 movl %a0@,%d0 | determine where RAM SIMMs start 342 andl #0x000000FF,%d0 343 movl %d0,%a0@+ 344 addl #0x10,%d0 | bank 3 start 345 movl %d0,%a0@ 346 347 | and return to where we came from. 348 jmp %a2@ 349 350 Ldjmemcdone: 351 movl #0x400000,%a2 352 movl #0x9000000,%a0 353 movl #0xFFFF,%d0 354 Lcopyback1: 355 movl %a0@+,%a2@+ 356 dbra %d0,Lcopyback1 357 movl #0xFFFF,%d0 358 Lcopyback2: 359 movl %a0@+,%a2@+ 360 dbra %d0,Lcopyback2 361 362 Lnodjmemc: 363 movl %sp@+,%a3 364 #endif 365 366 movl #MMU40_TCR_BITS,%d0 367 .long 0x4e7b0003 | movc %d0,%tc ;Enable MMU 368 movl #CACHE40_ON,%d0 369 movc %d0,%cacr | turn on both caches 370 jra Lloaddone 371 372 Lenablepre040MMU: 373 tstl _C_LABEL(mmutype) | TTx instructions will break 68851 374 jgt LnokillTT 375 376 lea _ASM_LABEL(longscratch),%a0 | disable TTx registers on 68030 377 movl #0,%a0@ 378 .long 0xf0100800 | movl %a0@,%tt0 379 .long 0xf0100c00 | movl %a0@,%tt1 380 381 LnokillTT: 382 #if defined(M68020) || defined(M68030) 383 lea _C_LABEL(protorp),%a0 384 movl %a1,%a0@(4) | segtable address 385 pmove %a0@,%srp | load the supervisor root pointer 386 pflusha 387 lea _ASM_LABEL(longscratch),%a2 388 movl #MMU51_TCR_BITS,%a2@ | value to load %TC with 389 pmove %a2@,%tc | load it 390 #endif /* M68020 || M68030 */ 391 392 /* 393 * Should be running mapped from this point on 394 */ 395 Lloaddone: 396 lea _ASM_LABEL(tmpstk),%sp | temporary stack 397 398 /* phase 2 of pmap setup, returns lwp0 SP in %a0 */ 399 jbsr _C_LABEL(pmap_bootstrap2) 400 movl %a0,%sp | now running on lwp0's stack 401 movl #0,%a6 | terminate the stack back trace 402 403 /* flush TLB and turn on caches */ 404 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 405 jeq Ltbia040 | yes, cache already on 406 pflusha 407 movl #CACHE_ON,%d0 408 movc %d0,%cacr | clear cache(s) 409 #ifdef __notyet__ 410 tstl _C_LABEL(ectype) 411 jeq Lnocache0 412 | Enable external cache here 413 #endif 414 jra Lnocache0 415 416 Ltbia040: 417 .word 0xf518 | pflusha 418 419 Lnocache0: 420 movl %d7,%sp@- | push nextpa saved above 421 jbsr _C_LABEL(machine_init) | additional pre-main initialization 422 addql #4,%sp 423 jra _C_LABEL(main) | main() (never returns) 424 425 /* 426 * Use common m68k bus error and address error handlers. 427 */ 428 .data 429 GLOBAL(mac68k_a2_fromfault) 430 .long 0 431 GLOBAL(m68k_fault_addr) 432 .long 0 433 434 /* 435 * Interrupt handlers. 436 * 437 * Most 68k-based Macintosh computers 438 * 439 * Level 0: Spurious: ignored 440 * Level 1: VIA1 (clock, ADB) 441 * Level 2: VIA2 (NuBus, SCSI) 442 * Level 3: 443 * Level 4: Serial (SCC) 444 * Level 5: 445 * Level 6: 446 * Level 7: Non-maskable: parity errors, RESET button 447 * 448 * On the Q700, Q900 and Q950 in "A/UX mode": this should become: 449 * 450 * Level 0: Spurious: ignored 451 * Level 1: Software 452 * Level 2: VIA2 (except ethernet, sound) 453 * Level 3: Ethernet 454 * Level 4: Serial (SCC) 455 * Level 5: Sound 456 * Level 6: VIA1 457 * Level 7: NMIs: parity errors, RESET button, YANCC error 458 * 459 * On the 660AV and 840AV: 460 * 461 * Level 0: Spurious: ignored 462 * Level 1: VIA1 (clock, ADB) 463 * Level 2: VIA2 (NuBus, SCSI) 464 * Level 3: PSC device interrupt 465 * Level 4: PSC DMA and serial 466 * Level 5: ??? 467 * Level 6: ??? 468 * Level 7: NMIs: parity errors?, RESET button 469 */ 470 471 ENTRY_NOPROFILE(spurintr) 472 addql #1,_C_LABEL(intrcnt)+0 473 INTERRUPT_SAVEREG 474 CPUINFO_INCREMENT(CI_NINTR) 475 INTERRUPT_RESTOREREG 476 jra _ASM_LABEL(rei) 477 478 ENTRY_NOPROFILE(intrhand) 479 INTERRUPT_SAVEREG 480 jbsr _C_LABEL(intr_dispatch) | call dispatch routine 481 INTERRUPT_RESTOREREG 482 jra _ASM_LABEL(rei) | all done 483 484 ENTRY_NOPROFILE(lev7intr) 485 addql #1,_C_LABEL(intrcnt)+16 486 clrl %sp@- | pad %SR to longword 487 moveml #0xFFFF,%sp@- | save registers 488 movl %usp,%a0 | and save 489 movl %a0,%sp@(FR_SP) | the user stack pointer 490 jbsr _C_LABEL(nmihand) | call handler 491 movl %sp@(FR_SP),%a0 | restore 492 movl %a0,%usp | %USP 493 moveml %sp@+,#0x7FFF | and remaining registers 494 addql #8,%sp | pop SSP and align word 495 jra _ASM_LABEL(rei) 496 497 /* 498 * We could tweak rtclock_intr and gain 12 cycles on the 020 and 030 by 499 * saving the status register directly to the stack, but this would lose 500 * badly on the 040. Aligning the stack takes 10 more cycles than this 501 * code does, so it's a good compromise. 502 * 503 * A pointer to the clockframe is passed as an argument in the usual 504 * fashion. 505 */ 506 ENTRY_NOPROFILE(rtclock_intr) 507 movl %sp@(4),%a1 | stash pointer to clockframe 508 movl %d2,%sp@- | save %d2 509 movw %sr,%d2 | save SPL 510 | raise SPL to splclock() 511 movw _C_LABEL(ipl2psl_table)+IPL_CLOCK*2,%sr 512 movl %a1,%sp@- | push pointer to clockframe 513 jbsr _C_LABEL(hardclock) | call generic clock int routine 514 addql #4,%sp | pop param 515 jbsr _C_LABEL(mrg_VBLQueue) | give programs in the VBLqueue a chance 516 addql #1,_C_LABEL(intrcnt)+32 | record a clock interrupt 517 INTERRUPT_SAVEREG 518 CPUINFO_INCREMENT(CI_NINTR) 519 INTERRUPT_RESTOREREG 520 movw %d2,%sr | restore SPL 521 movl %sp@+,%d2 | restore %d2 522 rts | go back from whence we came 523 524 /* 525 * delay() - delay for a specified number of microseconds 526 * _delay() - calibrator helper for delay() 527 * 528 * Notice that delay_factor is scaled up by a factor of 128 to avoid loss 529 * of precision for small delays. As a result of this we need to avoid 530 * overflow. 531 * 532 * The branch target for the loops must be aligned on a half-line (8-byte) 533 * boundary to minimize cache effects. This guarantees both that there 534 * will be no prefetch stalls due to cache line burst operations and that 535 * the loops will run from a single cache half-line. 536 */ 537 .align 8 | align to half-line boundary 538 | (use nop instructions if necessary!) 539 ALTENTRY(_delay, _delay) 540 ENTRY(delay) 541 movl %sp@(4),%d0 | get microseconds to delay 542 cmpl #0x40000,%d0 | is it a "large" delay? 543 bls .Ldelayshort | no, normal calculation 544 movql #0x7f,%d1 | adjust for scaled multiplier (to 545 addl %d1,%d0 | avoid overflow) 546 lsrl #7,%d0 547 mulul _C_LABEL(delay_factor),%d0 | calculate number of loop iterations 548 bra .Ldelaysetup | go do it! 549 .Ldelayshort: 550 mulul _C_LABEL(delay_factor),%d0 | calculate number of loop iterations 551 lsrl #7,%d0 | adjust for scaled multiplier 552 .Ldelaysetup: 553 jeq .Ldelayexit | bail out if nothing to do 554 movql #0,%d1 | put bits 15-0 in %d1 for the 555 movw %d0,%d1 | inner loop, and move bits 556 movw #0,%d0 | 31-16 to the low-order word 557 subql #1,%d1 | of %d0 for the outer loop 558 swap %d0 559 .Ldelay: 560 tstl _C_LABEL(delay_flag) | this never changes for delay()! 561 dbeq %d1,.Ldelay | (used only for timing purposes) 562 dbeq %d0,.Ldelay 563 addqw #1,%d1 | adjust end count and 564 swap %d0 | return the longword result 565 orl %d1,%d0 566 .Ldelayexit: 567 rts 568 569 /* 570 * Handle the nitty-gritty of rebooting the machine. 571 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 572 * Note that we must be running in an address range that is mapped one-to-one 573 * logical to physical so that the PC is still valid immediately after the MMU 574 * is turned off. We have conveniently mapped the last page of physical 575 * memory this way. 576 */ 577 ENTRY_NOPROFILE(doboot) 578 #if defined(M68040) 579 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 580 jeq Lnocache5 | yes, skip 581 #endif 582 movl #CACHE_OFF,%d0 583 movc %d0,%cacr | disable on-chip cache(s) 584 Lnocache5: 585 movl _C_LABEL(last_page),%a0 | last page of physical memory 586 lea Lbootcode,%a1 | start of boot code 587 lea Lebootcode,%a3 | end of boot code 588 Lbootcopy: 589 movw %a1@+,%a0@+ | copy a word 590 cmpl %a3,%a1 | done yet? 591 jcs Lbootcopy | no, keep going 592 #if defined(M68040) 593 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 594 jne LmotommuE | no, skip 595 .word 0xf4f8 | cpusha bc 596 LmotommuE: 597 #endif 598 movl _C_LABEL(last_page),%a0 599 jmp %a0@ | jump to last page 600 601 Lbootcode: 602 lea %a0@(0x800),%sp | physical %SP in case of NMI 603 movl _C_LABEL(MacOSROMBase),%a1 | Load MacOS ROMBase 604 605 #if defined(M68040) 606 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 607 jne LmotommuF | no, skip 608 movl #0,%d0 609 movc %d0,%cacr | caches off 610 .long 0x4e7b0003 | movc %d0,%tc (disable MMU) 611 jra Ldoboot1 612 LmotommuF: 613 #endif 614 lea _ASM_LABEL(longscratch),%a3 615 movl #0,%a3@ | value for pmove to %TC (turn off MMU) 616 pmove %a3@,%tc | disable MMU 617 618 Ldoboot1: 619 lea %a1@(0x90),%a1 | offset of ROM reset routine 620 jmp %a1@ | and jump to ROM to reset machine 621 Lebootcode: 622 623 /* 624 * u_long ptest040(void *addr, u_int fc); 625 * 626 * ptest040() does an 040 PTESTR (addr) and returns the 040 MMUSR iff 627 * translation is enabled. This allows us to find the physical address 628 * corresponding to a MacOS logical address for get_physical(). 629 * sar 01-oct-1996 630 */ 631 ENTRY_NOPROFILE(ptest040) 632 #if defined(M68040) 633 .long 0x4e7a0003 | movc %tc,%d0 634 andw #0x8000,%d0 635 jeq Lget_phys1 | MMU is disabled 636 movc %dfc,%d1 | Save %DFC 637 movl %sp@(8),%d0 | Set FC for ptestr 638 movc %d0,%dfc 639 movl %sp@(4),%a0 | logical address to look up 640 .word 0xf568 | ptestr (%a0) 641 .long 0x4e7a0805 | movc %mmusr,%d0 642 movc %d1,%dfc | Restore %DFC 643 rts 644 Lget_phys1: 645 #endif 646 movql #0,%d0 | return failure 647 rts 648 649 /* 650 * LAK: (7/24/94) This routine was added so that the 651 * C routine that runs at startup can figure out how MacOS 652 * had mapped memory. We want to keep the same mapping so 653 * that when we set our MMU pointer, the PC doesn't point 654 * in the middle of nowhere. 655 * 656 * long get_pte(void *addr, unsigned long pte[2], unsigned short *psr) 657 * 658 * Takes "addr" and looks it up in the current MMU pages. Puts 659 * the PTE of that address in "pte" and the result of the 660 * search in "psr". "pte" should be 2 longs in case it is 661 * a long-format entry. 662 * 663 * One possible problem here is that setting the TT register 664 * may screw something up if we access user data space in a 665 * called function or in an interrupt service routine. 666 * 667 * Returns -1 on error, 0 if pte is a short-format pte, or 668 * 1 if pte is a long-format pte. 669 * 670 * Be sure to only call this routine if the MMU is enabled. This 671 * routine is probably more general than it needs to be -- it 672 * could simply return the physical address (replacing 673 * get_physical() in machdep). 674 * 675 * "gas" does not understand the %tt0 register, so we must hand- 676 * assemble the instructions. 677 */ 678 ENTRY_NOPROFILE(get_pte) 679 subql #4,%sp | make temporary space 680 681 lea _ASM_LABEL(longscratch),%a0 682 movl #MAC68K_TT_GET_PTE,%a0@ | See pmap.h 683 .long 0xf0100800 | pmove %a0@,%tt0 684 685 movl %sp@(8),%a0 | logical address to look up 686 movl #0,%a1 | clear in case of failure 687 ptestr #FC_USERD,%a0@,#7,%a1 | search for logical address 688 pmove %psr,%sp@ | store processor status register 689 movw %sp@,%d1 690 movl %sp@(16),%a0 | where to store the %psr 691 movw %d1,%a0@ | send back to caller 692 andw #0xc400,%d1 | if bus error, exceeded limit, or invalid 693 jne get_pte_fail1 | leave now 694 tstl %a1 | check address we got back 695 jeq get_pte_fail2 | if 0, then was not set -- fail 696 697 movl %a1,%d0 698 movl %d0,_ASM_LABEL(pte_tmp) | save for later 699 700 | send first long back to user 701 movl %sp@(12),%a0 | address of where to put pte 702 movsl %a1@,%d0 | 703 movl %d0,%a0@ | first long 704 705 andl #3,%d0 | dt bits of pte 706 cmpl #1,%d0 | should be 1 if page descriptor 707 jne get_pte_fail3 | if not, get out now 708 709 movl %sp@(16),%a0 | addr of stored %psr 710 movw %a0@,%d0 | get %psr again 711 andw #7,%d0 | number of levels it found 712 addw #-1,%d0 | find previous level 713 movl %sp@(8),%a0 | logical address to look up 714 movl #0,%a1 | clear in case of failure 715 716 cmpl #0,%d0 717 jeq pte_level_zero 718 cmpl #1,%d0 719 jeq pte_level_one 720 cmpl #2,%d0 721 jeq pte_level_two 722 cmpl #3,%d0 723 jeq pte_level_three 724 cmpl #4,%d0 725 jeq pte_level_four 726 cmpl #5,%d0 727 jeq pte_level_five 728 cmpl #6,%d0 729 jeq pte_level_six 730 jra get_pte_fail4 | really should have been one of these... 731 732 pte_level_zero: 733 | must get CRP to get length of entries at first level 734 lea _ASM_LABEL(longscratch),%a0 | space for two longs 735 pmove %crp,%a0@ | save root pointer 736 movl %a0@,%d0 | load high long 737 jra pte_got_parent 738 pte_level_one: 739 ptestr #FC_USERD,%a0@,#1,%a1 | search for logical address 740 pmove %psr,%sp@ | store processor status register 741 movw %sp@,%d1 742 jra pte_got_it 743 pte_level_two: 744 ptestr #FC_USERD,%a0@,#2,%a1 | search for logical address 745 pmove %psr,%sp@ | store processor status register 746 movw %sp@,%d1 747 jra pte_got_it 748 pte_level_three: 749 ptestr #FC_USERD,%a0@,#3,%a1 | search for logical address 750 pmove %psr,%sp@ | store processor status register 751 movw %sp@,%d1 752 jra pte_got_it 753 pte_level_four: 754 ptestr #FC_USERD,%a0@,#4,%a1 | search for logical address 755 pmove %psr,%sp@ | store processor status register 756 movw %sp@,%d1 757 jra pte_got_it 758 pte_level_five: 759 ptestr #FC_USERD,%a0@,#5,%a1 | search for logical address 760 pmove %psr,%sp@ | store processor status register 761 movw %sp@,%d1 762 jra pte_got_it 763 pte_level_six: 764 ptestr #FC_USERD,%a0@,#6,%a1 | search for logical address 765 pmove %psr,%sp@ | store processor status register 766 movw %sp@,%d1 767 768 pte_got_it: 769 andw #0xc400,%d1 | if bus error, exceeded limit, or invalid 770 jne get_pte_fail5 | leave now 771 tstl %a1 | check address we got back 772 jeq get_pte_fail6 | if 0, then was not set -- fail 773 774 movsl %a1@,%d0 | get pte of parent 775 movl %d0,_C_LABEL(macos_tt0) | XXX for later analysis (kill me) 776 pte_got_parent: 777 andl #3,%d0 | dt bits of pte 778 cmpl #2,%d0 | child is short-format descriptor 779 jeq short_format 780 cmpl #3,%d0 | child is long-format descriptor 781 jne get_pte_fail7 782 783 | long_format -- we must go back, change the tt, and get the 784 | second long. The reason we didn't do this in the first place 785 | is that the first long might have been the last long of RAM. 786 787 movl _ASM_LABEL(pte_tmp),%a1 | get address of our original pte 788 addql #4,%a1 | address of ite second long 789 790 | send second long back to user 791 movl %sp@(12),%a0 | address of where to put pte 792 movsl %a1@,%d0 | 793 movl %d0,%a0@(4) | write in second long 794 795 movql #1,%d0 | return long-format 796 jra get_pte_success 797 798 short_format: 799 movql #0,%d0 | return short-format 800 jra get_pte_success 801 802 get_pte_fail: 803 movql #-1,%d0 | return failure 804 805 get_pte_success: 806 lea _ASM_LABEL(longscratch),%a0 | disable tt 807 movl #0,%a0@ 808 .long 0xf0100800 | pmove %a0@,%tt0 809 810 addql #4,%sp | return temporary space 811 rts 812 813 get_pte_fail1: 814 jbsr _C_LABEL(printstar) 815 jra get_pte_fail 816 get_pte_fail2: 817 jbsr _C_LABEL(printstar) 818 jbsr _C_LABEL(printstar) 819 jra get_pte_fail 820 get_pte_fail3: 821 jbsr _C_LABEL(printstar) 822 jbsr _C_LABEL(printstar) 823 jbsr _C_LABEL(printstar) 824 jra get_pte_fail 825 get_pte_fail4: 826 jbsr _C_LABEL(printstar) 827 jbsr _C_LABEL(printstar) 828 jbsr _C_LABEL(printstar) 829 jbsr _C_LABEL(printstar) 830 jra get_pte_fail 831 get_pte_fail5: 832 jbsr _C_LABEL(printstar) 833 jbsr _C_LABEL(printstar) 834 jbsr _C_LABEL(printstar) 835 jbsr _C_LABEL(printstar) 836 jbsr _C_LABEL(printstar) 837 jra get_pte_fail 838 get_pte_fail6: 839 jbsr _C_LABEL(printstar) 840 jbsr _C_LABEL(printstar) 841 jbsr _C_LABEL(printstar) 842 jbsr _C_LABEL(printstar) 843 jbsr _C_LABEL(printstar) 844 jbsr _C_LABEL(printstar) 845 jra get_pte_fail 846 get_pte_fail7: 847 jbsr _C_LABEL(printstar) 848 jbsr _C_LABEL(printstar) 849 jbsr _C_LABEL(printstar) 850 jbsr _C_LABEL(printstar) 851 jbsr _C_LABEL(printstar) 852 jbsr _C_LABEL(printstar) 853 jbsr _C_LABEL(printstar) 854 jra get_pte_fail 855 get_pte_fail8: 856 jbsr _C_LABEL(printstar) 857 jbsr _C_LABEL(printstar) 858 jbsr _C_LABEL(printstar) 859 jbsr _C_LABEL(printstar) 860 jbsr _C_LABEL(printstar) 861 jbsr _C_LABEL(printstar) 862 jbsr _C_LABEL(printstar) 863 jbsr _C_LABEL(printstar) 864 jra get_pte_fail 865 get_pte_fail9: 866 jbsr _C_LABEL(printstar) 867 jbsr _C_LABEL(printstar) 868 jbsr _C_LABEL(printstar) 869 jbsr _C_LABEL(printstar) 870 jbsr _C_LABEL(printstar) 871 jbsr _C_LABEL(printstar) 872 jbsr _C_LABEL(printstar) 873 jbsr _C_LABEL(printstar) 874 jbsr _C_LABEL(printstar) 875 jra get_pte_fail 876 get_pte_fail10: 877 jbsr _C_LABEL(printstar) 878 jbsr _C_LABEL(printstar) 879 jbsr _C_LABEL(printstar) 880 jbsr _C_LABEL(printstar) 881 jbsr _C_LABEL(printstar) 882 jbsr _C_LABEL(printstar) 883 jbsr _C_LABEL(printstar) 884 jbsr _C_LABEL(printstar) 885 jbsr _C_LABEL(printstar) 886 jbsr _C_LABEL(printstar) 887 jra get_pte_fail 888 889 /* 890 * Misc. global variables. 891 */ 892 .data 893 GLOBAL(sanity_check) 894 .long 0x18621862 | this is our stack overflow checker. 895 896 .space 4 * PAGE_SIZE 897 .align 4 898 ASGLOBAL(tmpstk) 899 900 GLOBAL(machineid) 901 .long 0 | default to 320 902 903 GLOBAL(mmutype) 904 .long MMU_68851 | default to 68851 PMMU 905 906 GLOBAL(cputype) 907 .long CPU_68020 | default to 68020 CPU 908 909 #ifdef __notyet__ 910 GLOBAL(ectype) 911 .long EC_NONE | external cache type, default to none 912 #endif 913 914 GLOBAL(intiolimit) 915 .long 0 | KVA of end of internal IO space 916 917 GLOBAL(load_addr) 918 .long 0 | Physical address of kernel 919 920 ASLOCAL(lastpage) 921 .long 0 | LAK: to store the addr of last page in mem 922 923 GLOBAL(MacOSROMBase) 924 .long 0x40800000 925 GLOBAL(mac68k_vrsrc_cnt) 926 .long 0 927 GLOBAL(mac68k_vrsrc_vec) 928 .word 0, 0, 0, 0, 0, 0 929 930 #ifdef DEBUG 931 ASGLOBAL(fulltflush) 932 .long 0 933 934 ASGLOBAL(fullcflush) 935 .long 0 936 #endif 937 938 /* interrupt counters -- leave some space for overriding the names */ 939 940 GLOBAL(intrnames) 941 .asciz "spur " 942 .asciz "via1 " 943 .asciz "via2 " 944 .asciz "unused1 " 945 .asciz "scc " 946 .asciz "unused2 " 947 .asciz "unused3 " 948 .asciz "nmi " 949 .asciz "clock " 950 GLOBAL(eintrnames) 951 .even 952 953 GLOBAL(intrcnt) 954 .long 0,0,0,0,0,0,0,0,0 955 GLOBAL(eintrcnt) 956