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