1/* $NetBSD: locore.s,v 1.25 2002/05/14 02:03:02 matt Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1980, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: locore.s 1.66 92/12/22$ 41 * 42 * @(#)locore.s 8.6 (Berkeley) 5/27/94 43 */ 44 45/* 46 * locore.s for news68k - based on mvme68k and hp300 version 47 */ 48 49#include "opt_compat_netbsd.h" 50#include "opt_compat_svr4.h" 51#include "opt_compat_sunos.h" 52#include "opt_fpsp.h" 53#include "opt_ddb.h" 54#include "opt_kgdb.h" 55#include "opt_lockdebug.h" 56 57#include "assym.h" 58#include <machine/asm.h> 59#include <machine/trap.h> 60 61 62/* 63 * Temporary stack for a variety of purposes. 64 * Try and make this the first thing is the data segment so it 65 * is page aligned. Note that if we overflow here, we run into 66 * our text segment. 67 */ 68 .data 69 .space NBPG 70ASLOCAL(tmpstk) 71 72ASLOCAL(monitor_vbr) 73 .long 0 74 75ASLOCAL(monitor) 76 .long 0 77 78#include <news68k/news68k/vectors.s> 79 80 81/* 82 * Macro to relocate a symbol, used before MMU is enabled. 83 */ 84#define _RELOC(var, ar) \ 85 lea var,ar; \ 86 addl %a5,ar 87 88#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) 89#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) 90 91/* 92 * LED control for DEBUG. 93 */ 94#define SETLED(func) \ 95 movl #func,%d0; \ 96 jmp debug_led 97 98#define SETLED2(func) \ 99 movl #func,%d0; \ 100 jmp debug_led2 101 102#define TOMONITOR \ 103 moveal _ASM_LABEL(monitor), %a0; \ 104 jmp %a0@ 105/* 106 * Initialization 107 * 108 * The bootstrap loader loads us in starting at 0, and VBR is non-zero. 109 * On entry, args on stack are boot device, boot filename, console unit, 110 * boot flags (howto), boot device name, filesystem type name. 111 */ 112BSS(lowram,4) 113BSS(esym,4) 114 115/* 116 * This is for kvm_mkdb, and should be the address of the beginning 117 * of the kernel text segment (not necessarily the same as kernbase). 118 */ 119 .text 120GLOBAL(kernel_text) 121 122/* 123 * start of kernel and .text! 124 */ 125ASENTRY_NOPROFILE(start) 126 movw #PSL_HIGHIPL,%sr | no interrupts 127 128 movl #0x0, %a5 | RAM starts at 0 (%a5) 129 movl #0x0, %a6 | clear %fp to terminate debug trace 130 131 RELOC(bootdev,%a0) 132 movl %d6, %a0@ | save bootdev 133 RELOC(boothowto,%a0) 134 movl %d7, %a0@ | save boothowto 135 136 ASRELOC(tmpstk,%a0) 137 movl %a0,%sp | give ourselves a temporary stack 138 139 movc %vbr,%a0 140 movl %a0@(188),_ASM_LABEL(monitor)| save trap #15 to return PROM monitor 141 142 RELOC(esym, %a0) 143#ifdef DDB 144 movl %d2,%a0@ | store end of symbol table 145#else 146 clrl %a0@ 147#endif 148 /* %d2 now free */ 149 RELOC(lowram, %a0) 150 movl %a5,%a0 | store start of physical memory 151 movl #CACHE_OFF,%d0 152 movc %d0,%cacr | clear and disable on-chip cache(s) 153 154 movl #DC_FREEZE,%d0 | data freeze bit 155 movc %d0,%cacr | only exists on 68030 156 movc %cacr,%d0 | read it back 157 tstl %d0 | zero? 158 jeq Lnot68030 | yes, we have 68020/68040 159 160 movl #CACHE_OFF,%d0 161 movc %d0,%cacr | clear data freeze bit 162 163 RELOC(mmutype,%a0) 164 movl #MMU_68030,%a0@ 165 RELOC(cputype,%a0) 166 movl #CPU_68030,%a0@ 167 RELOC(fputype,%a0) 168 movl #FPU_68882,%a0@ 169 170 movl %d6,%d0 | check bootdev 171 andl #0x00007000,%d0 | BOOTDEV_HOST 172 cmpl #0x00007000,%d0 | news1200? 173 jne Lnot1200 | no, then skip 174 175 /* news1200 */ 176 /* XXX Are these needed?*/ 177 sf 0xe1100000 | AST disable (???) 178 sf 0xe10c0000 | level2 interrupt disable (???) 179 moveb #0x03,0xe1140002 | timer set (???) 180 moveb #0xd0,0xe1140003 | timer set (???) 181 sf 0xe1140000 | timer interrupt disable (???) 182 /* XXX */ 183 184 RELOC(systype,%a0) 185 movl #NEWS1200,%a0@ 186 RELOC(ectype, %a0) | 187 movl #EC_NONE,%a0@ | news1200 have no L2 cache 188 189 /* 190 * Fix up the physical addresses of the news1200's onboard 191 * I/O registers. 192 */ 193 RELOC(intiobase_phys, %a0); 194 movl #INTIOBASE1200,%a0@ 195 RELOC(intiotop_phys, %a0); 196 movl #INTIOTOP1200,%a0@ 197 198 RELOC(extiobase_phys, %a0); 199 movl #EXTIOBASE1200,%a0@ 200 RELOC(extiotop_phys, %a0); 201 movl #EXTIOTOP1200,%a0@ 202 203 RELOC(ctrl_power, %a0); 204 movl #0xe1000000,%a0@ | CTRL_POWER port for news1200 205 jra Lcom030 206 207Lnot1200: 208 tstl %d0 | news1400/1500/1600/1700? 209 jne Lnotyet | no, then skip 210 211 /* news1400/1500/1600/1700 */ 212 /* XXX Are these needed?*/ 213 sf 0xe1280000 | AST disable (???) 214 sf 0xe1180000 | level2 interrupt disable (???) 215 st 0xe1300000 | L2 cache enable (???) 216 st 0xe1900000 | L2 cache clear (???) 217 sf 0xe1000000 | timer interrupt disable (???) 218 moveb #0x36,0xe0c80000 | XXX reset FDC for PWS-1560 219 /* XXX */ 220 221 /* news1400/1500/1600/1700 - 68030 CPU/MMU, 68882 FPU */ 222 RELOC(systype,%a0) 223 movl #NEWS1700,%a0@ 224 225 cmpb #0xf2,0xe1c00000 | read model id from idrom 226 jle 1f | news1600/1700 ? 227 228 RELOC(ectype, %a0) | no, we are news1400/1500 229 movl #EC_NONE,%a0 | and do not have L2 cache 230 jra 2f 2311: 232 RELOC(ectype, %a0) | yes, we are news1600/1700 233 movl #EC_PHYS,%a0@ | and have a physical address cache 2342: 235 /* 236 * Fix up the physical addresses of the news1700's onboard 237 * I/O registers. 238 */ 239 RELOC(intiobase_phys, %a0); 240 movl #INTIOBASE1700,%a0@ 241 RELOC(intiotop_phys, %a0); 242 movl #INTIOTOP1700,%a0@ 243 244 RELOC(extiobase_phys, %a0); 245 movl #EXTIOBASE1700,%a0@ 246 RELOC(extiotop_phys, %a0); 247 movl #EXTIOTOP1700,%a0@ 248 249 RELOC(ctrl_power, %a0); 250 movl #0xe1380000,%a0@ | CTRL_POWER port for news1700 251Lcom030: 252 253 RELOC(vectab,%a0) 254 RELOC(busaddrerr2030,%a1) 255 movl %a1,%a0@(8) 256 movl %a1,%a0@(12) 257 258 movl %d4,%d1 259 addl %a5,%d1 260 moveq #PGSHIFT,%d2 261 lsrl %d2,%d1 | convert to page (click) number 262 RELOC(maxmem, %a0) 263 movl %d1,%a0@ | save as maxmem 264 265 movl %d4,%d1 | 266 moveq #PGSHIFT,%d2 267 lsrl %d2,%d1 | convert to page (click) number 268 RELOC(physmem, %a0) 269 movl %d1,%a0@ | save as physmem 270 271 jra Lstart1 272Lnot68030: 273 274#ifdef news700 /* XXX eventually... */ 275 RELOC(mmutype,%a0) 276 movl #MMU_68851,%a0@ 277 RELOC(cputype,%a0) 278 movl #CPU_68020,%a0@ 279 RELOC(fputype,%a0) 280 movl #FPU_68881,%a0@ 281 RELOC(ectype, %a0) 282 movl #EC_NONE,%a0@ 283#if 1 /* XXX */ 284 jra Lnotyet 285#else 286 /* XXX more XXX */ 287 jra Lstart1 288#endif 289Lnot700: 290#endif 291 292 /* 293 * If we fall to here, the board is not supported. 294 * Just drop out to the monitor. 295 */ 296 297 TOMONITOR 298 /* NOTREACHED */ 299 300Lnotyet: 301 /* 302 * If we get here, it means a particular model 303 * doesn't have the necessary support code in the 304 * kernel. Just drop out to the monitor. 305 */ 306 TOMONITOR 307 /* NOTREACHED */ 308 309Lstart1: 310/* initialize source/destination control registers for movs */ 311 moveq #FC_USERD,%d0 | user space 312 movc %d0,%sfc | as source 313 movc %d0,%dfc | and destination of transfers 314/* 315 * configure kernel and proc0 VA space so we can get going 316 */ 317 .globl _Sysseg, _pmap_bootstrap, _avail_start 318 319#ifdef DDB 320 RELOC(esym,%a0) | end of static kernel test/data/syms 321 movl %a0@,%d2 322 jne Lstart2 323#endif 324 RELOC(end,%a0) 325 movl %a0,%d2 | end of static kernel text/data 326Lstart2: 327 addl #NBPG-1,%d2 328 andl #PG_FRAME,%d2 | round to a page 329 movl %d2,%a4 330 addl %a5,%a4 | convert to PA 331#if 0 332 movl #0x0, %sp@- | firstpa 333#else 334 pea %a5@ 335#endif 336 pea %a4@ | nextpa 337 RELOC(pmap_bootstrap,%a0) 338 jbsr %a0@ | pmap_bootstrap(firstpa, nextpa) 339 addql #8,%sp 340/* 341 * Enable the MMU. 342 * Since the kernel is mapped logical == physical, we just turn it on. 343 */ 344 movc %vbr,%d0 | Preserve monitor's VBR address 345 movl %d0,_ASM_LABEL(monitor_vbr) 346 347 movl #_C_LABEL(vectab),%d0 | get our VBR address 348 movc %d0,%vbr 349 350 RELOC(Sysseg, %a0) | system segment table addr 351 movl %a0@,%d1 | read value (a KVA) 352 addl %a5,%d1 | convert to PA 353 RELOC(mmutype, %a0) 354 cmpl #MMU_68040,%a0@ | 68040? 355 jne Lmotommu1 | no, skip 356 .long 0x4e7b1807 | movc %d1,%srp 357 jra Lstploaddone 358Lmotommu1: 359 RELOC(protorp, %a0) 360 movl #0x80000202,%a0@ | nolimit + share global + 4 byte PTEs 361 movl %d1,%a0@(4) | + segtable address 362 pmove %a0@,%srp | load the supervisor root pointer 363 movl #0x80000002,%a0@ | reinit upper half for CRP loads 364Lstploaddone: 365 RELOC(mmutype, %a0) 366 cmpl #MMU_68040,%a0@ | 68040? 367 jne Lmotommu2 | no, skip 368 moveq #0,%d0 | ensure TT regs are disabled 369 .long 0x4e7b0004 | movc %d0,%itt0 370 .long 0x4e7b0005 | movc %d0,%itt1 371 .long 0x4e7b0006 | movc %d0,%dtt0 372 .long 0x4e7b0007 | movc %d0,%dtt1 373 .word 0xf4d8 | cinva bc 374 .word 0xf518 | pflusha 375 movl #0x8000,%d0 376 .long 0x4e7b0003 | movc %d0,%tc 377 movl #CACHE40_ON,%d0 378 movc %d0,%cacr | turn on both caches 379 jmp Lenab1 380Lmotommu2: 381#if 1 /* XXX use %tt0 register to map I/O space temporary */ 382 RELOC(protott0, %a0) 383 movl #0xe01f8550,%a0@ | use %tt0 (0xe0000000-0xffffffff) 384 .long 0xf0100800 | pmove %a0@,%tt0 385#endif 386 RELOC(prototc, %a2) 387 movl #0x82c0aa00,%a2@ | value to load TC with 388 pmove %a2@,%tc | load it 389 390/* 391 * Should be running mapped from this point on 392 */ 393Lenab1: 394/* select the software page size now */ 395 lea _ASM_LABEL(tmpstk),%sp | temporary stack 396 jbsr _C_LABEL(uvm_setpagesize) | select software page size 397/* set kernel stack, user SP, and initial pcb */ 398 movl _C_LABEL(proc0paddr),%a1| get proc0 pcb addr 399 lea %a1@(USPACE-4),%sp | set kernel stack to end of area 400 lea _C_LABEL(proc0),%a2 | initialize proc0.p_addr so that 401 movl %a1,%a2@(P_ADDR) | we don't deref NULL in trap() 402 movl #USRSTACK-4,%a2 403 movl %a2,%usp | init user SP 404 movl %a1,_C_LABEL(curpcb) | proc0 is running 405 406 tstl _C_LABEL(fputype) | Have an FPU? 407 jeq Lenab2 | No, skip. 408 clrl %a1@(PCB_FPCTX) | ensure null FP context 409 movl %a1,%sp@- 410 jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) 411 addql #4,%sp 412Lenab2: 413 jbsr _C_LABEL(TBIA) | invalidate TLB 414 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 415 jeq Ltbia040 | yes, cache already on 416 pflusha 417 tstl _C_LABEL(mmutype) 418 jpl Lenab3 | 68851 implies no d-cache 419 movl #CACHE_ON,%d0 420 tstl _C_LABEL(ectype) | have external cache? 421 jne 1f | Yes, skip 422 orl #CACHE_BE,%d0 | set cache burst enable 4231: 424 movc %d0,%cacr | clear cache 425 tstl _C_LABEL(ectype) | have external cache? 426 jeq Lenab3 | No, skip 427 movl _C_LABEL(cache_clr),%a0 428 st %a0@ | flush external cache 429 jra Lenab3 430Ltbia040: 431 .word 0xf518 432Lenab3: 433/* final setup for C code */ 434 jbsr _C_LABEL(news68k_init) | additional pre-main initialization 435 436/* 437 * Create a fake exception frame so that cpu_fork() can copy it. 438 * main() nevers returns; we exit to user mode from a forked process 439 * later on. 440 */ 441 clrw %sp@- | vector offset/frame type 442 clrl %sp@- | PC - filled in by "execve" 443 movw #PSL_USER,%sp@- | in user mode 444 clrl %sp@- | stack adjust count and padding 445 lea %sp@(-64),%sp | construct space for D0-D7/A0-A7 446 lea _C_LABEL(proc0),%a0 | save pointer to frame 447 movl %sp,%a0@(P_MD_REGS) | in proc0.p_md.md_regs 448 449 jra _C_LABEL(main) | main() 450 451 SETLED2(3); | main returned? 452 453/* 454 * proc_trampoline: call function in register a2 with a3 as an arg 455 * and then rei. 456 */ 457GLOBAL(proc_trampoline) 458 movl %a3,%sp@- | push function arg 459 jbsr %a2@ | call function 460 addql #4,%sp | pop arg 461 movl %sp@(FR_SP),%a0 | grab and load 462 movl %a0,%usp | user SP 463 moveml %sp@+,#0x7FFF | restore most user regs 464 addql #8,%sp | toss SP and stack adjust 465 jra _ASM_LABEL(rei) | and return 466 467/* 468 * Trap/interrupt vector routines 469 */ 470#include <m68k/m68k/trap_subr.s> 471 472 .data 473GLOBAL(m68k_fault_addr) 474 .long 0 475 476#if defined(M68020) || defined(M68030) 477ENTRY_NOPROFILE(busaddrerr2030) 478 clrl %sp@- | stack adjust count 479 moveml #0xFFFF,%sp@- | save user registers 480 movl %usp,%a0 | save the user SP 481 movl %a0,%sp@(FR_SP) | in the savearea 482 moveq #0,%d0 483 movw %sp@(FR_HW+10),%d0 | grab SSW for fault processing 484 btst #12,%d0 | RB set? 485 jeq LbeX0 | no, test RC 486 bset #14,%d0 | yes, must set FB 487 movw %d0,%sp@(FR_HW+10) | for hardware too 488LbeX0: 489 btst #13,%d0 | RC set? 490 jeq LbeX1 | no, skip 491 bset #15,%d0 | yes, must set FC 492 movw %d0,%sp@(FR_HW+10) | for hardware too 493LbeX1: 494 btst #8,%d0 | data fault? 495 jeq Lbe0 | no, check for hard cases 496 movl %sp@(FR_HW+16),%d1 | fault address is as given in frame 497 jra Lbe10 | thats it 498Lbe0: 499 btst #4,%sp@(FR_HW+6) | long (type B) stack frame? 500 jne Lbe4 | yes, go handle 501 movl %sp@(FR_HW+2),%d1 | no, can use save PC 502 btst #14,%d0 | FB set? 503 jeq Lbe3 | no, try FC 504 addql #4,%d1 | yes, adjust address 505 jra Lbe10 | done 506Lbe3: 507 btst #15,%d0 | FC set? 508 jeq Lbe10 | no, done 509 addql #2,%d1 | yes, adjust address 510 jra Lbe10 | done 511Lbe4: 512 movl %sp@(FR_HW+36),%d1 | long format, use stage B address 513 btst #15,%d0 | FC set? 514 jeq Lbe10 | no, all done 515 subql #2,%d1 | yes, adjust address 516Lbe10: 517 movl %d1,%sp@- | push fault VA 518 movl %d0,%sp@- | and padded SSW 519 movw %sp@(FR_HW+8+6),%d0 | get frame format/vector offset 520 andw #0x0FFF,%d0 | clear out frame format 521 cmpw #12,%d0 | address error vector? 522 jeq Lisaerr | yes, go to it 523 movl %d1,%a0 | fault address 524 movl %sp@,%d0 | function code from ssw 525 btst #8,%d0 | data fault? 526 jne Lbe10a 527#if 0 528 movql #1,%d0 | user program access FC 529#else 530 moveq #1,%d0 | user program access FC 531#endif 532 | (we dont separate data/program) 533 btst #5,%sp@(FR_HW+8) | supervisor mode? 534 jeq Lbe10a | if no, done 535 movql #5,%d0 | else supervisor program access 536Lbe10a: 537 ptestr %d0,%a0@,#7 | do a table search 538 pmove %psr,%sp@ | save result 539 movb %sp@,%d1 540 btst #2,%d1 | invalid (incl. limit viol. and berr)? 541 jeq Lmightnotbemerr | no -> wp check 542 btst #7,%d1 | is it MMU table berr? 543 jne Lisberr1 | yes, needs not be fast. 544Lismerr: 545 movl #T_MMUFLT,%sp@- | show that we are an MMU fault 546 jra _ASM_LABEL(faultstkadj) | and deal with it 547Lmightnotbemerr: 548 btst #3,%d1 | write protect bit set? 549 jeq Lisberr1 | no: must be bus error 550 movl %sp@,%d0 | ssw into low word of %d0 551 andw #0xc0,%d0 | Write protect is set on page: 552 cmpw #0x40,%d0 | was it read cycle? 553 jne Lismerr | no, was not WPE, must be MMU fault 554 jra Lisberr1 | real bus err needs not be fast. 555Lisaerr: 556 movl #T_ADDRERR,%sp@- | mark address error 557 jra _ASM_LABEL(faultstkadj) | and deal with it 558Lisberr1: 559 clrw %sp@ | re-clear pad word 560 tstl _C_LABEL(nofault) | catch bus error? 561 jeq Lisberr | no, handle as usual 562 movl %sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr 563 movl _C_LABEL(nofault),%sp@- | yes, 564 jbsr _C_LABEL(longjmp) | longjmp(nofault) 565 /* NOTREACHED */ 566#endif /* M68020 || M68030 */ 567 568Lisberr: | also used by M68040/60 569 movl #T_BUSERR,%sp@- | mark bus error 570 jra _ASM_LABEL(faultstkadj) | and deal with it 571 572/* 573 * FP exceptions. 574 */ 575ENTRY_NOPROFILE(fpfline) 576#ifdef FPU_EMULATE 577 clrl %sp@- | stack adjust count 578 moveml #0xFFFF,%sp@- | save registers 579 moveq #T_FPEMULI,%d0 | denote as FP emulation trap 580 jra _ASM_LABEL(fault) | do it 581#else 582 jra _C_LABEL(illinst) 583#endif 584 585ENTRY_NOPROFILE(fpunsupp) 586#ifdef FPU_EMULATE 587 clrl %sp@- | stack adjust count 588 moveml #0xFFFF,%sp@- | save registers 589 moveq #T_FPEMULD,%d0 | denote as FP emulation trap 590 jra _ASM_LABEL(fault) | do it 591#else 592 jra _C_LABEL(illinst) 593#endif 594 595/* 596 * Handles all other FP coprocessor exceptions. 597 * Note that since some FP exceptions generate mid-instruction frames 598 * and may cause signal delivery, we need to test for stack adjustment 599 * after the trap call. 600 */ 601ENTRY_NOPROFILE(fpfault) 602 clrl %sp@- | stack adjust count 603 moveml #0xFFFF,%sp@- | save user registers 604 movl %usp,%a0 | and save 605 movl %a0,%sp@(FR_SP) | the user stack pointer 606 clrl %sp@- | no VA arg 607 movl _C_LABEL(curpcb),%a0 | current pcb 608 lea %a0@(PCB_FPCTX),%a0 | address of FP savearea 609 fsave %a0@ | save state 610 tstb %a0@ | null state frame? 611 jeq Lfptnull | yes, safe 612 clrw %d0 | no, need to tweak BIU 613 movb %a0@(1),%d0 | get frame size 614 bset #3,%a0@(0,%d0:w)| set exc_pend bit of BIU 615Lfptnull: 616 fmovem %fpsr,%sp@- | push fpsr as code argument 617 frestore %a0@ | restore state 618 movl #T_FPERR,%sp@- | push type arg 619 jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup 620 621 622/* 623 * Other exceptions only cause four and six word stack frame and require 624 * no post-trap stack adjustment. 625 */ 626 627ENTRY_NOPROFILE(badtrap) 628 moveml #0xC0C0,%sp@- | save scratch regs 629 movw %sp@(22),%sp@- | push exception vector info 630 clrw %sp@- 631 movl %sp@(22),%sp@- | and PC 632 jbsr _C_LABEL(straytrap) | report 633 addql #8,%sp | pop args 634 moveml %sp@+,#0x0303 | restore regs 635 jra _ASM_LABEL(rei) | all done 636 637ENTRY_NOPROFILE(trap0) 638 clrl %sp@- | stack adjust count 639 moveml #0xFFFF,%sp@- | save user registers 640 movl %usp,%a0 | save the user SP 641 movl %a0,%sp@(FR_SP) | in the savearea 642 movl %d0,%sp@- | push syscall number 643 jbsr _C_LABEL(syscall) | handle it 644 addql #4,%sp | pop syscall arg 645 tstl _C_LABEL(astpending) 646 jne Lrei2 647 movl %sp@(FR_SP),%a0 | grab and restore 648 movl %a0,%usp | user SP 649 moveml %sp@+,#0x7FFF | restore most registers 650 addql #8,%sp | pop SP and stack adjust 651 rte 652 653/* 654 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 655 * cachectl(command, addr, length) 656 * command in %d0, addr in %a1, length in %d1 657 */ 658ENTRY_NOPROFILE(trap12) 659 movl _C_LABEL(curproc),%sp@- | push curproc pointer 660 movl %d1,%sp@- | push length 661 movl %a1,%sp@- | push addr 662 movl %d0,%sp@- | push command 663 jbsr _C_LABEL(cachectl1) | do it 664 lea %sp@(16),%sp | pop args 665 jra _ASM_LABEL(rei) | all done 666 667/* 668 * Trace (single-step) trap. Kernel-mode is special. 669 * User mode traps are simply passed on to trap(). 670 */ 671ENTRY_NOPROFILE(trace) 672 clrl %sp@- | stack adjust count 673 moveml #0xFFFF,%sp@- 674 moveq #T_TRACE,%d0 675 676 | Check PSW and see what happen. 677 | T=0 S=0 (should not happen) 678 | T=1 S=0 trace trap from user mode 679 | T=0 S=1 trace trap on a trap instruction 680 | T=1 S=1 trace trap from system mode (kernel breakpoint) 681 682 movw %sp@(FR_HW),%d1 | get PSW 683 notw %d1 | XXX no support for T0 on 680[234]0 684 andw #PSL_TS,%d1 | from system mode (T=1, S=1)? 685 jeq Lkbrkpt | yes, kernel breakpoint 686 jra _ASM_LABEL(fault) | no, user-mode fault 687 688/* 689 * Trap 15 is used for: 690 * - GDB breakpoints (in user programs) 691 * - KGDB breakpoints (in the kernel) 692 * - trace traps for SUN binaries (not fully supported yet) 693 * User mode traps are simply passed to trap(). 694 */ 695ENTRY_NOPROFILE(trap15) 696 clrl %sp@- | stack adjust count 697 moveml #0xFFFF,%sp@- 698 moveq #T_TRAP15,%d0 699 movw %sp@(FR_HW),%d1 | get PSW 700 andw #PSL_S,%d1 | from system mode? 701 jne Lkbrkpt | yes, kernel breakpoint 702 jra _ASM_LABEL(fault) | no, user-mode fault 703 704Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type) 705 | Save the system sp rather than the user sp. 706 movw #PSL_HIGHIPL,%sr | lock out interrupts 707 lea %sp@(FR_SIZE),%a6 | Save stack pointer 708 movl %a6,%sp@(FR_SP) | from before trap 709 710 | If were are not on tmpstk switch to it. 711 | (so debugger can change the stack pointer) 712 movl %a6,%d1 713 cmpl #_ASM_LABEL(tmpstk),%d1 714 jls Lbrkpt2 | already on tmpstk 715 | Copy frame to the temporary stack 716 movl %sp,%a0 | a0=src 717 lea _ASM_LABEL(tmpstk)-96,%a1 | a1=dst 718 movl %a1,%sp | sp=new frame 719 movql #FR_SIZE,%d1 720Lbrkpt1: 721 movl %a0@+,%a1@+ 722 subql #4,%d1 723 bgt Lbrkpt1 724 725Lbrkpt2: 726 | Call the trap handler for the kernel debugger. 727 | Do not call trap() to do it, so that we can 728 | set breakpoints in trap() if we want. We know 729 | the trap type is either T_TRACE or T_BREAKPOINT. 730 | If we have both DDB and KGDB, let KGDB see it first, 731 | because KGDB will just return 0 if not connected. 732 | Save args in %d2, %a2 733 movl %d0,%d2 | trap type 734 movl %sp,%a2 | frame ptr 735#ifdef KGDB 736 | Let KGDB handle it (if connected) 737 movl %a2,%sp@- | push frame ptr 738 movl %d2,%sp@- | push trap type 739 jbsr _C_LABEL(kgdb_trap) | handle the trap 740 addql #8,%sp | pop args 741 cmpl #0,%d0 | did kgdb handle it? 742 jne Lbrkpt3 | yes, done 743#endif 744#ifdef DDB 745 | Let DDB handle it 746 movl %a2,%sp@- | push frame ptr 747 movl %d2,%sp@- | push trap type 748 jbsr _C_LABEL(kdb_trap) | handle the trap 749 addql #8,%sp | pop args 750#if 0 /* not needed on hp300 */ 751 cmpl #0,%d0 | did ddb handle it? 752 jne Lbrkpt3 | yes, done 753#endif 754#endif 755 /* Sun 3 drops into PROM here. */ 756Lbrkpt3: 757 | The stack pointer may have been modified, or 758 | data below it modified (by kgdb push call), 759 | so push the hardware frame at the current sp 760 | before restoring registers and returning. 761 762 movl %sp@(FR_SP),%a0 | modified %sp 763 lea %sp@(FR_SIZE),%a1 | end of our frame 764 movl %a1@-,%a0@- | copy 2 longs with 765 movl %a1@-,%a0@- | ... predecrement 766 movl %a0,%sp@(FR_SP) | %sp = h/w frame 767 moveml %sp@+,#0x7FFF | restore all but %sp 768 movl %sp@,%sp | ... and %sp 769 rte | all done 770 771/* 772 * Use common m68k sigreturn routine. 773 */ 774#include <m68k/m68k/sigreturn.s> 775 776/* 777 * Interrupt handlers. 778 * 779 * For auto-vectored interrupts, the CPU provides the 780 * vector 0x18+level. Note we count spurious interrupts, 781 * but don't do anything else with them. 782 * 783 * _intrhand_autovec is the entry point for auto-vectored 784 * interrupts. 785 * 786 * For vectored interrupts, we pull the pc, evec, and exception frame 787 * and pass them to the vectored interrupt dispatcher. The vectored 788 * interrupt dispatcher will deal with strays. 789 * 790 * _intrhand_vectored is the entry point for vectored interrupts. 791 */ 792 793#define INTERRUPT_SAVEREG moveml #0xC0C0,%sp@- 794#define INTERRUPT_RESTOREREG moveml %sp@+,#0x0303 795 796ENTRY_NOPROFILE(spurintr) /* Level 0 */ 797 addql #1,_C_LABEL(intrcnt)+0 798 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 799 rte 800 801ENTRY_NOPROFILE(intrhand_autovec) /* Levels 1 through 6 */ 802 INTERRUPT_SAVEREG 803 movw %sp@(22),%sp@- | push exception vector 804 clrw %sp@- 805 jbsr _C_LABEL(isrdispatch_autovec) | call dispatcher 806 addql #4,%sp 807 INTERRUPT_RESTOREREG 808 rte 809 810ENTRY_NOPROFILE(lev1intr) /* Level 1: AST interrupt */ 811 movl %a0,%sp@- 812 addql #1,_C_LABEL(intrcnt)+4 813 addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS 814 movl _C_LABEL(ctrl_ast),%a0 815 clrb %a0@ | disable AST interrupt 816 movl %sp@+,%a0 817 jra _ASM_LABEL(rei) | handle AST 818 819ENTRY_NOPROFILE(lev2intr) /* Level 2: software interrupt */ 820 INTERRUPT_SAVEREG 821 jbsr _C_LABEL(intrhand_lev2) 822 INTERRUPT_RESTOREREG 823 rte 824 825ENTRY_NOPROFILE(lev3intr) /* Level 3: fd, lpt, vme etc. */ 826 INTERRUPT_SAVEREG 827 jbsr _C_LABEL(intrhand_lev3) 828 INTERRUPT_RESTOREREG 829 rte 830 831ENTRY_NOPROFILE(lev4intr) /* Level 4: scsi, le, vme etc. */ 832 INTERRUPT_SAVEREG 833 jbsr _C_LABEL(intrhand_lev4) 834 INTERRUPT_RESTOREREG 835 rte 836 837#if 0 838ENTRY_NOPROFILE(lev5intr) /* Level 5: kb, ms (zs is vectored) */ 839 INTERRUPT_SAVEREG 840 jbsr _C_LABEL(intrhand_lev5) 841 INTERRUPT_RESTOREREG 842 rte 843#endif 844 845ENTRY_NOPROFILE(_isr_clock) /* Level 6: clock (see clock_hb.c) */ 846 INTERRUPT_SAVEREG 847 lea %sp@(16),%a1 848 movl %a1,%sp@- 849 jbsr _C_LABEL(clock_intr) 850 addql #4,%sp 851 INTERRUPT_RESTOREREG 852 rte 853 854#if 0 855ENTRY_NOPROFILE(lev7intr) /* Level 7: NMI */ 856 addql #1,_C_LABEL(intrcnt)+32 857 clrl %sp@- 858 moveml #0xFFFF,%sp@- | save registers 859 movl %usp,%a0 | and save 860 movl %a0,%sp@(FR_SP) | the user stack pointer 861 jbsr _C_LABEL(nmintr) | call handler: XXX wrapper 862 movl %sp@(FR_SP),%a0 | restore 863 movl %a0,%usp | user SP 864 moveml %sp@+,#0x7FFF | and remaining registers 865 addql #8,%sp | pop SP and stack adjust 866 rte 867#endif 868 869ENTRY_NOPROFILE(intrhand_vectored) 870 INTERRUPT_SAVEREG 871 lea %sp@(16),%a1 | get pointer to frame 872 movl %a1,%sp@- 873 movw %sp@(26),%d0 874 movl %d0,%sp@- | push exception vector info 875 movl %sp@(26),%sp@- | and PC 876 jbsr _C_LABEL(isrdispatch_vectored) | call dispatcher 877 lea %sp@(12),%sp | pop value args 878 INTERRUPT_RESTOREREG 879 rte 880 881#undef INTERRUPT_SAVEREG 882#undef INTERRUPT_RESTOREREG 883 884/* 885 * Emulation of VAX REI instruction. 886 * 887 * This code deals with checking for and servicing ASTs 888 * (profiling, scheduling) and software interrupts (network, softclock). 889 * We check for ASTs first, just like the VAX. To avoid excess overhead 890 * the T_ASTFLT handling code will also check for software interrupts so we 891 * do not have to do it here. After identifing that we need an AST we 892 * drop the IPL to allow device interrupts. 893 * 894 * This code is complicated by the fact that sendsig may have been called 895 * necessitating a stack cleanup. 896 */ 897/* 898 * news68k has hardware support for AST and software interrupt. 899 * We just use it rather than VAX REI emulation. 900 */ 901 902ASENTRY_NOPROFILE(rei) 903 tstl _C_LABEL(astpending) | AST pending? 904 jne Lrei1 | no, done 905 rte 906Lrei1: 907 btst #5,%sp@ | yes, are we returning to user mode? 908 jeq 1f | no, done 909 rte 9101: 911 movw #PSL_LOWIPL,%sr | lower SPL 912 clrl %sp@- | stack adjust 913 moveml #0xFFFF,%sp@- | save all registers 914 movl %usp,%a1 | including 915 movl %a1,%sp@(FR_SP) | the users SP 916Lrei2: 917 clrl %sp@- | VA == none 918 clrl %sp@- | code == none 919 movl #T_ASTFLT,%sp@- | type == async system trap 920 jbsr _C_LABEL(trap) | go handle it 921 lea %sp@(12),%sp | pop value args 922 movl %sp@(FR_SP),%a0 | restore user SP 923 movl %a0,%usp | from save area 924 movw %sp@(FR_ADJ),%d0 | need to adjust stack? 925 jne Laststkadj | yes, go to it 926 moveml %sp@+,#0x7FFF | no, restore most user regs 927 addql #8,%sp | toss SP and stack adjust 928 rte | and do real RTE 929Laststkadj: 930 lea %sp@(FR_HW),%a1 | pointer to HW frame 931 addql #8,%a1 | source pointer 932 movl %a1,%a0 | source 933 addw %d0,%a0 | + hole size = dest pointer 934 movl %a1@-,%a0@- | copy 935 movl %a1@-,%a0@- | 8 bytes 936 movl %a0,%sp@(FR_SP) | new SSP 937 moveml %sp@+,#0x7FFF | restore user registers 938 movl %sp@,%sp | and our SP 939 rte | real return 940 941/* 942 * Use common m68k sigcode. 943 */ 944#include <m68k/m68k/sigcode.s> 945#ifdef COMPAT_SUNOS 946#include <m68k/m68k/sunos_sigcode.s> 947#endif 948#ifdef COMPAT_SVR4 949#include <m68k/m68k/svr4_sigcode.s> 950#endif 951 952/* 953 * Primitives 954 */ 955 956/* 957 * Use common m68k support routines. 958 */ 959#include <m68k/m68k/support.s> 960 961/* 962 * Use common m68k process manipulation routines. 963 */ 964#include <m68k/m68k/proc_subr.s> 965 966 .data 967GLOBAL(curpcb) 968GLOBAL(masterpaddr) | XXXcompatibility (debuggers) 969 .long 0 970 971ASLOCAL(mdpflag) 972 .byte 0 | copy of proc md_flags low byte 973#ifdef __ELF__ 974 .align 4 975#else 976 .align 2 977#endif 978 979ASBSS(nullpcb,SIZEOF_PCB) 980 981/* 982 * At exit of a process, do a switch for the last time. 983 * Switch to a safe stack and PCB, and select a new process to run. The 984 * old stack and u-area will be freed by the reaper. 985 * 986 * MUST BE CALLED AT SPLHIGH! 987 */ 988ENTRY(switch_exit) 989 movl %sp@(4),%a0 990 /* save state into garbage pcb */ 991 movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) 992 lea _ASM_LABEL(tmpstk),%sp | goto a tmp stack 993 994 /* Schedule the vmspace and stack to be freed. */ 995 movl %a0,%sp@- | exit2(p) 996 jbsr _C_LABEL(exit2) 997 lea %sp@(4),%sp | pop args 998 999#if defined(LOCKDEBUG) 1000 /* Acquire sched_lock */ 1001 jbsr C_LABEL(sched_lock_idle) 1002#endif 1003 1004 jra _C_LABEL(cpu_switch) 1005 1006/* 1007 * When no processes are on the runq, Swtch branches to Idle 1008 * to wait for something to come ready. 1009 */ 1010ASENTRY_NOPROFILE(Idle) 1011#if defined(LOCKDEBUG) 1012 /* Release sched_lock */ 1013 jbsr _C_LABEL(sched_unlock_idle) 1014#endif 1015 movw #PSL_LOWIPL,%sr 1016 1017 /* Try to zero some pages. */ 1018 movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO,%d0 1019 jeq 1f 1020 jbsr _C_LABEL(uvm_pageidlezero) 1021 jra 2f 10221: 1023 stop #PSL_LOWIPL 10242: 1025 movw #PSL_HIGHIPL,%sr 1026#if defined(LOCKDEBUG) 1027 /* Acquire sched_lock */ 1028 jbsr _C_LABEL(sched_lock_idle) 1029#endif 1030 movl _C_LABEL(sched_whichqs),%d0 1031 jeq _ASM_LABEL(Idle) 1032 jra Lsw1 1033 1034Lbadsw: 1035 PANIC("switch") 1036 /*NOTREACHED*/ 1037 1038/* 1039 * cpu_switch() 1040 * 1041 * NOTE: On the mc68851 we attempt to avoid flushing the 1042 * entire ATC. The effort involved in selective flushing may not be 1043 * worth it, maybe we should just flush the whole thing? 1044 * 1045 * NOTE 2: With the new VM layout we now no longer know if an inactive 1046 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1047 * bit). For now, we just always flush the full ATC. 1048 */ 1049ENTRY(cpu_switch) 1050 movl _C_LABEL(curpcb),%a0 | current pcb 1051 movw %sr,%a0@(PCB_PS) | save sr before changing ipl 1052#ifdef notyet 1053 movl _C_LABEL(curproc),%sp@- | remember last proc running 1054#endif 1055 clrl _C_LABEL(curproc) 1056 1057 /* 1058 * Find the highest-priority queue that isn't empty, 1059 * then take the first proc from that queue. 1060 */ 1061 movl _C_LABEL(sched_whichqs),%d0 1062 jeq _ASM_LABEL(Idle) 1063Lsw1: 1064 /* 1065 * Interrupts are blocked, sched_lock is held. If 1066 * we come here via Idle, %d0 contains the contents 1067 * of a non-zero sched_whichqs. 1068 */ 1069 movl %d0,%d1 1070 negl %d0 1071 andl %d1,%d0 1072 bfffo %d0{#0:#32},%d1 1073 eorib #31,%d1 1074 1075 movl %d1,%d0 1076 lslb #3,%d1 | convert queue number to index 1077 addl #_C_LABEL(sched_qs),%d1 | locate queue (q) 1078 movl %d1,%a1 1079 movl %a1@(P_FORW),%a0 | p = q->p_forw 1080 cmpal %d1,%a0 | anyone on queue? 1081 jeq Lbadsw | no, panic 1082#ifdef DIAGNOSTIC 1083 tstl %a0@(P_WCHAN) 1084 jne Lbadsw 1085 cmpb #SRUN,%a0@(P_STAT) 1086 jne Lbadsw 1087#endif 1088 movl %a0@(P_FORW),%a1@(P_FORW) | q->p_forw = p->p_forw 1089 movl %a0@(P_FORW),%a1 | n = p->p_forw 1090 movl %d1,%a1@(P_BACK) | n->p_back = q 1091 cmpal %d1,%a1 | anyone left on queue? 1092 jne Lsw2 | yes, skip 1093 movl _C_LABEL(sched_whichqs),%d1 1094 bclr %d0,%d1 | no, clear bit 1095 movl %d1,_C_LABEL(sched_whichqs) 1096Lsw2: 1097 /* p->p_cpu initialized in fork1() for single-processor */ 1098 movb #SONPROC,%a0@(P_STAT) | p->p_stat = SONPROC 1099 movl %a0,_C_LABEL(curproc) 1100 clrl _C_LABEL(want_resched) 1101#ifdef notyet 1102 movl %sp@+,%a1 1103 cmpl %a0,%a1 | switching to same proc? 1104 jeq Lswdone | yes, skip save and restore 1105#endif 1106 /* 1107 * Save state of previous process in its pcb. 1108 */ 1109 movl _C_LABEL(curpcb),%a1 1110 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1111 movl %usp,%a2 | grab USP (a2 has been saved) 1112 movl %a2,%a1@(PCB_USP) | and save it 1113 1114 tstl _C_LABEL(fputype) | Do we have an FPU? 1115 jeq Lswnofpsave | No Then don't attempt save. 1116 lea %a1@(PCB_FPCTX),%a2 | pointer to FP save area 1117 fsave %a2@ | save FP state 1118 tstb %a2@ | null state frame? 1119 jeq Lswnofpsave | yes, all done 1120 fmovem %fp0-%fp7,%a2@(FPF_REGS) | save FP general registers 1121 fmovem %fpcr/%fpsr/%fpi,%a2@(FPF_FPCR) | save FP control registers 1122Lswnofpsave: 1123 1124 clrl %a0@(P_BACK) | clear back link 1125 /* low byte of p_md.md_flags */ 1126 movb %a0@(P_MD_FLAGS+3),_ASM_LABEL(mdpflag) 1127 movl %a0@(P_ADDR),%a1 | get p_addr 1128 movl %a1,_C_LABEL(curpcb) 1129 1130#if defined(LOCKDEBUG) 1131 /* 1132 * Done mucking with the run queues, release the 1133 * scheduler lock, but keep interrupts out. 1134 */ 1135 movl %a0,sp@- | not args... 1136 movl %a1,sp@- | ...just saving 1137 jbsr _C_LABEL(sched_unlock_idle) 1138 movl sp@+,%a1 1139 movl sp@+,%a0 1140#endif 1141 1142 /* 1143 * Activate process's address space. 1144 * XXX Should remember the last USTP value loaded, and call this 1145 * XXX only of it has changed. 1146 */ 1147 pea %a0@ | push proc 1148 jbsr _C_LABEL(pmap_activate) | pmap_activate(p) 1149 addql #4,%sp 1150 movl _C_LABEL(curpcb),%a1 | restore p_addr 1151 1152 lea _ASM_LABEL(tmpstk),%sp | now goto a tmp stack for NMI 1153 1154 moveml %a1@(PCB_REGS),#0xFCFC | and registers 1155 movl %a1@(PCB_USP),%a0 1156 movl %a0,%usp | and USP 1157 1158 tstl _C_LABEL(fputype) | If we don't have an FPU, 1159 jeq Lnofprest | don't try to restore it. 1160 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1161 tstb %a0@ | null state frame? 1162 jeq Lresfprest | yes, easy 1163 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1164 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1165Lresfprest: 1166 frestore %a0@ | restore state 1167Lnofprest: 1168 movw %a1@(PCB_PS),%sr | no, restore PS 1169 moveq #1,%d0 | return 1 (for alternate returns) 1170 rts 1171 1172/* 1173 * savectx(pcb) 1174 * Update pcb, saving current processor state. 1175 */ 1176ENTRY(savectx) 1177 movl %sp@(4),%a1 1178 movw %sr,%a1@(PCB_PS) 1179 movl %usp,%a0 | grab USP 1180 movl %a0,%a1@(PCB_USP) | and save it 1181 moveml #0xFCFC,%a1@(PCB_REGS) | save non-scratch registers 1182 1183 tstl _C_LABEL(fputype) | Do we have FPU? 1184 jeq Lsvnofpsave | No? Then don't save state. 1185 lea %a1@(PCB_FPCTX),%a0 | pointer to FP save area 1186 fsave %a0@ | save FP state 1187 tstb %a0@ | null state frame? 1188 jeq Lsvnofpsave | yes, all done 1189 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1190 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1191Lsvnofpsave: 1192 moveq #0,%d0 | return 0 1193 rts 1194 1195/* 1196 * Invalidate entire TLB. 1197 */ 1198ENTRY(TBIA) 1199_C_LABEL(_TBIA): 1200 tstl _C_LABEL(mmutype) | MMU type? 1201 pflusha | flush entire TLB 1202 jpl Lmc68851a | 68851 implies no d-cache 1203 movc %cacr,%d0 1204 orl #DC_CLR,%d0 1205 movc %d0,%cacr | invalidate on-chip d-cache 1206#if 0 1207 jmp _C_LABEL(_DCIA) 1208#endif 1209Lmc68851a: 1210 rts 1211 1212/* 1213 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1214 */ 1215ENTRY(TBIS) 1216 tstl _C_LABEL(mmutype) | MMU type? 1217 movl %sp@(4),%a0 | get addr to flush 1218 jpl Lmc68851b | is 68851? 1219 pflush #0,#0,%a0@ | flush address from both sides 1220 movc %cacr,%d0 1221 orl #DC_CLR,%d0 1222 movc %d0,%cacr | invalidate on-chip data cache 1223 rts 1224Lmc68851b: 1225 pflushs #0,#0,%a0@ | flush address from both sides 1226 rts 1227 1228/* 1229 * Invalidate supervisor side of TLB 1230 */ 1231ENTRY(TBIAS) 1232 tstl _C_LABEL(mmutype) | MMU type? 1233 jpl Lmc68851c | 68851? 1234 pflush #4,#4 | flush supervisor TLB entries 1235 movc %cacr,%d0 1236 orl #DC_CLR,%d0 1237 movc %d0,%cacr | invalidate on-chip d-cache 1238 rts 1239Lmc68851c: 1240 pflushs #4,#4 | flush supervisor TLB entries 1241#if 0 1242 jmp _C_LABEL(_DCIS) 1243#endif 1244 rts 1245 1246/* 1247 * Invalidate user side of TLB 1248 */ 1249ENTRY(TBIAU) 1250 tstl _C_LABEL(mmutype) | MMU type? 1251 jpl Lmc68851d | 68851? 1252 pflush #0,#4 | flush user TLB entries 1253 movc %cacr,%d0 1254 orl #DC_CLR,%d0 1255 movc %d0,%cacr | invalidate on-chip d-cache 1256 rts 1257Lmc68851d: 1258 pflushs #0,#4 | flush user TLB entries 1259#if 0 1260 jmp _C_LABEL(_DCIU) 1261#endif 1262 rts 1263 1264/* 1265 * Invalidate instruction cache 1266 */ 1267ENTRY(ICIA) 1268 movc %cacr,%d0 1269 orl #IC_CLR,%d0 1270 movc %d0,%cacr | invalidate i-cache 1271#if 0 1272 tstl _C_LABEL(ectype) | got external PAC? 1273 jge Lnocache1 | no, all done 1274 1275 movl _C_LABEL(cache_clr),%a0 1276 st %a0@ | NEWS-OS does `st 0xe1900000' 1277 1278Lnocache1: 1279#endif 1280 rts 1281 1282/* 1283 * Invalidate data cache. 1284 * news68k external cache does not allow for invalidation of user/supervisor 1285 * portions. (probably...) 1286 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing 1287 * problems with DC_WA. The only cases we have to worry about are context 1288 * switch and TLB changes, both of which are handled "in-line" in resume 1289 * and TBI*. 1290 * 1291 * XXX: NEWS-OS *does* flush 68030 on-chip cache... Should this be done? 1292 */ 1293ENTRY(DCIA) 1294ENTRY(DCIS) 1295ENTRY(DCIU) 1296_C_LABEL(_DCIA): 1297_C_LABEL(_DCIS): 1298_C_LABEL(_DCIU): 1299#if 0 1300 movc %cacr,%d0 1301 orl #DC_CLR,%d0 1302 movc %d0,%cacr 1303#endif 1304 tstl _C_LABEL(ectype) | got external VAC? 1305 jle Lnocache2 | no, all done 1306 1307 movl _C_LABEL(cache_clr),%a0 1308 st %a0@ | NEWS-OS does `st 0xe1900000' 1309Lnocache2: 1310 rts 1311 1312ENTRY(PCIA) 1313#if 0 1314 movc %cacr,%d0 1315 orl #DC_CLR,%d0 1316 movc %d0,%cacr | invalidate on-chip d-cache 1317#endif 1318 tstl _C_LABEL(ectype) | got external PAC? 1319 jge Lnocache6 | no, all done 1320 1321 movl _C_LABEL(cache_clr),%a0 1322 st %a0@ | NEWS-OS does `st 0xe1900000' 1323Lnocache6: 1324 rts 1325 1326ENTRY(ecacheon) 1327 tstl _C_LABEL(ectype) 1328 jeq Lnocache7 1329 movl _C_LABEL(cache_ctl),%a0 1330 st %a0@ | NEWS-OS does `st 0xe1300000' 1331Lnocache7: 1332 rts 1333 1334ENTRY(ecacheoff) 1335 tstl _C_LABEL(ectype) 1336 jeq Lnocache8 1337 movl _C_LABEL(cache_ctl),%a0 1338 sf %a0@ | NEWS-OS does `sf 0xe1300000' 1339Lnocache8: 1340 rts 1341 1342ENTRY_NOPROFILE(getsfc) 1343 movc %sfc,%d0 1344 rts 1345 1346ENTRY_NOPROFILE(getdfc) 1347 movc %dfc,%d0 1348 rts 1349 1350/* 1351 * Load a new user segment table pointer. 1352 */ 1353ENTRY(loadustp) 1354 movl %sp@(4),%d0 | new USTP 1355 moveq #PGSHIFT, %d1 1356 lsll %d1,%d0 | convert to addr 1357 pflusha | flush entire TLB 1358 lea _C_LABEL(protorp),%a0 | CRP prototype 1359 movl %d0,%a0@(4) | stash USTP 1360 pmove %a0@,%crp | load root pointer 1361 movc %cacr,%d0 1362 orl #DCIC_CLR,%d0 1363 movc %d0,%cacr | invalidate cache(s) 1364 rts 1365 1366ENTRY(ploadw) 1367 movl %sp@(4),%a0 | address to load 1368 ploadw #1,%a0@ | pre-load translation 1369 rts 1370 1371ENTRY(getsr) 1372 moveq #0,%d0 1373 movw %sr,%d0 1374 rts 1375 1376/* 1377 * _delay(unsigned N) 1378 * 1379 * Delay for at least (N/256) microseconds. 1380 * This routine depends on the variable: delay_divisor 1381 * which should be set based on the CPU clock rate. 1382 */ 1383ENTRY_NOPROFILE(_delay) 1384 | %d0 = arg = (usecs << 8) 1385 movl %sp@(4),%d0 1386 | %d1 = delay_divisor 1387 movl _C_LABEL(delay_divisor),%d1 1388 jra L_delay /* Jump into the loop! */ 1389 1390 /* 1391 * Align the branch target of the loop to a half-line (8-byte) 1392 * boundary to minimize cache effects. This guarantees both 1393 * that there will be no prefetch stalls due to cache line burst 1394 * operations and that the loop will run from a single cache 1395 * half-line. 1396 */ 1397#ifdef __ELF__ 1398 .align 8 1399#else 1400 .align 3 1401#endif 1402L_delay: 1403 subl %d1,%d0 1404 jgt L_delay 1405 rts 1406 1407/* 1408 * Save and restore 68881 state. 1409 */ 1410ENTRY(m68881_save) 1411 movl %sp@(4),%a0 | save area pointer 1412 fsave %a0@ | save state 1413Lm68881fpsave: 1414 tstb %a0@ | null state frame? 1415 jeq Lm68881sdone | yes, all done 1416 fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general registers 1417 fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control registers 1418Lm68881sdone: 1419 rts 1420 1421ENTRY(m68881_restore) 1422 movl %sp@(4),%a0 | save area pointer 1423Lm68881fprestore: 1424 tstb %a0@ | null state frame? 1425 jeq Lm68881rdone | yes, easy 1426 fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control registers 1427 fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general registers 1428Lm68881rdone: 1429 frestore %a0@ | restore state 1430 rts 1431 1432/* 1433 * Handle the nitty-gritty of rebooting the machine. 1434 * Basically we just turn off the MMU, restore the PROM's initial VBR 1435 * and jump through the PROM halt vector with argument via %d7 1436 * depending on how the system was halted. 1437 */ 1438ENTRY_NOPROFILE(doboot) 1439#if defined(M68040) 1440 cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? 1441 jeq Lnocache5 | yes, skip 1442#endif 1443 movl #CACHE_OFF,%d0 1444 movc %d0,%cacr | disable on-chip cache(s) 1445Lnocache5: 1446 movl _C_LABEL(boothowto),%d7 | load howto 1447 movl _C_LABEL(bootdev),%d6 | load bootdev 1448 movl %sp@(4),%d2 | arg 1449 movl _C_LABEL(ctrl_power),%a0| CTRL_POWER port 1450 movl _ASM_LABEL(monitor_vbr),%d3 | Fetch original VBR value 1451 lea _ASM_LABEL(tmpstk),%sp | physical SP in case of NMI 1452 movl #0,%a7@- | value for pmove to TC (turn off MMU) 1453 pmove %a7@,%tc | disable MMU 1454 movc %d3,%vbr | Restore monitor's VBR 1455 movl %d2,%d0 | 1456 andl #0x800,%d0 | mask off 1457 tstl %d0 | power down? 1458 beq 1f | 1459 clrb %a0@ | clear CTRL_POWER port 14601: 1461 tstl %d2 | autoboot? 1462 beq 2f | yes! 1463 movl %d2,%d7 | 14642: 1465 trap #15 1466 /* NOTREACHED */ 1467 1468ASENTRY_NOPROFILE(debug_led) 1469 lea 0xe0dc0000,%a0 1470 movl %d0,%a0@ 1471 14721: nop 1473 jmp 1b 1474 rts 1475 1476ASENTRY_NOPROFILE(debug_led2) 1477 movl _C_LABEL(intiobase),%d1 1478 addl #(0xe0dc0000-INTIOBASE1700),%d1 1479 movl %d1,%a0 1480 movl %d0,%a0@ 1481 14821: nop 1483 jmp 1b 1484 rts 1485 1486 1487/* 1488 * Misc. global variables. 1489 */ 1490 .data 1491 1492GLOBAL(systype) 1493 .long NEWS1700 | default to NEWS1700 1494 1495GLOBAL(mmutype) 1496 .long MMU_68030 | default to MMU_68030 1497 1498GLOBAL(cputype) 1499 .long CPU_68030 | default to CPU_68030 1500 1501GLOBAL(fputype) 1502 .long FPU_68882 | default to FPU_68882 1503 1504GLOBAL(ectype) 1505 .long EC_NONE | external cache type, default to none 1506 1507GLOBAL(protorp) 1508 .long 0,0 | prototype root pointer 1509 1510GLOBAL(prototc) 1511 .long 0 | prototype translation control 1512 1513GLOBAL(protott0) 1514 .long 0 | prototype transparent translation register 0 1515 1516GLOBAL(protott1) 1517 .long 0 | prototype transparent translation register 1 1518 1519/* 1520 * Information from first stage boot program 1521 */ 1522GLOBAL(bootpart) 1523 .long 0 1524GLOBAL(bootdevlun) 1525 .long 0 1526GLOBAL(bootctrllun) 1527 .long 0 1528GLOBAL(bootaddr) 1529 .long 0 1530 1531GLOBAL(want_resched) 1532 .long 0 1533 1534GLOBAL(proc0paddr) 1535 .long 0 | KVA of proc0 u-area 1536 1537GLOBAL(intiobase) 1538 .long 0 | KVA of base of internal IO space 1539 1540GLOBAL(extiobase) 1541 .long 0 | KVA of base of internal IO space 1542 1543GLOBAL(intiolimit) 1544 .long 0 | KVA of end of internal IO space 1545 1546GLOBAL(intiobase_phys) 1547 .long 0 | PA of board's I/O registers 1548 1549GLOBAL(intiotop_phys) 1550 .long 0 | PA of top of board's I/O registers 1551 1552GLOBAL(extiobase_phys) 1553 .long 0 | PA of external I/O registers 1554 1555GLOBAL(extiotop_phys) 1556 .long 0 | PA of top of external I/O registers 1557 1558GLOBAL(ctrl_power) 1559 .long 0 | PA of power control port 1560 1561GLOBAL(cache_ctl) 1562 .long 0 | KVA of external cache control port 1563 1564GLOBAL(cache_clr) 1565 .long 0 | KVA of external cache clear port 1566 1567 1568/* interrupt counters */ 1569GLOBAL(intrnames) 1570 .asciz "spur" 1571 .asciz "AST" | lev1: AST 1572 .asciz "softint" | lev2: software interrupt 1573 .asciz "lev3" | lev3: slot intr, VME intr 2, fd, lpt 1574 .asciz "lev4" | lev4: slot intr, VME intr 4, le, scsi 1575 .asciz "lev5" | lev5: kb, ms, zs 1576 .asciz "clock" | lev6: clock 1577 .asciz "nmi" | parity error 1578GLOBAL(eintrnames) 1579 .even 1580 1581GLOBAL(intrcnt) 1582 .long 0,0,0,0,0,0,0,0 1583GLOBAL(eintrcnt) 1584