1/* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 OMRON Corporation. 4 * Copyright (c) 1980, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * %sccs.include.redist.c% 12 * 13 * from: Utah $Hdr: locore.s 1.62 92/01/20$ 14 * from: hp300/hp300/locore.s 7.22 (Berkeley) 2/18/93 15 * 16 * @(#)locore.s 7.10 (Berkeley) 03/17/93 17 */ 18 19/* 20 * STACKCHECK enables two types of kernel stack checking: 21 * 1. stack "overflow". On every clock interrupt we ensure that 22 * the current kernel stack has not grown into the user struct 23 * page, i.e. size exceeded UPAGES-1 pages. 24 * 2. stack "underflow". Before every rte to user mode we ensure 25 * that we will be exactly at the base of the stack after the 26 * exception frame has been popped. 27 * Both checks are performed at splclock since they operate on the 28 * global temporary stack. 29 */ 30/* #define STACKCHECK */ 31 32#include "assym.s" 33#include <luna68k/luna68k/vectors.s> 34 35/* 36 * Temporary stack for a variety of purposes. 37 * Try and make this the first thing is the data segment so it 38 * is page aligned. Note that if we overflow here, we run into 39 * our text segment. 40 */ 41 .data 42 .space NBPG 43tmpstk: 44 45 .text 46/* 47 * This is where we wind up if the kernel jumps to location 0. 48 * (i.e. a bogus PC) This is known to immediately follow the vector 49 * table and is hence at 0x400 (see reset vector in vectors.s). 50 */ 51 .globl _panic 52 pea Ljmp0panic 53 jbsr _panic 54 /* NOTREACHED */ 55Ljmp0panic: 56 .asciz "kernel jump to zero" 57 .even 58 59/* 60 * Do a dump. 61 * Called by auto-restart. 62 */ 63 .globl _dumpsys 64 .globl _doadump 65_doadump: 66 jbsr _dumpsys 67 jbsr _doboot 68 /*NOTREACHED*/ 69 70/* 71 * Trap/interrupt vector routines 72 */ 73 74 .globl _trap, _nofault, _longjmp 75_buserr: 76 tstl _nofault | device probe? 77 jeq _addrerr | no, handle as usual 78 movl _nofault,sp@- | yes, 79 jbsr _longjmp | longjmp(nofault) 80_addrerr: 81 clrl sp@- | stack adjust count 82 moveml #0xFFFF,sp@- | save user registers 83 movl usp,a0 | save the user SP 84 movl a0,sp@(FR_SP) | in the savearea 85 lea sp@(FR_HW),a1 | grab base of HW berr frame 86 moveq #0,d0 87 movw a1@(10),d0 | grab SSW for fault processing 88 btst #12,d0 | RB set? 89 jeq LbeX0 | no, test RC 90 bset #14,d0 | yes, must set FB 91 movw d0,a1@(10) | for hardware too 92LbeX0: 93 btst #13,d0 | RC set? 94 jeq LbeX1 | no, skip 95 bset #15,d0 | yes, must set FC 96 movw d0,a1@(10) | for hardware too 97LbeX1: 98 btst #8,d0 | data fault? 99 jeq Lbe0 | no, check for hard cases 100 movl a1@(16),d1 | fault address is as given in frame 101 jra Lbe10 | thats it 102Lbe0: 103 btst #4,a1@(6) | long (type B) stack frame? 104 jne Lbe4 | yes, go handle 105 movl a1@(2),d1 | no, can use save PC 106 btst #14,d0 | FB set? 107 jeq Lbe3 | no, try FC 108 addql #4,d1 | yes, adjust address 109 jra Lbe10 | done 110Lbe3: 111 btst #15,d0 | FC set? 112 jeq Lbe10 | no, done 113 addql #2,d1 | yes, adjust address 114 jra Lbe10 | done 115Lbe4: 116 movl a1@(36),d1 | long format, use stage B address 117 btst #15,d0 | FC set? 118 jeq Lbe10 | no, all done 119 subql #2,d1 | yes, adjust address 120Lbe10: 121 movl d1,sp@- | push fault VA 122 movl d0,sp@- | and padded SSW 123 movw a1@(6),d0 | get frame format/vector offset 124 andw #0x0FFF,d0 | clear out frame format 125 cmpw #12,d0 | address error vector? 126 jeq Lisaerr | yes, go to it 127 movl d1,a0 | fault address 128 ptestr #1,a0@,#7 | do a table search 129 pmove psr,sp@ | save result 130 btst #7,sp@ | bus error bit set? 131 jeq Lismerr | no, must be MMU fault 132 clrw sp@ | yes, re-clear pad word 133 jra Lisberr | and process as normal bus error 134Lismerr: 135 movl #T_MMUFLT,sp@- | show that we are an MMU fault 136 jra Ltrapnstkadj | and deal with it 137Lisaerr: 138 movl #T_ADDRERR,sp@- | mark address error 139 jra Ltrapnstkadj | and deal with it 140Lisberr: 141 movl #T_BUSERR,sp@- | mark bus error 142Ltrapnstkadj: 143 jbsr _trap | handle the error 144 lea sp@(12),sp | pop value args 145 movl sp@(FR_SP),a0 | restore user SP 146 movl a0,usp | from save area 147 movw sp@(FR_ADJ),d0 | need to adjust stack? 148 jne Lstkadj | yes, go to it 149 moveml sp@+,#0x7FFF | no, restore most user regs 150 addql #8,sp | toss SSP and stkadj 151 jra rei | all done 152Lstkadj: 153 lea sp@(FR_HW),a1 | pointer to HW frame 154 addql #8,a1 | source pointer 155 movl a1,a0 | source 156 addw d0,a0 | + hole size = dest pointer 157 movl a1@-,a0@- | copy 158 movl a1@-,a0@- | 8 bytes 159 movl a0,sp@(FR_SP) | new SSP 160 moveml sp@+,#0x7FFF | restore user registers 161 movl sp@,sp | and our SP 162 jra rei | all done 163 164/* 165 * FP exceptions. 166 */ 167_fpfline: 168 jra _illinst 169 170_fpunsupp: 171 jra _illinst 172 173/* 174 * Handles all other FP coprocessor exceptions. 175 * Note that since some FP exceptions generate mid-instruction frames 176 * and may cause signal delivery, we need to test for stack adjustment 177 * after the trap call. 178 */ 179_fpfault: 180#ifdef FPCOPROC 181 clrl sp@- | stack adjust count 182 moveml #0xFFFF,sp@- | save user registers 183 movl usp,a0 | and save 184 movl a0,sp@(FR_SP) | the user stack pointer 185 clrl sp@- | no VA arg 186 movl _curpcb,a0 | current pcb 187 lea a0@(PCB_FPCTX),a0 | address of FP savearea 188 fsave a0@ | save state 189 tstb a0@ | null state frame? 190 jeq Lfptnull | yes, safe 191 clrw d0 | no, need to tweak BIU 192 movb a0@(1),d0 | get frame size 193 bset #3,a0@(0,d0:w) | set exc_pend bit of BIU 194Lfptnull: 195 fmovem fpsr,sp@- | push fpsr as code argument 196 frestore a0@ | restore state 197 movl #T_FPERR,sp@- | push type arg 198 jra Ltrapnstkadj | call trap and deal with stack cleanup 199#else 200 jra _badtrap | treat as an unexpected trap 201#endif 202 203/* 204 * Coprocessor and format errors can generate mid-instruction stack 205 * frames and cause signal delivery hence we need to check for potential 206 * stack adjustment. 207 */ 208_coperr: 209 clrl sp@- | stack adjust count 210 moveml #0xFFFF,sp@- 211 movl usp,a0 | get and save 212 movl a0,sp@(FR_SP) | the user stack pointer 213 clrl sp@- | no VA arg 214 clrl sp@- | or code arg 215 movl #T_COPERR,sp@- | push trap type 216 jra Ltrapnstkadj | call trap and deal with stack adjustments 217 218_fmterr: 219 clrl sp@- | stack adjust count 220 moveml #0xFFFF,sp@- 221 movl usp,a0 | get and save 222 movl a0,sp@(FR_SP) | the user stack pointer 223 clrl sp@- | no VA arg 224 clrl sp@- | or code arg 225 movl #T_FMTERR,sp@- | push trap type 226 jra Ltrapnstkadj | call trap and deal with stack adjustments 227 228/* 229 * Other exceptions only cause four and six word stack frame and require 230 * no post-trap stack adjustment. 231 */ 232_illinst: 233 clrl sp@- 234 moveml #0xFFFF,sp@- 235 moveq #T_ILLINST,d0 236 jra fault 237 238_zerodiv: 239 clrl sp@- 240 moveml #0xFFFF,sp@- 241 moveq #T_ZERODIV,d0 242 jra fault 243 244_chkinst: 245 clrl sp@- 246 moveml #0xFFFF,sp@- 247 moveq #T_CHKINST,d0 248 jra fault 249 250_trapvinst: 251 clrl sp@- 252 moveml #0xFFFF,sp@- 253 moveq #T_TRAPVINST,d0 254 jra fault 255 256_privinst: 257 clrl sp@- 258 moveml #0xFFFF,sp@- 259 moveq #T_PRIVINST,d0 260 jra fault 261 262 .globl fault 263fault: 264 movl usp,a0 | get and save 265 movl a0,sp@(FR_SP) | the user stack pointer 266 clrl sp@- | no VA arg 267 clrl sp@- | or code arg 268 movl d0,sp@- | push trap type 269 jbsr _trap | handle trap 270 lea sp@(12),sp | pop value args 271 movl sp@(FR_SP),a0 | restore 272 movl a0,usp | user SP 273 moveml sp@+,#0x7FFF | restore most user regs 274 addql #8,sp | pop SP and stack adjust 275 jra rei | all done 276 277 .globl _straytrap 278_badtrap: 279 moveml #0xC0C0,sp@- | save scratch regs 280 movw sp@(22),sp@- | push exception vector info 281 clrw sp@- 282 movl sp@(22),sp@- | and PC 283 jbsr _straytrap | report 284 addql #8,sp | pop args 285 moveml sp@+,#0x0303 | restore regs 286 jra rei | all done 287 288 .globl _syscall 289_trap0: 290 clrl sp@- | stack adjust count 291 moveml #0xFFFF,sp@- | save user registers 292 movl usp,a0 | save the user SP 293 movl a0,sp@(FR_SP) | in the savearea 294 movl d0,sp@- | push syscall number 295 jbsr _syscall | handle it 296 addql #4,sp | pop syscall arg 297 movl sp@(FR_SP),a0 | grab and restore 298 movl a0,usp | user SP 299 moveml sp@+,#0x7FFF | restore most registers 300 addql #8,sp | pop SP and stack adjust 301 jra rei | all done 302 303/* 304 * trap1 is sigreturn and trap2 is breakpoint. 305 */ 306_trap1: 307 jra sigreturn | trap1 is sigreturn 308 309_trap2: 310 jra _trace | trap2 is breakpoint 311 312/* 313 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) 314 * cachectl(command, addr, length) 315 * command in d0, addr in a1, length in d1 316 */ 317 .globl _cachectl 318_trap12: 319 movl d1,sp@- | push length 320 movl a1,sp@- | push addr 321 movl d0,sp@- | push command 322 jbsr _cachectl | do it 323 lea sp@(12),sp | pop args 324 jra rei | all done 325 326/* 327 * Trap 15 is used for: 328 * - KGDB traps 329 * - trace traps for SUN binaries (not fully supported yet) 330 * We just pass it on and let trap() sort it all out 331 */ 332_trap15: 333 clrl sp@- 334 moveml #0xFFFF,sp@- 335#ifdef KGDB 336 moveq #T_TRAP15,d0 337 movw sp@(FR_HW),d1 | get PSW 338 andw #PSL_S,d1 | from user mode? 339 jeq fault | yes, just a regular fault 340 movl d0,sp@- 341 .globl _kgdb_trap_glue 342 jbsr _kgdb_trap_glue | returns if no debugger 343 addl #4,sp 344#endif 345 moveq #T_TRAP15,d0 346 jra fault 347 348/* 349 * Hit a breakpoint (trap 1 or 2) instruction. 350 * Push the code and treat as a normal fault. 351 */ 352_trace: 353 clrl sp@- 354 moveml #0xFFFF,sp@- 355#ifdef KGDB 356 moveq #T_TRACE,d0 357 movw sp@(FR_HW),d1 | get SSW 358 andw #PSL_S,d1 | from user mode? 359 jeq fault | no, regular fault 360 movl d0,sp@- 361 jbsr _kgdb_trap_glue | returns if no debugger 362 addl #4,sp 363#endif 364 moveq #T_TRACE,d0 365 jra fault 366 367/* 368 * The sigreturn() syscall comes here. It requires special handling 369 * because we must open a hole in the stack to fill in the (possibly much 370 * larger) original stack frame. 371 */ 372sigreturn: 373 lea sp@(-84),sp | leave enough space for largest frame 374 movl sp@(84),sp@ | move up current 8 byte frame 375 movl sp@(88),sp@(4) 376 movl #84,sp@- | default: adjust by 84 bytes 377 moveml #0xFFFF,sp@- | save user registers 378 movl usp,a0 | save the user SP 379 movl a0,sp@(FR_SP) | in the savearea 380 movl #SYS_sigreturn,sp@- | push syscall number 381 jbsr _syscall | handle it 382 addql #4,sp | pop syscall# 383 movl sp@(FR_SP),a0 | grab and restore 384 movl a0,usp | user SP 385 lea sp@(FR_HW),a1 | pointer to HW frame 386 movw sp@(FR_ADJ),d0 | do we need to adjust the stack? 387 jeq Lsigr1 | no, just continue 388 moveq #92,d1 | total size 389 subw d0,d1 | - hole size = frame size 390 lea a1@(92),a0 | destination 391 addw d1,a1 | source 392 lsrw #1,d1 | convert to word count 393 subqw #1,d1 | minus 1 for dbf 394Lsigrlp: 395 movw a1@-,a0@- | copy a word 396 dbf d1,Lsigrlp | continue 397 movl a0,a1 | new HW frame base 398Lsigr1: 399 movl a1,sp@(FR_SP) | new SP value 400 moveml sp@+,#0x7FFF | restore user registers 401 movl sp@,sp | and our SP 402 jra rei | all done 403 404/* 405 * Interrupt handlers. 406 * All DIO device interrupts are auto-vectored. Most can be configured 407 * to interrupt in the range IPL2 to IPL5. Here are our assignments: 408 * 409 * Level 0: Spurious: ignored. 410 * Level 1: (low XP) 411 * Level 2: SCSI 412 * Level 3: LANCE 413 * Level 4: [PC98] 414 * Level 5: Clock 415 * Level 6: RS232C 416 * Level 7: Non-maskable: parity errors, Abort SW 417 */ 418 .globl _hardclock, _nmihand 419 420_spurintr: 421 addql #1,_intrcnt+0 422 addql #1,_cnt+V_INTR 423 jra rei 424 425_lev1intr: 426 addql #1,_intrcnt+4 427 addql #1,_cnt+V_INTR 428 jra rei | XP not surpported yet XXXX 429 430_lev2intr: 431 addql #1,_intrcnt+8 432 moveml #0xC0C0,sp@- 433 jbsr __scintr 434 moveml sp@+,#0x0303 435 addql #1,_cnt+V_INTR 436 jra rei 437 438_lev3intr: 439 addql #1,_intrcnt+12 440 moveml #0xC0C0,sp@- 441 jbsr __leintr 442 moveml sp@+,#0x0303 443 addql #1,_cnt+V_INTR 444 jra rei 445 446_lev4intr: 447 addql #1,_intrcnt+16 448 addql #1,_cnt+V_INTR 449 jra rei | EX-PC not surpported yet XXXX 450 451_lev6intr: 452 addql #1,_intrcnt+24 453 moveml #0xC0C0,sp@- 454 jbsr __siointr 455 moveml sp@+,#0x0303 456 addql #1,_cnt+V_INTR 457 jra rei 458 459_lev5intr: 460#ifdef STACKCHECK 461 .globl _panicstr,_badkstack 462 cmpl #_kstack+NBPG,sp | are we still in stack page? 463 jcc Lstackok | yes, continue normally 464 tstl _curproc | if !curproc could have swtch_exit'ed, 465 jeq Lstackok | might be on tmpstk 466 tstl _panicstr | have we paniced? 467 jne Lstackok | yes, do not re-panic 468 movl sp@(4),tmpstk-4 | no, copy common 469 movl sp@,tmpstk-8 | frame info 470 movl sp,tmpstk-16 | no, save original SP 471 lea tmpstk-16,sp | switch to tmpstk 472 moveml #0xFFFE,sp@- | push remaining registers 473 movl #1,sp@- | is an overflow 474 jbsr _badkstack | badkstack(1, frame) 475 addql #4,sp 476 moveml sp@+,#0x7FFF | restore most registers 477 movl sp@,sp | and SP 478Lstackok: 479#endif 480 moveml #0xC0C0,sp@- 481 lea sp@(16),a1 | a1 = &clockframe 482 btst #CLK_INT,CLOCK_REG | system-clock intrrupt? 483 jeq Lnottimer | no, skip hardclock 484 movb #CLK_CLR,CLOCK_REG | clear system-clock interrupt 485 tstl _clock_on | system-clock started? 486 jeq Lnottimer | no, skip hardclock 487 addql #1,_intrcnt+28 | count hardclock interrupt 488 movl a1,sp@- 489 jbsr _hardclock | hardclock(&frame) 490 addql #4,sp 491Lnottimer: 492 moveml sp@+,#0x0303 | restore scratch regs 493 addql #1,_cnt+V_INTR | chalk up another interrupt 494 jra rei | all done 495 496_lev7intr: 497 addql #1,_intrcnt+36 498 clrl sp@- | pad SR to longword 499 moveml #0xFFFF,sp@- | save registers 500 movl usp,a0 | and save 501 movl a0,sp@(FR_SP) | the user stack pointer 502 jbsr _nmihand | call handler 503 movl sp@(FR_SP),a0 | restore 504 movl a0,usp | user SP 505 moveml sp@+,#0x7FFF | and remaining registers 506 addql #8,sp | pop SSP and align word 507 jra rei | all done 508 509/* 510 * Emulation of VAX REI instruction. 511 * 512 * This code deals with checking for and servicing ASTs 513 * (profiling, scheduling) and software interrupts (network, softclock). 514 * We check for ASTs first, just like the VAX. To avoid excess overhead 515 * the T_ASTFLT handling code will also check for software interrupts so we 516 * do not have to do it here. After identifing that we need an AST we 517 * drop the IPL to allow device interrupts. 518 * 519 * This code is complicated by the fact that sendsig may have been called 520 * necessitating a stack cleanup. 521 */ 522 .comm _ssir,1 523 .globl _astpending 524rei: 525#ifdef STACKCHECK 526 tstl _panicstr | have we paniced? 527 jne Ldorte1 | yes, do not make matters worse 528#endif 529 tstl _astpending | AST pending? 530 jeq Lchksir | no, go check for SIR 531Lrei1: 532 btst #5,sp@ | yes, are we returning to user mode? 533 jne Lchksir | no, go check for SIR 534 movw #PSL_LOWIPL,sr | lower SPL 535 clrl sp@- | stack adjust 536 moveml #0xFFFF,sp@- | save all registers 537 movl usp,a1 | including 538 movl a1,sp@(FR_SP) | the users SP 539 clrl sp@- | VA == none 540 clrl sp@- | code == none 541 movl #T_ASTFLT,sp@- | type == async system trap 542 jbsr _trap | go handle it 543 lea sp@(12),sp | pop value args 544 movl sp@(FR_SP),a0 | restore user SP 545 movl a0,usp | from save area 546 movw sp@(FR_ADJ),d0 | need to adjust stack? 547 jne Laststkadj | yes, go to it 548 moveml sp@+,#0x7FFF | no, restore most user regs 549 addql #8,sp | toss SP and stack adjust 550#ifdef STACKCHECK 551 jra Ldorte 552#else 553 rte | and do real RTE 554#endif 555Laststkadj: 556 lea sp@(FR_HW),a1 | pointer to HW frame 557 addql #8,a1 | source pointer 558 movl a1,a0 | source 559 addw d0,a0 | + hole size = dest pointer 560 movl a1@-,a0@- | copy 561 movl a1@-,a0@- | 8 bytes 562 movl a0,sp@(FR_SP) | new SSP 563 moveml sp@+,#0x7FFF | restore user registers 564 movl sp@,sp | and our SP 565#ifdef STACKCHECK 566 jra Ldorte 567#else 568 rte | and do real RTE 569#endif 570Lchksir: 571 tstb _ssir | SIR pending? 572 jeq Ldorte | no, all done 573 movl d0,sp@- | need a scratch register 574 movw sp@(4),d0 | get SR 575 andw #PSL_IPL7,d0 | mask all but IPL 576 jne Lnosir | came from interrupt, no can do 577 movl sp@+,d0 | restore scratch register 578Lgotsir: 579 movw #SPL1,sr | prevent others from servicing int 580 tstb _ssir | too late? 581 jeq Ldorte | yes, oh well... 582 clrl sp@- | stack adjust 583 moveml #0xFFFF,sp@- | save all registers 584 movl usp,a1 | including 585 movl a1,sp@(FR_SP) | the users SP 586 clrl sp@- | VA == none 587 clrl sp@- | code == none 588 movl #T_SSIR,sp@- | type == software interrupt 589 jbsr _trap | go handle it 590 lea sp@(12),sp | pop value args 591 movl sp@(FR_SP),a0 | restore 592 movl a0,usp | user SP 593 moveml sp@+,#0x7FFF | and all remaining registers 594 addql #8,sp | pop SP and stack adjust 595#ifdef STACKCHECK 596 jra Ldorte 597#else 598 rte 599#endif 600Lnosir: 601 movl sp@+,d0 | restore scratch register 602Ldorte: 603#ifdef STACKCHECK 604 movw #SPL6,sr | avoid trouble 605 btst #5,sp@ | are we returning to user mode? 606 jne Ldorte1 | no, skip it 607 movl a6,tmpstk-20 608 movl d0,tmpstk-76 609 moveq #0,d0 610 movb sp@(6),d0 | get format/vector 611 lsrl #3,d0 | convert to index 612 lea _exframesize,a6 | into exframesize 613 addl d0,a6 | to get pointer to correct entry 614 movw a6@,d0 | get size for this frame 615 addql #8,d0 | adjust for unaccounted for bytes 616 lea _kstackatbase,a6 | desired stack base 617 subl d0,a6 | - frame size == our stack 618 cmpl a6,sp | are we where we think? 619 jeq Ldorte2 | yes, skip it 620 lea tmpstk,a6 | will be using tmpstk 621 movl sp@(4),a6@- | copy common 622 movl sp@,a6@- | frame info 623 clrl a6@- 624 movl sp,a6@- | save sp 625 subql #4,a6 | skip over already saved a6 626 moveml #0x7FFC,a6@- | push remaining regs (d0/a6/a7 done) 627 lea a6@(-4),sp | switch to tmpstk (skip saved d0) 628 clrl sp@- | is an underflow 629 jbsr _badkstack | badkstack(0, frame) 630 addql #4,sp 631 moveml sp@+,#0x7FFF | restore most registers 632 movl sp@,sp | and SP 633 rte 634Ldorte2: 635 movl tmpstk-76,d0 636 movl tmpstk-20,a6 637Ldorte1: 638#endif 639 rte | real return 640 641/* 642 * Kernel access to the current processes kernel stack is via a fixed 643 * virtual address. It is at the same address as in the users VA space. 644 * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack. 645 */ 646 .data 647 .set _kstack,KERNELSTACK | KERNELSTACK(0x3ff00000) != USRSTACK 648_Umap: .long 0 649 .globl _kstack, _Umap 650 651/* 652 * Initialization 653 * 654 * Kernel is loaded at 0. 655 * VBR contains zero from ROM. Exceptions will continue to vector 656 * through ROM until MMU is turned on at which time they will vector 657 * through our table (vectors.s). 658 */ 659 .comm _lowram,4 660 661 .text 662 .globl _edata 663 .globl _etext,_end 664 .globl start 665start: 666 movw #PSL_HIGHIPL,sr | no interrupts 667 lea tmpstk,sp | give ourselves a temporary stack 668 clrl d0 | XXXX if loader set vbr = 0 669 movc d0,vbr | XXXX please remove these 2 lines 670/* 671 * a5 contains parameters address from booter. 672 * First, we copy whole parameters to Kernel InterFace Field 673 */ 674 675 movl #KIFF_SIZE,sp@- | KIFF size 676 pea _KernInter | KIFF address 677 pea a5@ | bootor's KIFF address 678 jbsr _bcopy 679 lea sp@(12),sp | pop value args 680 681 movl a5@(KI_MAXADDR),d0 | maxaddr 682 moveq #PGSHIFT,d1 683 lsrl d1,d0 | convert to page (click) number 684 movl d0,_maxmem | argument saved in maxmem 685 movl d0,_physmem | physmem = maxmem 686 clrl _lowram | lowram = 0 687 movl #0,a5 | kernel is loaded at 0 688 movl #CACHE_OFF,d0 689 movc d0,cacr | clear and disable on-chip cache(s) 690 691/* initialize source/destination control registers for movs */ 692 moveq #FC_USERD,d0 | user space 693 movc d0,sfc | as source 694 movc d0,dfc | and destination of transfers 695 696/* 697 * LUNA PIO initialization. 698 */ 699 movw PIO0_A,d0 | dipsw-1,2 (from port A&B) 700 movw d0,_dipswitch 701 702/* configure kernel and proc0 VA space so we can get going */ 703 .globl _Sysseg, _pmap_bootstrap, _avail_start 704 movl #_end,d5 | end of static kernel text/data 705 addl #NBPG-1,d5 706 andl #PG_FRAME,d5 | round to a page 707 movl d5,a4 | PA=VA 708 pea a5@ | firstpa 709 pea a4@ | nextpa 710 jbsr _pmap_bootstrap | bootstrap(firstpa, nextpa) 711 addql #8,sp 712 713/* 714 * Prepare to enable MMU. 715 */ 716 movl _Sysseg,a1 | system segment table addr read value (a KVA) 717 lea _protorp,a0 718 movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs 719 movl a1,a0@(4) | + segtable address 720 pmove a0@,srp | load the supervisor root pointer 721 movl #0x80000002,a0@ | reinit upper half for CRP loads 722/* we must set tt-registers here */ 723 lea _protott0,a0 724 .word 0xf010 | pmove a0@,mmutt0 725 .word 0x0800 726 lea _protott1,a0 727 .word 0xf010 | pmove a0@,mmutt1 728 .word 0x0c00 729 movl #0x82c0aa00,a2@ | value to load TC with 730 pmove a2@,tc | load it 731 732/* 733 * Should be running mapped from this point on 734 */ 735#ifdef FPCOPROC 736/* fpp check */ 737 movl a1,sp@- 738 jbsr _checkfpp | check fpp 739 frestore _fppnull | reset 740 movl sp@+,a1 741#endif 742/* select the software page size now */ 743 lea tmpstk,sp | temporary stack 744 jbsr _vm_set_page_size | select software page size 745/* set kernel stack, user SP, and initial pcb */ 746 lea _kstack,a1 | proc0 kernel stack 747 lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area 748 movl #USRSTACK-4,a2 749 movl a2,usp | init user SP 750 movl _proc0paddr,a1 | get proc0 pcb addr 751 movl a1,_curpcb | proc0 is running 752#ifdef FPCOPROC 753 clrl a1@(PCB_FPCTX) | ensure null FP context 754 movl a1,sp@- 755 jbsr _m68881_restore | restore it (does not kill a1) 756 addql #4,sp 757#endif 758/* flush TLB and turn on caches */ 759 jbsr _TBIA | invalidate TLB 760 movl #CACHE_ON,d0 761 movc d0,cacr | clear cache(s) 762/* final setup for C code */ 763 movw #PSL_LOWIPL,sr | lower SPL 764 movl d7,_boothowto | save reboot flags 765 movl d6,_bootdev | and boot device 766 jbsr _main | call main() 767 768/* proc[1] == init now running here; 769 * create a null exception frame and return to user mode in icode 770 */ 771 clrw sp@- | vector offset/frame type 772 clrl sp@- | return to icode location 0 773 movw #PSL_USER,sp@- | in user mode 774 rte 775 776/* 777 * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig(). 778 * 779 * Stack looks like: 780 * 781 * sp+0 -> signal number 782 * sp+4 signal specific code 783 * sp+8 pointer to signal context frame (scp) 784 * sp+12 address of handler 785 * sp+16 saved hardware state 786 * . 787 * . 788 * scp+0-> beginning of signal context frame 789 */ 790 .globl _sigcode, _esigcode, _sigcodetrap 791 .data 792_sigcode: 793 movl sp@(12),a0 | signal handler addr (4 bytes) 794 jsr a0@ | call signal handler (2 bytes) 795 addql #4,sp | pop signo (2 bytes) 796_sigcodetrap: 797 trap #1 | special syscall entry (2 bytes) 798 movl d0,sp@(4) | save errno (4 bytes) 799 moveq #1,d0 | syscall == exit (2 bytes) 800 trap #0 | exit(errno) (2 bytes) 801 .align 2 802_esigcode: 803 804/* 805 * Icode is copied out to process 1 to exec init. 806 * If the exec fails, process 1 exits. 807 */ 808 .globl _icode,_szicode 809 .text 810_icode: 811 clrl sp@- 812 pea pc@((argv-.)+2) 813 pea pc@((init-.)+2) 814 clrl sp@- 815 moveq #SYS_execve,d0 816 trap #0 817 moveq #SYS_exit,d0 818 trap #0 819init: 820 .asciz "/sbin/init" 821 .even 822argv: 823 .long init+6-_icode | argv[0] = "init" ("/sbin/init" + 6) 824 .long eicode-_icode | argv[1] follows icode after copyout 825 .long 0 826eicode: 827 828_szicode: 829 .long _szicode-_icode 830 831/* 832 * Primitives 833 */ 834 835#ifdef GPROF 836#define ENTRY(name) \ 837 .globl _/**/name; _/**/name: link a6,#0; jbsr mcount; unlk a6 838#define ALTENTRY(name, rname) \ 839 ENTRY(name); jra rname+12 840#else 841#define ENTRY(name) \ 842 .globl _/**/name; _/**/name: 843#define ALTENTRY(name, rname) \ 844 .globl _/**/name; _/**/name: 845#endif 846 847/* 848 * For gcc2 849 */ 850ENTRY(__main) 851 rts 852 853/* 854 * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 855 * 856 * Copy a null terminated string from the user address space into 857 * the kernel address space. 858 * NOTE: maxlength must be < 64K 859 */ 860ENTRY(copyinstr) 861 movl _curpcb,a0 | current pcb 862 movl #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults 863 movl sp@(4),a0 | a0 = fromaddr 864 movl sp@(8),a1 | a1 = toaddr 865 moveq #0,d0 866 movw sp@(14),d0 | d0 = maxlength 867 jlt Lcisflt1 | negative count, error 868 jeq Lcisdone | zero count, all done 869 subql #1,d0 | set up for dbeq 870Lcisloop: 871 movsb a0@+,d1 | grab a byte 872 nop 873 movb d1,a1@+ | copy it 874 dbeq d0,Lcisloop | if !null and more, continue 875 jne Lcisflt2 | ran out of room, error 876 moveq #0,d0 | got a null, all done 877Lcisdone: 878 tstl sp@(16) | return length desired? 879 jeq Lcisret | no, just return 880 subl sp@(4),a0 | determine how much was copied 881 movl sp@(16),a1 | return location 882 movl a0,a1@ | stash it 883Lcisret: 884 movl _curpcb,a0 | current pcb 885 clrl a0@(PCB_ONFAULT) | clear fault addr 886 rts 887Lcisflt1: 888 moveq #EFAULT,d0 | copy fault 889 jra Lcisdone 890Lcisflt2: 891 moveq #ENAMETOOLONG,d0 | ran out of space 892 jra Lcisdone 893 894/* 895 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 896 * 897 * Copy a null terminated string from the kernel 898 * address space to the user address space. 899 * NOTE: maxlength must be < 64K 900 */ 901ENTRY(copyoutstr) 902 movl _curpcb,a0 | current pcb 903 movl #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults 904 movl sp@(4),a0 | a0 = fromaddr 905 movl sp@(8),a1 | a1 = toaddr 906 moveq #0,d0 907 movw sp@(14),d0 | d0 = maxlength 908 jlt Lcosflt1 | negative count, error 909 jeq Lcosdone | zero count, all done 910 subql #1,d0 | set up for dbeq 911Lcosloop: 912 movb a0@+,d1 | grab a byte 913 movsb d1,a1@+ | copy it 914 nop 915 dbeq d0,Lcosloop | if !null and more, continue 916 jne Lcosflt2 | ran out of room, error 917 moveq #0,d0 | got a null, all done 918Lcosdone: 919 tstl sp@(16) | return length desired? 920 jeq Lcosret | no, just return 921 subl sp@(4),a0 | determine how much was copied 922 movl sp@(16),a1 | return location 923 movl a0,a1@ | stash it 924Lcosret: 925 movl _curpcb,a0 | current pcb 926 clrl a0@(PCB_ONFAULT) | clear fault addr 927 rts 928Lcosflt1: 929 moveq #EFAULT,d0 | copy fault 930 jra Lcosdone 931Lcosflt2: 932 moveq #ENAMETOOLONG,d0 | ran out of space 933 jra Lcosdone 934 935/* 936 * copystr(fromaddr, toaddr, maxlength, &lencopied) 937 * 938 * Copy a null terminated string from one point to another in 939 * the kernel address space. 940 * NOTE: maxlength must be < 64K 941 */ 942ENTRY(copystr) 943 movl sp@(4),a0 | a0 = fromaddr 944 movl sp@(8),a1 | a1 = toaddr 945 moveq #0,d0 946 movw sp@(14),d0 | d0 = maxlength 947 jlt Lcsflt1 | negative count, error 948 jeq Lcsdone | zero count, all done 949 subql #1,d0 | set up for dbeq 950Lcsloop: 951 movb a0@+,a1@+ | copy a byte 952 dbeq d0,Lcsloop | if !null and more, continue 953 jne Lcsflt2 | ran out of room, error 954 moveq #0,d0 | got a null, all done 955Lcsdone: 956 tstl sp@(16) | return length desired? 957 jeq Lcsret | no, just return 958 subl sp@(4),a0 | determine how much was copied 959 movl sp@(16),a1 | return location 960 movl a0,a1@ | stash it 961Lcsret: 962 rts 963Lcsflt1: 964 moveq #EFAULT,d0 | copy fault 965 jra Lcsdone 966Lcsflt2: 967 moveq #ENAMETOOLONG,d0 | ran out of space 968 jra Lcsdone 969 970/* 971 * Copyin(from_user, to_kernel, len) 972 * Copyout(from_kernel, to_user, len) 973 * 974 * Copy specified amount of data between kernel and user space. 975 * 976 * XXX both use the DBcc instruction which has 16-bit limitation so only 977 * 64k units can be copied, where "unit" is either a byte or a longword 978 * depending on alignment. To be safe, assume it can copy at most 979 * 64k bytes. Don't make MAXBSIZE or MAXPHYS larger than 64k without 980 * fixing this code! 981 */ 982ENTRY(copyin) 983 movl d2,sp@- | scratch register 984 movl _curpcb,a0 | current pcb 985 movl #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults 986 movl sp@(16),d2 | check count 987 jlt Lciflt | negative, error 988 jeq Lcidone | zero, done 989 movl sp@(8),a0 | src address 990 movl sp@(12),a1 | dest address 991 movl a0,d0 992 btst #0,d0 | src address odd? 993 jeq Lcieven | no, go check dest 994 movsb a0@+,d1 | yes, get a byte 995 nop 996 movb d1,a1@+ | put a byte 997 subql #1,d2 | adjust count 998 jeq Lcidone | exit if done 999Lcieven: 1000 movl a1,d0 1001 btst #0,d0 | dest address odd? 1002 jne Lcibyte | yes, must copy by bytes 1003 movl d2,d0 | no, get count 1004 lsrl #2,d0 | convert to longwords 1005 jeq Lcibyte | no longwords, copy bytes 1006 subql #1,d0 | set up for dbf 1007Lcilloop: 1008 movsl a0@+,d1 | get a long 1009 nop 1010 movl d1,a1@+ | put a long 1011 dbf d0,Lcilloop | til done 1012 andl #3,d2 | what remains 1013 jeq Lcidone | all done 1014Lcibyte: 1015 subql #1,d2 | set up for dbf 1016Lcibloop: 1017 movsb a0@+,d1 | get a byte 1018 nop 1019 movb d1,a1@+ | put a byte 1020 dbf d2,Lcibloop | til done 1021Lcidone: 1022 moveq #0,d0 | success 1023Lciexit: 1024 movl _curpcb,a0 | current pcb 1025 clrl a0@(PCB_ONFAULT) | clear fault catcher 1026 movl sp@+,d2 | restore scratch reg 1027 rts 1028Lciflt: 1029 moveq #EFAULT,d0 | got a fault 1030 jra Lciexit 1031 1032ENTRY(copyout) 1033 movl d2,sp@- | scratch register 1034 movl _curpcb,a0 | current pcb 1035 movl #Lcoflt,a0@(PCB_ONFAULT) | catch faults 1036 movl sp@(16),d2 | check count 1037 jlt Lcoflt | negative, error 1038 jeq Lcodone | zero, done 1039 movl sp@(8),a0 | src address 1040 movl sp@(12),a1 | dest address 1041 movl a0,d0 1042 btst #0,d0 | src address odd? 1043 jeq Lcoeven | no, go check dest 1044 movb a0@+,d1 | yes, get a byte 1045 movsb d1,a1@+ | put a byte 1046 nop 1047 subql #1,d2 | adjust count 1048 jeq Lcodone | exit if done 1049Lcoeven: 1050 movl a1,d0 1051 btst #0,d0 | dest address odd? 1052 jne Lcobyte | yes, must copy by bytes 1053 movl d2,d0 | no, get count 1054 lsrl #2,d0 | convert to longwords 1055 jeq Lcobyte | no longwords, copy bytes 1056 subql #1,d0 | set up for dbf 1057Lcolloop: 1058 movl a0@+,d1 | get a long 1059 movsl d1,a1@+ | put a long 1060 nop 1061 dbf d0,Lcolloop | til done 1062 andl #3,d2 | what remains 1063 jeq Lcodone | all done 1064Lcobyte: 1065 subql #1,d2 | set up for dbf 1066Lcobloop: 1067 movb a0@+,d1 | get a byte 1068 movsb d1,a1@+ | put a byte 1069 nop 1070 dbf d2,Lcobloop | til done 1071Lcodone: 1072 moveq #0,d0 | success 1073Lcoexit: 1074 movl _curpcb,a0 | current pcb 1075 clrl a0@(PCB_ONFAULT) | clear fault catcher 1076 movl sp@+,d2 | restore scratch reg 1077 rts 1078Lcoflt: 1079 moveq #EFAULT,d0 | got a fault 1080 jra Lcoexit 1081 1082/* 1083 * non-local gotos 1084 */ 1085ENTRY(setjmp) 1086 movl sp@(4),a0 | savearea pointer 1087 moveml #0xFCFC,a0@ | save d2-d7/a2-a7 1088 movl sp@,a0@(48) | and return address 1089 moveq #0,d0 | return 0 1090 rts 1091 1092ENTRY(longjmp) 1093 movl sp@(4),a0 1094 moveml a0@+,#0xFCFC 1095 movl a0@,sp@ 1096 moveq #1,d0 1097 rts 1098 1099/* 1100 * The following primitives manipulate the run queues. 1101 * _whichqs tells which of the 32 queues _qs 1102 * have processes in them. Setrq puts processes into queues, Remrq 1103 * removes them from queues. The running process is on no queue, 1104 * other processes are on a queue related to p->p_pri, divided by 4 1105 * actually to shrink the 0-127 range of priorities into the 32 available 1106 * queues. 1107 */ 1108 1109 .globl _whichqs,_qs,_cnt,_panic 1110 .globl _curproc,_want_resched 1111 1112/* 1113 * Setrq(p) 1114 * 1115 * Call should be made at spl6(), and p->p_stat should be SRUN 1116 */ 1117ENTRY(setrq) 1118 movl sp@(4),a0 1119 tstl a0@(P_RLINK) 1120 jeq Lset1 1121 movl #Lset2,sp@- 1122 jbsr _panic 1123Lset1: 1124 clrl d0 1125 movb a0@(P_PRI),d0 1126 lsrb #2,d0 1127 movl _whichqs,d1 1128 bset d0,d1 1129 movl d1,_whichqs 1130 lslb #3,d0 1131 addl #_qs,d0 1132 movl d0,a0@(P_LINK) 1133 movl d0,a1 1134 movl a1@(P_RLINK),a0@(P_RLINK) 1135 movl a0,a1@(P_RLINK) 1136 movl a0@(P_RLINK),a1 1137 movl a0,a1@(P_LINK) 1138 rts 1139 1140Lset2: 1141 .asciz "setrq" 1142 .even 1143 1144/* 1145 * Remrq(p) 1146 * 1147 * Call should be made at spl6(). 1148 */ 1149ENTRY(remrq) 1150 movl sp@(4),a0 1151 clrl d0 1152 movb a0@(P_PRI),d0 1153 lsrb #2,d0 1154 movl _whichqs,d1 1155 bclr d0,d1 1156 jne Lrem1 1157 movl #Lrem3,sp@- 1158 jbsr _panic 1159Lrem1: 1160 movl d1,_whichqs 1161 movl a0@(P_LINK),a1 1162 movl a0@(P_RLINK),a1@(P_RLINK) 1163 movl a0@(P_RLINK),a1 1164 movl a0@(P_LINK),a1@(P_LINK) 1165 movl #_qs,a1 1166 movl d0,d1 1167 lslb #3,d1 1168 addl d1,a1 1169 cmpl a1@(P_LINK),a1 1170 jeq Lrem2 1171 movl _whichqs,d1 1172 bset d0,d1 1173 movl d1,_whichqs 1174Lrem2: 1175 clrl a0@(P_RLINK) 1176 rts 1177 1178Lrem3: 1179 .asciz "remrq" 1180Lsw0: 1181 .asciz "swtch" 1182 .even 1183 1184 .globl _curpcb 1185 .globl _masterpaddr | XXX compatibility (debuggers) 1186 .data 1187_masterpaddr: | XXX compatibility (debuggers) 1188_curpcb: 1189 .long 0 1190mdpflag: 1191 .byte 0 | copy of proc md_flags low byte 1192 .align 2 1193 .comm nullpcb,SIZEOF_PCB 1194 .text 1195 1196/* 1197 * At exit of a process, do a swtch for the last time. 1198 * The mapping of the pcb at p->p_addr has already been deleted, 1199 * and the memory for the pcb+stack has been freed. 1200 * The ipl is high enough to prevent the memory from being reallocated. 1201 */ 1202ENTRY(swtch_exit) 1203 movl #nullpcb,_curpcb | save state into garbage pcb 1204 lea tmpstk,sp | goto a tmp stack 1205 jra _cpu_swtch 1206 1207/* 1208 * When no processes are on the runq, Swtch branches to idle 1209 * to wait for something to come ready. 1210 */ 1211 .globl idle 1212Lidle: 1213 stop #PSL_LOWIPL 1214idle: 1215 movw #PSL_HIGHIPL,sr 1216 tstl _whichqs 1217 jeq Lidle 1218 movw #PSL_LOWIPL,sr 1219 jra Lsw1 1220 1221Lbadsw: 1222 movl #Lsw0,sp@- 1223 jbsr _panic 1224 /*NOTREACHED*/ 1225 1226/* 1227 * cpu_swtch() 1228 * 1229 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1230 * entire ATC. The effort involved in selective flushing may not be 1231 * worth it, maybe we should just flush the whole thing? 1232 * 1233 * NOTE 2: With the new VM layout we now no longer know if an inactive 1234 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1235 * bit). For now, we just always flush the full ATC. 1236 */ 1237ENTRY(cpu_swtch) 1238 movl _curpcb,a0 | current pcb 1239 movw sr,a0@(PCB_PS) | save sr before changing ipl 1240#ifdef notyet 1241 movl _curproc,sp@- | remember last proc running 1242#endif 1243 clrl _curproc 1244 addql #1,_cnt+V_SWTCH 1245 1246Lsw1: 1247 /* 1248 * Find the highest-priority queue that isn't empty, 1249 * then take the first proc from that queue. 1250 */ 1251 clrl d0 1252 lea _whichqs,a0 1253 movl a0@,d1 1254Lswchk: 1255 btst d0,d1 1256 jne Lswfnd 1257 addqb #1,d0 1258 cmpb #32,d0 1259 jne Lswchk 1260 jra idle 1261Lswfnd: 1262 movw #PSL_HIGHIPL,sr | lock out interrupts 1263 movl a0@,d1 | and check again... 1264 bclr d0,d1 1265 jeq Lsw1 | proc moved, rescan 1266 movl d1,a0@ | update whichqs 1267 moveq #1,d1 | double check for higher priority 1268 lsll d0,d1 | process (which may have snuck in 1269 subql #1,d1 | while we were finding this one) 1270 andl a0@,d1 1271 jeq Lswok | no one got in, continue 1272 movl a0@,d1 1273 bset d0,d1 | otherwise put this one back 1274 movl d1,a0@ 1275 jra Lsw1 | and rescan 1276Lswok: 1277 movl d0,d1 1278 lslb #3,d1 | convert queue number to index 1279 addl #_qs,d1 | locate queue (q) 1280 movl d1,a1 1281 cmpl a1@(P_LINK),a1 | anyone on queue? 1282 jeq Lbadsw | no, panic 1283 movl a1@(P_LINK),a0 | p = q->p_link 1284 movl a0@(P_LINK),a1@(P_LINK) | q->p_link = p->p_link 1285 movl a0@(P_LINK),a1 | q = p->p_link 1286 movl a0@(P_RLINK),a1@(P_RLINK) | q->p_rlink = p->p_rlink 1287 cmpl a0@(P_LINK),d1 | anyone left on queue? 1288 jeq Lsw2 | no, skip 1289 movl _whichqs,d1 1290 bset d0,d1 | yes, reset bit 1291 movl d1,_whichqs 1292Lsw2: 1293 movl a0,_curproc 1294 clrl _want_resched 1295#ifdef notyet 1296 movl sp@+,a1 1297 cmpl a0,a1 | switching to same proc? 1298 jeq Lswdone | yes, skip save and restore 1299#endif 1300 /* 1301 * Save state of previous process in its pcb. 1302 */ 1303 movl _curpcb,a1 1304 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1305 movl usp,a2 | grab USP (a2 has been saved) 1306 movl a2,a1@(PCB_USP) | and save it 1307#ifdef FPCOPROC 1308 lea a1@(PCB_FPCTX),a2 | pointer to FP save area 1309 fsave a2@ | save FP state 1310 tstb a2@ | null state frame? 1311 jeq Lswnofpsave | yes, all done 1312 fmovem fp0-fp7,a2@(216) | save FP general registers 1313 fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers 1314Lswnofpsave: 1315#endif 1316 1317#ifdef DIAGNOSTIC 1318 tstl a0@(P_WCHAN) 1319 jne Lbadsw 1320 cmpb #SRUN,a0@(P_STAT) 1321 jne Lbadsw 1322#endif 1323 clrl a0@(P_RLINK) | clear back link 1324 movb a0@(P_MDFLAG+3),mdpflag | low byte of p_md.md_flags 1325 movl a0@(P_ADDR),a1 | get p_addr 1326 movl a1,_curpcb 1327 1328 /* see if pmap_activate needs to be called; should remove this */ 1329 movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace 1330#ifdef DIAGNOSTIC 1331 tstl a0 | map == VM_MAP_NULL? 1332 jeq Lbadsw | panic 1333#endif 1334 lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap 1335 tstl a0@(PM_STCHG) | pmap->st_changed? 1336 jeq Lswnochg | no, skip 1337 pea a1@ | push pcb (at p_addr) 1338 pea a0@ | push pmap 1339 jbsr _pmap_activate | pmap_activate(pmap, pcb) 1340 addql #8,sp 1341 movl _curpcb,a1 | restore p_addr 1342Lswnochg: 1343 1344 movl #PGSHIFT,d1 1345 movl a1,d0 1346 lsrl d1,d0 | convert p_addr to page number 1347 lsll #2,d0 | and now to Sysmap offset 1348 addl _Sysmap,d0 | add Sysmap base to get PTE addr 1349#ifdef notdef 1350 movw #PSL_HIGHIPL,sr | go crit while changing PTEs 1351#endif 1352 lea tmpstk,sp | now goto a tmp stack for NMI 1353 movl d0,a0 | address of new context 1354 movl _Umap,a2 | address of PTEs for kstack 1355 moveq #UPAGES-1,d0 | sizeof kstack 1356Lres1: 1357 movl a0@+,d1 | get PTE 1358 andl #~PG_PROT,d1 | mask out old protection 1359 orl #PG_RW+PG_V,d1 | ensure valid and writable 1360 movl d1,a2@+ | load it up 1361 dbf d0,Lres1 | til done 1362 movl #CACHE_CLR,d0 1363 movc d0,cacr | invalidate cache(s) 1364 pflusha | flush entire TLB 1365 movl a1@(PCB_USTP),d0 | get USTP 1366 moveq #PGSHIFT,d1 1367 lsll d1,d0 | convert to addr 1368 lea _protorp,a0 | CRP prototype 1369 movl d0,a0@(4) | stash USTP 1370 pmove a0@,crp | load new user root pointer 1371 moveml a1@(PCB_REGS),#0xFCFC | and registers 1372 movl a1@(PCB_USP),a0 1373 movl a0,usp | and USP 1374#ifdef FPCOPROC 1375 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1376 tstb a0@ | null state frame? 1377 jeq Lresfprest | yes, easy 1378 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 1379 fmovem a0@(216),fp0-fp7 | restore FP general registers 1380Lresfprest: 1381 frestore a0@ | restore state 1382#endif 1383 movw a1@(PCB_PS),sr | no, restore PS 1384 moveq #1,d0 | return 1 (for alternate returns) 1385 rts 1386 1387/* 1388 * savectx(pcb, altreturn) 1389 * Update pcb, saving current processor state and arranging 1390 * for alternate return ala longjmp in swtch if altreturn is true. 1391 */ 1392ENTRY(savectx) 1393 movl sp@(4),a1 1394 movw sr,a1@(PCB_PS) 1395 movl usp,a0 | grab USP 1396 movl a0,a1@(PCB_USP) | and save it 1397 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1398#ifdef FPCOPROC 1399 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1400 fsave a0@ | save FP state 1401 tstb a0@ | null state frame? 1402 jeq Lsvnofpsave | yes, all done 1403 fmovem fp0-fp7,a0@(216) | save FP general registers 1404 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 1405Lsvnofpsave: 1406#endif 1407 tstl sp@(8) | altreturn? 1408 jeq Lsavedone 1409 movl sp,d0 | relocate current sp relative to a1 1410 subl #_kstack,d0 | (sp is relative to kstack): 1411 addl d0,a1 | a1 += sp - kstack; 1412 movl sp@,a1@ | write return pc at (relocated) sp@ 1413Lsavedone: 1414 moveq #0,d0 | return 0 1415 rts 1416 1417/* 1418 * {fu,su},{byte,sword,word} 1419 */ 1420ALTENTRY(fuiword, _fuword) 1421ENTRY(fuword) 1422 movl sp@(4),a0 | address to read 1423 movl _curpcb,a1 | current pcb 1424 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1425 movsl a0@,d0 | do read from user space 1426 nop 1427 jra Lfsdone 1428 1429ENTRY(fusword) 1430 movl sp@(4),a0 1431 movl _curpcb,a1 | current pcb 1432 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1433 moveq #0,d0 1434 movsw a0@,d0 | do read from user space 1435 nop 1436 jra Lfsdone 1437 1438/* Just like fusword, but tells trap code not to page in. */ 1439ENTRY(fuswintr) 1440 movl sp@(4),a0 1441 movl _curpcb,a1 1442 movl #_fswintr,a1@(PCB_ONFAULT) 1443 moveq #0,d0 1444 movsw a0@,d0 1445 nop 1446 jra Lfsdone 1447 1448ALTENTRY(fuibyte, _fubyte) 1449ENTRY(fubyte) 1450 movl sp@(4),a0 | address to read 1451 movl _curpcb,a1 | current pcb 1452 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1453 moveq #0,d0 1454 movsb a0@,d0 | do read from user space 1455 nop 1456 jra Lfsdone 1457 1458Lfserr: 1459 moveq #-1,d0 | error indicator 1460Lfsdone: 1461 clrl a1@(PCB_ONFAULT) | clear fault address 1462 rts 1463 1464/* Just like Lfserr, but the address is different (& exported). */ 1465 .globl _fswintr 1466_fswintr: 1467 moveq #-1,d0 1468 jra Lfsdone 1469 1470 1471/* 1472 * Write a longword in user instruction space. 1473 * Largely the same as suword but with a final i-cache purge on those 1474 * machines with split caches. 1475 */ 1476ENTRY(suiword) 1477 movl sp@(4),a0 | address to write 1478 movl sp@(8),d0 | value to put there 1479 movl _curpcb,a1 | current pcb 1480 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1481 movsl d0,a0@ | do write to user space 1482 nop 1483 moveq #0,d0 | indicate no fault 1484 movl #IC_CLEAR,d1 1485 movc d1,cacr | invalidate i-cache 1486 jra Lfsdone 1487 1488ENTRY(suword) 1489 movl sp@(4),a0 | address to write 1490 movl sp@(8),d0 | value to put there 1491 movl _curpcb,a1 | current pcb 1492 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1493 movsl d0,a0@ | do write to user space 1494 nop 1495 moveq #0,d0 | indicate no fault 1496 jra Lfsdone 1497 1498ENTRY(susword) 1499 movl sp@(4),a0 | address to write 1500 movw sp@(10),d0 | value to put there 1501 movl _curpcb,a1 | current pcb 1502 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1503 movsw d0,a0@ | do write to user space 1504 nop 1505 moveq #0,d0 | indicate no fault 1506 jra Lfsdone 1507 1508ENTRY(suswintr) 1509 movl sp@(4),a0 1510 movw sp@(10),d0 1511 movl _curpcb,a1 1512 movl #_fswintr,a1@(PCB_ONFAULT) 1513 movsw d0,a0@ 1514 nop 1515 moveq #0,d0 1516 jra Lfsdone 1517 1518ALTENTRY(suibyte, _subyte) 1519ENTRY(subyte) 1520 movl sp@(4),a0 | address to write 1521 movb sp@(11),d0 | value to put there 1522 movl _curpcb,a1 | current pcb 1523 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1524 movsb d0,a0@ | do write to user space 1525 nop 1526 moveq #0,d0 | indicate no fault 1527 jra Lfsdone 1528 1529/* 1530 * Invalidate entire TLB. 1531 */ 1532ENTRY(TBIA) 1533__TBIA: 1534 pflusha | flush entire TLB 1535 movl #DC_CLEAR,d0 1536 movc d0,cacr | invalidate on-chip d-cache 1537 rts 1538 1539/* 1540 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1541 */ 1542ENTRY(TBIS) 1543#ifdef DEBUG 1544 tstl fulltflush | being conservative? 1545 jne __TBIA | yes, flush entire TLB 1546#endif 1547 1548 movl sp@(4),a0 | get addr to flush 1549 pflush #0,#0,a0@ | flush address from both sides 1550 movl #DC_CLEAR,d0 1551 movc d0,cacr | invalidate on-chip data cache 1552 rts 1553 1554/* 1555 * Invalidate supervisor side of TLB 1556 */ 1557ENTRY(TBIAS) 1558#ifdef DEBUG 1559 tstl fulltflush | being conservative? 1560 jne __TBIA | yes, flush everything 1561#endif 1562 pflush #4,#4 | flush supervisor TLB entries 1563 movl #DC_CLEAR,d0 1564 movc d0,cacr | invalidate on-chip d-cache 1565 rts 1566 1567/* 1568 * Invalidate user side of TLB 1569 */ 1570ENTRY(TBIAU) 1571#ifdef DEBUG 1572 tstl fulltflush | being conservative? 1573 jne __TBIA | yes, flush everything 1574#endif 1575 pflush #0,#4 | flush user TLB entries 1576 movl #DC_CLEAR,d0 1577 movc d0,cacr | invalidate on-chip d-cache 1578 rts 1579 1580/* 1581 * Invalidate instruction cache 1582 */ 1583ENTRY(ICIA) 1584 movl #IC_CLEAR,d0 1585 movc d0,cacr | invalidate i-cache 1586 rts 1587 1588ENTRY(PCIA) 1589 movl #DC_CLEAR,d0 1590 movc d0,cacr | invalidate on-chip d-cache 1591 rts 1592 1593/* 1594 * Get callers current SP value. 1595 * Note that simply taking the address of a local variable in a C function 1596 * doesn't work because callee saved registers may be outside the stack frame 1597 * defined by A6 (e.g. GCC generated code). 1598 */ 1599 .globl _getsp 1600_getsp: 1601 movl sp,d0 | get current SP 1602 addql #4,d0 | compensate for return address 1603 rts 1604 1605 .globl _getsfc, _getdfc 1606_getsfc: 1607 movc sfc,d0 1608 rts 1609_getdfc: 1610 movc dfc,d0 1611 rts 1612 1613/* 1614 * Load a new user segment table pointer. 1615 */ 1616ENTRY(loadustp) 1617 movl sp@(4),d0 | new USTP 1618 moveq #PGSHIFT,d1 1619 lsll d1,d0 | convert to addr 1620 lea _protorp,a0 | CRP prototype 1621 movl d0,a0@(4) | stash USTP 1622 pmove a0@,crp | load root pointer 1623 movl #DC_CLEAR,d0 1624 movc d0,cacr | invalidate on-chip d-cache 1625 rts 1626 1627ENTRY(ploadw) 1628 movl sp@(4),a0 | address to load 1629 ploadw #1,a0@ | pre-load translation 1630 rts 1631 1632/* 1633 * Set processor priority level calls. Most are implemented with 1634 * inline asm expansions. However, spl0 requires special handling 1635 * as we need to check for our emulated software interrupts. 1636 */ 1637 1638ENTRY(spl0) 1639 moveq #0,d0 1640 movw sr,d0 | get old SR for return 1641 movw #PSL_LOWIPL,sr | restore new SR 1642 tstb _ssir | software interrupt pending? 1643 jeq Lspldone | no, all done 1644 subql #4,sp | make room for RTE frame 1645 movl sp@(4),sp@(2) | position return address 1646 clrw sp@(6) | set frame type 0 1647 movw #PSL_LOWIPL,sp@ | and new SR 1648 jra Lgotsir | go handle it 1649Lspldone: 1650 rts 1651 1652ENTRY(_insque) 1653 movw sr,d0 1654 movw #PSL_HIGHIPL,sr | atomic 1655 movl sp@(8),a0 | where to insert (after) 1656 movl sp@(4),a1 | element to insert (e) 1657 movl a0@,a1@ | e->next = after->next 1658 movl a0,a1@(4) | e->prev = after 1659 movl a1,a0@ | after->next = e 1660 movl a1@,a0 1661 movl a1,a0@(4) | e->next->prev = e 1662 movw d0,sr 1663 rts 1664 1665ENTRY(_remque) 1666 movw sr,d0 1667 movw #PSL_HIGHIPL,sr | atomic 1668 movl sp@(4),a0 | element to remove (e) 1669 movl a0@,a1 1670 movl a0@(4),a0 1671 movl a0,a1@(4) | e->next->prev = e->prev 1672 movl a1,a0@ | e->prev->next = e->next 1673 movw d0,sr 1674 rts 1675 1676/* 1677 * bzero(addr, count) 1678 */ 1679ALTENTRY(blkclr, _bzero) 1680ENTRY(bzero) 1681 movl sp@(4),a0 | address 1682 movl sp@(8),d0 | count 1683 jeq Lbzdone | if zero, nothing to do 1684 movl a0,d1 1685 btst #0,d1 | address odd? 1686 jeq Lbzeven | no, can copy words 1687 clrb a0@+ | yes, zero byte to get to even boundary 1688 subql #1,d0 | decrement count 1689 jeq Lbzdone | none left, all done 1690Lbzeven: 1691 movl d0,d1 1692 andl #31,d0 1693 lsrl #5,d1 | convert count to 8*longword count 1694 jeq Lbzbyte | no such blocks, zero byte at a time 1695Lbzloop: 1696 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 1697 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 1698 subql #1,d1 | one more block zeroed 1699 jne Lbzloop | more to go, do it 1700 tstl d0 | partial block left? 1701 jeq Lbzdone | no, all done 1702Lbzbyte: 1703 clrb a0@+ 1704 subql #1,d0 | one more byte cleared 1705 jne Lbzbyte | more to go, do it 1706Lbzdone: 1707 rts 1708 1709/* 1710 * strlen(str) 1711 */ 1712ENTRY(strlen) 1713 moveq #-1,d0 1714 movl sp@(4),a0 | string 1715Lslloop: 1716 addql #1,d0 | increment count 1717 tstb a0@+ | null? 1718 jne Lslloop | no, keep going 1719 rts 1720 1721/* 1722 * bcmp(s1, s2, len) 1723 * 1724 * WARNING! This guy only works with counts up to 64K 1725 */ 1726ENTRY(bcmp) 1727 movl sp@(4),a0 | string 1 1728 movl sp@(8),a1 | string 2 1729 moveq #0,d0 1730 movw sp@(14),d0 | length 1731 jeq Lcmpdone | if zero, nothing to do 1732 subqw #1,d0 | set up for DBcc loop 1733Lcmploop: 1734 cmpmb a0@+,a1@+ | equal? 1735 dbne d0,Lcmploop | yes, keep going 1736 addqw #1,d0 | +1 gives zero on match 1737Lcmpdone: 1738 rts 1739 1740/* 1741 * {ov}bcopy(from, to, len) 1742 * 1743 * Works for counts up to 128K. 1744 */ 1745ALTENTRY(ovbcopy, _bcopy) 1746ENTRY(bcopy) 1747 movl sp@(12),d0 | get count 1748 jeq Lcpyexit | if zero, return 1749 movl sp@(4),a0 | src address 1750 movl sp@(8),a1 | dest address 1751 cmpl a1,a0 | src before dest? 1752 jlt Lcpyback | yes, copy backwards (avoids overlap) 1753 movl a0,d1 1754 btst #0,d1 | src address odd? 1755 jeq Lcfeven | no, go check dest 1756 movb a0@+,a1@+ | yes, copy a byte 1757 subql #1,d0 | update count 1758 jeq Lcpyexit | exit if done 1759Lcfeven: 1760 movl a1,d1 1761 btst #0,d1 | dest address odd? 1762 jne Lcfbyte | yes, must copy by bytes 1763 movl d0,d1 | no, get count 1764 lsrl #2,d1 | convert to longwords 1765 jeq Lcfbyte | no longwords, copy bytes 1766 subql #1,d1 | set up for dbf 1767Lcflloop: 1768 movl a0@+,a1@+ | copy longwords 1769 dbf d1,Lcflloop | til done 1770 andl #3,d0 | get remaining count 1771 jeq Lcpyexit | done if none 1772Lcfbyte: 1773 subql #1,d0 | set up for dbf 1774Lcfbloop: 1775 movb a0@+,a1@+ | copy bytes 1776 dbf d0,Lcfbloop | til done 1777Lcpyexit: 1778 rts 1779Lcpyback: 1780 addl d0,a0 | add count to src 1781 addl d0,a1 | add count to dest 1782 movl a0,d1 1783 btst #0,d1 | src address odd? 1784 jeq Lcbeven | no, go check dest 1785 movb a0@-,a1@- | yes, copy a byte 1786 subql #1,d0 | update count 1787 jeq Lcpyexit | exit if done 1788Lcbeven: 1789 movl a1,d1 1790 btst #0,d1 | dest address odd? 1791 jne Lcbbyte | yes, must copy by bytes 1792 movl d0,d1 | no, get count 1793 lsrl #2,d1 | convert to longwords 1794 jeq Lcbbyte | no longwords, copy bytes 1795 subql #1,d1 | set up for dbf 1796Lcblloop: 1797 movl a0@-,a1@- | copy longwords 1798 dbf d1,Lcblloop | til done 1799 andl #3,d0 | get remaining count 1800 jeq Lcpyexit | done if none 1801Lcbbyte: 1802 subql #1,d0 | set up for dbf 1803Lcbbloop: 1804 movb a0@-,a1@- | copy bytes 1805 dbf d0,Lcbbloop | til done 1806 rts 1807 1808/* 1809 * Emulate fancy VAX string operations: 1810 * scanc(count, startc, table, mask) 1811 * skpc(mask, count, startc) 1812 * locc(mask, count, startc) 1813 */ 1814ENTRY(scanc) 1815 movl sp@(4),d0 | get length 1816 jeq Lscdone | nothing to do, return 1817 movl sp@(8),a0 | start of scan 1818 movl sp@(12),a1 | table to compare with 1819 movb sp@(19),d1 | and mask to use 1820 movw d2,sp@- | need a scratch register 1821 clrw d2 | clear it out 1822 subqw #1,d0 | adjust for dbra 1823Lscloop: 1824 movb a0@+,d2 | get character 1825 movb a1@(0,d2:w),d2 | get table entry 1826 andb d1,d2 | mask it 1827 dbne d0,Lscloop | keep going til no more or non-zero 1828 addqw #1,d0 | overshot by one 1829 movw sp@+,d2 | restore scratch 1830Lscdone: 1831 rts 1832 1833ENTRY(skpc) 1834 movl sp@(8),d0 | get length 1835 jeq Lskdone | nothing to do, return 1836 movb sp@(7),d1 | mask to use 1837 movl sp@(12),a0 | where to start 1838 subqw #1,d0 | adjust for dbcc 1839Lskloop: 1840 cmpb a0@+,d1 | compate with mask 1841 dbne d0,Lskloop | keep going til no more or zero 1842 addqw #1,d0 | overshot by one 1843Lskdone: 1844 rts 1845 1846ENTRY(locc) 1847 movl sp@(8),d0 | get length 1848 jeq Llcdone | nothing to do, return 1849 movb sp@(7),d1 | mask to use 1850 movl sp@(12),a0 | where to start 1851 subqw #1,d0 | adjust for dbcc 1852Llcloop: 1853 cmpb a0@+,d1 | compate with mask 1854 dbeq d0,Llcloop | keep going til no more or non-zero 1855 addqw #1,d0 | overshot by one 1856Llcdone: 1857 rts 1858 1859/* 1860 * Emulate VAX FFS (find first set) instruction. 1861 */ 1862ENTRY(ffs) 1863 moveq #-1,d0 1864 movl sp@(4),d1 1865 jeq Lffsdone 1866Lffsloop: 1867 addql #1,d0 1868 btst d0,d1 1869 jeq Lffsloop 1870Lffsdone: 1871 addql #1,d0 1872 rts 1873 1874#ifdef FPCOPROC 1875/* 1876 * Save and restore 68881 state. 1877 * Pretty awful looking since our assembler does not 1878 * recognize FP mnemonics. 1879 */ 1880ENTRY(m68881_save) 1881 movl sp@(4),a0 | save area pointer 1882 fsave a0@ | save state 1883 tstb a0@ | null state frame? 1884 jeq Lm68881sdone | yes, all done 1885 fmovem fp0-fp7,a0@(216) | save FP general registers 1886 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 1887Lm68881sdone: 1888 rts 1889 1890ENTRY(m68881_restore) 1891 movl sp@(4),a0 | save area pointer 1892 tstb a0@ | null state frame? 1893 jeq Lm68881rdone | yes, easy 1894 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 1895 fmovem a0@(216),fp0-fp7 | restore FP general registers 1896Lm68881rdone: 1897 frestore a0@ | restore state 1898 rts 1899 1900/* LUNA */ 1901 1902 .globl _fpp_svarea 1903 1904/* Fpp is MC68882 ? */ 1905ENTRY(is_68882) 1906 frestore _fppnull | initialize fpp 1907 movl #2,d0 1908 fmovecr #0,fp1 1909 fsinx fp1,fp2 1910 lea _fpp_svarea,a0 | save area 1911 movw sr,d1 | save status reg. 1912 movw #0x2700,sr | mask intrrupt 1913 fsave a0@ | save fpp context 1914 movw d1,sr | restore status reg. 1915 movl a0@,d1 1916 andl #0x00ff0000,d1 | check status field 1917 cmpl #0x00180000,d1 | 68881(idle)? 1918 beq _is81 1919 cmpl #0x00b40000,d1 | 68881(busy)? 1920 beq _is81 1921 cmpl #0x00380000,d1 | 68882(idle)? 1922 beq _is82 1923 cmpl #0x00d40000,d1 | 68882(busy)? 1924 beq _is82 1925 bra _is82out | default 68881 1926_is81: 1927 clrl d0 1928 bra _is82out 1929_is82: 1930 movl #1,d0 1931_is82out: 1932 frestore a0@ 1933 rts 1934 1935#ifdef OLD_LUNA 1936/* We have fpp ? */ 1937ENTRY(havefpp) 1938 movl a2,sp@- 1939 clrl d0 1940 movl vb,a2 1941 movl a2@(FLINE_VEC),a0 | save vectors 1942 movl a2@(COPRO_VEC),a1 1943 movl sp,d1 1944 movl #_fpvec,a2@(FLINE_VEC) | change vectors 1945 movl #_fpvec,a2@(COPRO_VEC) 1946 fnop | cause exception ? 1947 movl #1,d0 1948_fpvec: movl a0,a2@(FLINE_VEC) | restore vectors 1949 movl a1,a2@(COPRO_VEC) 1950 movl d1,sp 1951 movl sp@+,a2 1952 rts 1953#endif 1954#endif 1955 1956/* 1957 * Handle the nitty-gritty of rebooting the machine. 1958 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 1959 * Note that we must be running in an address range that is mapped one-to-one 1960 * logical to physical so that the PC is still valid immediately after the MMU 1961 * is turned off. We have conveniently mapped the last page of physical 1962 * memory this way. 1963 */ 1964 .globl _doboot 1965_doboot: 1966 movl #0x41000004,a0 1967 movl a0@,a1 | get PROM restart entry address 1968 movl #CACHE_OFF,d0 1969 movc d0,cacr | disable on-chip cache(s) 1970 movl #_tcroff,a0 | value for pmove to TC (turn off MMU) 1971 pmove a0@,tc | disable MMU 1972 jmp a1@ | goto REBOOT 1973 1974 .data 1975 .globl _protorp,_protott0,_protott1 1976_protorp: 1977 .long 0,0 | prototype root pointer 1978_protott0: 1979 .long 0x807F8543 | prototype tt0 register (for kernel) 1980_protott1: 1981 .long 0 | prototype tt0 register (for user) 1982 .globl _cold 1983_cold: 1984 .long 1 | cold start flag 1985 .globl _want_resched 1986_want_resched: 1987 .long 0 1988 .globl _proc0paddr 1989_proc0paddr: 1990 .long 0 | KVA of proc0 u-area 1991 1992 .globl _tcroff 1993_tcroff: 1994 .long 0 | TC reg. reset flag 1995 1996#ifdef FPCOPROC 1997 .globl _fppnull 1998_fppnull: 1999 .long 0 2000#endif 2001 .globl _clock_on 2002_clock_on: 2003 .long 0 | clock is enable ? 2004 .globl _dipswitch 2005_dipswitch: 2006 .word 0 | dipsw(front panel) value 2007 .globl _KernInter 2008_KernInter: | Kernel InterFace Field 2009 .space KIFF_SIZE 2010#ifdef DEBUG 2011 .globl fulltflush, fullcflush 2012fulltflush: 2013 .long 0 2014fullcflush: 2015 .long 0 2016#endif 2017/* interrupt counters */ 2018 .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames 2019_intrnames: 2020 .asciz "spur" 2021 .asciz "lev1" 2022 .asciz "lev2" 2023 .asciz "lev3" 2024 .asciz "lev4" 2025 .asciz "clock" 2026 .asciz "lev7" 2027 .asciz "nmi" 2028_eintrnames: 2029 .even 2030_intrcnt: 2031 .long 0,0,0,0,0,0,0,0,0 2032_eintrcnt: 2033