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