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