1/* $NetBSD: locore.s,v 1.121 2002/05/19 21:40:04 jdolecek Exp $ */ 2 3/* 4 * Copyright (c) 1994, 1995 Gordon W. Ross 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1980, 1990, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 42 * 43 * @(#)locore.s 8.6 (Berkeley) 5/27/94 44 */ 45 46#include "opt_compat_netbsd.h" 47#include "opt_compat_svr4.h" 48#include "opt_compat_sunos.h" 49#include "opt_ddb.h" 50#include "opt_fpsp.h" 51#include "opt_kgdb.h" 52#include "opt_lockdebug.h" 53 54#include "assym.h" 55#include <machine/asm.h> 56#include <machine/trap.h> 57 58#include "opt_useleds.h" 59#ifdef USELEDS 60#include <hp300/hp300/leds.h> 61#endif 62 63#define MMUADDR(ar) movl _C_LABEL(MMUbase),ar 64#define CLKADDR(ar) movl _C_LABEL(CLKbase),ar 65 66/* 67 * This is for kvm_mkdb, and should be the address of the beginning 68 * of the kernel text segment (not necessarily the same as kernbase). 69 */ 70 .text 71GLOBAL(kernel_text) 72 73/* 74 * Clear and skip the first page of text; it will not be mapped at 75 * VA 0. 76 * 77 * The bootloader places the bootinfo in this page, and we allocate 78 * a VA for it and map it in pmap_bootstrap(). 79 */ 80 .fill NBPG/4,4,0 81 82/* 83 * Temporary stack for a variety of purposes. 84 * Try and make this the first thing is the data segment so it 85 * is page aligned. Note that if we overflow here, we run into 86 * our text segment. 87 */ 88 .data 89 .space NBPG 90ASLOCAL(tmpstk) 91 92#include <hp300/hp300/vectors.s> 93 94/* 95 * Macro to relocate a symbol, used before MMU is enabled. 96 */ 97#define _RELOC(var, ar) \ 98 movel #var,ar; \ 99 addl %a5,ar 100 101#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 102#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 103 104/* 105 * Final bits of grunt work required to reboot the system. The MMU 106 * must be disabled when this is invoked. 107 */ 108#define DOREBOOT \ 109 /* Jump to REQ_REBOOT */ \ 110 jmp 0x1A4; 111 112/* 113 * Initialization 114 * 115 * A4 contains the address of the end of the symtab 116 * A5 contains physical load point from boot 117 * VBR contains zero from ROM. Exceptions will continue to vector 118 * through ROM until MMU is turned on at which time they will vector 119 * through our table (vectors.s). 120 */ 121 122BSS(lowram,4) 123BSS(esym,4) 124 125ASENTRY_NOPROFILE(start) 126 movw #PSL_HIGHIPL,%sr | no interrupts 127 ASRELOC(tmpstk, %a0) 128 movl %a0,%sp | give ourselves a temporary stack 129 RELOC(esym, %a0) 130#if 1 131 movl %a4,%a0@ | store end of symbol table 132#else 133 clrl %a0@ | no symbol table, yet 134#endif 135 RELOC(lowram, %a0) 136 movl %a5,%a0@ | store start of physical memory 137 movl #CACHE_OFF,%d0 138 movc %d0,%cacr | clear and disable on-chip cache(s) 139 140/* check for internal HP-IB in SYSFLAG */ 141 btst #5,0xfffffed2 | internal HP-IB? 142 jeq Lhaveihpib | yes, have HP-IB just continue 143 RELOC(internalhpib, %a0) 144 movl #0,%a0@ | no, clear associated address 145Lhaveihpib: 146 147 RELOC(boothowto, %a0) | save reboot flags 148 movl %d7,%a0@ 149 RELOC(bootdev, %a0) | and boot device 150 movl %d6,%a0@ 151 152 /* 153 * All data registers are now free. All address registers 154 * except %a5 are free. %a5 is used by the RELOC() macro, 155 * and cannot be used until after the MMU is enabled. 156 */ 157 158/* determine our CPU/MMU combo - check for all regardless of kernel config */ 159 movl #INTIOBASE+MMUBASE,%a1 160 movl #0x200,%d0 | data freeze bit 161 movc %d0,%cacr | only exists on 68030 162 movc %cacr,%d0 | read it back 163 tstl %d0 | zero? 164 jeq Lnot68030 | yes, we have 68020/68040 165 166 /* 167 * 68030 models 168 */ 169 170 RELOC(mmutype, %a0) | no, we have 68030 171 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU 172 RELOC(cputype, %a0) 173 movl #CPU_68030,%a0@ | and 68030 CPU 174 RELOC(machineid, %a0) 175 movl #0x80,%a1@(MMUCMD) | set magic cookie 176 movl %a1@(MMUCMD),%d0 | read it back 177 btst #7,%d0 | cookie still on? 178 jeq Lnot370 | no, 360 or 375 179 movl #0,%a1@(MMUCMD) | clear magic cookie 180 movl %a1@(MMUCMD),%d0 | read it back 181 btst #7,%d0 | still on? 182 jeq Lisa370 | no, must be a 370 183 movl #HP_340,%a0@ | yes, must be a 340 184 jra Lstart1 185Lnot370: 186 movl #HP_360,%a0@ | type is at least a 360 187 movl #0,%a1@(MMUCMD) | clear magic cookie2 188 movl %a1@(MMUCMD),%d0 | read it back 189 btst #16,%d0 | still on? 190 jeq Lstart1 | no, must be a 360 191 RELOC(mmuid, %a0) | save MMU ID 192 lsrl #MMUID_SHIFT,%d0 193 andl #MMUID_MASK,%d0 194 movl %d0,%a0@ 195 RELOC(machineid, %a0) 196 cmpb #MMUID_345,%d0 | are we a 345? 197 beq Lisa345 198 cmpb #MMUID_375,%d0 | how about a 375? 199 beq Lisa375 200 movl #HP_400,%a0@ | must be a 400 201 jra Lhaspac 202Lisa345: 203 movl #HP_345,%a0@ 204 jra Lhaspac 205Lisa375: 206 movl #HP_375,%a0@ 207 jra Lhaspac 208Lisa370: 209 movl #HP_370,%a0@ | set to 370 210Lhaspac: 211 RELOC(ectype, %a0) 212 movl #EC_PHYS,%a0@ | also has a physical address cache 213 jra Lstart1 214 215 /* 216 * End of 68030 section 217 */ 218 219Lnot68030: 220 bset #31,%d0 | data cache enable bit 221 movc %d0,%cacr | only exists on 68040 222 movc %cacr,%d0 | read it back 223 tstl %d0 | zero? 224 beq Lis68020 | yes, we have 68020 225 moveq #0,%d0 | now turn it back off 226 movec %d0,%cacr | before we access any data 227 228 /* 229 * 68040 models 230 */ 231 232 RELOC(mmutype, %a0) 233 movl #MMU_68040,%a0@ | with a 68040 MMU 234 RELOC(cputype, %a0) 235 movl #CPU_68040,%a0@ | and a 68040 CPU 236 RELOC(fputype, %a0) 237 movl #FPU_68040,%a0@ | ...and FPU 238 RELOC(ectype, %a0) 239 movl #EC_NONE,%a0@ | and no cache (for now XXX) 240 RELOC(mmuid,%a0) | save MMU ID 241 movl %a1@(MMUCMD),%d0 242 lsrl #MMUID_SHIFT,%d0 243 andl #MMUID_MASK,%d0 244 movl %d0,%a0@ 245 RELOC(machineid, %a0) 246 cmpb #MMUID_425_T,%d0 | are we a 425t? 247 jeq Lisa425 248 cmpb #MMUID_425_S,%d0 | how about 425s? 249 jeq Lisa425 250 cmpb #MMUID_425_E,%d0 | or maybe a 425e? 251 jeq Lisa425 252 cmpb #MMUID_433_T,%d0 | or a 433t? 253 jeq Lisa433 254 cmpb #MMUID_433_S,%d0 | or a 433s? 255 jeq Lisa433 256 cmpb #MMUID_385,%d0 | or a 385? 257 jeq Lisa385 258 movl #HP_380,%a0@ | guess we're a 380 259 jra Lstart1 260Lisa425: 261 movl #HP_425,%a0@ 262 jra Lstart1 263Lisa433: 264 movl #HP_433,%a0@ 265 jra Lstart1 266Lisa385: 267 movl #HP_385,%a0@ 268 jra Lstart1 269 270 /* 271 * End of 68040 section 272 */ 273 274 /* 275 * 68020 models 276 */ 277 278Lis68020: 279 RELOC(fputype, %a0) | all of the 68020 systems 280 movl #FPU_68881,%a0@ | have a 68881 FPU 281 movl #1,%a1@(MMUCMD) | a 68020, write HP MMU location 282 movl %a1@(MMUCMD),%d0 | read it back 283 btst #0,%d0 | non-zero? 284 jne Lishpmmu | yes, we have HP MMU 285 RELOC(mmutype, %a0) 286 movl #MMU_68851,%a0@ | no, we have PMMU 287 RELOC(machineid, %a0) 288 movl #HP_330,%a0@ | and 330 CPU 289 jra Lstart1 290Lishpmmu: 291 RELOC(ectype, %a0) | 320 or 350 292 movl #EC_VIRT,%a0@ | both have a virtual address cache 293 movl #0x80,%a1@(MMUCMD) | set magic cookie 294 movl %a1@(MMUCMD),%d0 | read it back 295 btst #7,%d0 | cookie still on? 296 jeq Lis320 | no, just a 320 297 RELOC(machineid, %a0) 298 movl #HP_350,%a0@ | yes, a 350 299 jra Lstart1 300Lis320: 301 RELOC(machineid, %a0) 302 movl #HP_320,%a0@ 303 304 /* 305 * End of 68020 section 306 */ 307 308Lstart1: 309 /* 310 * Now that we know what CPU we have, initialize the address error 311 * and bus error handlers in the vector table: 312 * 313 * vectab+8 bus error 314 * vectab+12 address error 315 */ 316 RELOC(cputype, %a0) 317#if 0 318 /* XXX assembler/linker feature/bug */ 319 RELOC(vectab, %a2) 320#else 321 movl #_C_LABEL(vectab),%a2 322 addl %a5,%a2 323#endif 324#if defined(M68040) 325 cmpl #CPU_68040,%a0@ | 68040? 326 jne 1f | no, skip 327 movl #_C_LABEL(buserr40),%a2@(8) 328 movl #_C_LABEL(addrerr4060),%a2@(12) 329 jra Lstart2 3301: 331#endif 332#if defined(M68020) || defined(M68030) 333 cmpl #CPU_68040,%a0@ | 68040? 334 jeq 1f | yes, skip 335 movl #_C_LABEL(busaddrerr2030),%a2@(8) 336 movl #_C_LABEL(busaddrerr2030),%a2@(12) 337 jra Lstart2 3381: 339#endif 340 /* Config botch; no hope. */ 341 DOREBOOT 342 343Lstart2: 344 movl #0,%a1@(MMUCMD) | clear out MMU again 345/* initialize source/destination control registers for movs */ 346 moveq #FC_USERD,%d0 | user space 347 movc %d0,%sfc | as source 348 movc %d0,%dfc | and destination of transfers 349/* initialize memory sizes (for pmap_bootstrap) */ 350 movl #MAXADDR,%d1 | last page 351 moveq #PGSHIFT,%d2 352 lsrl %d2,%d1 | convert to page (click) number 353 RELOC(maxmem, %a0) 354 movl %d1,%a0@ | save as maxmem 355 movl %a5,%d0 | lowram value from ROM via boot 356 lsrl %d2,%d0 | convert to page number 357 subl %d0,%d1 | compute amount of RAM present 358 RELOC(physmem, %a0) 359 movl %d1,%a0@ | and physmem 360 361/* configure kernel and proc0 VA space so we can get going */ 362#ifdef DDB 363 RELOC(esym,%a0) | end of static kernel test/data/syms 364 movl %a0@,%d5 365 jne Lstart3 366#endif 367 movl #_C_LABEL(end),%d5 | end of static kernel text/data 368Lstart3: 369 addl #NBPG-1,%d5 370 andl #PG_FRAME,%d5 | round to a page 371 movl %d5,%a4 372 addl %a5,%a4 | convert to PA 373 pea %a5@ | firstpa 374 pea %a4@ | nextpa 375 RELOC(pmap_bootstrap,%a0) 376 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 377 addql #8,%sp 378 379/* 380 * Prepare to enable MMU. 381 * Since the kernel is not mapped logical == physical we must insure 382 * that when the MMU is turned on, all prefetched addresses (including 383 * the PC) are valid. In order guarentee that, we use the last physical 384 * page (which is conveniently mapped == VA) and load it up with enough 385 * code to defeat the prefetch, then we execute the jump back to here. 386 * 387 * Is this all really necessary, or am I paranoid?? 388 */ 389 RELOC(Sysseg, %a0) | system segment table addr 390 movl %a0@,%d1 | read value (a KVA) 391 addl %a5,%d1 | convert to PA 392 RELOC(mmutype, %a0) 393 tstl %a0@ | HP MMU? 394 jeq Lhpmmu2 | yes, skip 395 cmpl #MMU_68040,%a0@ | 68040? 396 jne Lmotommu1 | no, skip 397 .long 0x4e7b1807 | movc %d1,%srp 398 jra Lstploaddone 399Lmotommu1: 400 RELOC(protorp, %a0) 401 movl #0x80000202,%a0@ | nolimit + share global + 4 byte PTEs 402 movl %d1,%a0@(4) | + segtable address 403 pmove %a0@,%srp | load the supervisor root pointer 404 movl #0x80000002,%a0@ | reinit upper half for CRP loads 405 jra Lstploaddone | done 406Lhpmmu2: 407 moveq #PGSHIFT,%d2 408 lsrl %d2,%d1 | convert to page frame 409 movl %d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register 410Lstploaddone: 411 lea MAXADDR,%a2 | PA of last RAM page 412#if 0 413 ASRELOC(Lhighcode, %a1) | addr of high code 414 ASRELOC(Lehighcode, %a3) | end addr 415#else 416 /* don't want pc-relative addressing */ 417 .word 0x43f9 | lea Lhighcode, %a1 418 .long Lhighcode 419 addl %a5, %a1 420 .word 0x47f9 | lea Lehighcode, %a3 421 .long Lehighcode 422 addl %a5, %a3 423#endif 424Lcodecopy: 425 movw %a1@+,%a2@+ | copy a word 426 cmpl %a3,%a1 | done yet? 427 jcs Lcodecopy | no, keep going 428 jmp MAXADDR | go for it! 429 430 /* 431 * BEGIN MMU TRAMPOLINE. This section of code is not 432 * executed in-place. It's copied to the last page 433 * of RAM (mapped va == pa) and executed there. 434 */ 435 436Lhighcode: 437 /* 438 * Set up the vector table, and race to get the MMU 439 * enabled. 440 */ 441 movl #_C_LABEL(vectab),%d0 | set Vector Base Register 442 movc %d0,%vbr 443 444 RELOC(mmutype, %a0) 445 tstl %a0@ | HP MMU? 446 jeq Lhpmmu3 | yes, skip 447 cmpl #MMU_68040,%a0@ | 68040? 448 jne Lmotommu2 | no, skip 449 movw #0,INTIOBASE+MMUBASE+MMUCMD+2 450 movw #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2 451 | enable FPU and caches 452 moveq #0,%d0 | ensure TT regs are disabled 453 .long 0x4e7b0004 | movc %d0,%itt0 454 .long 0x4e7b0005 | movc %d0,%itt1 455 .long 0x4e7b0006 | movc %d0,%dtt0 456 .long 0x4e7b0007 | movc %d0,%dtt1 457 .word 0xf4d8 | cinva bc 458 .word 0xf518 | pflusha 459 movl #0x8000,%d0 460 .long 0x4e7b0003 | movc %d0,%tc 461 movl #0x80008000,%d0 462 movc %d0,%cacr | turn on both caches 463 jmp Lenab1:l | forced not be pc-relative 464Lmotommu2: 465 movl #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD 466 | enable 68881 and i-cache 467 RELOC(prototc, %a2) 468 movl #0x82c0aa00,%a2@ | value to load TC with 469 pmove %a2@,%tc | load it 470 jmp Lenab1:l | forced not be pc-relative 471Lhpmmu3: 472 movl #0,INTIOBASE+MMUBASE+MMUCMD | clear external cache 473 movl #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU 474 jmp Lenab1:l | forced not be pc-relative 475Lehighcode: 476 477 /* 478 * END MMU TRAMPOLINE. Address register %a5 is now free. 479 */ 480 481/* 482 * Should be running mapped from this point on 483 */ 484Lenab1: 485/* select the software page size now */ 486 lea _ASM_LABEL(tmpstk),%sp | temporary stack 487 jbsr _C_LABEL(uvm_setpagesize) | select software page size 488/* set kernel stack, user SP, and initial pcb */ 489 movl _C_LABEL(proc0paddr),%a1 | get proc0 pcb addr 490 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 491 lea _C_LABEL(proc0),%a2 | initialize proc0.p_addr so that 492 movl %a1,%a2@(P_ADDR) | we don't deref NULL in trap() 493 movl #USRSTACK-4,%a2 494 movl %a2,%usp | init user SP 495 movl %a1,_C_LABEL(curpcb) | proc0 is running 496 497 tstl _C_LABEL(fputype) | Have an FPU? 498 jeq Lenab2 | No, skip. 499 clrl %a1@(PCB_FPCTX) | ensure null FP context 500 movl %a1,%sp@- 501 jbsr _C_LABEL(m68881_restore) | restore it (does not kill %a1) 502 addql #4,%sp 503Lenab2: 504/* flush TLB and turn on caches */ 505 jbsr _C_LABEL(TBIA) | invalidate TLB 506 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 507 jeq Lnocache0 | yes, cache already on 508 movl #CACHE_ON,%d0 509 movc %d0,%cacr | clear cache(s) 510 tstl _C_LABEL(ectype) 511 jeq Lnocache0 512 MMUADDR(%a0) 513 orl #MMU_CEN,%a0@(MMUCMD) | turn on external cache 514Lnocache0: 515/* Final setup for call to main(). */ 516 jbsr _C_LABEL(hp300_init) 517 518/* 519 * Create a fake exception frame so that cpu_fork() can copy it. 520 * main() nevers returns; we exit to user mode from a forked process 521 * later on. 522 */ 523 clrw %sp@- | vector offset/frame type 524 clrl %sp@- | PC - filled in by "execve" 525 movw #PSL_USER,%sp@- | in user mode 526 clrl %sp@- | stack adjust count and padding 527 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 528 lea _C_LABEL(proc0),%a0 | save pointer to frame 529 movl %sp,%a0@(P_MD_REGS) | in proc0.p_md.md_regs 530 531 jra _C_LABEL(main) | main() 532 PANIC("main() returned") 533 /* NOTREACHED */ 534 535/* 536 * proc_trampoline: call function in register %a2 with %a3 as an arg 537 * and then rei. 538 */ 539GLOBAL(proc_trampoline) 540 movl %a3,%sp@- | push function arg 541 jbsr %a2@ | call function 542 addql #4,%sp | pop arg 543 movl %sp@(FR_SP),%a0 | grab and load 544 movl %a0,%usp | user SP 545 moveml %sp@+,#0x7FFF | restore most user regs 546 addql #8,%sp | toss SP and stack adjust 547 jra _ASM_LABEL(rei) | and return 548 549 550/* 551 * Trap/interrupt vector routines 552 */ 553#include <m68k/m68k/trap_subr.s> 554 555 .data 556GLOBAL(m68k_fault_addr) 557 .long 0 558 559#if defined(M68040) || defined(M68060) 560ENTRY_NOPROFILE(addrerr4060) 561 clrl %sp@- | stack adjust count 562 moveml #0xFFFF,%sp@- | save user registers 563 movl %usp,%a0 | save the user SP 564 movl %a0,%sp@(FR_SP) | in the savearea 565 movl %sp@(FR_HW+8),%sp@- 566 clrl %sp@- | dummy code 567 movl #T_ADDRERR,%sp@- | mark address error 568 jra _ASM_LABEL(faultstkadj) | and deal with it 569#endif 570 571#if defined(M68060) 572ENTRY_NOPROFILE(buserr60) 573 clrl %sp@- | stack adjust count 574 moveml #0xFFFF,%sp@- | save user registers 575 movl %usp,%a0 | save the user SP 576 movl %a0,%sp@(FR_SP) | in the savearea 577 movel %sp@(FR_HW+12),%d0 | FSLW 578 btst #2,%d0 | branch prediction error? 579 jeq Lnobpe 580 movc %cacr,%d2 581 orl #IC60_CABC,%d2 | clear all branch cache entries 582 movc %d2,%cacr 583 movl %d0,%d1 584 addql #1,L60bpe 585 andl #0x7ffd,%d1 586 jeq _ASM_LABEL(faultstkadjnotrap2) 587Lnobpe: 588| we need to adjust for misaligned addresses 589 movl %sp@(FR_HW+8),%d1 | grab VA 590 btst #27,%d0 | check for mis-aligned access 591 jeq Lberr3 | no, skip 592 addl #28,%d1 | yes, get into next page 593 | operand case: 3, 594 | instruction case: 4+12+12 595 andl #PG_FRAME,%d1 | and truncate 596Lberr3: 597 movl %d1,%sp@- 598 movl %d0,%sp@- | code is FSLW now. 599 andw #0x1f80,%d0 600 jeq Lberr60 | it is a bus error 601 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 602 jra _ASM_LABEL(faultstkadj) | and deal with it 603Lberr60: 604 tstl _C_LABEL(nofault) | catch bus error? 605 jeq Lisberr | no, handle as usual 606 movl %sp@(FR_HW+8+8),_C_LABEL(m68k_fault_addr) | save fault addr 607 movl _C_LABEL(nofault),%sp@- | yes, 608 jbsr _C_LABEL(longjmp) | longjmp(nofault) 609 /* NOTREACHED */ 610#endif 611#if defined(M68040) 612ENTRY_NOPROFILE(buserr40) 613 clrl %sp@- | stack adjust count 614 moveml #0xFFFF,%sp@- | save user registers 615 movl %usp,%a0 | save the user SP 616 movl %a0,%sp@(FR_SP) | in the savearea 617 movl %sp@(FR_HW+20),%d1 | get fault address 618 moveq #0,%d0 619 movw %sp@(FR_HW+12),%d0 | get SSW 620 btst #11,%d0 | check for mis-aligned 621 jeq Lbe1stpg | no skip 622 addl #3,%d1 | get into next page 623 andl #PG_FRAME,%d1 | and truncate 624Lbe1stpg: 625 movl %d1,%sp@- | pass fault address. 626 movl %d0,%sp@- | pass SSW as code 627 btst #10,%d0 | test ATC 628 jeq Lberr40 | it is a bus error 629 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 630 jra _ASM_LABEL(faultstkadj) | and deal with it 631Lberr40: 632 tstl _C_LABEL(nofault) | catch bus error? 633 jeq Lisberr | no, handle as usual 634 movl %sp@(FR_HW+8+20),_C_LABEL(m68k_fault_addr) | save fault addr 635 movl _C_LABEL(nofault),%sp@- | yes, 636 jbsr _C_LABEL(longjmp) | longjmp(nofault) 637 /* NOTREACHED */ 638#endif 639 640#if defined(M68020) || defined(M68030) 641ENTRY_NOPROFILE(busaddrerr2030) 642 clrl %sp@- | stack adjust count 643 moveml #0xFFFF,%sp@- | save user registers 644 movl %usp,%a0 | save the user SP 645 movl %a0,%sp@(FR_SP) | in the savearea 646 moveq #0,%d0 647 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 648 btst #12,%d0 | RB set? 649 jeq LbeX0 | no, test RC 650 bset #14,%d0 | yes, must set FB 651 movw %d0,%sp@(FR_HW+10) | for hardware too 652LbeX0: 653 btst #13,%d0 | RC set? 654 jeq LbeX1 | no, skip 655 bset #15,%d0 | yes, must set FC 656 movw %d0,%sp@(FR_HW+10) | for hardware too 657LbeX1: 658 btst #8,%d0 | data fault? 659 jeq Lbe0 | no, check for hard cases 660 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 661 jra Lbe10 | thats it 662Lbe0: 663 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 664 jne Lbe4 | yes, go handle 665 movl %sp@(FR_HW+2),%d1 | no, can use save PC 666 btst #14,%d0 | FB set? 667 jeq Lbe3 | no, try FC 668 addql #4,%d1 | yes, adjust address 669 jra Lbe10 | done 670Lbe3: 671 btst #15,%d0 | FC set? 672 jeq Lbe10 | no, done 673 addql #2,%d1 | yes, adjust address 674 jra Lbe10 | done 675Lbe4: 676 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 677 btst #15,%d0 | FC set? 678 jeq Lbe10 | no, all done 679 subql #2,%d1 | yes, adjust address 680Lbe10: 681 movl %d1,%sp@- | push fault VA 682 movl %d0,%sp@- | and padded SSW 683 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 684 andw #0x0FFF,%d0 | clear out frame format 685 cmpw #12,%d0 | address error vector? 686 jeq Lisaerr | yes, go to it 687#if defined(M68K_MMU_MOTOROLA) 688#if defined(M68K_MMU_HP) 689 tstl _C_LABEL(mmutype) | HP MMU? 690 jeq Lbehpmmu | yes, different MMU fault handler 691#endif 692 movl %d1,%a0 | fault address 693 movl %sp@,%d0 | function code from ssw 694 btst #8,%d0 | data fault? 695 jne Lbe10a 696 movql #1,%d0 | user program access FC 697 | (we dont separate data/program) 698 btst #5,%sp@(FR_HW+8) | supervisor mode? 699 jeq Lbe10a | if no, done 700 movql #5,%d0 | else supervisor program access 701Lbe10a: 702 ptestr %d0,%a0@,#7 | do a table search 703 pmove %psr,%sp@ | save result 704 movb %sp@,%d1 705 btst #2,%d1 | invalid (incl. limit viol. and berr)? 706 jeq Lmightnotbemerr | no -> wp check 707 btst #7,%d1 | is it MMU table berr? 708 jne Lisberr1 | yes, needs not be fast. 709#endif /* M68K_MMU_MOTOROLA */ 710Lismerr: 711 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 712 jra _ASM_LABEL(faultstkadj) | and deal with it 713#if defined(M68K_MMU_MOTOROLA) 714Lmightnotbemerr: 715 btst #3,%d1 | write protect bit set? 716 jeq Lisberr1 | no: must be bus error 717 movl %sp@,%d0 | ssw into low word of %d0 718 andw #0xc0,%d0 | Write protect is set on page: 719 cmpw #0x40,%d0 | was it read cycle? 720 jne Lismerr | no, was not WPE, must be MMU fault 721 jra Lisberr1 | real bus err needs not be fast. 722#endif /* M68K_MMU_MOTOROLA */ 723#if defined(M68K_MMU_HP) 724Lbehpmmu: 725 MMUADDR(%a0) 726 movl %a0@(MMUSTAT),%d0 | read MMU status 727 btst #3,%d0 | MMU fault? 728 jeq Lisberr1 | no, just a non-MMU bus error 729 andl #~MMU_FAULT,%a0@(MMUSTAT)| yes, clear fault bits 730 movw %d0,%sp@ | pass MMU stat in upper half of code 731 jra Lismerr | and handle it 732#endif 733Lisaerr: 734 movl #T_ADDRERR,%sp@- | mark address error 735 jra _ASM_LABEL(faultstkadj) | and deal with it 736Lisberr1: 737 clrw %sp@ | re-clear pad word 738 tstl _C_LABEL(nofault) | catch bus error? 739 jeq Lisberr | no, handle as usual 740 movl %sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr 741 movl _C_LABEL(nofault),%sp@- | yes, 742 jbsr _C_LABEL(longjmp) | longjmp(nofault) 743 /* NOTREACHED */ 744#endif /* M68020 || M68030 */ 745 746Lisberr: | also used by M68040/60 747 movl #T_BUSERR,%sp@- | mark bus error 748 jra _ASM_LABEL(faultstkadj) | and deal with it 749 750/* 751 * FP exceptions. 752 */ 753ENTRY_NOPROFILE(fpfline) 754#if defined(M68040) 755 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 756 jne Lfp_unimp | no, skip FPSP 757 cmpw #0x202c,%sp@(6) | format type 2? 758 jne _C_LABEL(illinst) | no, not an FP emulation 759Ldofp_unimp: 760#ifdef FPSP 761 jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it 762#endif 763Lfp_unimp: 764#endif /* M68040 */ 765#ifdef FPU_EMULATE 766 clrl %sp@- | stack adjust count 767 moveml #0xFFFF,%sp@- | save registers 768 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 769 jra _ASM_LABEL(fault) | do it 770#else 771 jra _C_LABEL(illinst) 772#endif 773 774ENTRY_NOPROFILE(fpunsupp) 775#if defined(M68040) 776 cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? 777 jne _C_LABEL(illinst) | no, treat as illinst 778#ifdef FPSP 779 jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it 780#endif 781Lfp_unsupp: 782#endif /* M68040 */ 783#ifdef FPU_EMULATE 784 clrl %sp@- | stack adjust count 785 moveml #0xFFFF,%sp@- | save registers 786 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 787 jra _ASM_LABEL(fault) | do it 788#else 789 jra _C_LABEL(illinst) 790#endif 791 792/* 793 * Handles all other FP coprocessor exceptions. 794 * Note that since some FP exceptions generate mid-instruction frames 795 * and may cause signal delivery, we need to test for stack adjustment 796 * after the trap call. 797 */ 798ENTRY_NOPROFILE(fpfault) 799 clrl %sp@- | stack adjust count 800 moveml #0xFFFF,%sp@- | save user registers 801 movl %usp,%a0 | and save 802 movl %a0,%sp@(FR_SP) | the user stack pointer 803 clrl %sp@- | no VA arg 804 movl _C_LABEL(curpcb),%a0 | current pcb 805 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 806 fsave %a0@ | save state 807#if defined(M68040) || defined(M68060) 808 /* always null state frame on 68040, 68060 */ 809 cmpl #FPU_68040,_C_LABEL(fputype) 810 jle Lfptnull 811#endif 812 tstb %a0@ | null state frame? 813 jeq Lfptnull | yes, safe 814 clrw %d0 | no, need to tweak BIU 815 movb %a0@(1),%d0 | get frame size 816 bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU 817Lfptnull: 818 fmovem %fpsr,%sp@- | push %fpsr as code argument 819 frestore %a0@ | restore state 820 movl #T_FPERR,%sp@- | push type arg 821 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 822 823/* 824 * Other exceptions only cause four and six word stack frame and require 825 * no post-trap stack adjustment. 826 */ 827 828ENTRY_NOPROFILE(badtrap) 829 moveml #0xC0C0,%sp@- | save scratch regs 830 movw %sp@(22),%sp@- | push exception vector info 831 clrw %sp@- 832 movl %sp@(22),%sp@- | and PC 833 jbsr _C_LABEL(straytrap) | report 834 addql #8,%sp | pop args 835 moveml %sp@+,#0x0303 | restore regs 836 jra _ASM_LABEL(rei) | all done 837 838ENTRY_NOPROFILE(trap0) 839 clrl %sp@- | stack adjust count 840 moveml #0xFFFF,%sp@- | save user registers 841 movl %usp,%a0 | save the user SP 842 movl %a0,%sp@(FR_SP) | in the savearea 843 movl %d0,%sp@- | push syscall number 844 jbsr _C_LABEL(syscall) | handle it 845 addql #4,%sp | pop syscall arg 846 tstl _C_LABEL(astpending) 847 jne Lrei2 848 tstb _C_LABEL(ssir) 849 jeq Ltrap1 850 movw #SPL1,%sr 851 tstb _C_LABEL(ssir) 852 jne Lsir1 853Ltrap1: 854 movl %sp@(FR_SP),%a0 | grab and restore 855 movl %a0,%usp | user SP 856 moveml %sp@+,#0x7FFF | restore most registers 857 addql #8,%sp | pop SP and stack adjust 858 rte 859 860/* 861 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 862 * cachectl(command, addr, length) 863 * command in %d0, addr in %a1, length in %d1 864 */ 865ENTRY_NOPROFILE(trap12) 866 movl _C_LABEL(curproc),%sp@- | push current proc pointer 867 movl %d1,%sp@- | push length 868 movl %a1,%sp@- | push addr 869 movl %d0,%sp@- | push command 870 jbsr _C_LABEL(cachectl1) | do it 871 lea %sp@(16),%sp | pop args 872 jra _ASM_LABEL(rei) | all done 873 874/* 875 * Trace (single-step) trap. Kernel-mode is special. 876 * User mode traps are simply passed on to trap(). 877 */ 878ENTRY_NOPROFILE(trace) 879 clrl %sp@- | stack adjust count 880 moveml #0xFFFF,%sp@- 881 moveq #T_TRACE,%d0 882 883 | Check PSW and see what happen. 884 | T=0 S=0 (should not happen) 885 | T=1 S=0 trace trap from user mode 886 | T=0 S=1 trace trap on a trap instruction 887 | T=1 S=1 trace trap from system mode (kernel breakpoint) 888 889 movw %sp@(FR_HW),%d1 | get PSW 890 notw %d1 | XXX no support for T0 on 680[234]0 891 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 892 jeq Lkbrkpt | yes, kernel breakpoint 893 jra _ASM_LABEL(fault) | no, user-mode fault 894 895/* 896 * Trap 15 is used for: 897 * - GDB breakpoints (in user programs) 898 * - KGDB breakpoints (in the kernel) 899 * - trace traps for SUN binaries (not fully supported yet) 900 * User mode traps are simply passed to trap(). 901 */ 902ENTRY_NOPROFILE(trap15) 903 clrl %sp@- | stack adjust count 904 moveml #0xFFFF,%sp@- 905 moveq #T_TRAP15,%d0 906 movw %sp@(FR_HW),%d1 | get PSW 907 andw #PSL_S,%d1 | from system mode? 908 jne Lkbrkpt | yes, kernel breakpoint 909 jra _ASM_LABEL(fault) | no, user-mode fault 910 911Lkbrkpt: | Kernel-mode breakpoint or trace trap. (%d0=trap_type) 912 | Save the system sp rather than the user sp. 913 movw #PSL_HIGHIPL,%sr | lock out interrupts 914 lea %sp@(FR_SIZE),%a6 | Save stack pointer 915 movl %a6,%sp@(FR_SP) | from before trap 916 917 | If were are not on tmpstk switch to it. 918 | (so debugger can change the stack pointer) 919 movl %a6,%d1 920 cmpl #_ASM_LABEL(tmpstk),%d1 921 jls Lbrkpt2 | already on tmpstk 922 | Copy frame to the temporary stack 923 movl %sp,%a0 | %a0=src 924 lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst 925 movl %a1,%sp | %sp=new frame 926 moveq #FR_SIZE,%d1 927Lbrkpt1: 928 movl %a0@+,%a1@+ 929 subql #4,%d1 930 bgt Lbrkpt1 931 932Lbrkpt2: 933 | Call the trap handler for the kernel debugger. 934 | Do not call trap() to do it, so that we can 935 | set breakpoints in trap() if we want. We know 936 | the trap type is either T_TRACE or T_BREAKPOINT. 937 | If we have both DDB and KGDB, let KGDB see it first, 938 | because KGDB will just return 0 if not connected. 939 | Save args in %d2, %a2 940 movl %d0,%d2 | trap type 941 movl %sp,%a2 | frame ptr 942#ifdef KGDB 943 | Let KGDB handle it (if connected) 944 movl %a2,%sp@- | push frame ptr 945 movl %d2,%sp@- | push trap type 946 jbsr _C_LABEL(kgdb_trap) | handle the trap 947 addql #8,%sp | pop args 948 cmpl #0,%d0 | did kgdb handle it? 949 jne Lbrkpt3 | yes, done 950#endif 951#ifdef DDB 952 | Let DDB handle it 953 movl %a2,%sp@- | push frame ptr 954 movl %d2,%sp@- | push trap type 955 jbsr _C_LABEL(kdb_trap) | handle the trap 956 addql #8,%sp | pop args 957#if 0 /* not needed on hp300 */ 958 cmpl #0,%d0 | did ddb handle it? 959 jne Lbrkpt3 | yes, done 960#endif 961#endif 962 /* Sun 3 drops into PROM here. */ 963Lbrkpt3: 964 | The stack pointer may have been modified, or 965 | data below it modified (by kgdb push call), 966 | so push the hardware frame at the current sp 967 | before restoring registers and returning. 968 969 movl %sp@(FR_SP),%a0 | modified %sp 970 lea %sp@(FR_SIZE),%a1 | end of our frame 971 movl %a1@-,%a0@- | copy 2 longs with 972 movl %a1@-,%a0@- | ... predecrement 973 movl %a0,%sp@(FR_SP) | %sp = h/w frame 974 moveml %sp@+,#0x7FFF | restore all but %sp 975 movl %sp@,%sp | ... and %sp 976 rte | all done 977 978/* Use common m68k sigreturn */ 979#include <m68k/m68k/sigreturn.s> 980 981/* 982 * Interrupt handlers. 983 * All device interrupts are auto-vectored. The CPU provides 984 * the vector 0x18+level. Note we count spurious interrupts, but 985 * we don't do anything else with them. 986 */ 987 988#define INTERRUPT_SAVEREG moveml #0xC0C0,%sp@- 989#define INTERRUPT_RESTOREREG moveml %sp@+,#0x0303 990 991/* 64-bit evcnt counter increments */ 992#define EVCNT_COUNTER(ipl) \ 993 _C_LABEL(hp300_intr_list) + (ipl)*SIZEOF_HI + HI_EVCNT 994#define EVCNT_INCREMENT(ipl) \ 995 movel %d2,-(%sp); \ 996 clrl %d0; \ 997 moveql #1,%d1; \ 998 addl %d1,EVCNT_COUNTER(ipl)+4; \ 999 movel EVCNT_COUNTER(ipl),%d2; \ 1000 addxl %d0,%d2; \ 1001 movel %d2,EVCNT_COUNTER(ipl); \ 1002 movel (%sp)+,%d2 1003 1004ENTRY_NOPROFILE(spurintr) /* level 0 */ 1005 EVCNT_INCREMENT(0) 1006 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 1007 jra _ASM_LABEL(rei) 1008 1009ENTRY_NOPROFILE(intrhand) /* levels 1 through 5 */ 1010 INTERRUPT_SAVEREG 1011 movw %sp@(22),%sp@- | push exception vector info 1012 clrw %sp@- 1013 jbsr _C_LABEL(intr_dispatch) | call dispatch routine 1014 addql #4,%sp 1015 INTERRUPT_RESTOREREG 1016 jra _ASM_LABEL(rei) | all done 1017 1018ENTRY_NOPROFILE(lev6intr) /* level 6: clock */ 1019 INTERRUPT_SAVEREG 1020 CLKADDR(%a0) 1021 movb %a0@(CLKSR),%d0 | read clock status 1022Lclkagain: 1023 btst #0,%d0 | clear timer1 int immediately to 1024 jeq Lnotim1 | minimize chance of losing another 1025 movpw %a0@(CLKMSB1),%d1 | due to statintr processing delay 1026Lnotim1: 1027 btst #2,%d0 | timer3 interrupt? 1028 jeq Lnotim3 | no, skip statclock 1029 movpw %a0@(CLKMSB3),%d1 | clear timer3 interrupt 1030 lea %sp@(16),%a1 | a1 = &clockframe 1031 movl %d0,%sp@- | save status 1032 movl %a1,%sp@- 1033 jbsr _C_LABEL(statintr) | statintr(&frame) 1034 addql #4,%sp 1035 movl %sp@+,%d0 | restore pre-statintr status 1036 CLKADDR(%a0) 1037Lnotim3: 1038 btst #0,%d0 | timer1 interrupt? 1039 jeq Lrecheck | no, skip hardclock 1040 EVCNT_INCREMENT(6) 1041 lea %sp@(16),%a1 | a1 = &clockframe 1042 movl %a1,%sp@- 1043#ifdef USELEDS 1044 tstl _C_LABEL(ledaddr) | using LEDs? 1045 jeq Lnoleds0 | no, skip this code 1046 movl _ASM_LABEL(heartbeat),%d0 | get tick count 1047 addql #1,%d0 | increment 1048 movl _C_LABEL(hz),%d1 1049 addl #50,%d1 | get the timing a little closer 1050 tstb _ASM_LABEL(beatstatus) | time to slow down? 1051 jeq Lslowthrob | yes, slow down 1052 lsrl #3,%d1 | no, fast throb 1053Lslowthrob: 1054 lsrl #1,%d1 | slow throb 1055 cmpl %d0,%d1 | are we there yet? 1056 jne Lnoleds1 | no, nothing to do 1057 addqb #1,_ASM_LABEL(beatstatus) | incr beat status 1058 cmpb #3,_ASM_LABEL(beatstatus) | time to reset? 1059 jle Ltwinkle | no, twinkle the lights 1060 movb #0,_ASM_LABEL(beatstatus) | reset the status indicator 1061Ltwinkle: 1062 movl #LED_PULSE,%sp@- 1063 movl #LED_DISK+LED_LANRCV+LED_LANXMT,%sp@- 1064 clrl %sp@- 1065 jbsr _C_LABEL(ledcontrol) | toggle pulse, turn all others off 1066 lea %sp@(12),%sp 1067 movql #0,%d0 1068Lnoleds1: 1069 movl %d0,_ASM_LABEL(heartbeat) 1070Lnoleds0: 1071#endif /* USELEDS */ 1072 jbsr _C_LABEL(hardclock) | hardclock(&frame) 1073 addql #4,%sp 1074 CLKADDR(%a0) 1075Lrecheck: 1076 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS | chalk up another interrupt 1077 movb %a0@(CLKSR),%d0 | see if anything happened 1078 jmi Lclkagain | while we were in hardclock/statintr 1079 INTERRUPT_RESTOREREG 1080 jra _ASM_LABEL(rei) | all done 1081 1082ENTRY_NOPROFILE(lev7intr) /* level 7: parity errors, reset key */ 1083 EVCNT_INCREMENT(7) 1084 clrl %sp@- 1085 moveml #0xFFFF,%sp@- | save registers 1086 movl %usp,%a0 | and save 1087 movl %a0,%sp@(FR_SP) | the user stack pointer 1088 jbsr _C_LABEL(nmihand) | call handler 1089 movl %sp@(FR_SP),%a0 | restore 1090 movl %a0,%usp | user SP 1091 moveml %sp@+,#0x7FFF | and remaining registers 1092 addql #8,%sp | pop SP and stack adjust 1093 jra _ASM_LABEL(rei) | all done 1094 1095/* 1096 * Emulation of VAX REI instruction. 1097 * 1098 * This code deals with checking for and servicing ASTs (profiling, 1099 * scheduling) and software interrupts. We check for ASTs first, just 1100 * like the VAX. After identifing that we need an AST we 1101 * drop the IPL to allow device interrupts. 1102 * 1103 * This code is complicated by the fact that sendsig may have been called 1104 * necessitating a stack cleanup. 1105 */ 1106 1107ASENTRY_NOPROFILE(rei) 1108 tstl _C_LABEL(astpending) | AST pending? 1109 jeq Lchksir | no, go check for SIR 1110Lrei1: 1111 btst #5,%sp@ | yes, are we returning to user mode? 1112 jne Lchksir | no, go check for SIR 1113 movw #PSL_LOWIPL,%sr | lower SPL 1114 clrl %sp@- | stack adjust 1115 moveml #0xFFFF,%sp@- | save all registers 1116 movl %usp,%a1 | including 1117 movl %a1,%sp@(FR_SP) | the users SP 1118Lrei2: 1119 clrl %sp@- | VA == none 1120 clrl %sp@- | code == none 1121 movl #T_ASTFLT,%sp@- | type == async system trap 1122 jbsr _C_LABEL(trap) | go handle it 1123 lea %sp@(12),%sp | pop value args 1124 movl %sp@(FR_SP),%a0 | restore user SP 1125 movl %a0,%usp | from save area 1126 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 1127 jne Laststkadj | yes, go to it 1128 moveml %sp@+,#0x7FFF | no, restore most user regs 1129 addql #8,%sp | toss SP and stack adjust 1130 rte | and do real RTE 1131Laststkadj: 1132 lea %sp@(FR_HW),%a1 | pointer to HW frame 1133 addql #8,%a1 | source pointer 1134 movl %a1,%a0 | source 1135 addw %d0,%a0 | + hole size = dest pointer 1136 movl %a1@-,%a0@- | copy 1137 movl %a1@-,%a0@- | 8 bytes 1138 movl %a0,%sp@(FR_SP) | new SSP 1139 moveml %sp@+,#0x7FFF | restore user registers 1140 movl %sp@,%sp | and our SP 1141 rte | and do real RTE 1142Lchksir: 1143 tstb _C_LABEL(ssir) | SIR pending? 1144 jeq Ldorte | no, all done 1145 movl %d0,%sp@- | need a scratch register 1146 movw %sp@(4),%d0 | get SR 1147 andw #PSL_IPL7,%d0 | mask all but IPL 1148 jne Lnosir | came from interrupt, no can do 1149 movl %sp@+,%d0 | restore scratch register 1150Lgotsir: 1151 movw #SPL1,%sr | prevent others from servicing int 1152 tstb _C_LABEL(ssir) | too late? 1153 jeq Ldorte | yes, oh well... 1154 clrl %sp@- | stack adjust 1155 moveml #0xFFFF,%sp@- | save all registers 1156 movl %usp,%a1 | including 1157 movl %a1,%sp@(FR_SP) | the users SP 1158Lsir1: 1159 clrl %sp@- | VA == none 1160 clrl %sp@- | code == none 1161 movl #T_SSIR,%sp@- | type == software interrupt 1162 jbsr _C_LABEL(trap) | go handle it 1163 lea %sp@(12),%sp | pop value args 1164 movl %sp@(FR_SP),%a0 | restore 1165 movl %a0,%usp | user SP 1166 moveml %sp@+,#0x7FFF | and all remaining registers 1167 addql #8,%sp | pop SP and stack adjust 1168 rte 1169Lnosir: 1170 movl %sp@+,%d0 | restore scratch register 1171Ldorte: 1172 rte | real return 1173 1174/* 1175 * Use common m68k sigcode. 1176 */ 1177#include <m68k/m68k/sigcode.s> 1178#ifdef COMPAT_SUNOS 1179#include <m68k/m68k/sunos_sigcode.s> 1180#endif 1181#ifdef COMPAT_SVR4 1182#include <m68k/m68k/svr4_sigcode.s> 1183#endif 1184 1185/* 1186 * Primitives 1187 */ 1188 1189/* 1190 * Use common m68k support routines. 1191 */ 1192#include <m68k/m68k/support.s> 1193 1194/* 1195 * Use common m68k process manipulation routines. 1196 */ 1197#include <m68k/m68k/proc_subr.s> 1198 1199 .data 1200GLOBAL(curpcb) 1201GLOBAL(masterpaddr) | XXX compatibility (debuggers) 1202 .long 0 1203 1204ASLOCAL(mdpflag) 1205 .byte 0 | copy of proc md_flags low byte 1206#ifdef __ELF__ 1207 .align 4 1208#else 1209 .align 2 1210#endif 1211 1212ASBSS(nullpcb,SIZEOF_PCB) 1213 1214/* 1215 * At exit of a process, do a switch for the last time. 1216 * Switch to a safe stack and PCB, and select a new process to run. The 1217 * old stack and u-area will be freed by the reaper. 1218 * 1219 * MUST BE CALLED AT SPLHIGH! 1220 */ 1221ENTRY(switch_exit) 1222 movl %sp@(4),%a0 1223 /* save state into garbage pcb */ 1224 movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) 1225 lea _ASM_LABEL(tmpstk),%sp | goto a tmp stack 1226 1227 /* Schedule the vmspace and stack to be freed. */ 1228 movl %a0,%sp@- | exit2(p) 1229 jbsr _C_LABEL(exit2) 1230 lea %sp@(4),%sp | pop args 1231 1232#if defined(LOCKDEBUG) 1233 /* Acquire sched_lock */ 1234 jbsr _C_LABEL(sched_lock_idle) 1235#endif 1236 1237 jra _C_LABEL(cpu_switch) 1238 1239/* 1240 * When no processes are on the runq, Swtch branches to Idle 1241 * to wait for something to come ready. 1242 */ 1243ASENTRY_NOPROFILE(Idle) 1244#if defined(LOCKDEBUG) 1245 /* Release sched_lock */ 1246 jbsr _C_LABEL(sched_unlock_idle) 1247#endif 1248 stop #PSL_LOWIPL 1249 movw #PSL_HIGHIPL,%sr 1250#if defined(LOCKDEBUG) 1251 /* Acquire sched_lock */ 1252 jbsr _C_LABEL(sched_lock_idle) 1253#endif 1254 movl _C_LABEL(sched_whichqs),%d0 1255 jeq _ASM_LABEL(Idle) 1256 jra Lsw1 1257 1258Lbadsw: 1259 PANIC("switch") 1260 /*NOTREACHED*/ 1261 1262/* 1263 * cpu_switch() 1264 * 1265 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1266 * entire ATC. The effort involved in selective flushing may not be 1267 * worth it, maybe we should just flush the whole thing? 1268 * 1269 * NOTE 2: With the new VM layout we now no longer know if an inactive 1270 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1271 * bit). For now, we just always flush the full ATC. 1272 */ 1273ENTRY(cpu_switch) 1274 movl _C_LABEL(curpcb),%a0 | current pcb 1275 movw %sr,%a0@(PCB_PS) | save %sr before changing ipl 1276#ifdef notyet 1277 movl _C_LABEL(curproc),%sp@- | remember last proc running 1278#endif 1279 clrl _C_LABEL(curproc) 1280 1281 /* 1282 * Find the highest-priority queue that isn't empty, 1283 * then take the first proc from that queue. 1284 */ 1285 movl _C_LABEL(sched_whichqs),%d0 1286 jeq _ASM_LABEL(Idle) 1287Lsw1: 1288 /* 1289 * Interrupts are blocked, sched_lock is held. If 1290 * we come here via Idle, %d0 contains the contents 1291 * of a non-zero sched_whichqs. 1292 */ 1293 movl %d0,%d1 1294 negl %d0 1295 andl %d1,%d0 1296 bfffo %d0{#0:#32},%d1 1297 eorib #31,%d1 1298 1299 movl %d1,%d0 1300 lslb #3,%d1 | convert queue number to index 1301 addl #_C_LABEL(sched_qs),%d1 | locate queue (q) 1302 movl %d1,%a1 1303 movl %a1@(P_FORW),%a0 | p = q->p_forw 1304 cmpal %d1,%a0 | anyone on queue? 1305 jeq Lbadsw | no, panic 1306#ifdef DIAGNOSTIC 1307 tstl %a0@(P_WCHAN) 1308 jne Lbadsw 1309 cmpb #SRUN,%a0@(P_STAT) 1310 jne Lbadsw 1311#endif 1312 movl %a0@(P_FORW),%a1@(P_FORW) | q->p_forw = p->p_forw 1313 movl %a0@(P_FORW),%a1 | n = p->p_forw 1314 movl %d1,%a1@(P_BACK) | n->p_back = q 1315 cmpal %d1,%a1 | anyone left on queue? 1316 jne Lsw2 | yes, skip 1317 movl _C_LABEL(sched_whichqs),%d1 1318 bclr %d0,%d1 | no, clear bit 1319 movl %d1,_C_LABEL(sched_whichqs) 1320Lsw2: 1321 /* p->p_cpu initialized in fork1() for single-processor */ 1322 movb #SONPROC,%a0@(P_STAT) | p->p_stat = SONPROC 1323 movl %a0,_C_LABEL(curproc) 1324 clrl _C_LABEL(want_resched) 1325#ifdef notyet 1326 movl %sp@+,%a1 1327 cmpl %a0,%a1 | switching to same proc? 1328 jeq Lswdone | yes, skip save and restore 1329#endif 1330 /* 1331 * Save state of previous process in its pcb. 1332 */ 1333 movl _C_LABEL(curpcb),%a1 1334 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1335 movl %usp,%a2 | grab USP (%a2 has been saved) 1336 movl %a2,%a1@(PCB_USP) | and save it 1337 1338 tstl _C_LABEL(fputype) | Do we have an FPU? 1339 jeq Lswnofpsave | No Then don't attempt save. 1340 lea %a1@(PCB_FPCTX),%a2 | pointer to FP save area 1341 fsave %a2@ | save FP state 1342 tstb %a2@ | null state frame? 1343 jeq Lswnofpsave | yes, all done 1344 fmovem %fp0-%fp7,%a2@(FPF_REGS) | save FP general registers 1345 fmovem %fpcr/%fpsr/%fpi,%a2@(FPF_FPCR) | save FP control registers 1346Lswnofpsave: 1347 1348 clrl %a0@(P_BACK) | clear back link 1349 movb %a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags 1350 movl %a0@(P_ADDR),%a1 | get p_addr 1351 movl %a1,_C_LABEL(curpcb) 1352 1353#if defined(LOCKDEBUG) 1354 /* 1355 * Done mucking with the run queues, release the 1356 * scheduler lock, but keep interrupts out. 1357 */ 1358 movl %a0,sp@- | not args... 1359 movl %a1,sp@- | ...just saving 1360 jbsr _C_LABEL(sched_unlock_idle) 1361 movl sp@+,%a1 1362 movl sp@+,%a0 1363#endif 1364 1365 /* 1366 * Activate process's address space. 1367 * XXX Should remember the last USTP value loaded, and call this 1368 * XXX only if it has changed. 1369 */ 1370 pea %a0@ | push proc 1371 jbsr _C_LABEL(pmap_activate) | pmap_activate(p) 1372 addql #4,%sp 1373 movl _C_LABEL(curpcb),%a1 | restore p_addr 1374 1375 lea _ASM_LABEL(tmpstk),%sp | now goto a tmp stack for NMI 1376 1377 moveml %a1@(PCB_REGS),#0xFCFC | and registers 1378 movl %a1@(PCB_USP),%a0 1379 movl %a0,%usp | and USP 1380 1381 tstl _C_LABEL(fputype) | If we don't have an FPU, 1382 jeq Lnofprest | don't try to restore it. 1383 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1384 tstb %a0@ | null state frame? 1385 jeq Lresfprest | yes, easy 1386#if defined(M68040) 1387#if defined(M68020) || defined(M68030) 1388 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1389 jne Lresnot040 | no, skip 1390#endif 1391 clrl %sp@- | yes... 1392 frestore %sp@+ | ...magic! 1393Lresnot040: 1394#endif 1395 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1396 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1397Lresfprest: 1398 frestore %a0@ | restore state 1399 1400Lnofprest: 1401 movw %a1@(PCB_PS),%sr | no, restore PS 1402 moveq #1,%d0 | return 1 (for alternate returns) 1403 rts 1404 1405/* 1406 * savectx(pcb) 1407 * Update pcb, saving current processor state. 1408 */ 1409ENTRY(savectx) 1410 movl %sp@(4),%a1 1411 movw %sr,%a1@(PCB_PS) 1412 movl %usp,%a0 | grab USP 1413 movl %a0,%a1@(PCB_USP) | and save it 1414 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1415 1416 tstl _C_LABEL(fputype) | Do we have FPU? 1417 jeq Lsvnofpsave | No? Then don't save state. 1418 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1419 fsave %a0@ | save FP state 1420 tstb %a0@ | null state frame? 1421 jeq Lsvnofpsave | yes, all done 1422 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1423 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1424Lsvnofpsave: 1425 moveq #0,%d0 | return 0 1426 rts 1427 1428#if defined(M68040) 1429ENTRY(suline) 1430 movl %sp@(4),%a0 | address to write 1431 movl _C_LABEL(curpcb),%a1 | current pcb 1432 movl #Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault 1433 movl %sp@(8),%a1 | address of line 1434 movl %a1@+,%d0 | get lword 1435 movsl %d0,%a0@+ | put lword 1436 nop | sync 1437 movl %a1@+,%d0 | get lword 1438 movsl %d0,%a0@+ | put lword 1439 nop | sync 1440 movl %a1@+,%d0 | get lword 1441 movsl %d0,%a0@+ | put lword 1442 nop | sync 1443 movl %a1@+,%d0 | get lword 1444 movsl %d0,%a0@+ | put lword 1445 nop | sync 1446 moveq #0,%d0 | indicate no fault 1447 jra Lsldone 1448Lslerr: 1449 moveq #-1,%d0 1450Lsldone: 1451 movl _C_LABEL(curpcb),%a1 | current pcb 1452 clrl %a1@(PCB_ONFAULT) | clear fault address 1453 rts 1454#endif 1455 1456/* 1457 * Invalidate entire TLB. 1458 */ 1459ENTRY(TBIA) 1460_C_LABEL(_TBIA): 1461#if defined(M68040) 1462 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1463 jne Lmotommu3 | no, skip 1464 .word 0xf518 | yes, pflusha 1465 rts 1466Lmotommu3: 1467#endif 1468#if defined(M68K_MMU_MOTOROLA) 1469 tstl _C_LABEL(mmutype) | HP MMU? 1470 jeq Lhpmmu6 | yes, skip 1471 pflusha | flush entire TLB 1472 jpl Lmc68851a | 68851 implies no d-cache 1473 movl #DC_CLEAR,%d0 1474 movc %d0,%cacr | invalidate on-chip d-cache 1475Lmc68851a: 1476 rts 1477Lhpmmu6: 1478#endif 1479#if defined(M68K_MMU_HP) 1480 MMUADDR(%a0) 1481 movl %a0@(MMUTBINVAL),%sp@- | do not ask me, this 1482 addql #4,%sp | is how hpux does it 1483#ifdef DEBUG 1484 tstl _ASM_LABEL(fullcflush) 1485 jne _C_LABEL(_DCIA) | XXX: invalidate entire cache 1486#endif 1487#endif 1488 rts 1489 1490/* 1491 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1492 */ 1493ENTRY(TBIS) 1494#ifdef DEBUG 1495 tstl _ASM_LABEL(fulltflush) | being conservative? 1496 jne _C_LABEL(_TBIA) | yes, flush entire TLB 1497#endif 1498#if defined(M68040) 1499 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1500 jne Lmotommu4 | no, skip 1501 movl %sp@(4),%a0 1502 movc %dfc,%d1 1503 moveq #1,%d0 | user space 1504 movc %d0,%dfc 1505 .word 0xf508 | pflush %a0@ 1506 moveq #5,%d0 | super space 1507 movc %d0,%dfc 1508 .word 0xf508 | pflush %a0@ 1509 movc %d1,%dfc 1510 rts 1511Lmotommu4: 1512#endif 1513#if defined(M68K_MMU_MOTOROLA) 1514 tstl _C_LABEL(mmutype) | HP MMU? 1515 jeq Lhpmmu5 | yes, skip 1516 movl %sp@(4),%a0 | get addr to flush 1517 jpl Lmc68851b | is 68851? 1518 pflush #0,#0,%a0@ | flush address from both sides 1519 movl #DC_CLEAR,%d0 1520 movc %d0,%cacr | invalidate on-chip data cache 1521 rts 1522Lmc68851b: 1523 pflushs #0,#0,%a0@ | flush address from both sides 1524 rts 1525Lhpmmu5: 1526#endif 1527#if defined(M68K_MMU_HP) 1528 movl %sp@(4),%d0 | VA to invalidate 1529 bclr #0,%d0 | ensure even 1530 movl %d0,%a0 1531 movw %sr,%d1 | go critical 1532 movw #PSL_HIGHIPL,%sr | while in purge space 1533 moveq #FC_PURGE,%d0 | change address space 1534 movc %d0,%dfc | for destination 1535 moveq #0,%d0 | zero to invalidate? 1536 movsl %d0,%a0@ | hit it 1537 moveq #FC_USERD,%d0 | back to old 1538 movc %d0,%dfc | address space 1539 movw %d1,%sr | restore IPL 1540#endif 1541 rts 1542 1543/* 1544 * Invalidate supervisor side of TLB 1545 */ 1546ENTRY(TBIAS) 1547#ifdef DEBUG 1548 tstl _ASM_LABEL(fulltflush) | being conservative? 1549 jne _C_LABEL(_TBIA) | yes, flush everything 1550#endif 1551#if defined(M68040) 1552 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1553 jne Lmotommu5 | no, skip 1554 .word 0xf518 | yes, pflusha (for now) XXX 1555 rts 1556Lmotommu5: 1557#endif 1558#if defined(M68K_MMU_MOTOROLA) 1559 tstl _C_LABEL(mmutype) | HP MMU? 1560 jeq Lhpmmu7 | yes, skip 1561 jpl Lmc68851c | 68851? 1562 pflush #4,#4 | flush supervisor TLB entries 1563 movl #DC_CLEAR,%d0 1564 movc %d0,%cacr | invalidate on-chip d-cache 1565 rts 1566Lmc68851c: 1567 pflushs #4,#4 | flush supervisor TLB entries 1568 rts 1569Lhpmmu7: 1570#endif 1571#if defined(M68K_MMU_HP) 1572 MMUADDR(%a0) 1573 movl #0x8000,%d0 | more 1574 movl %d0,%a0@(MMUTBINVAL) | HP magic 1575#ifdef DEBUG 1576 tstl _ASM_LABEL(fullcflush) 1577 jne _C_LABEL(_DCIS) | XXX: invalidate entire sup. cache 1578#endif 1579#endif 1580 rts 1581 1582/* 1583 * Invalidate user side of TLB 1584 */ 1585ENTRY(TBIAU) 1586#ifdef DEBUG 1587 tstl _ASM_LABEL(fulltflush) | being conservative? 1588 jne _C_LABEL(_TBIA) | yes, flush everything 1589#endif 1590#if defined(M68040) 1591 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1592 jne Lmotommu6 | no, skip 1593 .word 0xf518 | yes, pflusha (for now) XXX 1594 rts 1595Lmotommu6: 1596#endif 1597#if defined(M68K_MMU_MOTOROLA) 1598 tstl _C_LABEL(mmutype) | HP MMU? 1599 jeq Lhpmmu8 | yes, skip 1600 jpl Lmc68851d | 68851? 1601 pflush #0,#4 | flush user TLB entries 1602 movl #DC_CLEAR,%d0 1603 movc %d0,%cacr | invalidate on-chip d-cache 1604 rts 1605Lmc68851d: 1606 pflushs #0,#4 | flush user TLB entries 1607 rts 1608Lhpmmu8: 1609#endif 1610#if defined(M68K_MMU_HP) 1611 MMUADDR(%a0) 1612 moveq #0,%d0 | more 1613 movl %d0,%a0@(MMUTBINVAL) | HP magic 1614#ifdef DEBUG 1615 tstl _ASM_LABEL(fullcflush) 1616 jne _C_LABEL(_DCIU) | XXX: invalidate entire user cache 1617#endif 1618#endif 1619 rts 1620 1621/* 1622 * Invalidate instruction cache 1623 */ 1624ENTRY(ICIA) 1625#if defined(M68040) 1626ENTRY(ICPA) 1627 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040 1628 jne Lmotommu7 | no, skip 1629 .word 0xf498 | cinva ic 1630 rts 1631Lmotommu7: 1632#endif 1633 movl #IC_CLEAR,%d0 1634 movc %d0,%cacr | invalidate i-cache 1635 rts 1636 1637/* 1638 * Invalidate data cache. 1639 * HP external cache allows for invalidation of user/supervisor portions. 1640 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing 1641 * problems with DC_WA. The only cases we have to worry about are context 1642 * switch and TLB changes, both of which are handled "in-line" in resume 1643 * and TBI*. 1644 */ 1645ENTRY(DCIA) 1646_C_LABEL(_DCIA): 1647#if defined(M68040) 1648 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040 1649 jne Lmotommu8 | no, skip 1650 /* XXX implement */ 1651 rts 1652Lmotommu8: 1653#endif 1654#if defined(M68K_MMU_HP) 1655 tstl _C_LABEL(ectype) | got external VAC? 1656 jle Lnocache2 | no, all done 1657 MMUADDR(%a0) 1658 andl #~MMU_CEN,%a0@(MMUCMD) | disable cache in MMU control reg 1659 orl #MMU_CEN,%a0@(MMUCMD) | reenable cache in MMU control reg 1660Lnocache2: 1661#endif 1662 rts 1663 1664ENTRY(DCIS) 1665_C_LABEL(_DCIS): 1666#if defined(M68040) 1667 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040 1668 jne Lmotommu9 | no, skip 1669 /* XXX implement */ 1670 rts 1671Lmotommu9: 1672#endif 1673#if defined(M68K_MMU_HP) 1674 tstl _C_LABEL(ectype) | got external VAC? 1675 jle Lnocache3 | no, all done 1676 MMUADDR(%a0) 1677 movl %a0@(MMUSSTP),%d0 | read the supervisor STP 1678 movl %d0,%a0@(MMUSSTP) | write it back 1679Lnocache3: 1680#endif 1681 rts 1682 1683ENTRY(DCIU) 1684_C_LABEL(_DCIU): 1685#if defined(M68040) 1686 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040 1687 jne LmotommuA | no, skip 1688 /* XXX implement */ 1689 rts 1690LmotommuA: 1691#endif 1692#if defined(M68K_MMU_HP) 1693 tstl _C_LABEL(ectype) | got external VAC? 1694 jle Lnocache4 | no, all done 1695 MMUADDR(%a0) 1696 movl %a0@(MMUUSTP),%d0 | read the user STP 1697 movl %d0,%a0@(MMUUSTP) | write it back 1698Lnocache4: 1699#endif 1700 rts 1701 1702#if defined(M68040) 1703ENTRY(ICPL) 1704 movl %sp@(4),%a0 | address 1705 .word 0xf488 | cinvl ic,%a0@ 1706 rts 1707ENTRY(ICPP) 1708 movl %sp@(4),%a0 | address 1709 .word 0xf490 | cinvp ic,%a0@ 1710 rts 1711ENTRY(DCPL) 1712 movl %sp@(4),%a0 | address 1713 .word 0xf448 | cinvl dc,%a0@ 1714 rts 1715ENTRY(DCPP) 1716 movl %sp@(4),%a0 | address 1717 .word 0xf450 | cinvp dc,%a0@ 1718 rts 1719ENTRY(DCPA) 1720 .word 0xf458 | cinva dc 1721 rts 1722ENTRY(DCFL) 1723 movl %sp@(4),%a0 | address 1724 .word 0xf468 | cpushl dc,%a0@ 1725 rts 1726ENTRY(DCFP) 1727 movl %sp@(4),%a0 | address 1728 .word 0xf470 | cpushp dc,%a0@ 1729 rts 1730#endif 1731 1732ENTRY(PCIA) 1733#if defined(M68040) 1734ENTRY(DCFA) 1735 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040 1736 jne LmotommuB | no, skip 1737 .word 0xf478 | cpusha dc 1738 rts 1739LmotommuB: 1740#endif 1741#if defined(M68K_MMU_MOTOROLA) 1742 movl #DC_CLEAR,%d0 1743 movc %d0,%cacr | invalidate on-chip d-cache 1744 tstl _C_LABEL(ectype) | got external PAC? 1745 jge Lnocache6 | no, all done 1746 MMUADDR(%a0) 1747 andl #~MMU_CEN,%a0@(MMUCMD) | disable cache in MMU control reg 1748 orl #MMU_CEN,%a0@(MMUCMD) | reenable cache in MMU control reg 1749Lnocache6: 1750#endif 1751 rts 1752 1753ENTRY(ecacheon) 1754 tstl _C_LABEL(ectype) 1755 jeq Lnocache7 1756 MMUADDR(%a0) 1757 orl #MMU_CEN,%a0@(MMUCMD) 1758Lnocache7: 1759 rts 1760 1761ENTRY(ecacheoff) 1762 tstl _C_LABEL(ectype) 1763 jeq Lnocache8 1764 MMUADDR(%a0) 1765 andl #~MMU_CEN,%a0@(MMUCMD) 1766Lnocache8: 1767 rts 1768 1769ENTRY_NOPROFILE(getsfc) 1770 movc %sfc,%d0 1771 rts 1772 1773ENTRY_NOPROFILE(getdfc) 1774 movc %dfc,%d0 1775 rts 1776 1777/* 1778 * Load a new user segment table pointer. 1779 */ 1780ENTRY(loadustp) 1781#if defined(M68K_MMU_MOTOROLA) 1782 tstl _C_LABEL(mmutype) | HP MMU? 1783 jeq Lhpmmu9 | yes, skip 1784 movl %sp@(4),%d0 | new USTP 1785 moveq #PGSHIFT,%d1 1786 lsll %d1,%d0 | convert to addr 1787#if defined(M68040) 1788 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1789 jne LmotommuC | no, skip 1790 .word 0xf518 | yes, pflusha 1791 .long 0x4e7b0806 | movc %d0,%urp 1792 rts 1793LmotommuC: 1794#endif 1795 pflusha | flush entire TLB 1796 lea _C_LABEL(protorp),%a0 | CRP prototype 1797 movl %d0,%a0@(4) | stash USTP 1798 pmove %a0@,%crp | load root pointer 1799 movl #CACHE_CLR,%d0 1800 movc %d0,%cacr | invalidate cache(s) 1801 rts 1802Lhpmmu9: 1803#endif 1804#if defined(M68K_MMU_HP) 1805 movl #CACHE_CLR,%d0 1806 movc %d0,%cacr | invalidate cache(s) 1807 MMUADDR(%a0) 1808 movl %a0@(MMUTBINVAL),%d1 | invalidate TLB 1809 tstl _C_LABEL(ectype) | have external VAC? 1810 jle 1f | no, skip 1811 andl #~MMU_CEN,%a0@(MMUCMD) | toggle cache enable 1812 orl #MMU_CEN,%a0@(MMUCMD) | to clear data cache 18131: 1814 movl %sp@(4),%a0@(MMUUSTP) | load a new USTP 1815#endif 1816 rts 1817 1818ENTRY(ploadw) 1819#if defined(M68K_MMU_MOTOROLA) 1820 movl %sp@(4),%a0 | address to load 1821#if defined(M68K_MMU_HP) 1822 tstl _C_LABEL(mmutype) | HP MMU? 1823 jeq Lploadwskp | yes, skip 1824#endif 1825#if defined(M68040) 1826 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1827 jeq Lploadwskp | yes, skip 1828#endif 1829 ploadw #1,%a0@ | pre-load translation 1830Lploadwskp: 1831#endif 1832 rts 1833 1834/* 1835 * Set processor priority level calls. Most are implemented with 1836 * inline asm expansions. However, spl0 requires special handling 1837 * as we need to check for our emulated software interrupts. 1838 */ 1839 1840ENTRY(spl0) 1841 moveq #0,%d0 1842 movw %sr,%d0 | get old SR for return 1843 movw #PSL_LOWIPL,%sr | restore new SR 1844 tstb _C_LABEL(ssir) | software interrupt pending? 1845 jeq Lspldone | no, all done 1846 subql #4,%sp | make room for RTE frame 1847 movl %sp@(4),%sp@(2) | position return address 1848 clrw %sp@(6) | set frame type 0 1849 movw #PSL_LOWIPL,%sp@ | and new SR 1850 jra Lgotsir | go handle it 1851Lspldone: 1852 rts 1853 1854/* 1855 * _delay(u_int N) 1856 * 1857 * Delay for at least (N/256) microsecends. 1858 * This routine depends on the variable: delay_divisor 1859 * which should be set based on the CPU clock rate. 1860 */ 1861ENTRY_NOPROFILE(_delay) 1862 | %d0 = arg = (usecs << 8) 1863 movl %sp@(4),%d0 1864 | %d1 = delay_divisor 1865 movl _C_LABEL(delay_divisor),%d1 1866 jra L_delay /* Jump into the loop! */ 1867 1868 /* 1869 * Align the branch target of the loop to a half-line (8-byte) 1870 * boundary to minimize cache effects. This guarantees both 1871 * that there will be no prefetch stalls due to cache line burst 1872 * operations and that the loop will run from a single cache 1873 * half-line. 1874 */ 1875#ifdef __ELF__ 1876 .align 8 1877#else 1878 .align 3 1879#endif 1880L_delay: 1881 subl %d1,%d0 1882 jgt L_delay 1883 rts 1884 1885/* 1886 * Save and restore 68881 state. 1887 */ 1888ENTRY(m68881_save) 1889 movl %sp@(4),%a0 | save area pointer 1890 fsave %a0@ | save state 1891 tstb %a0@ | null state frame? 1892 jeq Lm68881sdone | yes, all done 1893 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1894 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1895Lm68881sdone: 1896 rts 1897 1898ENTRY(m68881_restore) 1899 movl %sp@(4),%a0 | save area pointer 1900 tstb %a0@ | null state frame? 1901 jeq Lm68881rdone | yes, easy 1902 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1903 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1904Lm68881rdone: 1905 frestore %a0@ | restore state 1906 rts 1907 1908/* 1909 * Handle the nitty-gritty of rebooting the machine. 1910 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 1911 * Note that we must be running in an address range that is mapped one-to-one 1912 * logical to physical so that the PC is still valid immediately after the MMU 1913 * is turned off. We have conveniently mapped the last page of physical 1914 * memory this way. 1915 */ 1916ENTRY_NOPROFILE(doboot) 1917#if defined(M68040) 1918 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1919 jeq Lnocache5 | yes, skip 1920#endif 1921 movl #CACHE_OFF,%d0 1922 movc %d0,%cacr | disable on-chip cache(s) 1923 tstl _C_LABEL(ectype) | external cache? 1924 jeq Lnocache5 | no, skip 1925 MMUADDR(%a0) 1926 andl #~MMU_CEN,%a0@(MMUCMD) | disable external cache 1927Lnocache5: 1928 lea MAXADDR,%a0 | last page of physical memory 1929 movl _C_LABEL(boothowto),%a0@+ | store howto 1930 movl _C_LABEL(bootdev),%a0@+ | and devtype 1931 lea Lbootcode,%a1 | start of boot code 1932 lea Lebootcode,%a3 | end of boot code 1933Lbootcopy: 1934 movw %a1@+,%a0@+ | copy a word 1935 cmpl %a3,%a1 | done yet? 1936 jcs Lbootcopy | no, keep going 1937#if defined(M68040) 1938 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1939 jne LmotommuE | no, skip 1940 .word 0xf4f8 | cpusha bc 1941LmotommuE: 1942#endif 1943 jmp MAXADDR+8 | jump to last page 1944 1945Lbootcode: 1946 lea MAXADDR+0x800,%sp | physical SP in case of NMI 1947#if defined(M68040) 1948 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1949 jne LmotommuF | no, skip 1950 movl #0,%d0 1951 movc %d0,%cacr | caches off 1952 .long 0x4e7b0003 | movc %d0,%tc 1953 movl %d2,MAXADDR+NBPG-4 | restore old high page contents 1954 DOREBOOT 1955LmotommuF: 1956#endif 1957#if defined(M68K_MMU_MOTOROLA) 1958 tstl _C_LABEL(mmutype) | HP MMU? 1959 jeq LhpmmuB | yes, skip 1960 movl #0,%a0@ | value for pmove to TC (turn off MMU) 1961 pmove %a0@,%tc | disable MMU 1962 DOREBOOT 1963LhpmmuB: 1964#endif 1965#if defined(M68K_MMU_HP) 1966 MMUADDR(%a0) 1967 movl #0xFFFF0000,%a0@(MMUCMD) | totally disable MMU 1968 movl %d2,MAXADDR+NBPG-4 | restore old high page contents 1969 DOREBOOT 1970#endif 1971Lebootcode: 1972 1973/* 1974 * Misc. global variables. 1975 */ 1976 .data 1977GLOBAL(machineid) 1978 .long HP_320 | default to 320 1979 1980GLOBAL(mmuid) 1981 .long 0 | default to nothing 1982 1983GLOBAL(mmutype) 1984 .long MMU_HP | default to HP MMU 1985 1986GLOBAL(cputype) 1987 .long CPU_68020 | default to 68020 CPU 1988 1989GLOBAL(ectype) 1990 .long EC_NONE | external cache type, default to none 1991 1992GLOBAL(fputype) 1993 .long FPU_68882 | default to 68882 FPU 1994 1995GLOBAL(protorp) 1996 .long 0,0 | prototype root pointer 1997 1998GLOBAL(prototc) 1999 .long 0 | prototype translation control 2000 2001GLOBAL(internalhpib) 2002 .long 1 | has internal HP-IB, default to yes 2003 2004GLOBAL(want_resched) 2005 .long 0 2006 2007GLOBAL(proc0paddr) 2008 .long 0 | KVA of proc0 u-area 2009 2010GLOBAL(intiobase) 2011 .long 0 | KVA of base of internal IO space 2012 2013GLOBAL(intiolimit) 2014 .long 0 | KVA of end of internal IO space 2015 2016GLOBAL(extiobase) 2017 .long 0 | KVA of base of external IO space 2018 2019GLOBAL(CLKbase) 2020 .long 0 | KVA of base of clock registers 2021 2022GLOBAL(MMUbase) 2023 .long 0 | KVA of base of HP MMU registers 2024 2025#ifdef USELEDS 2026ASLOCAL(heartbeat) 2027 .long 0 | clock ticks since last heartbeat 2028 2029ASLOCAL(beatstatus) 2030 .long 0 | for determining a fast or slow throb 2031#endif 2032 2033#ifdef DEBUG 2034ASGLOBAL(fulltflush) 2035 .long 0 2036 2037ASGLOBAL(fullcflush) 2038 .long 0 2039#endif 2040 2041/* 2042 * Interrupt Counters 2043 * 2044 * We now use the evcnt(9) subsystem, but these are provided to keep 2045 * vmstat(8) happy. 2046 */ 2047 2048GLOBAL(intrnames) 2049GLOBAL(eintrnames) 2050GLOBAL(intrcnt) 2051GLOBAL(eintrcnt) 2052 .long 0 2053