1/* $NetBSD: locore.s,v 1.173 2022/05/30 09:56:03 andvar Exp $ */ 2 3/* 4 * Copyright (c) 1980, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 36 * 37 * @(#)locore.s 8.6 (Berkeley) 5/27/94 38 */ 39 40/* 41 * Copyright (c) 1994, 1995 Gordon W. Ross 42 * Copyright (c) 1988 University of Utah. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * the Systems Programming Group of the University of Utah Computer 46 * Science Department. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. All advertising materials mentioning features or use of this software 57 * must display the following acknowledgement: 58 * This product includes software developed by the University of 59 * California, Berkeley and its contributors. 60 * 4. Neither the name of the University nor the names of its contributors 61 * may be used to endorse or promote products derived from this software 62 * without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74 * SUCH DAMAGE. 75 * 76 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 77 * 78 * @(#)locore.s 8.6 (Berkeley) 5/27/94 79 */ 80 81#include "opt_compat_netbsd.h" 82#include "opt_compat_sunos.h" 83#include "opt_ddb.h" 84#include "opt_fpsp.h" 85#include "opt_kgdb.h" 86#include "opt_lockdebug.h" 87#include "opt_fpu_emulate.h" 88#include "opt_m68k_arch.h" 89 90#include "assym.h" 91#include <machine/asm.h> 92#include <machine/trap.h> 93 94#include "opt_useleds.h" 95#ifdef USELEDS 96#include <hp300/hp300/leds.h> 97#endif 98 99#include "audio.h" 100#include "ksyms.h" 101 102#define MMUADDR(ar) movl _C_LABEL(MMUbase),ar 103#define CLKADDR(ar) movl _C_LABEL(CLKbase),ar 104 105/* 106 * This is for kvm_mkdb, and should be the address of the beginning 107 * of the kernel text segment (not necessarily the same as kernbase). 108 */ 109 .text 110GLOBAL(kernel_text) 111 112/* 113 * Clear and skip the first page of text; it will not be mapped at 114 * VA 0. 115 * 116 * The bootloader places the bootinfo in this page, and we allocate 117 * a VA for it and map it later. 118 */ 119 .fill PAGE_SIZE/4,4,0 120 121/* 122 * Temporary stack for a variety of purposes. 123 * Try and make this the first thing is the data segment so it 124 * is page aligned. Note that if we overflow here, we run into 125 * our text segment. 126 */ 127 .data 128 .space PAGE_SIZE 129ASLOCAL(tmpstk) 130 131#include <hp300/hp300/vectors.s> 132 133/* 134 * Macro to relocate a symbol, used before MMU is enabled. 135 */ 136#ifdef __STDC__ 137#define IMMEDIATE # 138#define _RELOC(var, ar) \ 139 movel IMMEDIATE var,ar; \ 140 addl %a5,ar 141#else 142#define _RELOC(var, ar) \ 143 movel #var,ar; \ 144 addl %a5,ar 145#endif /* __STDC__ */ 146 147#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 148#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 149 150/* 151 * Final bits of grunt work required to reboot the system. The MMU 152 * must be disabled when this is invoked. 153 */ 154#define DOREBOOT \ 155 /* Reset Vector Base Register to what PROM expects. */ \ 156 movl #0,%d0; \ 157 movc %d0,%vbr; \ 158 /* Jump to REQ_REBOOT */ \ 159 jmp 0x1A4; 160 161/* 162 * Initialization 163 * 164 * A4 contains the address of the end of the symtab 165 * A5 contains physical load point from boot 166 * VBR contains zero from ROM. Exceptions will continue to vector 167 * through ROM until MMU is turned on at which time they will vector 168 * through our table (vectors.s). 169 */ 170 171BSS(lowram,4) 172BSS(esym,4) 173 174ASENTRY_NOPROFILE(start) 175 movw #PSL_HIGHIPL,%sr | no interrupts 176 ASRELOC(tmpstk, %a0) 177 movl %a0,%sp | give ourselves a temporary stack 178 RELOC(esym, %a0) 179#if 1 180 movl %a4,%a0@ | store end of symbol table 181#else 182 clrl %a0@ | no symbol table, yet 183#endif 184 RELOC(lowram, %a0) 185 movl %a5,%a0@ | store start of physical memory 186 movl #CACHE_OFF,%d0 187 movc %d0,%cacr | clear and disable on-chip cache(s) 188 189/* check for internal HP-IB in SYSFLAG */ 190 btst #5,0xfffffed2 | internal HP-IB? 191 jeq Lhaveihpib | yes, have HP-IB just continue 192 RELOC(internalhpib, %a0) 193 movl #0,%a0@ | no, clear associated address 194Lhaveihpib: 195 196 RELOC(boothowto, %a0) | save reboot flags 197 movl %d7,%a0@ 198 RELOC(bootdev, %a0) | and boot device 199 movl %d6,%a0@ 200 201 /* 202 * All data registers are now free. All address registers 203 * except %a5 are free. %a5 is used by the RELOC() macro, 204 * and cannot be used until after the MMU is enabled. 205 */ 206 207/* determine our CPU/MMU combo - check for all regardless of kernel config */ 208 movl #INTIOBASE+MMUBASE,%a1 209 movl #DC_FREEZE,%d0 | data freeze bit 210 movc %d0,%cacr | only exists on 68030 211 movc %cacr,%d0 | read it back 212 tstl %d0 | zero? 213 jeq Lnot68030 | yes, we have 68020/68040 214 215 /* 216 * 68030 models 217 */ 218 219 RELOC(mmutype, %a0) | no, we have 68030 220 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU 221 RELOC(cputype, %a0) 222 movl #CPU_68030,%a0@ | and 68030 CPU 223 RELOC(machineid, %a0) 224 movl #0x80,%a1@(MMUCMD) | set magic cookie 225 movl %a1@(MMUCMD),%d0 | read it back 226 btst #7,%d0 | cookie still on? 227 jeq Lnot370 | no, 360, 362 or 375 228 movl #0,%a1@(MMUCMD) | clear magic cookie 229 movl %a1@(MMUCMD),%d0 | read it back 230 btst #7,%d0 | still on? 231 jeq Lisa370 | no, must be a 370 232 movl #HP_340,%a0@ | yes, must be a 340 233 jra Lstart1 234Lnot370: 235 movl #HP_360,%a0@ | type is at least a 360 236 movl #0,%a1@(MMUCMD) | clear magic cookie2 237 movl %a1@(MMUCMD),%d0 | read it back 238 btst #16,%d0 | still on? 239 jeq Lisa36x | no, must be a 360 or a 362 240 RELOC(mmuid, %a0) | save MMU ID 241 lsrl #MMUID_SHIFT,%d0 242 andl #MMUID_MASK,%d0 243 movl %d0,%a0@ 244 RELOC(machineid, %a0) 245 cmpb #MMUID_345,%d0 | are we a 345? 246 beq Lisa345 247 cmpb #MMUID_375,%d0 | how about a 375? 248 beq Lisa375 249 movl #HP_400,%a0@ | must be a 400 250 jra Lhaspac 251Lisa36x: 252 /* 253 * If we found a 360, we need to check for a 362 (neither the 360 254 * nor the 362 have a nonzero mmuid). Identify 362 by checking 255 * on-board VRX framebuffer which has secid 0x11 at dio scode 132. 256 */ 257 movl #DIOII_BASE,%a0 | probe dio scode 132 258 ASRELOC(phys_badaddr,%a3) 259 jbsr %a3@ 260 tstl %d0 | device at scode 132? 261 jne Lstart1 | no, not 362, assume 360 262 movb %a0@(DIO_IDOFF),%d0 263 cmpb #DIO_DEVICE_ID_FRAMEBUFFER,%d0 | framebuffer? 264 jne Lstart1 | no, not 362, assume 360 265 movb %a0@(DIO_SECIDOFF),%d0 266 cmpb #0x11,%d0 | VRX sti on 362? 267 jne Lstart1 | no, not 362, assume 360 268 RELOC(machineid,%a0) 269 movl #HP_362,%a0@ 270 jra Lstart1 271Lisa345: 272 movl #HP_345,%a0@ 273 jra Lhaspac 274Lisa375: 275 movl #HP_375,%a0@ 276 jra Lhaspac 277Lisa370: 278 movl #HP_370,%a0@ | set to 370 279Lhaspac: 280 RELOC(ectype, %a0) 281 movl #EC_PHYS,%a0@ | also has a physical address cache 282 jra Lstart1 283 284 /* 285 * End of 68030 section 286 */ 287 288Lnot68030: 289 bset #31,%d0 | data cache enable bit 290 movc %d0,%cacr | only exists on 68040 291 movc %cacr,%d0 | read it back 292 tstl %d0 | zero? 293 beq Lis68020 | yes, we have 68020 294 moveq #0,%d0 | now turn it back off 295 movec %d0,%cacr | before we access any data 296 297 /* 298 * 68040 models 299 */ 300 301 RELOC(mmutype, %a0) 302 movl #MMU_68040,%a0@ | with a 68040 MMU 303 RELOC(cputype, %a0) 304 movl #CPU_68040,%a0@ | and a 68040 CPU 305 RELOC(fputype, %a0) 306 movl #FPU_68040,%a0@ | ...and FPU 307 RELOC(ectype, %a0) 308 movl #EC_NONE,%a0@ | and no cache (for now XXX) 309 RELOC(mmuid,%a0) | save MMU ID 310 movl %a1@(MMUCMD),%d0 311 lsrl #MMUID_SHIFT,%d0 312 andl #MMUID_MASK,%d0 313 movl %d0,%a0@ 314 RELOC(machineid, %a0) 315 cmpb #MMUID_425_T,%d0 | are we a 425t? 316 jeq Lisa425 317 cmpb #MMUID_425_S,%d0 | how about 425s? 318 jeq Lisa425 319 cmpb #MMUID_425_E,%d0 | or maybe a 425e? 320 jeq Lisa425 321 cmpb #MMUID_433_T,%d0 | or a 433t? 322 jeq Lisa433 323 cmpb #MMUID_433_S,%d0 | or a 433s? 324 jeq Lisa433 325 cmpb #MMUID_385,%d0 | or a 385? 326 jeq Lisa385 327 cmpb #MMUID_382,%d0 | or a 382? 328 jeq Lisa382 329 movl #HP_380,%a0@ | guess we're a 380 330 jra Lstart1 331Lisa425: 332 movl #HP_425,%a0@ 333 jra Lstart1 334Lisa433: 335 movl #HP_433,%a0@ 336 jra Lstart1 337Lisa385: 338 movl #HP_385,%a0@ 339 jra Lstart1 340Lisa382: 341 movl #HP_382,%a0@ 342 jra Lstart1 343 344 /* 345 * End of 68040 section 346 */ 347 348 /* 349 * 68020 models 350 */ 351 352Lis68020: 353 RELOC(fputype, %a0) | all of the 68020 systems 354 movl #FPU_68881,%a0@ | have a 68881 FPU 355 movl #1,%a1@(MMUCMD) | a 68020, write HP MMU location 356 movl %a1@(MMUCMD),%d0 | read it back 357 btst #0,%d0 | non-zero? 358 jne Lishpmmu | yes, we have HP MMU 359 RELOC(mmutype, %a0) 360 movl #MMU_68851,%a0@ | no, we have PMMU 361 RELOC(machineid, %a0) 362 movl #HP_330,%a0@ | and 330 CPU 363 jra Lstart1 364Lishpmmu: 365 RELOC(ectype, %a0) | 320 or 350 366 movl #EC_VIRT,%a0@ | both have a virtual address cache 367 movl #0x80,%a1@(MMUCMD) | set magic cookie 368 movl %a1@(MMUCMD),%d0 | read it back 369 btst #7,%d0 | cookie still on? 370 jeq Lis320 | no, just a 320 371 RELOC(machineid, %a0) 372 movl #HP_350,%a0@ | yes, a 350 373 jra Lstart1 374Lis320: 375 RELOC(machineid, %a0) 376 movl #HP_320,%a0@ 377 378 /* 379 * End of 68020 section 380 */ 381 382Lstart1: 383 /* 384 * Now that we know what CPU we have, initialize the address error 385 * and bus error handlers in the vector table: 386 * 387 * vectab+8 bus error 388 * vectab+12 address error 389 */ 390 RELOC(cputype, %a0) 391#if 0 392 /* XXX assembler/linker feature/bug */ 393 RELOC(vectab, %a2) 394#else 395 movl #_C_LABEL(vectab),%a2 396 addl %a5,%a2 397#endif 398#if defined(M68040) 399 cmpl #CPU_68040,%a0@ | 68040? 400 jne 1f | no, skip 401 movl #_C_LABEL(buserr40),%a2@(8) 402 movl #_C_LABEL(addrerr4060),%a2@(12) 403 jra Lstart2 4041: 405#endif 406#if defined(M68020) || defined(M68030) 407 cmpl #CPU_68040,%a0@ | 68040? 408 jeq 1f | yes, skip 409 movl #_C_LABEL(busaddrerr2030),%a2@(8) 410 movl #_C_LABEL(busaddrerr2030),%a2@(12) 411 jra Lstart2 4121: 413#endif 414 /* Config botch; no hope. */ 415 DOREBOOT 416 417Lstart2: 418 movl #0,%a1@(MMUCMD) | clear out MMU again 419/* initialize source/destination control registers for movs */ 420 moveq #FC_USERD,%d0 | user space 421 movc %d0,%sfc | as source 422 movc %d0,%dfc | and destination of transfers 423/* save the first PA as bootinfo_pa to map it to a virtual address later. */ 424 movl %a5,%d0 | lowram value from ROM via boot 425 RELOC(bootinfo_pa, %a0) 426 movl %d0,%a0@ | save the lowram as bootinfo PA 427/* initialize memory sizes (for pmap_bootstrap) */ 428 movl #MAXADDR,%d1 | last page 429 moveq #PGSHIFT,%d2 430 lsrl %d2,%d1 | convert to page (click) number 431 RELOC(maxmem, %a0) 432 movl %d1,%a0@ | save as maxmem 433 lsrl %d2,%d0 | convert the lowram to page number 434 subl %d0,%d1 | compute amount of RAM present 435 RELOC(physmem, %a0) 436 movl %d1,%a0@ | and physmem 437 438/* configure kernel and lwp0 VA space so we can get going */ 439#if NKSYMS || defined(DDB) || defined(MODULAR) 440 RELOC(esym,%a0) | end of static kernel test/data/syms 441 movl %a0@,%d5 442 jne Lstart3 443#endif 444 movl #_C_LABEL(end),%d5 | end of static kernel text/data 445Lstart3: 446 addl #PAGE_SIZE-1,%d5 447 andl #PG_FRAME,%d5 | round to a page 448 movl %d5,%a4 449 addl %a5,%a4 | convert to PA 450 pea %a5@ | firstpa 451 pea %a4@ | nextpa 452 RELOC(pmap_bootstrap,%a0) 453 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 454 addql #8,%sp 455 456/* 457 * Prepare to enable MMU. 458 * Since the kernel is not mapped logical == physical we must insure 459 * that when the MMU is turned on, all prefetched addresses (including 460 * the PC) are valid. In order guarantee that, we use the last physical 461 * page (which is conveniently mapped == VA) and load it up with enough 462 * code to defeat the prefetch, then we execute the jump back to here. 463 * 464 * Is this all really necessary, or am I paranoid?? 465 */ 466 RELOC(Sysseg_pa, %a0) | system segment table addr 467 movl %a0@,%d1 | read value (a PA) 468 RELOC(mmutype, %a0) 469 tstl %a0@ | HP MMU? 470 jeq Lhpmmu2 | yes, skip 471 cmpl #MMU_68040,%a0@ | 68040? 472 jne Lmotommu1 | no, skip 473 .long 0x4e7b1807 | movc %d1,%srp 474 jra Lstploaddone 475Lmotommu1: 476 RELOC(protorp, %a0) 477 movl #0x80000202,%a0@ | nolimit + share global + 4 byte PTEs 478 movl %d1,%a0@(4) | + segtable address 479 pmove %a0@,%srp | load the supervisor root pointer 480 movl #0x80000002,%a0@ | reinit upper half for CRP loads 481 jra Lstploaddone | done 482Lhpmmu2: 483 moveq #PGSHIFT,%d2 484 lsrl %d2,%d1 | convert to page frame 485 movl %d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register 486Lstploaddone: 487 lea MAXADDR,%a2 | PA of last RAM page 488#if 0 489 ASRELOC(Lhighcode, %a1) | addr of high code 490 ASRELOC(Lehighcode, %a3) | end addr 491#else 492 /* don't want pc-relative addressing */ 493 .word 0x43f9 | lea Lhighcode, %a1 494 .long Lhighcode 495 addl %a5, %a1 496 .word 0x47f9 | lea Lehighcode, %a3 497 .long Lehighcode 498 addl %a5, %a3 499#endif 500Lcodecopy: 501 movw %a1@+,%a2@+ | copy a word 502 cmpl %a3,%a1 | done yet? 503 jcs Lcodecopy | no, keep going 504 jmp MAXADDR | go for it! 505 506 /* 507 * BEGIN MMU TRAMPOLINE. This section of code is not 508 * executed in-place. It's copied to the last page 509 * of RAM (mapped va == pa) and executed there. 510 */ 511 512Lhighcode: 513 /* 514 * Set up the vector table, and race to get the MMU 515 * enabled. 516 */ 517 movl #_C_LABEL(vectab),%d0 | set Vector Base Register 518 movc %d0,%vbr 519 520 RELOC(mmutype, %a0) 521 tstl %a0@ | HP MMU? 522 jeq Lhpmmu3 | yes, skip 523 cmpl #MMU_68040,%a0@ | 68040? 524 jne Lmotommu2 | no, skip 525 movw #0,INTIOBASE+MMUBASE+MMUCMD+2 526 movw #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2 527 | enable FPU and caches 528 moveq #0,%d0 | ensure TT regs are disabled 529 .long 0x4e7b0004 | movc %d0,%itt0 530 .long 0x4e7b0005 | movc %d0,%itt1 531 .long 0x4e7b0006 | movc %d0,%dtt0 532 .long 0x4e7b0007 | movc %d0,%dtt1 533 .word 0xf4d8 | cinva bc 534 .word 0xf518 | pflusha 535#if PGSHIFT == 13 536 movl #0xc000,%d0 537#else 538 movl #0x8000,%d0 539#endif 540 .long 0x4e7b0003 | movc %d0,%tc 541 movl #CACHE40_ON,%d0 542 movc %d0,%cacr | turn on both caches 543 jmp Lenab1:l | forced not be pc-relative 544Lmotommu2: 545 movl #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD 546 | enable 68881 and i-cache 547 pflusha 548 RELOC(prototc, %a2) 549#if PGSHIFT == 13 550 movl #0x82d08b00,%a2@ | value to load TC with 551#else 552 movl #0x82c0aa00,%a2@ | value to load TC with 553#endif 554 pmove %a2@,%tc | load it 555 jmp Lenab1:l | forced not be pc-relative 556Lhpmmu3: 557 movl #0,INTIOBASE+MMUBASE+MMUCMD | clear external cache 558 movl #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU 559 jmp Lenab1:l | forced not be pc-relative 560Lehighcode: 561 562 /* 563 * END MMU TRAMPOLINE. Address register %a5 is now free. 564 */ 565 566/* 567 * Should be running mapped from this point on 568 */ 569Lenab1: 570 lea _ASM_LABEL(tmpstk),%sp | temporary stack 571/* call final pmap setup */ 572 jbsr _C_LABEL(pmap_bootstrap_finalize) 573/* set kernel stack, user SP */ 574 movl _C_LABEL(lwp0uarea),%a1 | get lwp0 uarea 575 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 576 movl #USRSTACK-4,%a2 577 movl %a2,%usp | init user SP 578 579 jbsr _C_LABEL(fpu_probe) 580 movl %d0,_C_LABEL(fputype) 581 tstl _C_LABEL(fputype) | Have an FPU? 582 jeq Lenab2 | No, skip. 583 clrl %a1@(PCB_FPCTX) | ensure null FP context 584 movl %a1,%sp@- 585 jbsr _C_LABEL(m68881_restore) | restore it (does not kill %a1) 586 addql #4,%sp 587Lenab2: 588/* flush TLB and turn on caches */ 589 jbsr _C_LABEL(_TBIA) | invalidate TLB 590 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 591 jeq Lnocache0 | yes, cache already on 592 movl #CACHE_ON,%d0 593 movc %d0,%cacr | clear cache(s) 594 tstl _C_LABEL(ectype) 595 jeq Lnocache0 596 MMUADDR(%a0) 597 orl #MMU_CEN,%a0@(MMUCMD) | turn on external cache 598Lnocache0: 599/* Final setup for call to main(). */ 600 jbsr _C_LABEL(hp300_init) 601 602/* 603 * Create a fake exception frame so that cpu_lwp_fork() can copy it. 604 * main() nevers returns; we exit to user mode from a forked process 605 * later on. 606 */ 607 clrw %sp@- | vector offset/frame type 608 clrl %sp@- | PC - filled in by "execve" 609 movw #PSL_USER,%sp@- | in user mode 610 clrl %sp@- | stack adjust count and padding 611 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 612 lea _C_LABEL(lwp0),%a0 | save pointer to frame 613 movl %sp,%a0@(L_MD_REGS) | in lwp0.l_md.md_regs 614 615 jra _C_LABEL(main) | main() 616 PANIC("main() returned") 617 /* NOTREACHED */ 618 619/* 620 * Trap/interrupt vector routines 621 */ 622#include <m68k/m68k/trap_subr.s> 623 624/* 625 * Use common m68k bus error and address error handlers. 626 */ 627#include <m68k/m68k/busaddrerr.s> 628 629/* 630 * FP exceptions. 631 */ 632ENTRY_NOPROFILE(fpfline) 633#if defined(M68040) 634 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 635 jne Lfp_unimp | no, skip FPSP 636 cmpw #0x202c,%sp@(6) | format type 2? 637 jne _C_LABEL(illinst) | no, not an FP emulation 638Ldofp_unimp: 639#ifdef FPSP 640 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 641#endif 642Lfp_unimp: 643#endif /* M68040 */ 644#ifdef FPU_EMULATE 645 clrl %sp@- | stack adjust count 646 moveml #0xFFFF,%sp@- | save registers 647 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 648 jra _ASM_LABEL(fault) | do it 649#else 650 jra _C_LABEL(illinst) 651#endif 652 653ENTRY_NOPROFILE(fpunsupp) 654#if defined(M68040) 655 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 656 jne _C_LABEL(illinst) | no, treat as illinst 657#ifdef FPSP 658 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 659#endif 660Lfp_unsupp: 661#endif /* M68040 */ 662#ifdef FPU_EMULATE 663 clrl %sp@- | stack adjust count 664 moveml #0xFFFF,%sp@- | save registers 665 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 666 jra _ASM_LABEL(fault) | do it 667#else 668 jra _C_LABEL(illinst) 669#endif 670 671/* 672 * Handles all other FP coprocessor exceptions. 673 * Note that since some FP exceptions generate mid-instruction frames 674 * and may cause signal delivery, we need to test for stack adjustment 675 * after the trap call. 676 */ 677ENTRY_NOPROFILE(fpfault) 678 clrl %sp@- | stack adjust count 679 moveml #0xFFFF,%sp@- | save user registers 680 movl %usp,%a0 | and save 681 movl %a0,%sp@(FR_SP) | the user stack pointer 682 clrl %sp@- | no VA arg 683 movl _C_LABEL(curpcb),%a0 | current pcb 684 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 685 fsave %a0@ | save state 686#if defined(M68040) || defined(M68060) 687 /* always null state frame on 68040, 68060 */ 688 cmpl #FPU_68040,_C_LABEL(fputype) 689 jge Lfptnull 690#endif 691 tstb %a0@ | null state frame? 692 jeq Lfptnull | yes, safe 693 clrw %d0 | no, need to tweak BIU 694 movb %a0@(1),%d0 | get frame size 695 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 696Lfptnull: 697 fmovem %fpsr,%sp@- | push %fpsr as code argument 698 frestore %a0@ | restore state 699 movl #T_FPERR,%sp@- | push type arg 700 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 701 702/* 703 * Other exceptions only cause four and six word stack frame and require 704 * no post-trap stack adjustment. 705 */ 706 707ENTRY_NOPROFILE(badtrap) 708 moveml #0xC0C0,%sp@- | save scratch regs 709 movw %sp@(22),%sp@- | push exception vector info 710 clrw %sp@- 711 movl %sp@(22),%sp@- | and PC 712 jbsr _C_LABEL(straytrap) | report 713 addql #8,%sp | pop args 714 moveml %sp@+,#0x0303 | restore regs 715 jra _ASM_LABEL(rei) | all done 716 717ENTRY_NOPROFILE(trap0) 718 clrl %sp@- | stack adjust count 719 moveml #0xFFFF,%sp@- | save user registers 720 movl %usp,%a0 | save the user SP 721 movl %a0,%sp@(FR_SP) | in the savearea 722 movl %d0,%sp@- | push syscall number 723 jbsr _C_LABEL(syscall) | handle it 724 addql #4,%sp | pop syscall arg 725 tstl _C_LABEL(astpending) | AST pending? 726 jne Lrei | yes, handle it via trap 727 movl %sp@(FR_SP),%a0 | grab and restore 728 movl %a0,%usp | user SP 729 moveml %sp@+,#0x7FFF | restore most registers 730 addql #8,%sp | pop SP and stack adjust 731 rte 732 733/* 734 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 735 * cachectl(command, addr, length) 736 * command in %d0, addr in %a1, length in %d1 737 */ 738ENTRY_NOPROFILE(trap12) 739 movl _C_LABEL(curlwp),%a0 740 movl %a0@(L_PROC),%sp@- | push current proc pointer 741 movl %d1,%sp@- | push length 742 movl %a1,%sp@- | push addr 743 movl %d0,%sp@- | push command 744 jbsr _C_LABEL(cachectl1) | do it 745 lea %sp@(16),%sp | pop args 746 jra _ASM_LABEL(rei) | all done 747 748/* 749 * Trace (single-step) trap. Kernel-mode is special. 750 * User mode traps are simply passed on to trap(). 751 */ 752ENTRY_NOPROFILE(trace) 753 clrl %sp@- | stack adjust count 754 moveml #0xFFFF,%sp@- 755 moveq #T_TRACE,%d0 756 757 | Check PSW and see what happen. 758 | T=0 S=0 (should not happen) 759 | T=1 S=0 trace trap from user mode 760 | T=0 S=1 trace trap on a trap instruction 761 | T=1 S=1 trace trap from system mode (kernel breakpoint) 762 763 movw %sp@(FR_HW),%d1 | get PSW 764 notw %d1 | XXX no support for T0 on 680[234]0 765 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 766 jeq Lkbrkpt | yes, kernel breakpoint 767 jra _ASM_LABEL(fault) | no, user-mode fault 768 769/* 770 * Trap 15 is used for: 771 * - GDB breakpoints (in user programs) 772 * - KGDB breakpoints (in the kernel) 773 * - trace traps for SUN binaries (not fully supported yet) 774 * User mode traps are simply passed to trap(). 775 */ 776ENTRY_NOPROFILE(trap15) 777 clrl %sp@- | stack adjust count 778 moveml #0xFFFF,%sp@- 779 moveq #T_TRAP15,%d0 780 movw %sp@(FR_HW),%d1 | get PSW 781 andw #PSL_S,%d1 | from system mode? 782 jne Lkbrkpt | yes, kernel breakpoint 783 jra _ASM_LABEL(fault) | no, user-mode fault 784 785Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type) 786 | Save the system sp rather than the user sp. 787 movw #PSL_HIGHIPL,%sr | lock out interrupts 788 lea %sp@(FR_SIZE),%a6 | Save stack pointer 789 movl %a6,%sp@(FR_SP) | from before trap 790 791 | If were are not on tmpstk switch to it. 792 | (so debugger can change the stack pointer) 793 movl %a6,%d1 794 cmpl #_ASM_LABEL(tmpstk),%d1 795 jls Lbrkpt2 | already on tmpstk 796 | Copy frame to the temporary stack 797 movl %sp,%a0 | %a0=src 798 lea _ASM_LABEL(tmpstk)-96,%a1 | %a1=dst 799 movl %a1,%sp | %sp=new frame 800 moveq #FR_SIZE,%d1 801Lbrkpt1: 802 movl %a0@+,%a1@+ 803 subql #4,%d1 804 jgt Lbrkpt1 805 806Lbrkpt2: 807 | Call the trap handler for the kernel debugger. 808 | Do not call trap() to do it, so that we can 809 | set breakpoints in trap() if we want. We know 810 | the trap type is either T_TRACE or T_BREAKPOINT. 811 | If we have both DDB and KGDB, let KGDB see it first, 812 | because KGDB will just return 0 if not connected. 813 | Save args in %d2, %a2 814 movl %d0,%d2 | trap type 815 movl %sp,%a2 | frame ptr 816#ifdef KGDB 817 | Let KGDB handle it (if connected) 818 movl %a2,%sp@- | push frame ptr 819 movl %d2,%sp@- | push trap type 820 jbsr _C_LABEL(kgdb_trap) | handle the trap 821 addql #8,%sp | pop args 822 cmpl #0,%d0 | did kgdb handle it? 823 jne Lbrkpt3 | yes, done 824#endif 825#ifdef DDB 826 | Let DDB handle it 827 movl %a2,%sp@- | push frame ptr 828 movl %d2,%sp@- | push trap type 829 jbsr _C_LABEL(kdb_trap) | handle the trap 830 addql #8,%sp | pop args 831#if 0 /* not needed on hp300 */ 832 cmpl #0,%d0 | did ddb handle it? 833 jne Lbrkpt3 | yes, done 834#endif 835#endif 836 /* Sun 3 drops into PROM here. */ 837Lbrkpt3: 838 | The stack pointer may have been modified, or 839 | data below it modified (by kgdb push call), 840 | so push the hardware frame at the current sp 841 | before restoring registers and returning. 842 843 movl %sp@(FR_SP),%a0 | modified %sp 844 lea %sp@(FR_SIZE),%a1 | end of our frame 845 movl %a1@-,%a0@- | copy 2 longs with 846 movl %a1@-,%a0@- | ... predecrement 847 movl %a0,%sp@(FR_SP) | %sp = h/w frame 848 moveml %sp@+,#0x7FFF | restore all but %sp 849 movl %sp@,%sp | ... and %sp 850 rte | all done 851 852/* Use common m68k sigreturn */ 853#include <m68k/m68k/sigreturn.s> 854 855/* 856 * Interrupt handlers. 857 * All device interrupts are auto-vectored. The CPU provides 858 * the vector 0x18+level. Note we count spurious interrupts, but 859 * we don't do anything else with them. 860 */ 861 862/* 64-bit evcnt counter increments */ 863#define EVCNT_COUNTER(ipl) \ 864 _C_LABEL(hp300_intr_list) + (ipl)*SIZEOF_HI + HI_EVCNT 865#define EVCNT_INCREMENT(ipl) \ 866 clrl %d0; \ 867 addql #1,EVCNT_COUNTER(ipl)+4; \ 868 movel EVCNT_COUNTER(ipl),%d1; \ 869 addxl %d0,%d1; \ 870 movel %d1,EVCNT_COUNTER(ipl) 871 872ENTRY_NOPROFILE(spurintr) /* level 0 */ 873 INTERRUPT_SAVEREG 874 EVCNT_INCREMENT(0) 875 CPUINFO_INCREMENT(CI_NINTR) 876 INTERRUPT_RESTOREREG 877 jra _ASM_LABEL(rei) 878 879ENTRY_NOPROFILE(intrhand) /* levels 1 through 5 */ 880 addql #1,_C_LABEL(idepth) | entering interrupt 881 INTERRUPT_SAVEREG 882 movw %sp@(22),%sp@- | push exception vector info 883 clrw %sp@- 884 jbsr _C_LABEL(intr_dispatch) | call dispatch routine 885 addql #4,%sp 886 INTERRUPT_RESTOREREG 887 subql #1,_C_LABEL(idepth) | exiting from interrupt 888 jra _ASM_LABEL(rei) | all done 889 890ENTRY_NOPROFILE(lev6intr) /* level 6: clock */ 891 addql #1,_C_LABEL(idepth) | entering interrupt 892 INTERRUPT_SAVEREG 893 CLKADDR(%a0) 894 movb %a0@(CLKSR),%d0 | read clock status 895Lclkagain: 896 btst #0,%d0 | clear timer1 int immediately to 897 jeq Lnotim1 | minimize chance of losing another 898 movpw %a0@(CLKMSB1),%d1 | due to statintr processing delay 899 movl _C_LABEL(clkint),%d1 | clkcounter += clkint 900 addl %d1,_C_LABEL(clkcounter) 901Lnotim1: 902 btst #2,%d0 | timer3 interrupt? 903 jeq Lnotim3 | no, skip statclock 904 movpw %a0@(CLKMSB3),%d1 | clear timer3 interrupt 905 lea %sp@(16),%a1 | a1 = &clockframe 906 movl %d0,%sp@- | save status 907 movl %a1,%sp@- 908 jbsr _C_LABEL(statintr) | statintr(&frame) 909 addql #4,%sp 910 movl %sp@+,%d0 | restore pre-statintr status 911 CLKADDR(%a0) 912Lnotim3: 913 btst #0,%d0 | timer1 interrupt? 914 jeq Lrecheck | no, skip hardclock 915 EVCNT_INCREMENT(6) 916 lea %sp@(16),%a1 | a1 = &clockframe 917 movl %a1,%sp@- 918#ifdef USELEDS 919 tstl _C_LABEL(ledaddr) | using LEDs? 920 jeq Lnoleds0 | no, skip this code 921 movl _ASM_LABEL(heartbeat),%d0 | get tick count 922 addql #1,%d0 | increment 923 movl _C_LABEL(hz),%d1 924 addl #50,%d1 | get the timing a little closer 925 tstb _ASM_LABEL(beatstatus) | time to slow down? 926 jeq Lslowthrob | yes, slow down 927 lsrl #3,%d1 | no, fast throb 928Lslowthrob: 929 lsrl #1,%d1 | slow throb 930 cmpl %d0,%d1 | are we there yet? 931 jne Lnoleds1 | no, nothing to do 932 addqb #1,_ASM_LABEL(beatstatus) | incr beat status 933 cmpb #3,_ASM_LABEL(beatstatus) | time to reset? 934 jle Ltwinkle | no, twinkle the lights 935 movb #0,_ASM_LABEL(beatstatus) | reset the status indicator 936Ltwinkle: 937 movl #LED_PULSE,%sp@- 938 movl #LED_DISK+LED_LANRCV+LED_LANXMT,%sp@- 939 clrl %sp@- 940 jbsr _C_LABEL(ledcontrol) | toggle pulse, turn all others off 941 lea %sp@(12),%sp 942 movql #0,%d0 943Lnoleds1: 944 movl %d0,_ASM_LABEL(heartbeat) 945Lnoleds0: 946#endif /* USELEDS */ 947 jbsr _C_LABEL(hardclock) | hardclock(&frame) 948 addql #4,%sp 949Lrecheck: 950 CPUINFO_INCREMENT(CI_NINTR) | chalk up another interrupt 951 CLKADDR(%a0) 952 movb %a0@(CLKSR),%d0 | see if anything happened 953 jmi Lclkagain | while we were in hardclock/statintr 954#if NAUDIO >0 955 movw %sp@(22),%sp@- | push exception vector info 956 clrw %sp@- 957 jbsr _C_LABEL(intr_dispatch) | call dispatch routine 958 addql #4,%sp 959#endif 960 INTERRUPT_RESTOREREG 961 subql #1,_C_LABEL(idepth) | exiting from interrupt 962 jra _ASM_LABEL(rei) | all done 963 964ENTRY_NOPROFILE(lev7intr) /* level 7: parity errors, reset key */ 965 clrl %sp@- 966 moveml #0xFFFF,%sp@- | save registers 967 EVCNT_INCREMENT(7) 968 movl %usp,%a0 | and save 969 movl %a0,%sp@(FR_SP) | the user stack pointer 970 jbsr _C_LABEL(nmihand) | call handler 971 movl %sp@(FR_SP),%a0 | restore 972 movl %a0,%usp | user SP 973 moveml %sp@+,#0x7FFF | and remaining registers 974 addql #8,%sp | pop SP and stack adjust 975 jra _ASM_LABEL(rei) | all done 976 977/* 978 * Emulation of VAX REI instruction. 979 * 980 * This code deals with checking for and servicing 981 * ASTs (profiling, scheduling). 982 * After identifying that we need an AST we drop the IPL 983 * to allow device interrupts. 984 * 985 * This code is complicated by the fact that sendsig may have been called 986 * necessitating a stack cleanup. 987 */ 988 989ASENTRY_NOPROFILE(rei) 990 tstl _C_LABEL(astpending) | AST pending? 991 jne 1f | no, done 992 rte 9931: 994 btst #5,%sp@ | yes, are we returning to user mode? 995 jeq 2f | no, done 996 rte 9972: 998 movw #PSL_LOWIPL,%sr | lower SPL 999 clrl %sp@- | stack adjust 1000 moveml #0xFFFF,%sp@- | save all registers 1001 movl %usp,%a1 | including 1002 movl %a1,%sp@(FR_SP) | the users SP 1003Lrei: 1004 clrl %sp@- | VA == none 1005 clrl %sp@- | code == none 1006 movl #T_ASTFLT,%sp@- | type == async system trap 1007 pea %sp@(12) | fp == address of trap frame 1008 jbsr _C_LABEL(trap) | go handle it 1009 lea %sp@(16),%sp | pop value args 1010 movl %sp@(FR_SP),%a0 | restore user SP 1011 movl %a0,%usp | from save area 1012 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 1013 jne Laststkadj | yes, go to it 1014 moveml %sp@+,#0x7FFF | no, restore most user regs 1015 addql #8,%sp | toss SP and stack adjust 1016 rte | and do real RTE 1017Laststkadj: 1018 lea %sp@(FR_HW),%a1 | pointer to HW frame 1019 addql #8,%a1 | source pointer 1020 movl %a1,%a0 | source 1021 addw %d0,%a0 | + hole size = dest pointer 1022 movl %a1@-,%a0@- | copy 1023 movl %a1@-,%a0@- | 8 bytes 1024 movl %a0,%sp@(FR_SP) | new SSP 1025 moveml %sp@+,#0x7FFF | restore user registers 1026 movl %sp@,%sp | and our SP 1027 rte | and do real RTE 1028 1029/* 1030 * Use common m68k sigcode. 1031 */ 1032#include <m68k/m68k/sigcode.s> 1033#ifdef COMPAT_SUNOS 1034#include <m68k/m68k/sunos_sigcode.s> 1035#endif 1036 1037/* 1038 * Primitives 1039 */ 1040 1041/* 1042 * Use common m68k support routines. 1043 */ 1044#include <m68k/m68k/support.s> 1045 1046/* 1047 * Use common m68k process/lwp switch and context save subroutines. 1048 */ 1049#define FPCOPROC /* XXX: Temp. reqd. */ 1050#include <m68k/m68k/switch_subr.s> 1051 1052 1053#if defined(M68040) 1054ENTRY(suline) 1055 movl %sp@(4),%a0 | address to write 1056 movl _C_LABEL(curpcb),%a1 | current pcb 1057 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 1058 movl %sp@(8),%a1 | address of line 1059 movl %a1@+,%d0 | get lword 1060 movsl %d0,%a0@+ | put lword 1061 nop | sync 1062 movl %a1@+,%d0 | get lword 1063 movsl %d0,%a0@+ | put lword 1064 nop | sync 1065 movl %a1@+,%d0 | get lword 1066 movsl %d0,%a0@+ | put lword 1067 nop | sync 1068 movl %a1@+,%d0 | get lword 1069 movsl %d0,%a0@+ | put lword 1070 nop | sync 1071 moveq #0,%d0 | indicate no fault 1072 jra Lsldone 1073Lslerr: 1074 moveq #-1,%d0 1075Lsldone: 1076 movl _C_LABEL(curpcb),%a1 | current pcb 1077 clrl %a1@(PCB_ONFAULT) | clear fault address 1078 rts 1079#endif 1080 1081ENTRY(ecacheon) 1082 tstl _C_LABEL(ectype) 1083 jeq Lnocache7 1084 MMUADDR(%a0) 1085 orl #MMU_CEN,%a0@(MMUCMD) 1086Lnocache7: 1087 rts 1088 1089ENTRY(ecacheoff) 1090 tstl _C_LABEL(ectype) 1091 jeq Lnocache8 1092 MMUADDR(%a0) 1093 andl #~MMU_CEN,%a0@(MMUCMD) 1094Lnocache8: 1095 rts 1096 1097/* 1098 * Load a new user segment table pointer. 1099 */ 1100ENTRY(loadustp) 1101#if defined(M68K_MMU_MOTOROLA) 1102 tstl _C_LABEL(mmutype) | HP MMU? 1103 jeq Lhpmmu9 | yes, skip 1104 movl %sp@(4),%d0 | new USTP 1105 moveq #PGSHIFT,%d1 1106 lsll %d1,%d0 | convert to addr 1107#if defined(M68040) 1108 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1109 jne LmotommuC | no, skip 1110 .word 0xf518 | yes, pflusha 1111 .long 0x4e7b0806 | movc %d0,%urp 1112 rts 1113LmotommuC: 1114#endif 1115 pflusha | flush entire TLB 1116 lea _C_LABEL(protorp),%a0 | CRP prototype 1117 movl %d0,%a0@(4) | stash USTP 1118 pmove %a0@,%crp | load root pointer 1119 movl #CACHE_CLR,%d0 1120 movc %d0,%cacr | invalidate cache(s) 1121 rts 1122Lhpmmu9: 1123#endif 1124#if defined(M68K_MMU_HP) 1125 movl #CACHE_CLR,%d0 1126 movc %d0,%cacr | invalidate cache(s) 1127 MMUADDR(%a0) 1128 movl %a0@(MMUTBINVAL),%d1 | invalidate TLB 1129 tstl _C_LABEL(ectype) | have external VAC? 1130 jle 1f | no, skip 1131 andl #~MMU_CEN,%a0@(MMUCMD) | toggle cache enable 1132 orl #MMU_CEN,%a0@(MMUCMD) | to clear data cache 11331: 1134 movl %sp@(4),%a0@(MMUUSTP) | load a new USTP 1135#endif 1136 rts 1137 1138ENTRY(ploadw) 1139#if defined(M68K_MMU_MOTOROLA) 1140 movl %sp@(4),%a0 | address to load 1141#if defined(M68K_MMU_HP) 1142 tstl _C_LABEL(mmutype) | HP MMU? 1143 jeq Lploadwskp | yes, skip 1144#endif 1145#if defined(M68040) 1146 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1147 jeq Lploadwskp | yes, skip 1148#endif 1149 ploadw #1,%a0@ | pre-load translation 1150Lploadwskp: 1151#endif 1152 rts 1153 1154/* 1155 * _delay(u_int N) 1156 * 1157 * Delay for at least (N/256) microseconds. 1158 * This routine depends on the variable: delay_divisor 1159 * which should be set based on the CPU clock rate. 1160 */ 1161ENTRY_NOPROFILE(_delay) 1162 | %d0 = arg = (usecs << 8) 1163 movl %sp@(4),%d0 1164 | %d1 = delay_divisor 1165 movl _C_LABEL(delay_divisor),%d1 1166 jra L_delay /* Jump into the loop! */ 1167 1168 /* 1169 * Align the branch target of the loop to a half-line (8-byte) 1170 * boundary to minimize cache effects. This guarantees both 1171 * that there will be no prefetch stalls due to cache line burst 1172 * operations and that the loop will run from a single cache 1173 * half-line. 1174 */ 1175 .align 8 1176L_delay: 1177 subl %d1,%d0 1178 jgt L_delay 1179 rts 1180 1181/* 1182 * Probe a memory address, and see if it causes a bus error. 1183 * This function is only to be used in physical mode, and before our 1184 * trap vectors are initialized. 1185 * Invoke with address to probe in %a0. 1186 * Alters: %a3 %d0 1187 */ 1188#define BUSERR 0xfffffffc 1189ASLOCAL(phys_badaddr) 1190 ASRELOC(_bsave,%a3) 1191 movl BUSERR,%a3@ | save ROM bus errror handler 1192 ASRELOC(_ssave,%a3) 1193 movl %sp,%a3@ | and current stack pointer 1194 ASRELOC(catchbad,%a3) 1195 movl %a3,BUSERR | plug in our handler 1196 movb %a0@,%d0 | access address 1197 ASRELOC(_bsave,%a3) | no fault! 1198 movl %a3@,BUSERR 1199 clrl %d0 | return success 1200 rts 1201ASLOCAL(catchbad) 1202 ASRELOC(_bsave,%a3) | got a bus error, so restore handler 1203 movl %a3@,BUSERR 1204 ASRELOC(_ssave,%a3) 1205 movl %a3@,%sp | and stack 1206 moveq #1,%d0 | return fault 1207 rts 1208#undef BUSERR 1209 1210 .data 1211ASLOCAL(_bsave) 1212 .long 0 1213ASLOCAL(_ssave) 1214 .long 0 1215 .text 1216 1217/* 1218 * Handle the nitty-gritty of rebooting the machine. 1219 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 1220 * Note that we must be running in an address range that is mapped one-to-one 1221 * logical to physical so that the PC is still valid immediately after the MMU 1222 * is turned off. We have conveniently mapped the last page of physical 1223 * memory this way. 1224 */ 1225ENTRY_NOPROFILE(doboot) 1226#if defined(M68040) 1227 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1228 jeq Lnocache5 | yes, skip 1229#endif 1230 movl #CACHE_OFF,%d0 1231 movc %d0,%cacr | disable on-chip cache(s) 1232 tstl _C_LABEL(ectype) | external cache? 1233 jeq Lnocache5 | no, skip 1234 MMUADDR(%a0) 1235 andl #~MMU_CEN,%a0@(MMUCMD) | disable external cache 1236Lnocache5: 1237 lea MAXADDR,%a0 | last page of physical memory 1238 movl _C_LABEL(boothowto),%a0@+ | store howto 1239 movl _C_LABEL(bootdev),%a0@+ | and devtype 1240 lea Lbootcode,%a1 | start of boot code 1241 lea Lebootcode,%a3 | end of boot code 1242Lbootcopy: 1243 movw %a1@+,%a0@+ | copy a word 1244 cmpl %a3,%a1 | done yet? 1245 jcs Lbootcopy | no, keep going 1246#if defined(M68040) 1247 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1248 jne LmotommuE | no, skip 1249 .word 0xf4f8 | cpusha bc 1250LmotommuE: 1251#endif 1252 jmp MAXADDR+8 | jump to last page 1253 1254Lbootcode: 1255 lea MAXADDR+0x800,%sp | physical SP in case of NMI 1256#if defined(M68040) 1257 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1258 jne LmotommuF | no, skip 1259 movl #0,%d0 1260 movc %d0,%cacr | caches off 1261 .long 0x4e7b0003 | movc %d0,%tc 1262 movl %d2,MAXADDR+PAGE_SIZE-4 | restore old high page contents 1263 DOREBOOT 1264LmotommuF: 1265#endif 1266#if defined(M68K_MMU_MOTOROLA) 1267 tstl _C_LABEL(mmutype) | HP MMU? 1268 jeq LhpmmuB | yes, skip 1269 movl #0,%a0@ | value for pmove to TC (turn off MMU) 1270 pmove %a0@,%tc | disable MMU 1271 DOREBOOT 1272LhpmmuB: 1273#endif 1274#if defined(M68K_MMU_HP) 1275 MMUADDR(%a0) 1276 movl #0xFFFF0000,%a0@(MMUCMD) | totally disable MMU 1277 movl %d2,MAXADDR+PAGE_SIZE-4 | restore old high page contents 1278 DOREBOOT 1279#endif 1280Lebootcode: 1281 1282/* 1283 * Misc. global variables. 1284 */ 1285 .data 1286GLOBAL(machineid) 1287 .long HP_320 | default to 320 1288 1289GLOBAL(mmuid) 1290 .long 0 | default to nothing 1291 1292GLOBAL(mmutype) 1293 .long MMU_HP | default to HP MMU 1294 1295GLOBAL(cputype) 1296 .long CPU_68020 | default to 68020 CPU 1297 1298GLOBAL(ectype) 1299 .long EC_NONE | external cache type, default to none 1300 1301GLOBAL(fputype) 1302 .long FPU_68882 | default to 68882 FPU 1303 1304GLOBAL(protorp) 1305 .long 0,0 | prototype root pointer 1306 1307GLOBAL(prototc) 1308 .long 0 | prototype translation control 1309 1310GLOBAL(internalhpib) 1311 .long 1 | has internal HP-IB, default to yes 1312 1313GLOBAL(intiobase) 1314 .long 0 | KVA of base of internal IO space 1315 1316GLOBAL(intiolimit) 1317 .long 0 | KVA of end of internal IO space 1318 1319GLOBAL(extiobase) 1320 .long 0 | KVA of base of external IO space 1321 1322GLOBAL(CLKbase) 1323 .long 0 | KVA of base of clock registers 1324 1325GLOBAL(MMUbase) 1326 .long 0 | KVA of base of HP MMU registers 1327 1328#ifdef USELEDS 1329ASLOCAL(heartbeat) 1330 .long 0 | clock ticks since last heartbeat 1331 1332ASLOCAL(beatstatus) 1333 .long 0 | for determining a fast or slow throb 1334#endif 1335 1336#ifdef DEBUG 1337ASGLOBAL(fulltflush) 1338 .long 0 1339 1340ASGLOBAL(fullcflush) 1341 .long 0 1342#endif 1343