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.14 (Berkeley) 06/02/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/* 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. 1265 * _whichqs tells which of the 32 queues _qs 1266 * have processes in them. Setrq puts processes into queues, Remrq 1267 * removes them from queues. The running process is on no queue, 1268 * other processes are on a queue related to p->p_pri, divided by 4 1269 * actually to shrink the 0-127 range of priorities into the 32 available 1270 * queues. 1271 */ 1272 1273 .globl _whichqs,_qs,_cnt,_panic 1274 .globl _curproc,_want_resched 1275 1276/* 1277 * Setrq(p) 1278 * 1279 * Call should be made at spl6(), and p->p_stat should be SRUN 1280 */ 1281ENTRY(setrq) 1282 movl sp@(4),a0 1283 tstl a0@(P_RLINK) 1284 jeq Lset1 1285 movl #Lset2,sp@- 1286 jbsr _panic 1287Lset1: 1288 clrl d0 1289 movb a0@(P_PRI),d0 1290 lsrb #2,d0 1291 movl _whichqs,d1 1292 bset d0,d1 1293 movl d1,_whichqs 1294 lslb #3,d0 1295 addl #_qs,d0 1296 movl d0,a0@(P_LINK) 1297 movl d0,a1 1298 movl a1@(P_RLINK),a0@(P_RLINK) 1299 movl a0,a1@(P_RLINK) 1300 movl a0@(P_RLINK),a1 1301 movl a0,a1@(P_LINK) 1302 rts 1303 1304Lset2: 1305 .asciz "setrq" 1306 .even 1307 1308/* 1309 * Remrq(p) 1310 * 1311 * Call should be made at spl6(). 1312 */ 1313ENTRY(remrq) 1314 movl sp@(4),a0 1315 clrl d0 1316 movb a0@(P_PRI),d0 1317 lsrb #2,d0 1318 movl _whichqs,d1 1319 bclr d0,d1 1320 jne Lrem1 1321 movl #Lrem3,sp@- 1322 jbsr _panic 1323Lrem1: 1324 movl d1,_whichqs 1325 movl a0@(P_LINK),a1 1326 movl a0@(P_RLINK),a1@(P_RLINK) 1327 movl a0@(P_RLINK),a1 1328 movl a0@(P_LINK),a1@(P_LINK) 1329 movl #_qs,a1 1330 movl d0,d1 1331 lslb #3,d1 1332 addl d1,a1 1333 cmpl a1@(P_LINK),a1 1334 jeq Lrem2 1335 movl _whichqs,d1 1336 bset d0,d1 1337 movl d1,_whichqs 1338Lrem2: 1339 clrl a0@(P_RLINK) 1340 rts 1341 1342Lrem3: 1343 .asciz "remrq" 1344Lsw0: 1345 .asciz "swtch" 1346 .even 1347 1348 .globl _curpcb 1349 .globl _masterpaddr | XXX compatibility (debuggers) 1350 .data 1351_masterpaddr: | XXX compatibility (debuggers) 1352_curpcb: 1353 .long 0 1354mdpflag: 1355 .byte 0 | copy of proc md_flags low byte 1356 .align 2 1357 .comm nullpcb,SIZEOF_PCB 1358 .text 1359 1360/* 1361 * At exit of a process, do a swtch for the last time. 1362 * The mapping of the pcb at p->p_addr has already been deleted, 1363 * and the memory for the pcb+stack has been freed. 1364 * The ipl is high enough to prevent the memory from being reallocated. 1365 */ 1366ENTRY(swtch_exit) 1367 movl #nullpcb,_curpcb | save state into garbage pcb 1368 lea tmpstk,sp | goto a tmp stack 1369 jra _cpu_swtch 1370 1371/* 1372 * When no processes are on the runq, Swtch branches to idle 1373 * to wait for something to come ready. 1374 */ 1375 .globl idle 1376Lidle: 1377 stop #PSL_LOWIPL 1378idle: 1379 movw #PSL_HIGHIPL,sr 1380 tstl _whichqs 1381 jeq Lidle 1382 movw #PSL_LOWIPL,sr 1383 jra Lsw1 1384 1385Lbadsw: 1386 movl #Lsw0,sp@- 1387 jbsr _panic 1388 /*NOTREACHED*/ 1389 1390/* 1391 * cpu_swtch() 1392 * 1393 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1394 * entire ATC. The effort involved in selective flushing may not be 1395 * worth it, maybe we should just flush the whole thing? 1396 * 1397 * NOTE 2: With the new VM layout we now no longer know if an inactive 1398 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1399 * bit). For now, we just always flush the full ATC. 1400 */ 1401ENTRY(cpu_swtch) 1402 movl _curpcb,a0 | current pcb 1403 movw sr,a0@(PCB_PS) | save sr before changing ipl 1404#ifdef notyet 1405 movl _curproc,sp@- | remember last proc running 1406#endif 1407 clrl _curproc 1408 addql #1,_cnt+V_SWTCH 1409 1410Lsw1: 1411 /* 1412 * Find the highest-priority queue that isn't empty, 1413 * then take the first proc from that queue. 1414 */ 1415 clrl d0 1416 lea _whichqs,a0 1417 movl a0@,d1 1418Lswchk: 1419 btst d0,d1 1420 jne Lswfnd 1421 addqb #1,d0 1422 cmpb #32,d0 1423 jne Lswchk 1424 jra idle 1425Lswfnd: 1426 movw #PSL_HIGHIPL,sr | lock out interrupts 1427 movl a0@,d1 | and check again... 1428 bclr d0,d1 1429 jeq Lsw1 | proc moved, rescan 1430 movl d1,a0@ | update whichqs 1431 moveq #1,d1 | double check for higher priority 1432 lsll d0,d1 | process (which may have snuck in 1433 subql #1,d1 | while we were finding this one) 1434 andl a0@,d1 1435 jeq Lswok | no one got in, continue 1436 movl a0@,d1 1437 bset d0,d1 | otherwise put this one back 1438 movl d1,a0@ 1439 jra Lsw1 | and rescan 1440Lswok: 1441 movl d0,d1 1442 lslb #3,d1 | convert queue number to index 1443 addl #_qs,d1 | locate queue (q) 1444 movl d1,a1 1445 cmpl a1@(P_LINK),a1 | anyone on queue? 1446 jeq Lbadsw | no, panic 1447 movl a1@(P_LINK),a0 | p = q->p_link 1448 movl a0@(P_LINK),a1@(P_LINK) | q->p_link = p->p_link 1449 movl a0@(P_LINK),a1 | q = p->p_link 1450 movl a0@(P_RLINK),a1@(P_RLINK) | q->p_rlink = p->p_rlink 1451 cmpl a0@(P_LINK),d1 | anyone left on queue? 1452 jeq Lsw2 | no, skip 1453 movl _whichqs,d1 1454 bset d0,d1 | yes, reset bit 1455 movl d1,_whichqs 1456Lsw2: 1457 movl a0,_curproc 1458 clrl _want_resched 1459#ifdef notyet 1460 movl sp@+,a1 1461 cmpl a0,a1 | switching to same proc? 1462 jeq Lswdone | yes, skip save and restore 1463#endif 1464 /* 1465 * Save state of previous process in its pcb. 1466 */ 1467 movl _curpcb,a1 1468 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1469 movl usp,a2 | grab USP (a2 has been saved) 1470 movl a2,a1@(PCB_USP) | and save it 1471#ifdef FPCOPROC 1472 lea a1@(PCB_FPCTX),a2 | pointer to FP save area 1473 fsave a2@ | save FP state 1474 tstb a2@ | null state frame? 1475 jeq Lswnofpsave | yes, all done 1476 fmovem fp0-fp7,a2@(216) | save FP general registers 1477 fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers 1478Lswnofpsave: 1479#endif 1480 1481#ifdef DIAGNOSTIC 1482 tstl a0@(P_WCHAN) 1483 jne Lbadsw 1484 cmpb #SRUN,a0@(P_STAT) 1485 jne Lbadsw 1486#endif 1487 clrl a0@(P_RLINK) | clear back link 1488 movb a0@(P_MDFLAG+3),mdpflag | low byte of p_md.md_flags 1489 movl a0@(P_ADDR),a1 | get p_addr 1490 movl a1,_curpcb 1491 1492 /* see if pmap_activate needs to be called; should remove this */ 1493 movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace 1494#ifdef DIAGNOSTIC 1495 tstl a0 | map == VM_MAP_NULL? 1496 jeq Lbadsw | panic 1497#endif 1498 lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap 1499 tstl a0@(PM_STCHG) | pmap->st_changed? 1500 jeq Lswnochg | no, skip 1501 pea a1@ | push pcb (at p_addr) 1502 pea a0@ | push pmap 1503 jbsr _pmap_activate | pmap_activate(pmap, pcb) 1504 addql #8,sp 1505 movl _curpcb,a1 | restore p_addr 1506Lswnochg: 1507 1508 movl #PGSHIFT,d1 1509 movl a1,d0 1510 lsrl d1,d0 | convert p_addr to page number 1511 lsll #2,d0 | and now to Sysmap offset 1512 addl _Sysmap,d0 | add Sysmap base to get PTE addr 1513#ifdef notdef 1514 movw #PSL_HIGHIPL,sr | go crit while changing PTEs 1515#endif 1516 lea tmpstk,sp | now goto a tmp stack for NMI 1517 movl d0,a0 | address of new context 1518 movl _Umap,a2 | address of PTEs for kstack 1519 moveq #UPAGES-1,d0 | sizeof kstack 1520Lres1: 1521 movl a0@+,d1 | get PTE 1522 andl #~PG_PROT,d1 | mask out old protection 1523 orl #PG_RW+PG_V,d1 | ensure valid and writable 1524 movl d1,a2@+ | load it up 1525 dbf d0,Lres1 | til done 1526#if defined(LUNA2) 1527 cmpl #-2,_mmutype | 68040? 1528 jne Lres1a | no, skip 1529 .word 0xf518 | yes, pflusha 1530 movl a1@(PCB_USTP),d0 | get USTP 1531 moveq #PGSHIFT,d1 1532 lsll d1,d0 | convert to addr 1533 .long 0x4e7b0806 | movc d0,urp 1534 jra Lcxswdone 1535Lres1a: 1536#endif 1537 movl #CACHE_CLR,d0 1538 movc d0,cacr | invalidate cache(s) 1539 pflusha | flush entire TLB 1540 movl a1@(PCB_USTP),d0 | get USTP 1541 moveq #PGSHIFT,d1 1542 lsll d1,d0 | convert to addr 1543 lea _protorp,a0 | CRP prototype 1544 movl d0,a0@(4) | stash USTP 1545 pmove a0@,crp | load new user root pointer 1546Lcxswdone: 1547 moveml a1@(PCB_REGS),#0xFCFC | and registers 1548 movl a1@(PCB_USP),a0 1549 movl a0,usp | and USP 1550#ifdef FPCOPROC 1551 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1552 tstb a0@ | null state frame? 1553 jeq Lresfprest | yes, easy 1554#if defined(LUNA2) 1555 cmpl #-2,_mmutype | 68040? 1556 jne Lresnot040 | no, skip 1557 clrl sp@- | yes... 1558 frestore sp@+ | ...magic! 1559Lresnot040: 1560#endif 1561 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 1562 fmovem a0@(216),fp0-fp7 | restore FP general registers 1563Lresfprest: 1564 frestore a0@ | restore state 1565#endif 1566 movw a1@(PCB_PS),sr | no, restore PS 1567 moveq #1,d0 | return 1 (for alternate returns) 1568 rts 1569 1570/* 1571 * savectx(pcb, altreturn) 1572 * Update pcb, saving current processor state and arranging 1573 * for alternate return ala longjmp in swtch if altreturn is true. 1574 */ 1575ENTRY(savectx) 1576 movl sp@(4),a1 1577 movw sr,a1@(PCB_PS) 1578 movl usp,a0 | grab USP 1579 movl a0,a1@(PCB_USP) | and save it 1580 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1581#ifdef FPCOPROC 1582 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1583 fsave a0@ | save FP state 1584 tstb a0@ | null state frame? 1585 jeq Lsvnofpsave | yes, all done 1586 fmovem fp0-fp7,a0@(216) | save FP general registers 1587 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 1588Lsvnofpsave: 1589#endif 1590 tstl sp@(8) | altreturn? 1591 jeq Lsavedone 1592 movl sp,d0 | relocate current sp relative to a1 1593 subl #_kstack,d0 | (sp is relative to kstack): 1594 addl d0,a1 | a1 += sp - kstack; 1595 movl sp@,a1@ | write return pc at (relocated) sp@ 1596Lsavedone: 1597 moveq #0,d0 | return 0 1598 rts 1599 1600/* 1601 * {fu,su},{byte,sword,word} 1602 */ 1603ALTENTRY(fuiword, _fuword) 1604ENTRY(fuword) 1605 movl sp@(4),a0 | address to read 1606 movl _curpcb,a1 | current pcb 1607 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1608 movsl a0@,d0 | do read from user space 1609 nop 1610 jra Lfsdone 1611 1612ENTRY(fusword) 1613 movl sp@(4),a0 1614 movl _curpcb,a1 | current pcb 1615 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1616 moveq #0,d0 1617 movsw a0@,d0 | do read from user space 1618 nop 1619 jra Lfsdone 1620 1621/* Just like fusword, but tells trap code not to page in. */ 1622ENTRY(fuswintr) 1623 movl sp@(4),a0 1624 movl _curpcb,a1 1625 movl #_fswintr,a1@(PCB_ONFAULT) 1626 moveq #0,d0 1627 movsw a0@,d0 1628 nop 1629 jra Lfsdone 1630 1631ALTENTRY(fuibyte, _fubyte) 1632ENTRY(fubyte) 1633 movl sp@(4),a0 | address to read 1634 movl _curpcb,a1 | current pcb 1635 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1636 moveq #0,d0 1637 movsb a0@,d0 | do read from user space 1638 nop 1639 jra Lfsdone 1640 1641Lfserr: 1642 moveq #-1,d0 | error indicator 1643Lfsdone: 1644 clrl a1@(PCB_ONFAULT) | clear fault address 1645 rts 1646 1647/* Just like Lfserr, but the address is different (& exported). */ 1648 .globl _fswintr 1649_fswintr: 1650 moveq #-1,d0 1651 jra Lfsdone 1652 1653 1654/* 1655 * Write a longword in user instruction space. 1656 * Largely the same as suword but with a final i-cache purge on those 1657 * machines with split caches. 1658 */ 1659ENTRY(suiword) 1660 movl sp@(4),a0 | address to write 1661 movl sp@(8),d0 | value to put there 1662 movl _curpcb,a1 | current pcb 1663 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1664 movsl d0,a0@ | do write to user space 1665 nop 1666 moveq #0,d0 | indicate no fault 1667#if defined(LUNA2) 1668 cmpl #-2,_mmutype | 68040? 1669 jne Lsuicpurge | no, skip 1670 .word 0xf498 | cinva ic (XXX overkill) 1671 jra Lfsdone 1672Lsuicpurge: 1673#endif 1674 movl #IC_CLEAR,d1 1675 movc d1,cacr | invalidate i-cache 1676 jra Lfsdone 1677 1678ENTRY(suword) 1679 movl sp@(4),a0 | address to write 1680 movl sp@(8),d0 | value to put there 1681 movl _curpcb,a1 | current pcb 1682 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1683 movsl d0,a0@ | do write to user space 1684 nop 1685 moveq #0,d0 | indicate no fault 1686 jra Lfsdone 1687 1688ENTRY(susword) 1689 movl sp@(4),a0 | address to write 1690 movw sp@(10),d0 | value to put there 1691 movl _curpcb,a1 | current pcb 1692 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1693 movsw d0,a0@ | do write to user space 1694 nop 1695 moveq #0,d0 | indicate no fault 1696 jra Lfsdone 1697 1698ENTRY(suswintr) 1699 movl sp@(4),a0 1700 movw sp@(10),d0 1701 movl _curpcb,a1 1702 movl #_fswintr,a1@(PCB_ONFAULT) 1703 movsw d0,a0@ 1704 nop 1705 moveq #0,d0 1706 jra Lfsdone 1707 1708ALTENTRY(suibyte, _subyte) 1709ENTRY(subyte) 1710 movl sp@(4),a0 | address to write 1711 movb sp@(11),d0 | value to put there 1712 movl _curpcb,a1 | current pcb 1713 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1714 movsb d0,a0@ | do write to user space 1715 nop 1716 moveq #0,d0 | indicate no fault 1717 jra Lfsdone 1718 1719#if defined(LUNA2) 1720ENTRY(suline) 1721 movl sp@(4),a0 | address to write 1722 movl _curpcb,a1 | current pcb 1723 movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault 1724 movl sp@(8),a1 | address of line 1725 movl a1@+,d0 | get lword 1726 movsl d0,a0@+ | put lword 1727 nop | sync 1728 movl a1@+,d0 | get lword 1729 movsl d0,a0@+ | put lword 1730 nop | sync 1731 movl a1@+,d0 | get lword 1732 movsl d0,a0@+ | put lword 1733 nop | sync 1734 movl a1@+,d0 | get lword 1735 movsl d0,a0@+ | put lword 1736 nop | sync 1737 moveq #0,d0 | indicate no fault 1738 jra Lsldone 1739Lslerr: 1740 moveq #-1,d0 1741Lsldone: 1742 movl _curpcb,a1 | current pcb 1743 clrl a1@(PCB_ONFAULT) | clear fault address 1744 rts 1745#endif 1746 1747/* 1748 * Invalidate entire TLB. 1749 */ 1750ENTRY(TBIA) 1751__TBIA: 1752#if defined(LUNA2) 1753 cmpl #-2,_mmutype | 68040? 1754 jne Lmotommu3 | no, skip 1755 .word 0xf518 | yes, pflusha 1756 rts 1757Lmotommu3: 1758#endif 1759 pflusha | flush entire TLB 1760 movl #DC_CLEAR,d0 1761 movc d0,cacr | invalidate on-chip d-cache 1762 rts 1763 1764/* 1765 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1766 */ 1767ENTRY(TBIS) 1768#ifdef DEBUG 1769 tstl fulltflush | being conservative? 1770 jne __TBIA | yes, flush entire TLB 1771#endif 1772#if defined(LUNA2) 1773 cmpl #-2,_mmutype | 68040? 1774 jne Lmotommu4 | no, skip 1775 movl sp@(4),a0 1776 movc dfc,d1 1777 moveq #1,d0 | user space 1778 movc d0,dfc 1779 .word 0xf508 | pflush a0@ 1780 moveq #5,d0 | super space 1781 movc d0,dfc 1782 .word 0xf508 | pflush a0@ 1783 movc d1,dfc 1784 rts 1785Lmotommu4: 1786#endif 1787 1788 movl sp@(4),a0 | get addr to flush 1789 pflush #0,#0,a0@ | flush address from both sides 1790 movl #DC_CLEAR,d0 1791 movc d0,cacr | invalidate on-chip data cache 1792 rts 1793 1794/* 1795 * Invalidate supervisor side of TLB 1796 */ 1797ENTRY(TBIAS) 1798#ifdef DEBUG 1799 tstl fulltflush | being conservative? 1800 jne __TBIA | yes, flush everything 1801#endif 1802#if defined(LUNA2) 1803 cmpl #-2,_mmutype | 68040? 1804 jne Lmotommu5 | no, skip 1805 .word 0xf518 | yes, pflusha (for now) XXX 1806 rts 1807Lmotommu5: 1808#endif 1809 pflush #4,#4 | flush supervisor TLB entries 1810 movl #DC_CLEAR,d0 1811 movc d0,cacr | invalidate on-chip d-cache 1812 rts 1813 1814/* 1815 * Invalidate user side of TLB 1816 */ 1817ENTRY(TBIAU) 1818#ifdef DEBUG 1819 tstl fulltflush | being conservative? 1820 jne __TBIA | yes, flush everything 1821#endif 1822#if defined(LUNA2) 1823 cmpl #-2,_mmutype | 68040? 1824 jne Lmotommu6 | no, skip 1825 .word 0xf518 | yes, pflusha (for now) XXX 1826 rts 1827Lmotommu6: 1828#endif 1829 pflush #0,#4 | flush user TLB entries 1830 movl #DC_CLEAR,d0 1831 movc d0,cacr | invalidate on-chip d-cache 1832 rts 1833 1834/* 1835 * Invalidate instruction cache 1836 */ 1837ENTRY(ICIA) 1838#if defined(LUNA2) 1839ENTRY(ICPA) 1840 cmpl #-2,_mmutype | 68040 1841 jne Lmotommu7 | no, skip 1842 .word 0xf498 | cinva ic 1843 rts 1844Lmotommu7: 1845#endif 1846 movl #IC_CLEAR,d0 1847 movc d0,cacr | invalidate i-cache 1848 rts 1849 1850/* 1851 * Invalidate data cache. 1852 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing 1853 * problems with DC_WA. The only cases we have to worry about are context 1854 * switch and TLB changes, both of which are handled "in-line" in resume 1855 * and TBI*. 1856 */ 1857ENTRY(DCIA) 1858__DCIA: 1859#if defined(LUNA2) 1860 cmpl #-2,_mmutype | 68040 1861 jne Lmotommu8 | no, skip 1862 /* XXX implement */ 1863 rts 1864Lmotommu8: 1865#endif 1866 rts 1867 1868ENTRY(DCIS) 1869__DCIS: 1870#if defined(LUNA2) 1871 cmpl #-2,_mmutype | 68040 1872 jne Lmotommu9 | no, skip 1873 /* XXX implement */ 1874 rts 1875Lmotommu9: 1876#endif 1877 rts 1878 1879ENTRY(DCIU) 1880__DCIU: 1881#if defined(LUNA2) 1882 cmpl #-2,_mmutype | 68040 1883 jne LmotommuA | no, skip 1884 /* XXX implement */ 1885 rts 1886LmotommuA: 1887#endif 1888 rts 1889 1890#if defined(LUNA2) 1891ENTRY(ICPL) 1892 movl sp@(4),a0 | address 1893 .word 0xf488 | cinvl ic,a0@ 1894 rts 1895ENTRY(ICPP) 1896 movl sp@(4),a0 | address 1897 .word 0xf490 | cinvp ic,a0@ 1898 rts 1899ENTRY(DCPL) 1900 movl sp@(4),a0 | address 1901 .word 0xf448 | cinvl dc,a0@ 1902 rts 1903ENTRY(DCPP) 1904 movl sp@(4),a0 | address 1905 .word 0xf450 | cinvp dc,a0@ 1906 rts 1907ENTRY(DCPA) 1908 .word 0xf458 | cinva dc 1909 rts 1910ENTRY(DCFL) 1911 movl sp@(4),a0 | address 1912 .word 0xf468 | cpushl dc,a0@ 1913 rts 1914ENTRY(DCFP) 1915 movl sp@(4),a0 | address 1916 .word 0xf470 | cpushp dc,a0@ 1917 rts 1918#endif 1919 1920ENTRY(PCIA) 1921#if defined(LUNA2) 1922ENTRY(DCFA) 1923 cmpl #-2,_mmutype | 68040 1924 jne LmotommuB | no, skip 1925 .word 0xf478 | cpusha dc 1926 rts 1927LmotommuB: 1928#endif 1929 movl #DC_CLEAR,d0 1930 movc d0,cacr | invalidate on-chip d-cache 1931 rts 1932 1933#if 0 /****************************************************************/ 1934/* external cache control */ 1935ENTRY(ecacheon) 1936 rts 1937 1938ENTRY(ecacheoff) 1939 rts 1940#endif /****************************************************************/ 1941 1942/* 1943 * Get callers current SP value. 1944 * Note that simply taking the address of a local variable in a C function 1945 1946 * doesn't work because callee saved registers may be outside the stack frame 1947 * defined by A6 (e.g. GCC generated code). 1948 */ 1949 .globl _getsp 1950_getsp: 1951 movl sp,d0 | get current SP 1952 addql #4,d0 | compensate for return address 1953 rts 1954 1955 .globl _getsfc, _getdfc 1956_getsfc: 1957 movc sfc,d0 1958 rts 1959_getdfc: 1960 movc dfc,d0 1961 rts 1962 1963/* 1964 * Load a new user segment table pointer. 1965 */ 1966ENTRY(loadustp) 1967 movl sp@(4),d0 | new USTP 1968 moveq #PGSHIFT,d1 1969 lsll d1,d0 | convert to addr 1970#if defined(LUNA2) 1971 cmpl #-2,_mmutype | 68040? 1972 jne LmotommuC | no, skip 1973 .long 0x4e7b0806 | movc d0,urp 1974 rts 1975LmotommuC: 1976#endif 1977 lea _protorp,a0 | CRP prototype 1978 movl d0,a0@(4) | stash USTP 1979 pmove a0@,crp | load root pointer 1980 movl #DC_CLEAR,d0 1981 movc d0,cacr | invalidate on-chip d-cache 1982 rts 1983 1984ENTRY(ploadw) 1985 movl sp@(4),a0 | address to load 1986 ploadw #1,a0@ | pre-load translation 1987 rts 1988 1989/* 1990 * Set processor priority level calls. Most are implemented with 1991 * inline asm expansions. However, spl0 requires special handling 1992 * as we need to check for our emulated software interrupts. 1993 */ 1994 1995ENTRY(spl0) 1996 moveq #0,d0 1997 movw sr,d0 | get old SR for return 1998 movw #PSL_LOWIPL,sr | restore new SR 1999 tstb _ssir | software interrupt pending? 2000 jeq Lspldone | no, all done 2001 subql #4,sp | make room for RTE frame 2002 movl sp@(4),sp@(2) | position return address 2003 clrw sp@(6) | set frame type 0 2004 movw #PSL_LOWIPL,sp@ | and new SR 2005 jra Lgotsir | go handle it 2006Lspldone: 2007 rts 2008 2009ENTRY(_insque) 2010 movw sr,d0 2011 movw #PSL_HIGHIPL,sr | atomic 2012 movl sp@(8),a0 | where to insert (after) 2013 movl sp@(4),a1 | element to insert (e) 2014 movl a0@,a1@ | e->next = after->next 2015 movl a0,a1@(4) | e->prev = after 2016 movl a1,a0@ | after->next = e 2017 movl a1@,a0 2018 movl a1,a0@(4) | e->next->prev = e 2019 movw d0,sr 2020 rts 2021 2022ENTRY(_remque) 2023 movw sr,d0 2024 movw #PSL_HIGHIPL,sr | atomic 2025 movl sp@(4),a0 | element to remove (e) 2026 movl a0@,a1 2027 movl a0@(4),a0 2028 movl a0,a1@(4) | e->next->prev = e->prev 2029 movl a1,a0@ | e->prev->next = e->next 2030 movw d0,sr 2031 rts 2032 2033/* 2034 * bzero(addr, count) 2035 */ 2036ALTENTRY(blkclr, _bzero) 2037ENTRY(bzero) 2038 movl sp@(4),a0 | address 2039 movl sp@(8),d0 | count 2040 jeq Lbzdone | if zero, nothing to do 2041 movl a0,d1 2042 btst #0,d1 | address odd? 2043 jeq Lbzeven | no, can copy words 2044 clrb a0@+ | yes, zero byte to get to even boundary 2045 subql #1,d0 | decrement count 2046 jeq Lbzdone | none left, all done 2047Lbzeven: 2048 movl d0,d1 2049 andl #31,d0 2050 lsrl #5,d1 | convert count to 8*longword count 2051 jeq Lbzbyte | no such blocks, zero byte at a time 2052Lbzloop: 2053 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2054 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2055 subql #1,d1 | one more block zeroed 2056 jne Lbzloop | more to go, do it 2057 tstl d0 | partial block left? 2058 jeq Lbzdone | no, all done 2059Lbzbyte: 2060 clrb a0@+ 2061 subql #1,d0 | one more byte cleared 2062 jne Lbzbyte | more to go, do it 2063Lbzdone: 2064 rts 2065 2066/* 2067 * strlen(str) 2068 */ 2069ENTRY(strlen) 2070 moveq #-1,d0 2071 movl sp@(4),a0 | string 2072Lslloop: 2073 addql #1,d0 | increment count 2074 tstb a0@+ | null? 2075 jne Lslloop | no, keep going 2076 rts 2077 2078/* 2079 * bcmp(s1, s2, len) 2080 * 2081 * WARNING! This guy only works with counts up to 64K 2082 */ 2083ENTRY(bcmp) 2084 movl sp@(4),a0 | string 1 2085 movl sp@(8),a1 | string 2 2086 moveq #0,d0 2087 movw sp@(14),d0 | length 2088 jeq Lcmpdone | if zero, nothing to do 2089 subqw #1,d0 | set up for DBcc loop 2090Lcmploop: 2091 cmpmb a0@+,a1@+ | equal? 2092 dbne d0,Lcmploop | yes, keep going 2093 addqw #1,d0 | +1 gives zero on match 2094Lcmpdone: 2095 rts 2096 2097/* 2098 * {ov}bcopy(from, to, len) 2099 * 2100 * Works for counts up to 128K. 2101 */ 2102ALTENTRY(ovbcopy, _bcopy) 2103ENTRY(bcopy) 2104 movl sp@(12),d0 | get count 2105 jeq Lcpyexit | if zero, return 2106 movl sp@(4),a0 | src address 2107 movl sp@(8),a1 | dest address 2108 cmpl a1,a0 | src before dest? 2109 jlt Lcpyback | yes, copy backwards (avoids overlap) 2110 movl a0,d1 2111 btst #0,d1 | src address odd? 2112 jeq Lcfeven | no, go check dest 2113 movb a0@+,a1@+ | yes, copy a byte 2114 subql #1,d0 | update count 2115 jeq Lcpyexit | exit if done 2116Lcfeven: 2117 movl a1,d1 2118 btst #0,d1 | dest address odd? 2119 jne Lcfbyte | yes, must copy by bytes 2120 movl d0,d1 | no, get count 2121 lsrl #2,d1 | convert to longwords 2122 jeq Lcfbyte | no longwords, copy bytes 2123 subql #1,d1 | set up for dbf 2124Lcflloop: 2125 movl a0@+,a1@+ | copy longwords 2126 dbf d1,Lcflloop | til done 2127 andl #3,d0 | get remaining count 2128 jeq Lcpyexit | done if none 2129Lcfbyte: 2130 subql #1,d0 | set up for dbf 2131Lcfbloop: 2132 movb a0@+,a1@+ | copy bytes 2133 dbf d0,Lcfbloop | til done 2134Lcpyexit: 2135 rts 2136Lcpyback: 2137 addl d0,a0 | add count to src 2138 addl d0,a1 | add count to dest 2139 movl a0,d1 2140 btst #0,d1 | src address odd? 2141 jeq Lcbeven | no, go check dest 2142 movb a0@-,a1@- | yes, copy a byte 2143 subql #1,d0 | update count 2144 jeq Lcpyexit | exit if done 2145Lcbeven: 2146 movl a1,d1 2147 btst #0,d1 | dest address odd? 2148 jne Lcbbyte | yes, must copy by bytes 2149 movl d0,d1 | no, get count 2150 lsrl #2,d1 | convert to longwords 2151 jeq Lcbbyte | no longwords, copy bytes 2152 subql #1,d1 | set up for dbf 2153Lcblloop: 2154 movl a0@-,a1@- | copy longwords 2155 dbf d1,Lcblloop | til done 2156 andl #3,d0 | get remaining count 2157 jeq Lcpyexit | done if none 2158Lcbbyte: 2159 subql #1,d0 | set up for dbf 2160Lcbbloop: 2161 movb a0@-,a1@- | copy bytes 2162 dbf d0,Lcbbloop | til done 2163 rts 2164 2165/* 2166 * Emulate fancy VAX string operations: 2167 * scanc(count, startc, table, mask) 2168 * skpc(mask, count, startc) 2169 * locc(mask, count, startc) 2170 */ 2171ENTRY(scanc) 2172 movl sp@(4),d0 | get length 2173 jeq Lscdone | nothing to do, return 2174 movl sp@(8),a0 | start of scan 2175 movl sp@(12),a1 | table to compare with 2176 movb sp@(19),d1 | and mask to use 2177 movw d2,sp@- | need a scratch register 2178 clrw d2 | clear it out 2179 subqw #1,d0 | adjust for dbra 2180Lscloop: 2181 movb a0@+,d2 | get character 2182 movb a1@(0,d2:w),d2 | get table entry 2183 andb d1,d2 | mask it 2184 dbne d0,Lscloop | keep going til no more or non-zero 2185 addqw #1,d0 | overshot by one 2186 movw sp@+,d2 | restore scratch 2187Lscdone: 2188 rts 2189 2190ENTRY(skpc) 2191 movl sp@(8),d0 | get length 2192 jeq Lskdone | nothing to do, return 2193 movb sp@(7),d1 | mask to use 2194 movl sp@(12),a0 | where to start 2195 subqw #1,d0 | adjust for dbcc 2196Lskloop: 2197 cmpb a0@+,d1 | compate with mask 2198 dbne d0,Lskloop | keep going til no more or zero 2199 addqw #1,d0 | overshot by one 2200Lskdone: 2201 rts 2202 2203ENTRY(locc) 2204 movl sp@(8),d0 | get length 2205 jeq Llcdone | nothing to do, return 2206 movb sp@(7),d1 | mask to use 2207 movl sp@(12),a0 | where to start 2208 subqw #1,d0 | adjust for dbcc 2209Llcloop: 2210 cmpb a0@+,d1 | compate with mask 2211 dbeq d0,Llcloop | keep going til no more or non-zero 2212 addqw #1,d0 | overshot by one 2213Llcdone: 2214 rts 2215 2216/* 2217 * Emulate VAX FFS (find first set) instruction. 2218 */ 2219ENTRY(ffs) 2220 moveq #-1,d0 2221 movl sp@(4),d1 2222 jeq Lffsdone 2223Lffsloop: 2224 addql #1,d0 2225 btst d0,d1 2226 jeq Lffsloop 2227Lffsdone: 2228 addql #1,d0 2229 rts 2230 2231#ifdef FPCOPROC 2232/* 2233 * Save and restore 68881 state. 2234 * Pretty awful looking since our assembler does not 2235 * recognize FP mnemonics. 2236 */ 2237ENTRY(m68881_save) 2238 movl sp@(4),a0 | save area pointer 2239 fsave a0@ | save state 2240 tstb a0@ | null state frame? 2241 jeq Lm68881sdone | yes, all done 2242 fmovem fp0-fp7,a0@(216) | save FP general registers 2243 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 2244Lm68881sdone: 2245 rts 2246 2247ENTRY(m68881_restore) 2248 movl sp@(4),a0 | save area pointer 2249 tstb a0@ | null state frame? 2250 jeq Lm68881rdone | yes, easy 2251 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 2252 fmovem a0@(216),fp0-fp7 | restore FP general registers 2253Lm68881rdone: 2254 frestore a0@ | restore state 2255 rts 2256 2257/* LUNA */ 2258 2259 .globl _fpp_svarea 2260 2261/* Fpp is MC68882 ? */ 2262ENTRY(is_68882) 2263 frestore _fppnull | initialize fpp 2264 movl #2,d0 2265 fmovecr #0,fp1 2266 fsinx fp1,fp2 2267 lea _fpp_svarea,a0 | save area 2268 movw sr,d1 | save status reg. 2269 movw #0x2700,sr | mask intrrupt 2270 fsave a0@ | save fpp context 2271 movw d1,sr | restore status reg. 2272 movl a0@,d1 2273 andl #0x00ff0000,d1 | check status field 2274 cmpl #0x00180000,d1 | 68881(idle)? 2275 beq _is81 2276 cmpl #0x00b40000,d1 | 68881(busy)? 2277 beq _is81 2278 cmpl #0x00380000,d1 | 68882(idle)? 2279 beq _is82 2280 cmpl #0x00d40000,d1 | 68882(busy)? 2281 beq _is82 2282 bra _is82out | default 68881 2283_is81: 2284 clrl d0 2285 bra _is82out 2286_is82: 2287 movl #1,d0 2288_is82out: 2289 frestore a0@ 2290 rts 2291 2292#ifdef OLD_LUNA 2293/* We have fpp ? */ 2294ENTRY(havefpp) 2295 movl a2,sp@- 2296 clrl d0 2297 movl vb,a2 2298 movl a2@(FLINE_VEC),a0 | save vectors 2299 movl a2@(COPRO_VEC),a1 2300 movl sp,d1 2301 movl #_fpvec,a2@(FLINE_VEC) | change vectors 2302 movl #_fpvec,a2@(COPRO_VEC) 2303 fnop | cause exception ? 2304 movl #1,d0 2305_fpvec: movl a0,a2@(FLINE_VEC) | restore vectors 2306 movl a1,a2@(COPRO_VEC) 2307 movl d1,sp 2308 movl sp@+,a2 2309 rts 2310#endif 2311#endif 2312 2313/* 2314 * Handle the nitty-gritty of rebooting the machine. 2315 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 2316 * Note that we must be running in an address range that is mapped one-to-one 2317 * logical to physical so that the PC is still valid immediately after the MMU 2318 * is turned off. We have conveniently mapped the last page of physical 2319 * memory this way. 2320 */ 2321 .globl _doboot 2322_doboot: 2323 movl #0x41000004,a0 2324 movl a0@,a1 | get PROM restart entry address 2325#if defined(LUNA2) 2326 cmpl #-2,_mmutype | 68040? 2327 jne LmotommuF | no, skip 2328 2329 movw #PSL_HIGHIPL,sr | no interrupts 2330 2331 movl #0x41000000,a0 2332 movl a0@,d0 2333 movc d0,isp | set ISP 2334 2335 .word 0xf4f8 | cpusha bc 2336 movl #0,d0 2337 movc d0,cacr | caches off 2338 movql #0,d0 2339 .long 0x4e7b0004 | movc d0,itt0 2340 .long 0x4e7b0005 | movc d0,itt1 2341 .long 0x4e7b0006 | movc d0,dtt0 2342 .long 0x4e7b0007 | movc d0,dtt1 2343 2344 .long 0x4e7b0003 | movc d0,tc 2345 2346 jmp a1@ | goto REBOOT 2347LmotommuF: 2348#endif 2349 movl #CACHE_OFF,d0 2350 movc d0,cacr | disable on-chip cache(s) 2351 movl #_tcroff,a0 | value for pmove to TC (turn off MMU) 2352 pmove a0@,tc | disable MMU 2353 jmp a1@ | goto REBOOT 2354 2355 .data 2356 .globl _machineid,_mmutype 2357_machineid: 2358 .long 1 | default to LUNA-I 2359_mmutype: 2360 .long -1 | default to 68030 PMMU 2361 .globl _protorp,_protott0,_protott1 2362_protorp: 2363 .long 0,0 | prototype root pointer 2364_protott0: 2365 .long 0x403f8543 | tt0 (for LUNA1 kernel 0x40000000-0x7fffffff) 2366_protott1: 2367 .long 0x807F8543 | tt1 (for LUNA1 kernel 0x80000000-0xffffffff) 2368_mapping_tc: 2369 .long 0 2370 .globl _cold 2371_cold: 2372 .long 1 | cold start flag 2373 .globl _want_resched 2374_want_resched: 2375 .long 0 2376 .globl _proc0paddr 2377_proc0paddr: 2378 .long 0 | KVA of proc0 u-area 2379 2380 .globl _tcroff 2381_tcroff: 2382 .long 0 | TC reg. reset flag 2383 2384#ifdef FPCOPROC 2385 .globl _fppnull 2386_fppnull: 2387 .long 0 2388#endif 2389 .globl _clock_on 2390_clock_on: 2391 .long 0 | clock is enable ? 2392 .globl _dipswitch 2393_dipswitch: 2394 .word 0 | dipsw(front panel) value 2395 .globl _KernInter 2396_KernInter: | Kernel InterFace Field 2397 .space KIFF_SIZE 2398#ifdef DEBUG 2399 .globl fulltflush, fullcflush 2400fulltflush: 2401 .long 0 2402fullcflush: 2403 .long 0 2404#endif 2405#ifdef HPFPLIB 2406/* 2407 * Undefined symbols from hpux_float.o: 2408 * 2409 * kdb_printf: A kernel debugger print routine, we just use printf instead. 2410 * processor: HP-UX equiv. of machineid, set to 3 if it is a 68040. 2411 * u: Ye ole u-area. The code wants to grab the first longword 2412 * indirect off of that and clear the 0x40000 bit there. 2413 * Oddly enough this was incorrect even in HP-UX! 2414 * runrun: Old name for want_resched. 2415 */ 2416 .globl _kdb_printf,_processor,_u,_runrun 2417_kdb_printf: 2418 .long _printf 2419_processor: 2420 .long 0 2421_u: 2422 .long .+4 2423 .long 0 2424 .set _runrun,_want_resched 2425#endif 2426/* interrupt counters */ 2427 .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames 2428_intrnames: 2429 .asciz "spur" 2430 .asciz "lev1" 2431 .asciz "lev2" 2432 .asciz "lev3" 2433 .asciz "lev4" 2434 .asciz "clock" 2435 .asciz "lev7" 2436 .asciz "nmi" 2437_eintrnames: 2438 .even 2439_intrcnt: 2440 .long 0,0,0,0,0,0,0,0,0 2441_eintrcnt: 2442