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