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.12 (Berkeley) 05/12/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 swtch_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 807/* initialize source/destination control registers for movs */ 808 moveq #FC_USERD,d0 | user space 809 movc d0,sfc | as source 810 movc d0,dfc | and destination of transfers 811 812/* 813 * LUNA PIO initialization. 814 */ 815 movw PIO0_A,d0 | dipsw-1,2 (from port A&B) 816 movw d0,_dipswitch 817 818/* configure kernel and proc0 VA space so we can get going */ 819 .globl _Sysseg, _pmap_bootstrap, _avail_start 820 movl #_end,d5 | end of static kernel text/data 821 addl #NBPG-1,d5 822 andl #PG_FRAME,d5 | round to a page 823 movl d5,a4 | PA=VA 824 pea a5@ | firstpa 825 pea a4@ | nextpa 826 jbsr _pmap_bootstrap | bootstrap(firstpa, nextpa) 827 addql #8,sp 828 829/* 830 * Prepare to enable MMU. 831 */ 832 movl _Sysseg,d1 | system segment table addr read value (a KVA) 833#if defined(LUNA2) 834 cmpl #-2,_mmutype | 68040? 835 jne Lmotommu1 | no, skip 836 837 .long 0x4e7b1807 | movc d1,srp 838/* we must set tt-registers here */ 839 movl #0x403FA040,d0 | tt0 for LUNA2 0x40000000-0x7fffffff 840 .long 0x4e7b0004 | movc d0,itt0 841 .long 0x4e7b0006 | movc d0,dtt0 842 movl #0x807FA040,d0 | tt1 for LUNA2 0x80000000-0xffffffff 843 .long 0x4e7b0005 | movc d0,itt1 844 .long 0x4e7b0007 | movc d0,dtt1 845 .word 0xf4d8 | cinva bc 846 .word 0xf518 | pflusha 847 movl #0x8000,d0 848 .long 0x4e7b0003 | movc d0,tc 849 movl #0x80008000,d0 850 movc d0,cacr | turn on both caches 851 jmp Lenab1 852Lmotommu1: 853#endif 854 lea _protorp,a0 855 movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs 856 movl d1,a0@(4) | + segtable address 857 pmove a0@,srp | load the supervisor root pointer 858 movl #0x80000002,a0@ | reinit upper half for CRP loads 859/* we must set tt-registers here */ 860 lea _protott0,a0 | tt0 for LUNA1 0x40000000-0x7fffffff 861 .word 0xf010 | pmove a0@,mmutt0 862 .word 0x0800 863 lea _protott1,a0 | tt1 for LUNA1 0x80000000-0xffffffff 864 .word 0xf010 | pmove a0@,mmutt1 865 .word 0x0c00 866 lea _mapping_tc,a2 867 movl #0x82c0aa00,a2@ | value to load TC with 868 pmove a2@,tc | load it 869 870/* 871 * Should be running mapped from this point on 872 */ 873Lenab1: 874#ifdef FPCOPROC 875/* fpp check */ 876 movl a1,sp@- 877 jbsr _checkfpp | check fpp 878 frestore _fppnull | reset 879 movl sp@+,a1 880#endif 881/* select the software page size now */ 882 lea tmpstk,sp | temporary stack 883 jbsr _vm_set_page_size | select software page size 884/* set kernel stack, user SP, and initial pcb */ 885 lea _kstack,a1 | proc0 kernel stack 886 lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area 887 movl #USRSTACK-4,a2 888 movl a2,usp | init user SP 889 movl _proc0paddr,a1 | get proc0 pcb addr 890 movl a1,_curpcb | proc0 is running 891#ifdef FPCOPROC 892 clrl a1@(PCB_FPCTX) | ensure null FP context 893 movl a1,sp@- 894 jbsr _m68881_restore | restore it (does not kill a1) 895 addql #4,sp 896#endif 897/* flush TLB and turn on caches */ 898 jbsr _TBIA | invalidate TLB 899#if defined(LUNA2) 900 cmpl #-2,_mmutype | 68040? 901 jeq Lnocache0 | yes, cache already on 902#endif 903 movl #CACHE_ON,d0 904 movc d0,cacr | clear cache(s) 905Lnocache0: 906/* final setup for C code */ 907 movw #PSL_LOWIPL,sr | lower SPL 908 movl d7,_boothowto | save reboot flags 909 movl d6,_bootdev | and boot device 910 jbsr _main | call main() 911 912/* proc[1] == init now running here; 913 * create a null exception frame and return to user mode in icode 914 */ 915#if defined(LUNA2) 916 cmpl #-2,_mmutype | 68040? 917 jne Lnoflush | no, skip 918 .word 0xf478 | cpusha dc 919 .word 0xf498 | cinva ic 920Lnoflush: 921#endif 922 clrw sp@- | vector offset/frame type 923 clrl sp@- | return to icode location 0 924 movw #PSL_USER,sp@- | in user mode 925 rte 926 927/* 928 * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig(). 929 * 930 * Stack looks like: 931 * 932 * sp+0 -> signal number 933 * sp+4 signal specific code 934 * sp+8 pointer to signal context frame (scp) 935 * sp+12 address of handler 936 * sp+16 saved hardware state 937 * . 938 * . 939 * scp+0-> beginning of signal context frame 940 */ 941 .globl _sigcode, _esigcode, _sigcodetrap 942 .data 943_sigcode: 944 movl sp@(12),a0 | signal handler addr (4 bytes) 945 jsr a0@ | call signal handler (2 bytes) 946 addql #4,sp | pop signo (2 bytes) 947_sigcodetrap: 948 trap #1 | special syscall entry (2 bytes) 949 movl d0,sp@(4) | save errno (4 bytes) 950 moveq #1,d0 | syscall == exit (2 bytes) 951 trap #0 | exit(errno) (2 bytes) 952 .align 2 953_esigcode: 954 955/* 956 * Icode is copied out to process 1 to exec init. 957 * If the exec fails, process 1 exits. 958 */ 959 .globl _icode,_szicode 960 .text 961_icode: 962 clrl sp@- 963 pea pc@((argv-.)+2) 964 pea pc@((init-.)+2) 965 clrl sp@- 966 moveq #SYS_execve,d0 967 trap #0 968 moveq #SYS_exit,d0 969 trap #0 970init: 971 .asciz "/sbin/init" 972 .even 973argv: 974 .long init+6-_icode | argv[0] = "init" ("/sbin/init" + 6) 975 .long eicode-_icode | argv[1] follows icode after copyout 976 .long 0 977eicode: 978 979_szicode: 980 .long _szicode-_icode 981 982/* 983 * Primitives 984 */ 985 986#ifdef __STDC__ 987#define EXPORT(name) .globl _ ## name; _ ## name: 988#else 989#define EXPORT(name) .globl _/**/name; _/**/name: 990#endif 991#ifdef GPROF 992#define ENTRY(name) \ 993 EXPORT(name) link a6,\#0; jbsr mcount; unlk a6 994#define ALTENTRY(name, rname) \ 995 ENTRY(name); jra rname+12 996#else 997#define ENTRY(name) \ 998 EXPORT(name) 999#define ALTENTRY(name, rname) \ 1000 ENTRY(name) 1001#endif 1002 1003/* 1004 * For gcc2 1005 */ 1006ENTRY(__main) 1007 rts 1008 1009/* 1010 * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 1011 * 1012 * Copy a null terminated string from the user address space into 1013 * the kernel address space. 1014 * NOTE: maxlength must be < 64K 1015 */ 1016ENTRY(copyinstr) 1017 movl _curpcb,a0 | current pcb 1018 movl #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults 1019 movl sp@(4),a0 | a0 = fromaddr 1020 movl sp@(8),a1 | a1 = toaddr 1021 moveq #0,d0 1022 movw sp@(14),d0 | d0 = maxlength 1023 jlt Lcisflt1 | negative count, error 1024 jeq Lcisdone | zero count, all done 1025 subql #1,d0 | set up for dbeq 1026Lcisloop: 1027 movsb a0@+,d1 | grab a byte 1028 nop 1029 movb d1,a1@+ | copy it 1030 dbeq d0,Lcisloop | if !null and more, continue 1031 jne Lcisflt2 | ran out of room, error 1032 moveq #0,d0 | got a null, all done 1033Lcisdone: 1034 tstl sp@(16) | return length desired? 1035 jeq Lcisret | no, just return 1036 subl sp@(4),a0 | determine how much was copied 1037 movl sp@(16),a1 | return location 1038 movl a0,a1@ | stash it 1039Lcisret: 1040 movl _curpcb,a0 | current pcb 1041 clrl a0@(PCB_ONFAULT) | clear fault addr 1042 rts 1043Lcisflt1: 1044 moveq #EFAULT,d0 | copy fault 1045 jra Lcisdone 1046Lcisflt2: 1047 moveq #ENAMETOOLONG,d0 | ran out of space 1048 jra Lcisdone 1049 1050/* 1051 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 1052 * 1053 * Copy a null terminated string from the kernel 1054 * address space to the user address space. 1055 * NOTE: maxlength must be < 64K 1056 */ 1057ENTRY(copyoutstr) 1058 movl _curpcb,a0 | current pcb 1059 movl #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults 1060 movl sp@(4),a0 | a0 = fromaddr 1061 movl sp@(8),a1 | a1 = toaddr 1062 moveq #0,d0 1063 movw sp@(14),d0 | d0 = maxlength 1064 jlt Lcosflt1 | negative count, error 1065 jeq Lcosdone | zero count, all done 1066 subql #1,d0 | set up for dbeq 1067Lcosloop: 1068 movb a0@+,d1 | grab a byte 1069 movsb d1,a1@+ | copy it 1070 nop 1071 dbeq d0,Lcosloop | if !null and more, continue 1072 jne Lcosflt2 | ran out of room, error 1073 moveq #0,d0 | got a null, all done 1074Lcosdone: 1075 tstl sp@(16) | return length desired? 1076 jeq Lcosret | no, just return 1077 subl sp@(4),a0 | determine how much was copied 1078 movl sp@(16),a1 | return location 1079 movl a0,a1@ | stash it 1080Lcosret: 1081 movl _curpcb,a0 | current pcb 1082 clrl a0@(PCB_ONFAULT) | clear fault addr 1083 rts 1084Lcosflt1: 1085 moveq #EFAULT,d0 | copy fault 1086 jra Lcosdone 1087Lcosflt2: 1088 moveq #ENAMETOOLONG,d0 | ran out of space 1089 jra Lcosdone 1090 1091/* 1092 * copystr(fromaddr, toaddr, maxlength, &lencopied) 1093 * 1094 * Copy a null terminated string from one point to another in 1095 * the kernel address space. 1096 * NOTE: maxlength must be < 64K 1097 */ 1098ENTRY(copystr) 1099 movl sp@(4),a0 | a0 = fromaddr 1100 movl sp@(8),a1 | a1 = toaddr 1101 moveq #0,d0 1102 movw sp@(14),d0 | d0 = maxlength 1103 jlt Lcsflt1 | negative count, error 1104 jeq Lcsdone | zero count, all done 1105 subql #1,d0 | set up for dbeq 1106Lcsloop: 1107 movb a0@+,a1@+ | copy a byte 1108 dbeq d0,Lcsloop | if !null and more, continue 1109 jne Lcsflt2 | ran out of room, error 1110 moveq #0,d0 | got a null, all done 1111Lcsdone: 1112 tstl sp@(16) | return length desired? 1113 jeq Lcsret | no, just return 1114 subl sp@(4),a0 | determine how much was copied 1115 movl sp@(16),a1 | return location 1116 movl a0,a1@ | stash it 1117Lcsret: 1118 rts 1119Lcsflt1: 1120 moveq #EFAULT,d0 | copy fault 1121 jra Lcsdone 1122Lcsflt2: 1123 moveq #ENAMETOOLONG,d0 | ran out of space 1124 jra Lcsdone 1125 1126/* 1127 * Copyin(from_user, to_kernel, len) 1128 * Copyout(from_kernel, to_user, len) 1129 * 1130 * Copy specified amount of data between kernel and user space. 1131 * 1132 * XXX both use the DBcc instruction which has 16-bit limitation so only 1133 * 64k units can be copied, where "unit" is either a byte or a longword 1134 * depending on alignment. To be safe, assume it can copy at most 1135 * 64k bytes. Don't make MAXBSIZE or MAXPHYS larger than 64k without 1136 * fixing this code! 1137 */ 1138ENTRY(copyin) 1139 movl d2,sp@- | scratch register 1140 movl _curpcb,a0 | current pcb 1141 movl #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults 1142 movl sp@(16),d2 | check count 1143 jlt Lciflt | negative, error 1144 jeq Lcidone | zero, done 1145 movl sp@(8),a0 | src address 1146 movl sp@(12),a1 | dest address 1147 movl a0,d0 1148 btst #0,d0 | src address odd? 1149 jeq Lcieven | no, go check dest 1150 movsb a0@+,d1 | yes, get a byte 1151 nop 1152 movb d1,a1@+ | put a byte 1153 subql #1,d2 | adjust count 1154 jeq Lcidone | exit if done 1155Lcieven: 1156 movl a1,d0 1157 btst #0,d0 | dest address odd? 1158 jne Lcibyte | yes, must copy by bytes 1159 movl d2,d0 | no, get count 1160 lsrl #2,d0 | convert to longwords 1161 jeq Lcibyte | no longwords, copy bytes 1162 subql #1,d0 | set up for dbf 1163Lcilloop: 1164 movsl a0@+,d1 | get a long 1165 nop 1166 movl d1,a1@+ | put a long 1167 dbf d0,Lcilloop | til done 1168 andl #3,d2 | what remains 1169 jeq Lcidone | all done 1170Lcibyte: 1171 subql #1,d2 | set up for dbf 1172Lcibloop: 1173 movsb a0@+,d1 | get a byte 1174 nop 1175 movb d1,a1@+ | put a byte 1176 dbf d2,Lcibloop | til done 1177Lcidone: 1178 moveq #0,d0 | success 1179Lciexit: 1180 movl _curpcb,a0 | current pcb 1181 clrl a0@(PCB_ONFAULT) | clear fault catcher 1182 movl sp@+,d2 | restore scratch reg 1183 rts 1184Lciflt: 1185 moveq #EFAULT,d0 | got a fault 1186 jra Lciexit 1187 1188ENTRY(copyout) 1189 movl d2,sp@- | scratch register 1190 movl _curpcb,a0 | current pcb 1191 movl #Lcoflt,a0@(PCB_ONFAULT) | catch faults 1192 movl sp@(16),d2 | check count 1193 jlt Lcoflt | negative, error 1194 jeq Lcodone | zero, done 1195 movl sp@(8),a0 | src address 1196 movl sp@(12),a1 | dest address 1197 movl a0,d0 1198 btst #0,d0 | src address odd? 1199 jeq Lcoeven | no, go check dest 1200 movb a0@+,d1 | yes, get a byte 1201 movsb d1,a1@+ | put a byte 1202 nop 1203 subql #1,d2 | adjust count 1204 jeq Lcodone | exit if done 1205Lcoeven: 1206 movl a1,d0 1207 btst #0,d0 | dest address odd? 1208 jne Lcobyte | yes, must copy by bytes 1209 movl d2,d0 | no, get count 1210 lsrl #2,d0 | convert to longwords 1211 jeq Lcobyte | no longwords, copy bytes 1212 subql #1,d0 | set up for dbf 1213Lcolloop: 1214 movl a0@+,d1 | get a long 1215 movsl d1,a1@+ | put a long 1216 nop 1217 dbf d0,Lcolloop | til done 1218 andl #3,d2 | what remains 1219 jeq Lcodone | all done 1220Lcobyte: 1221 subql #1,d2 | set up for dbf 1222Lcobloop: 1223 movb a0@+,d1 | get a byte 1224 movsb d1,a1@+ | put a byte 1225 nop 1226 dbf d2,Lcobloop | til done 1227Lcodone: 1228 moveq #0,d0 | success 1229Lcoexit: 1230 movl _curpcb,a0 | current pcb 1231 clrl a0@(PCB_ONFAULT) | clear fault catcher 1232 movl sp@+,d2 | restore scratch reg 1233 rts 1234Lcoflt: 1235 moveq #EFAULT,d0 | got a fault 1236 jra Lcoexit 1237 1238/* 1239 * non-local gotos 1240 */ 1241ENTRY(setjmp) 1242 movl sp@(4),a0 | savearea pointer 1243 moveml #0xFCFC,a0@ | save d2-d7/a2-a7 1244 movl sp@,a0@(48) | and return address 1245 moveq #0,d0 | return 0 1246 rts 1247 1248ENTRY(longjmp) 1249 movl sp@(4),a0 1250 moveml a0@+,#0xFCFC 1251 movl a0@,sp@ 1252 moveq #1,d0 1253 rts 1254 1255/* 1256 * The following primitives manipulate the run queues. 1257 * _whichqs tells which of the 32 queues _qs 1258 * have processes in them. Setrq puts processes into queues, Remrq 1259 * removes them from queues. The running process is on no queue, 1260 * other processes are on a queue related to p->p_pri, divided by 4 1261 * actually to shrink the 0-127 range of priorities into the 32 available 1262 * queues. 1263 */ 1264 1265 .globl _whichqs,_qs,_cnt,_panic 1266 .globl _curproc,_want_resched 1267 1268/* 1269 * Setrq(p) 1270 * 1271 * Call should be made at spl6(), and p->p_stat should be SRUN 1272 */ 1273ENTRY(setrq) 1274 movl sp@(4),a0 1275 tstl a0@(P_RLINK) 1276 jeq Lset1 1277 movl #Lset2,sp@- 1278 jbsr _panic 1279Lset1: 1280 clrl d0 1281 movb a0@(P_PRI),d0 1282 lsrb #2,d0 1283 movl _whichqs,d1 1284 bset d0,d1 1285 movl d1,_whichqs 1286 lslb #3,d0 1287 addl #_qs,d0 1288 movl d0,a0@(P_LINK) 1289 movl d0,a1 1290 movl a1@(P_RLINK),a0@(P_RLINK) 1291 movl a0,a1@(P_RLINK) 1292 movl a0@(P_RLINK),a1 1293 movl a0,a1@(P_LINK) 1294 rts 1295 1296Lset2: 1297 .asciz "setrq" 1298 .even 1299 1300/* 1301 * Remrq(p) 1302 * 1303 * Call should be made at spl6(). 1304 */ 1305ENTRY(remrq) 1306 movl sp@(4),a0 1307 clrl d0 1308 movb a0@(P_PRI),d0 1309 lsrb #2,d0 1310 movl _whichqs,d1 1311 bclr d0,d1 1312 jne Lrem1 1313 movl #Lrem3,sp@- 1314 jbsr _panic 1315Lrem1: 1316 movl d1,_whichqs 1317 movl a0@(P_LINK),a1 1318 movl a0@(P_RLINK),a1@(P_RLINK) 1319 movl a0@(P_RLINK),a1 1320 movl a0@(P_LINK),a1@(P_LINK) 1321 movl #_qs,a1 1322 movl d0,d1 1323 lslb #3,d1 1324 addl d1,a1 1325 cmpl a1@(P_LINK),a1 1326 jeq Lrem2 1327 movl _whichqs,d1 1328 bset d0,d1 1329 movl d1,_whichqs 1330Lrem2: 1331 clrl a0@(P_RLINK) 1332 rts 1333 1334Lrem3: 1335 .asciz "remrq" 1336Lsw0: 1337 .asciz "swtch" 1338 .even 1339 1340 .globl _curpcb 1341 .globl _masterpaddr | XXX compatibility (debuggers) 1342 .data 1343_masterpaddr: | XXX compatibility (debuggers) 1344_curpcb: 1345 .long 0 1346mdpflag: 1347 .byte 0 | copy of proc md_flags low byte 1348 .align 2 1349 .comm nullpcb,SIZEOF_PCB 1350 .text 1351 1352/* 1353 * At exit of a process, do a swtch for the last time. 1354 * The mapping of the pcb at p->p_addr has already been deleted, 1355 * and the memory for the pcb+stack has been freed. 1356 * The ipl is high enough to prevent the memory from being reallocated. 1357 */ 1358ENTRY(swtch_exit) 1359 movl #nullpcb,_curpcb | save state into garbage pcb 1360 lea tmpstk,sp | goto a tmp stack 1361 jra _cpu_swtch 1362 1363/* 1364 * When no processes are on the runq, Swtch branches to idle 1365 * to wait for something to come ready. 1366 */ 1367 .globl idle 1368Lidle: 1369 stop #PSL_LOWIPL 1370idle: 1371 movw #PSL_HIGHIPL,sr 1372 tstl _whichqs 1373 jeq Lidle 1374 movw #PSL_LOWIPL,sr 1375 jra Lsw1 1376 1377Lbadsw: 1378 movl #Lsw0,sp@- 1379 jbsr _panic 1380 /*NOTREACHED*/ 1381 1382/* 1383 * cpu_swtch() 1384 * 1385 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1386 * entire ATC. The effort involved in selective flushing may not be 1387 * worth it, maybe we should just flush the whole thing? 1388 * 1389 * NOTE 2: With the new VM layout we now no longer know if an inactive 1390 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1391 * bit). For now, we just always flush the full ATC. 1392 */ 1393ENTRY(cpu_swtch) 1394 movl _curpcb,a0 | current pcb 1395 movw sr,a0@(PCB_PS) | save sr before changing ipl 1396#ifdef notyet 1397 movl _curproc,sp@- | remember last proc running 1398#endif 1399 clrl _curproc 1400 addql #1,_cnt+V_SWTCH 1401 1402Lsw1: 1403 /* 1404 * Find the highest-priority queue that isn't empty, 1405 * then take the first proc from that queue. 1406 */ 1407 clrl d0 1408 lea _whichqs,a0 1409 movl a0@,d1 1410Lswchk: 1411 btst d0,d1 1412 jne Lswfnd 1413 addqb #1,d0 1414 cmpb #32,d0 1415 jne Lswchk 1416 jra idle 1417Lswfnd: 1418 movw #PSL_HIGHIPL,sr | lock out interrupts 1419 movl a0@,d1 | and check again... 1420 bclr d0,d1 1421 jeq Lsw1 | proc moved, rescan 1422 movl d1,a0@ | update whichqs 1423 moveq #1,d1 | double check for higher priority 1424 lsll d0,d1 | process (which may have snuck in 1425 subql #1,d1 | while we were finding this one) 1426 andl a0@,d1 1427 jeq Lswok | no one got in, continue 1428 movl a0@,d1 1429 bset d0,d1 | otherwise put this one back 1430 movl d1,a0@ 1431 jra Lsw1 | and rescan 1432Lswok: 1433 movl d0,d1 1434 lslb #3,d1 | convert queue number to index 1435 addl #_qs,d1 | locate queue (q) 1436 movl d1,a1 1437 cmpl a1@(P_LINK),a1 | anyone on queue? 1438 jeq Lbadsw | no, panic 1439 movl a1@(P_LINK),a0 | p = q->p_link 1440 movl a0@(P_LINK),a1@(P_LINK) | q->p_link = p->p_link 1441 movl a0@(P_LINK),a1 | q = p->p_link 1442 movl a0@(P_RLINK),a1@(P_RLINK) | q->p_rlink = p->p_rlink 1443 cmpl a0@(P_LINK),d1 | anyone left on queue? 1444 jeq Lsw2 | no, skip 1445 movl _whichqs,d1 1446 bset d0,d1 | yes, reset bit 1447 movl d1,_whichqs 1448Lsw2: 1449 movl a0,_curproc 1450 clrl _want_resched 1451#ifdef notyet 1452 movl sp@+,a1 1453 cmpl a0,a1 | switching to same proc? 1454 jeq Lswdone | yes, skip save and restore 1455#endif 1456 /* 1457 * Save state of previous process in its pcb. 1458 */ 1459 movl _curpcb,a1 1460 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1461 movl usp,a2 | grab USP (a2 has been saved) 1462 movl a2,a1@(PCB_USP) | and save it 1463#ifdef FPCOPROC 1464 lea a1@(PCB_FPCTX),a2 | pointer to FP save area 1465 fsave a2@ | save FP state 1466 tstb a2@ | null state frame? 1467 jeq Lswnofpsave | yes, all done 1468 fmovem fp0-fp7,a2@(216) | save FP general registers 1469 fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers 1470Lswnofpsave: 1471#endif 1472 1473#ifdef DIAGNOSTIC 1474 tstl a0@(P_WCHAN) 1475 jne Lbadsw 1476 cmpb #SRUN,a0@(P_STAT) 1477 jne Lbadsw 1478#endif 1479 clrl a0@(P_RLINK) | clear back link 1480 movb a0@(P_MDFLAG+3),mdpflag | low byte of p_md.md_flags 1481 movl a0@(P_ADDR),a1 | get p_addr 1482 movl a1,_curpcb 1483 1484 /* see if pmap_activate needs to be called; should remove this */ 1485 movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace 1486#ifdef DIAGNOSTIC 1487 tstl a0 | map == VM_MAP_NULL? 1488 jeq Lbadsw | panic 1489#endif 1490 lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap 1491 tstl a0@(PM_STCHG) | pmap->st_changed? 1492 jeq Lswnochg | no, skip 1493 pea a1@ | push pcb (at p_addr) 1494 pea a0@ | push pmap 1495 jbsr _pmap_activate | pmap_activate(pmap, pcb) 1496 addql #8,sp 1497 movl _curpcb,a1 | restore p_addr 1498Lswnochg: 1499 1500 movl #PGSHIFT,d1 1501 movl a1,d0 1502 lsrl d1,d0 | convert p_addr to page number 1503 lsll #2,d0 | and now to Sysmap offset 1504 addl _Sysmap,d0 | add Sysmap base to get PTE addr 1505#ifdef notdef 1506 movw #PSL_HIGHIPL,sr | go crit while changing PTEs 1507#endif 1508 lea tmpstk,sp | now goto a tmp stack for NMI 1509 movl d0,a0 | address of new context 1510 movl _Umap,a2 | address of PTEs for kstack 1511 moveq #UPAGES-1,d0 | sizeof kstack 1512Lres1: 1513 movl a0@+,d1 | get PTE 1514 andl #~PG_PROT,d1 | mask out old protection 1515 orl #PG_RW+PG_V,d1 | ensure valid and writable 1516 movl d1,a2@+ | load it up 1517 dbf d0,Lres1 | til done 1518#if defined(LUNA2) 1519 cmpl #-2,_mmutype | 68040? 1520 jne Lres1a | no, skip 1521 .word 0xf518 | yes, pflusha 1522 movl a1@(PCB_USTP),d0 | get USTP 1523 moveq #PGSHIFT,d1 1524 lsll d1,d0 | convert to addr 1525 .long 0x4e7b0806 | movc d0,urp 1526 jra Lcxswdone 1527Lres1a: 1528#endif 1529 movl #CACHE_CLR,d0 1530 movc d0,cacr | invalidate cache(s) 1531 pflusha | flush entire TLB 1532 movl a1@(PCB_USTP),d0 | get USTP 1533 moveq #PGSHIFT,d1 1534 lsll d1,d0 | convert to addr 1535 lea _protorp,a0 | CRP prototype 1536 movl d0,a0@(4) | stash USTP 1537 pmove a0@,crp | load new user root pointer 1538Lcxswdone: 1539 moveml a1@(PCB_REGS),#0xFCFC | and registers 1540 movl a1@(PCB_USP),a0 1541 movl a0,usp | and USP 1542#ifdef FPCOPROC 1543 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1544 tstb a0@ | null state frame? 1545 jeq Lresfprest | yes, easy 1546#if defined(LUNA2) 1547 cmpl #-2,_mmutype | 68040? 1548 jne Lresnot040 | no, skip 1549 clrl sp@- | yes... 1550 frestore sp@+ | ...magic! 1551Lresnot040: 1552#endif 1553 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 1554 fmovem a0@(216),fp0-fp7 | restore FP general registers 1555Lresfprest: 1556 frestore a0@ | restore state 1557#endif 1558 movw a1@(PCB_PS),sr | no, restore PS 1559 moveq #1,d0 | return 1 (for alternate returns) 1560 rts 1561 1562/* 1563 * savectx(pcb, altreturn) 1564 * Update pcb, saving current processor state and arranging 1565 * for alternate return ala longjmp in swtch if altreturn is true. 1566 */ 1567ENTRY(savectx) 1568 movl sp@(4),a1 1569 movw sr,a1@(PCB_PS) 1570 movl usp,a0 | grab USP 1571 movl a0,a1@(PCB_USP) | and save it 1572 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1573#ifdef FPCOPROC 1574 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1575 fsave a0@ | save FP state 1576 tstb a0@ | null state frame? 1577 jeq Lsvnofpsave | yes, all done 1578 fmovem fp0-fp7,a0@(216) | save FP general registers 1579 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 1580Lsvnofpsave: 1581#endif 1582 tstl sp@(8) | altreturn? 1583 jeq Lsavedone 1584 movl sp,d0 | relocate current sp relative to a1 1585 subl #_kstack,d0 | (sp is relative to kstack): 1586 addl d0,a1 | a1 += sp - kstack; 1587 movl sp@,a1@ | write return pc at (relocated) sp@ 1588Lsavedone: 1589 moveq #0,d0 | return 0 1590 rts 1591 1592/* 1593 * {fu,su},{byte,sword,word} 1594 */ 1595ALTENTRY(fuiword, _fuword) 1596ENTRY(fuword) 1597 movl sp@(4),a0 | address to read 1598 movl _curpcb,a1 | current pcb 1599 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1600 movsl a0@,d0 | do read from user space 1601 nop 1602 jra Lfsdone 1603 1604ENTRY(fusword) 1605 movl sp@(4),a0 1606 movl _curpcb,a1 | current pcb 1607 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1608 moveq #0,d0 1609 movsw a0@,d0 | do read from user space 1610 nop 1611 jra Lfsdone 1612 1613/* Just like fusword, but tells trap code not to page in. */ 1614ENTRY(fuswintr) 1615 movl sp@(4),a0 1616 movl _curpcb,a1 1617 movl #_fswintr,a1@(PCB_ONFAULT) 1618 moveq #0,d0 1619 movsw a0@,d0 1620 nop 1621 jra Lfsdone 1622 1623ALTENTRY(fuibyte, _fubyte) 1624ENTRY(fubyte) 1625 movl sp@(4),a0 | address to read 1626 movl _curpcb,a1 | current pcb 1627 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1628 moveq #0,d0 1629 movsb a0@,d0 | do read from user space 1630 nop 1631 jra Lfsdone 1632 1633Lfserr: 1634 moveq #-1,d0 | error indicator 1635Lfsdone: 1636 clrl a1@(PCB_ONFAULT) | clear fault address 1637 rts 1638 1639/* Just like Lfserr, but the address is different (& exported). */ 1640 .globl _fswintr 1641_fswintr: 1642 moveq #-1,d0 1643 jra Lfsdone 1644 1645 1646/* 1647 * Write a longword in user instruction space. 1648 * Largely the same as suword but with a final i-cache purge on those 1649 * machines with split caches. 1650 */ 1651ENTRY(suiword) 1652 movl sp@(4),a0 | address to write 1653 movl sp@(8),d0 | value to put there 1654 movl _curpcb,a1 | current pcb 1655 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1656 movsl d0,a0@ | do write to user space 1657 nop 1658 moveq #0,d0 | indicate no fault 1659#if defined(LUNA2) 1660 cmpl #-2,_mmutype | 68040? 1661 jne Lsuicpurge | no, skip 1662 .word 0xf498 | cinva ic (XXX overkill) 1663 jra Lfsdone 1664Lsuicpurge: 1665#endif 1666 movl #IC_CLEAR,d1 1667 movc d1,cacr | invalidate i-cache 1668 jra Lfsdone 1669 1670ENTRY(suword) 1671 movl sp@(4),a0 | address to write 1672 movl sp@(8),d0 | value to put there 1673 movl _curpcb,a1 | current pcb 1674 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1675 movsl d0,a0@ | do write to user space 1676 nop 1677 moveq #0,d0 | indicate no fault 1678 jra Lfsdone 1679 1680ENTRY(susword) 1681 movl sp@(4),a0 | address to write 1682 movw sp@(10),d0 | value to put there 1683 movl _curpcb,a1 | current pcb 1684 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1685 movsw d0,a0@ | do write to user space 1686 nop 1687 moveq #0,d0 | indicate no fault 1688 jra Lfsdone 1689 1690ENTRY(suswintr) 1691 movl sp@(4),a0 1692 movw sp@(10),d0 1693 movl _curpcb,a1 1694 movl #_fswintr,a1@(PCB_ONFAULT) 1695 movsw d0,a0@ 1696 nop 1697 moveq #0,d0 1698 jra Lfsdone 1699 1700ALTENTRY(suibyte, _subyte) 1701ENTRY(subyte) 1702 movl sp@(4),a0 | address to write 1703 movb sp@(11),d0 | value to put there 1704 movl _curpcb,a1 | current pcb 1705 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1706 movsb d0,a0@ | do write to user space 1707 nop 1708 moveq #0,d0 | indicate no fault 1709 jra Lfsdone 1710 1711#if defined(LUNA2) 1712ENTRY(suline) 1713 movl sp@(4),a0 | address to write 1714 movl _curpcb,a1 | current pcb 1715 movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault 1716 movl sp@(8),a1 | address of line 1717 movl a1@+,d0 | get lword 1718 movsl d0,a0@+ | put lword 1719 nop | sync 1720 movl a1@+,d0 | get lword 1721 movsl d0,a0@+ | put lword 1722 nop | sync 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 moveq #0,d0 | indicate no fault 1730 jra Lsldone 1731Lslerr: 1732 moveq #-1,d0 1733Lsldone: 1734 movl _curpcb,a1 | current pcb 1735 clrl a1@(PCB_ONFAULT) | clear fault address 1736 rts 1737#endif 1738 1739/* 1740 * Invalidate entire TLB. 1741 */ 1742ENTRY(TBIA) 1743__TBIA: 1744#if defined(LUNA2) 1745 cmpl #-2,_mmutype | 68040? 1746 jne Lmotommu3 | no, skip 1747 .word 0xf518 | yes, pflusha 1748 rts 1749Lmotommu3: 1750#endif 1751 pflusha | flush entire TLB 1752 movl #DC_CLEAR,d0 1753 movc d0,cacr | invalidate on-chip d-cache 1754 rts 1755 1756/* 1757 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1758 */ 1759ENTRY(TBIS) 1760#ifdef DEBUG 1761 tstl fulltflush | being conservative? 1762 jne __TBIA | yes, flush entire TLB 1763#endif 1764#if defined(LUNA2) 1765 cmpl #-2,_mmutype | 68040? 1766 jne Lmotommu4 | no, skip 1767 movl sp@(4),a0 1768 movc dfc,d1 1769 moveq #1,d0 | user space 1770 movc d0,dfc 1771 .word 0xf508 | pflush a0@ 1772 moveq #5,d0 | super space 1773 movc d0,dfc 1774 .word 0xf508 | pflush a0@ 1775 movc d1,dfc 1776 rts 1777Lmotommu4: 1778#endif 1779 1780 movl sp@(4),a0 | get addr to flush 1781 pflush #0,#0,a0@ | flush address from both sides 1782 movl #DC_CLEAR,d0 1783 movc d0,cacr | invalidate on-chip data cache 1784 rts 1785 1786/* 1787 * Invalidate supervisor side of TLB 1788 */ 1789ENTRY(TBIAS) 1790#ifdef DEBUG 1791 tstl fulltflush | being conservative? 1792 jne __TBIA | yes, flush everything 1793#endif 1794#if defined(LUNA2) 1795 cmpl #-2,_mmutype | 68040? 1796 jne Lmotommu5 | no, skip 1797 .word 0xf518 | yes, pflusha (for now) XXX 1798 rts 1799Lmotommu5: 1800#endif 1801 pflush #4,#4 | flush supervisor TLB entries 1802 movl #DC_CLEAR,d0 1803 movc d0,cacr | invalidate on-chip d-cache 1804 rts 1805 1806/* 1807 * Invalidate user side of TLB 1808 */ 1809ENTRY(TBIAU) 1810#ifdef DEBUG 1811 tstl fulltflush | being conservative? 1812 jne __TBIA | yes, flush everything 1813#endif 1814#if defined(LUNA2) 1815 cmpl #-2,_mmutype | 68040? 1816 jne Lmotommu6 | no, skip 1817 .word 0xf518 | yes, pflusha (for now) XXX 1818 rts 1819Lmotommu6: 1820#endif 1821 pflush #0,#4 | flush user TLB entries 1822 movl #DC_CLEAR,d0 1823 movc d0,cacr | invalidate on-chip d-cache 1824 rts 1825 1826/* 1827 * Invalidate instruction cache 1828 */ 1829ENTRY(ICIA) 1830#if defined(LUNA2) 1831ENTRY(ICPA) 1832 cmpl #-2,_mmutype | 68040 1833 jne Lmotommu7 | no, skip 1834 .word 0xf498 | cinva ic 1835 rts 1836Lmotommu7: 1837#endif 1838 movl #IC_CLEAR,d0 1839 movc d0,cacr | invalidate i-cache 1840 rts 1841 1842/* 1843 * Invalidate data cache. 1844 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing 1845 * problems with DC_WA. The only cases we have to worry about are context 1846 * switch and TLB changes, both of which are handled "in-line" in resume 1847 * and TBI*. 1848 */ 1849ENTRY(DCIA) 1850__DCIA: 1851#if defined(LUNA2) 1852 cmpl #-2,_mmutype | 68040 1853 jne Lmotommu8 | no, skip 1854 /* XXX implement */ 1855 rts 1856Lmotommu8: 1857#endif 1858 rts 1859 1860ENTRY(DCIS) 1861__DCIS: 1862#if defined(LUNA2) 1863 cmpl #-2,_mmutype | 68040 1864 jne Lmotommu9 | no, skip 1865 /* XXX implement */ 1866 rts 1867Lmotommu9: 1868#endif 1869 rts 1870 1871ENTRY(DCIU) 1872__DCIU: 1873#if defined(LUNA2) 1874 cmpl #-2,_mmutype | 68040 1875 jne LmotommuA | no, skip 1876 /* XXX implement */ 1877 rts 1878LmotommuA: 1879#endif 1880 rts 1881 1882#if defined(LUNA2) 1883ENTRY(ICPL) 1884 movl sp@(4),a0 | address 1885 .word 0xf488 | cinvl ic,a0@ 1886 rts 1887ENTRY(ICPP) 1888 movl sp@(4),a0 | address 1889 .word 0xf490 | cinvp ic,a0@ 1890 rts 1891ENTRY(DCPL) 1892 movl sp@(4),a0 | address 1893 .word 0xf448 | cinvl dc,a0@ 1894 rts 1895ENTRY(DCPP) 1896 movl sp@(4),a0 | address 1897 .word 0xf450 | cinvp dc,a0@ 1898 rts 1899ENTRY(DCPA) 1900 .word 0xf458 | cinva dc 1901 rts 1902ENTRY(DCFL) 1903 movl sp@(4),a0 | address 1904 .word 0xf468 | cpushl dc,a0@ 1905 rts 1906ENTRY(DCFP) 1907 movl sp@(4),a0 | address 1908 .word 0xf470 | cpushp dc,a0@ 1909 rts 1910#endif 1911 1912ENTRY(PCIA) 1913#if defined(LUNA2) 1914ENTRY(DCFA) 1915 cmpl #-2,_mmutype | 68040 1916 jne LmotommuB | no, skip 1917 .word 0xf478 | cpusha dc 1918 rts 1919LmotommuB: 1920#endif 1921 movl #DC_CLEAR,d0 1922 movc d0,cacr | invalidate on-chip d-cache 1923 rts 1924 1925#if 0 /****************************************************************/ 1926/* external cache control */ 1927ENTRY(ecacheon) 1928 rts 1929 1930ENTRY(ecacheoff) 1931 rts 1932#endif /****************************************************************/ 1933 1934/* 1935 * Get callers current SP value. 1936 * Note that simply taking the address of a local variable in a C function 1937 1938 * doesn't work because callee saved registers may be outside the stack frame 1939 * defined by A6 (e.g. GCC generated code). 1940 */ 1941 .globl _getsp 1942_getsp: 1943 movl sp,d0 | get current SP 1944 addql #4,d0 | compensate for return address 1945 rts 1946 1947 .globl _getsfc, _getdfc 1948_getsfc: 1949 movc sfc,d0 1950 rts 1951_getdfc: 1952 movc dfc,d0 1953 rts 1954 1955/* 1956 * Load a new user segment table pointer. 1957 */ 1958ENTRY(loadustp) 1959 movl sp@(4),d0 | new USTP 1960 moveq #PGSHIFT,d1 1961 lsll d1,d0 | convert to addr 1962#if defined(LUNA2) 1963 cmpl #-2,_mmutype | 68040? 1964 jne LmotommuC | no, skip 1965 .long 0x4e7b0806 | movc d0,urp 1966 rts 1967LmotommuC: 1968#endif 1969 lea _protorp,a0 | CRP prototype 1970 movl d0,a0@(4) | stash USTP 1971 pmove a0@,crp | load root pointer 1972 movl #DC_CLEAR,d0 1973 movc d0,cacr | invalidate on-chip d-cache 1974 rts 1975 1976ENTRY(ploadw) 1977 movl sp@(4),a0 | address to load 1978 ploadw #1,a0@ | pre-load translation 1979 rts 1980 1981/* 1982 * Set processor priority level calls. Most are implemented with 1983 * inline asm expansions. However, spl0 requires special handling 1984 * as we need to check for our emulated software interrupts. 1985 */ 1986 1987ENTRY(spl0) 1988 moveq #0,d0 1989 movw sr,d0 | get old SR for return 1990 movw #PSL_LOWIPL,sr | restore new SR 1991 tstb _ssir | software interrupt pending? 1992 jeq Lspldone | no, all done 1993 subql #4,sp | make room for RTE frame 1994 movl sp@(4),sp@(2) | position return address 1995 clrw sp@(6) | set frame type 0 1996 movw #PSL_LOWIPL,sp@ | and new SR 1997 jra Lgotsir | go handle it 1998Lspldone: 1999 rts 2000 2001ENTRY(_insque) 2002 movw sr,d0 2003 movw #PSL_HIGHIPL,sr | atomic 2004 movl sp@(8),a0 | where to insert (after) 2005 movl sp@(4),a1 | element to insert (e) 2006 movl a0@,a1@ | e->next = after->next 2007 movl a0,a1@(4) | e->prev = after 2008 movl a1,a0@ | after->next = e 2009 movl a1@,a0 2010 movl a1,a0@(4) | e->next->prev = e 2011 movw d0,sr 2012 rts 2013 2014ENTRY(_remque) 2015 movw sr,d0 2016 movw #PSL_HIGHIPL,sr | atomic 2017 movl sp@(4),a0 | element to remove (e) 2018 movl a0@,a1 2019 movl a0@(4),a0 2020 movl a0,a1@(4) | e->next->prev = e->prev 2021 movl a1,a0@ | e->prev->next = e->next 2022 movw d0,sr 2023 rts 2024 2025/* 2026 * bzero(addr, count) 2027 */ 2028ALTENTRY(blkclr, _bzero) 2029ENTRY(bzero) 2030 movl sp@(4),a0 | address 2031 movl sp@(8),d0 | count 2032 jeq Lbzdone | if zero, nothing to do 2033 movl a0,d1 2034 btst #0,d1 | address odd? 2035 jeq Lbzeven | no, can copy words 2036 clrb a0@+ | yes, zero byte to get to even boundary 2037 subql #1,d0 | decrement count 2038 jeq Lbzdone | none left, all done 2039Lbzeven: 2040 movl d0,d1 2041 andl #31,d0 2042 lsrl #5,d1 | convert count to 8*longword count 2043 jeq Lbzbyte | no such blocks, zero byte at a time 2044Lbzloop: 2045 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2046 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2047 subql #1,d1 | one more block zeroed 2048 jne Lbzloop | more to go, do it 2049 tstl d0 | partial block left? 2050 jeq Lbzdone | no, all done 2051Lbzbyte: 2052 clrb a0@+ 2053 subql #1,d0 | one more byte cleared 2054 jne Lbzbyte | more to go, do it 2055Lbzdone: 2056 rts 2057 2058/* 2059 * strlen(str) 2060 */ 2061ENTRY(strlen) 2062 moveq #-1,d0 2063 movl sp@(4),a0 | string 2064Lslloop: 2065 addql #1,d0 | increment count 2066 tstb a0@+ | null? 2067 jne Lslloop | no, keep going 2068 rts 2069 2070/* 2071 * bcmp(s1, s2, len) 2072 * 2073 * WARNING! This guy only works with counts up to 64K 2074 */ 2075ENTRY(bcmp) 2076 movl sp@(4),a0 | string 1 2077 movl sp@(8),a1 | string 2 2078 moveq #0,d0 2079 movw sp@(14),d0 | length 2080 jeq Lcmpdone | if zero, nothing to do 2081 subqw #1,d0 | set up for DBcc loop 2082Lcmploop: 2083 cmpmb a0@+,a1@+ | equal? 2084 dbne d0,Lcmploop | yes, keep going 2085 addqw #1,d0 | +1 gives zero on match 2086Lcmpdone: 2087 rts 2088 2089/* 2090 * {ov}bcopy(from, to, len) 2091 * 2092 * Works for counts up to 128K. 2093 */ 2094ALTENTRY(ovbcopy, _bcopy) 2095ENTRY(bcopy) 2096 movl sp@(12),d0 | get count 2097 jeq Lcpyexit | if zero, return 2098 movl sp@(4),a0 | src address 2099 movl sp@(8),a1 | dest address 2100 cmpl a1,a0 | src before dest? 2101 jlt Lcpyback | yes, copy backwards (avoids overlap) 2102 movl a0,d1 2103 btst #0,d1 | src address odd? 2104 jeq Lcfeven | no, go check dest 2105 movb a0@+,a1@+ | yes, copy a byte 2106 subql #1,d0 | update count 2107 jeq Lcpyexit | exit if done 2108Lcfeven: 2109 movl a1,d1 2110 btst #0,d1 | dest address odd? 2111 jne Lcfbyte | yes, must copy by bytes 2112 movl d0,d1 | no, get count 2113 lsrl #2,d1 | convert to longwords 2114 jeq Lcfbyte | no longwords, copy bytes 2115 subql #1,d1 | set up for dbf 2116Lcflloop: 2117 movl a0@+,a1@+ | copy longwords 2118 dbf d1,Lcflloop | til done 2119 andl #3,d0 | get remaining count 2120 jeq Lcpyexit | done if none 2121Lcfbyte: 2122 subql #1,d0 | set up for dbf 2123Lcfbloop: 2124 movb a0@+,a1@+ | copy bytes 2125 dbf d0,Lcfbloop | til done 2126Lcpyexit: 2127 rts 2128Lcpyback: 2129 addl d0,a0 | add count to src 2130 addl d0,a1 | add count to dest 2131 movl a0,d1 2132 btst #0,d1 | src address odd? 2133 jeq Lcbeven | no, go check dest 2134 movb a0@-,a1@- | yes, copy a byte 2135 subql #1,d0 | update count 2136 jeq Lcpyexit | exit if done 2137Lcbeven: 2138 movl a1,d1 2139 btst #0,d1 | dest address odd? 2140 jne Lcbbyte | yes, must copy by bytes 2141 movl d0,d1 | no, get count 2142 lsrl #2,d1 | convert to longwords 2143 jeq Lcbbyte | no longwords, copy bytes 2144 subql #1,d1 | set up for dbf 2145Lcblloop: 2146 movl a0@-,a1@- | copy longwords 2147 dbf d1,Lcblloop | til done 2148 andl #3,d0 | get remaining count 2149 jeq Lcpyexit | done if none 2150Lcbbyte: 2151 subql #1,d0 | set up for dbf 2152Lcbbloop: 2153 movb a0@-,a1@- | copy bytes 2154 dbf d0,Lcbbloop | til done 2155 rts 2156 2157/* 2158 * Emulate fancy VAX string operations: 2159 * scanc(count, startc, table, mask) 2160 * skpc(mask, count, startc) 2161 * locc(mask, count, startc) 2162 */ 2163ENTRY(scanc) 2164 movl sp@(4),d0 | get length 2165 jeq Lscdone | nothing to do, return 2166 movl sp@(8),a0 | start of scan 2167 movl sp@(12),a1 | table to compare with 2168 movb sp@(19),d1 | and mask to use 2169 movw d2,sp@- | need a scratch register 2170 clrw d2 | clear it out 2171 subqw #1,d0 | adjust for dbra 2172Lscloop: 2173 movb a0@+,d2 | get character 2174 movb a1@(0,d2:w),d2 | get table entry 2175 andb d1,d2 | mask it 2176 dbne d0,Lscloop | keep going til no more or non-zero 2177 addqw #1,d0 | overshot by one 2178 movw sp@+,d2 | restore scratch 2179Lscdone: 2180 rts 2181 2182ENTRY(skpc) 2183 movl sp@(8),d0 | get length 2184 jeq Lskdone | nothing to do, return 2185 movb sp@(7),d1 | mask to use 2186 movl sp@(12),a0 | where to start 2187 subqw #1,d0 | adjust for dbcc 2188Lskloop: 2189 cmpb a0@+,d1 | compate with mask 2190 dbne d0,Lskloop | keep going til no more or zero 2191 addqw #1,d0 | overshot by one 2192Lskdone: 2193 rts 2194 2195ENTRY(locc) 2196 movl sp@(8),d0 | get length 2197 jeq Llcdone | nothing to do, return 2198 movb sp@(7),d1 | mask to use 2199 movl sp@(12),a0 | where to start 2200 subqw #1,d0 | adjust for dbcc 2201Llcloop: 2202 cmpb a0@+,d1 | compate with mask 2203 dbeq d0,Llcloop | keep going til no more or non-zero 2204 addqw #1,d0 | overshot by one 2205Llcdone: 2206 rts 2207 2208/* 2209 * Emulate VAX FFS (find first set) instruction. 2210 */ 2211ENTRY(ffs) 2212 moveq #-1,d0 2213 movl sp@(4),d1 2214 jeq Lffsdone 2215Lffsloop: 2216 addql #1,d0 2217 btst d0,d1 2218 jeq Lffsloop 2219Lffsdone: 2220 addql #1,d0 2221 rts 2222 2223#ifdef FPCOPROC 2224/* 2225 * Save and restore 68881 state. 2226 * Pretty awful looking since our assembler does not 2227 * recognize FP mnemonics. 2228 */ 2229ENTRY(m68881_save) 2230 movl sp@(4),a0 | save area pointer 2231 fsave a0@ | save state 2232 tstb a0@ | null state frame? 2233 jeq Lm68881sdone | yes, all done 2234 fmovem fp0-fp7,a0@(216) | save FP general registers 2235 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 2236Lm68881sdone: 2237 rts 2238 2239ENTRY(m68881_restore) 2240 movl sp@(4),a0 | save area pointer 2241 tstb a0@ | null state frame? 2242 jeq Lm68881rdone | yes, easy 2243 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 2244 fmovem a0@(216),fp0-fp7 | restore FP general registers 2245Lm68881rdone: 2246 frestore a0@ | restore state 2247 rts 2248 2249/* LUNA */ 2250 2251 .globl _fpp_svarea 2252 2253/* Fpp is MC68882 ? */ 2254ENTRY(is_68882) 2255 frestore _fppnull | initialize fpp 2256 movl #2,d0 2257 fmovecr #0,fp1 2258 fsinx fp1,fp2 2259 lea _fpp_svarea,a0 | save area 2260 movw sr,d1 | save status reg. 2261 movw #0x2700,sr | mask intrrupt 2262 fsave a0@ | save fpp context 2263 movw d1,sr | restore status reg. 2264 movl a0@,d1 2265 andl #0x00ff0000,d1 | check status field 2266 cmpl #0x00180000,d1 | 68881(idle)? 2267 beq _is81 2268 cmpl #0x00b40000,d1 | 68881(busy)? 2269 beq _is81 2270 cmpl #0x00380000,d1 | 68882(idle)? 2271 beq _is82 2272 cmpl #0x00d40000,d1 | 68882(busy)? 2273 beq _is82 2274 bra _is82out | default 68881 2275_is81: 2276 clrl d0 2277 bra _is82out 2278_is82: 2279 movl #1,d0 2280_is82out: 2281 frestore a0@ 2282 rts 2283 2284#ifdef OLD_LUNA 2285/* We have fpp ? */ 2286ENTRY(havefpp) 2287 movl a2,sp@- 2288 clrl d0 2289 movl vb,a2 2290 movl a2@(FLINE_VEC),a0 | save vectors 2291 movl a2@(COPRO_VEC),a1 2292 movl sp,d1 2293 movl #_fpvec,a2@(FLINE_VEC) | change vectors 2294 movl #_fpvec,a2@(COPRO_VEC) 2295 fnop | cause exception ? 2296 movl #1,d0 2297_fpvec: movl a0,a2@(FLINE_VEC) | restore vectors 2298 movl a1,a2@(COPRO_VEC) 2299 movl d1,sp 2300 movl sp@+,a2 2301 rts 2302#endif 2303#endif 2304 2305/* 2306 * Handle the nitty-gritty of rebooting the machine. 2307 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 2308 * Note that we must be running in an address range that is mapped one-to-one 2309 * logical to physical so that the PC is still valid immediately after the MMU 2310 * is turned off. We have conveniently mapped the last page of physical 2311 * memory this way. 2312 */ 2313 .globl _doboot 2314_doboot: 2315 movl #0x41000004,a0 2316 movl a0@,a1 | get PROM restart entry address 2317#if defined(LUNA2) 2318 cmpl #-2,_mmutype | 68040? 2319 jne LmotommuF | no, skip 2320 2321 movl #0x41000000,a0 2322 movl a0@,d0 2323 movc d0,isp | set ISP 2324 2325 movw #PSL_HIGHIPL,sr | no interrupts 2326 2327 .word 0xf4f8 | cpusha bc 2328 movl #0,d0 2329 movc d0,cacr | caches off 2330 movql #0,d0 2331 .long 0x4e7b0004 | movc d0,itt0 2332 .long 0x4e7b0005 | movc d0,itt1 2333 .long 0x4e7b0006 | movc d0,dtt0 2334 .long 0x4e7b0007 | movc d0,dtt1 2335 2336 .long 0x4e7b0003 | movc d0,tc 2337 2338 jmp a1@ | goto REBOOT 2339LmotommuF: 2340#endif 2341 movl #CACHE_OFF,d0 2342 movc d0,cacr | disable on-chip cache(s) 2343 movl #_tcroff,a0 | value for pmove to TC (turn off MMU) 2344 pmove a0@,tc | disable MMU 2345 jmp a1@ | goto REBOOT 2346 2347 .data 2348 .globl _machineid,_mmutype 2349_machineid: 2350 .long 1 | default to LUNA-I 2351_mmutype: 2352 .long -1 | default to 68030 PMMU 2353 .globl _protorp,_protott0,_protott1 2354_protorp: 2355 .long 0,0 | prototype root pointer 2356_protott0: 2357 .long 0x403f8543 | tt0 (for LUNA1 kernel 0x40000000-0x7fffffff) 2358_protott1: 2359 .long 0x807F8543 | tt1 (for LUNA1 kernel 0x80000000-0xffffffff) 2360_mapping_tc: 2361 .long 0 2362 .globl _cold 2363_cold: 2364 .long 1 | cold start flag 2365 .globl _want_resched 2366_want_resched: 2367 .long 0 2368 .globl _proc0paddr 2369_proc0paddr: 2370 .long 0 | KVA of proc0 u-area 2371 2372 .globl _tcroff 2373_tcroff: 2374 .long 0 | TC reg. reset flag 2375 2376#ifdef FPCOPROC 2377 .globl _fppnull 2378_fppnull: 2379 .long 0 2380#endif 2381 .globl _clock_on 2382_clock_on: 2383 .long 0 | clock is enable ? 2384 .globl _dipswitch 2385_dipswitch: 2386 .word 0 | dipsw(front panel) value 2387 .globl _KernInter 2388_KernInter: | Kernel InterFace Field 2389 .space KIFF_SIZE 2390#ifdef DEBUG 2391 .globl fulltflush, fullcflush 2392fulltflush: 2393 .long 0 2394fullcflush: 2395 .long 0 2396#endif 2397#ifdef HPFPLIB 2398/* 2399 * Undefined symbols from hpux_float.o: 2400 * 2401 * kdb_printf: A kernel debugger print routine, we just use printf instead. 2402 * processor: HP-UX equiv. of machineid, set to 3 if it is a 68040. 2403 * u: Ye ole u-area. The code wants to grab the first longword 2404 * indirect off of that and clear the 0x40000 bit there. 2405 * Oddly enough this was incorrect even in HP-UX! 2406 * runrun: Old name for want_resched. 2407 */ 2408 .globl _kdb_printf,_processor,_u,_runrun 2409_kdb_printf: 2410 .long _printf 2411_processor: 2412 .long 0 2413_u: 2414 .long .+4 2415 .long 0 2416 .set _runrun,_want_resched 2417#endif 2418/* interrupt counters */ 2419 .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames 2420_intrnames: 2421 .asciz "spur" 2422 .asciz "lev1" 2423 .asciz "lev2" 2424 .asciz "lev3" 2425 .asciz "lev4" 2426 .asciz "clock" 2427 .asciz "lev7" 2428 .asciz "nmi" 2429_eintrnames: 2430 .even 2431_intrcnt: 2432 .long 0,0,0,0,0,0,0,0,0 2433_eintrcnt: 2434