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