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.18 (Berkeley) 10/11/92 15 */ 16 17#include "assym.s" 18#include <hp300/hp300/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@- | pad ps 567 moveml #0xC0C0,sp@- 568#ifdef DEBUG 569 .globl _panicstr, _regdump, _panic 570 cmpl #_kstack+NBPG,sp | are we still in stack pages? 571 jcc Lstackok | yes, continue normally 572 tstl _curproc | if !curproc could have swtch_exit'ed, 573 jeq Lstackok | might be on tmpstk 574 tstl _panicstr | have we paniced? 575 jne Lstackok | yes, do not re-panic 576 lea tmpstk,sp | no, switch to tmpstk 577 moveml #0xFFFF,sp@- | push all registers 578 movl #Lstkrip,sp@- | push panic message 579 jbsr _printf | preview 580 addql #4,sp 581 movl sp,a0 | remember this spot 582 movl #256,sp@- | longword count 583 movl a0,sp@- | and reg pointer 584 jbsr _regdump | dump core 585 addql #8,sp | pop params 586 movl #Lstkrip,sp@- | push panic message 587 jbsr _panic | ES and D 588Lstkrip: 589 .asciz "k-stack overflow" 590 .even 591Lstackok: 592#endif 593 CLKADDR(a0) 594 lea sp@(16),a1 | a1 = &clockframe 595 movb a0@(CLKSR),d0 | read clock status 596 btst #2,d0 | timer3 interrupt? 597 jeq 1f | no, skip statintr 598 addql #1,_intrcnt+32 | count statclock interrupts 599 movl d0,sp@- | save status 600 movl a1,sp@- 601 jbsr _statintr | statintr(&frame) 602 addql #4,sp 603 movl sp@+,d0 | restore registers 604 CLKADDR(a0) 605 lea sp@(16),a1 6061: 607 btst #0,d0 | timer1 interrupt? 608 jeq 2f | no, skip hardclock 609 movb a0@(CLKMSB1),d1 | clear timer1 interrupt 610 addql #1,_intrcnt+28 | count hardclock interrupts 611 movl a1,sp@- 612 jbsr _hardclock | hardclock(&frame) 613 addql #4,sp 6142: 615 moveml sp@+,#0x0303 | restore scratch regs 616 addql #2,sp | pop pad word 617 addql #1,_cnt+V_INTR | chalk up another interrupt 618 jra rei | all done 619 620_lev7intr: 621 addql #1,_intrcnt+36 622 clrw sp@- | pad SR to longword 623 moveml #0xFFFF,sp@- | save registers 624 movl usp,a0 | and save 625 movl a0,sp@(60) | the user stack pointer 626 jbsr _nmihand | call handler 627 movl sp@(60),a0 | restore 628 movl a0,usp | user SP 629 moveml sp@+,#0x7FFF | and remaining registers 630 addql #6,sp | pop SSP and align word 631 jra rei | all done 632 633/* 634 * Emulation of VAX REI instruction. 635 * 636 * This code deals with checking for and servicing ASTs 637 * (profiling, scheduling) and software interrupts (network, softclock). 638 * We check for ASTs first, just like the VAX. To avoid excess overhead 639 * the T_ASTFLT handling code will also check for software interrupts so we 640 * do not have to do it here. 641 * 642 * This code is complicated by the fact that sendsig may have been called 643 * necessitating a stack cleanup. 644 */ 645 .comm _ssir,1 646 .globl _astpending 647rei: 648#ifdef DEBUG 649 tstl _panicstr | have we paniced? 650 jne Ldorte | yes, do not make matters worse 651#endif 652 tstl _astpending | AST pending? 653 jeq Lchksir | no, go check for SIR 654Lrei1: 655 btst #5,sp@ | yes, are we returning to user mode? 656 jne Lchksir | no, go check for SIR 657 clrw sp@- | pad SR to longword 658 moveml #0xFFFF,sp@- | save all registers 659 movl usp,a1 | including 660 movl a1,sp@(60) | the users SP 661 clrl sp@- | VA == none 662 clrl sp@- | code == none 663 movl #T_ASTFLT,sp@- | type == async system trap 664 jbsr _trap | go handle it 665 lea sp@(12),sp | pop value args 666 movl sp@(60),a0 | restore user SP 667 movl a0,usp | from save area 668 movw sp@(64),d0 | need to adjust stack? 669 jne Laststkadj | yes, go to it 670 moveml sp@+,#0x7FFF | no, restore most user regs 671 addql #6,sp | toss SSP and pad 672 rte | and do real RTE 673Laststkadj: 674 lea sp@(66),a1 | pointer to HW frame 675 addql #8,a1 | source pointer 676 movl a1,a0 | source 677 addw d0,a0 | + hole size = dest pointer 678 movl a1@-,a0@- | copy 679 movl a1@-,a0@- | 8 bytes 680 movl a0,sp@(60) | new SSP 681 moveml sp@+,#0x7FFF | restore user registers 682 movl sp@,sp | and our SP 683 rte | and return 684Lchksir: 685 tstb _ssir | SIR pending? 686 jeq Ldorte | no, all done 687 movl d0,sp@- | need a scratch register 688 movw sp@(4),d0 | get SR 689 andw #PSL_IPL7,d0 | mask all but IPL 690 jne Lnosir | came from interrupt, no can do 691 movl sp@+,d0 | restore scratch register 692Lgotsir: 693 movw #SPL1,sr | prevent others from servicing int 694 tstb _ssir | too late? 695 jeq Ldorte | yes, oh well... 696 clrw sp@- | pad SR to longword 697 moveml #0xFFFF,sp@- | save all registers 698 movl usp,a1 | including 699 movl a1,sp@(60) | the users SP 700 clrl sp@- | VA == none 701 clrl sp@- | code == none 702 movl #T_SSIR,sp@- | type == software interrupt 703 jbsr _trap | go handle it 704 lea sp@(12),sp | pop value args 705 movl sp@(60),a0 | restore 706 movl a0,usp | user SP 707 moveml sp@+,#0x7FFF | and all remaining registers 708 addql #6,sp | pop SSP and align word 709 rte 710Lnosir: 711 movl sp@+,d0 | restore scratch register 712Ldorte: 713 rte | real return 714 715/* 716 * Kernel access to the current processes kernel stack is via a fixed 717 * virtual address. It is at the same address as in the users VA space. 718 * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack. 719 */ 720 .data 721 .set _kstack,USRSTACK 722_Umap: .long 0 723 .globl _kstack, _Umap 724 725#define RELOC(var, ar) \ 726 lea var,ar; \ 727 addl a5,ar 728 729/* 730 * Initialization 731 * 732 * A5 contains physical load point from boot 733 * VBR contains zero from ROM. Exceptions will continue to vector 734 * through ROM until MMU is turned on at which time they will vector 735 * through our table (vectors.s). 736 */ 737 .comm _lowram,4 738 739 .text 740 .globl _edata 741 .globl _etext,_end 742 .globl start 743start: 744 movw #PSL_HIGHIPL,sr | no interrupts 745 RELOC(tmpstk, a0) 746 movl a0,sp | give ourselves a temporary stack 747 RELOC(_lowram, a0) 748 movl a5,a0@ | store start of physical memory 749 movl #CACHE_OFF,d0 750 movc d0,cacr | clear and disable on-chip cache(s) 751 752/* determine our CPU/MMU combo - check for all regardless of kernel config */ 753 movl #INTIOBASE+MMUBASE,a1 754 movl #0x200,d0 | data freeze bit 755 movc d0,cacr | only exists on 68030 756 movc cacr,d0 | read it back 757 tstl d0 | zero? 758 jeq Lnot68030 | yes, we have 68020/68040 759 RELOC(_mmutype, a0) | no, we have 68030 760 movl #-1,a0@ | set to reflect 68030 PMMU 761 RELOC(_machineid, a0) 762 movl #0x80,a1@(MMUCMD) | set magic cookie 763 movl a1@(MMUCMD),d0 | read it back 764 btst #7,d0 | cookie still on? 765 jeq Lnot370 | no, 360 or 375 766 movl #0,a1@(MMUCMD) | clear magic cookie 767 movl a1@(MMUCMD),d0 | read it back 768 btst #7,d0 | still on? 769 jeq Lisa370 | no, must be a 370 770 movl #5,a0@ | yes, must be a 340 771 jra Lstart1 772Lnot370: 773 movl #3,a0@ | type is at least a 360 774 movl #0,a1@(MMUCMD) | clear magic cookie2 775 movl a1@(MMUCMD),d0 | read it back 776 btst #16,d0 | still on? 777 jeq Lstart1 | no, must be a 360 778 movl #6,a0@ | yes, must be a 345/375 779 jra Lhaspac 780Lisa370: 781 movl #4,a0@ | set to 370 782Lhaspac: 783 RELOC(_ectype, a0) 784 movl #-1,a0@ | also has a physical address cache 785 jra Lstart1 786Lnot68030: 787 bset #31,d0 | data cache enable bit 788 movc d0,cacr | only exists on 68040 789 movc cacr,d0 | read it back 790 tstl d0 | zero? 791 beq Lis68020 | yes, we have 68020 792 moveq #0,d0 | now turn it back off 793 movec d0,cacr | before we access any data 794 RELOC(_machineid, a0) 795 movl #7,a0@ | we have a 380 796 RELOC(_mmutype, a0) 797 movl #-2,a0@ | with a 68040 MMU 798 RELOC(_ectype, a0) 799 movl #0,a0@ | and no cache (for now XXX) 800#ifdef HPFPLIB 801 RELOC(_processor, a0) 802 movl #3,a0@ | HP-UX style processor id 803#endif 804 jra Lstart1 805Lis68020: 806 movl #1,a1@(MMUCMD) | a 68020, write HP MMU location 807 movl a1@(MMUCMD),d0 | read it back 808 btst #0,d0 | non-zero? 809 jne Lishpmmu | yes, we have HP MMU 810 RELOC(_mmutype, a0) 811 movl #1,a0@ | no, we have PMMU 812 RELOC(_machineid, a0) 813 movl #1,a0@ | and 330 CPU 814 jra Lstart1 815Lishpmmu: 816 RELOC(_ectype, a0) | 320 or 350 817 movl #1,a0@ | both have a virtual address cache 818 movl #0x80,a1@(MMUCMD) | set magic cookie 819 movl a1@(MMUCMD),d0 | read it back 820 btst #7,d0 | cookie still on? 821 jeq Lstart1 | no, just a 320 822 RELOC(_machineid, a0) 823 movl #2,a0@ | yes, a 350 824 825Lstart1: 826 movl #0,a1@(MMUCMD) | clear out MMU again 827/* initialize source/destination control registers for movs */ 828 moveq #FC_USERD,d0 | user space 829 movc d0,sfc | as source 830 movc d0,dfc | and destination of transfers 831/* initialize memory sizes (for pmap_bootstrap) */ 832 movl #MAXADDR,d1 | last page 833 moveq #PGSHIFT,d2 834 lsrl d2,d1 | convert to page (click) number 835 RELOC(_maxmem, a0) 836 movl d1,a0@ | save as maxmem 837 movl a5,d0 | lowram value from ROM via boot 838 lsrl d2,d0 | convert to page number 839 subl d0,d1 | compute amount of RAM present 840 RELOC(_physmem, a0) 841 movl d1,a0@ | and physmem 842/* configure kernel and proc0 VA space so we can get going */ 843 .globl _Sysseg, _pmap_bootstrap, _avail_start 844 movl #_end,d5 | end of static kernel text/data 845 addl #NBPG-1,d5 846 andl #PG_FRAME,d5 | round to a page 847 movl d5,a4 848 addl a5,a4 | convert to PA 849 pea a5@ | firstpa 850 pea a4@ | nextpa 851 RELOC(_pmap_bootstrap,a0) 852 jbsr a0@ | pmap_bootstrap(firstpa, nextpa) 853 addql #8,sp 854 855/* 856 * Prepare to enable MMU. 857 * Since the kernel is not mapped logical == physical we must insure 858 * that when the MMU is turned on, all prefetched addresses (including 859 * the PC) are valid. In order guarentee that, we use the last physical 860 * page (which is conveniently mapped == VA) and load it up with enough 861 * code to defeat the prefetch, then we execute the jump back to here. 862 * 863 * Is this all really necessary, or am I paranoid?? 864 */ 865 RELOC(_Sysseg, a0) | system segment table addr 866 movl a0@,d1 | read value (a KVA) 867 addl a5,d1 | convert to PA 868 RELOC(_mmutype, a0) 869 tstl a0@ | HP MMU? 870 jeq Lhpmmu2 | yes, skip 871 cmpl #-2,a0@ | 68040? 872 jne Lmotommu1 | no, skip 873 .long 0x4e7b1807 | movc d1,srp 874 jra Lstploaddone 875Lmotommu1: 876 RELOC(_protorp, a0) 877 movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs 878 movl d1,a0@(4) | + segtable address 879 pmove a0@,srp | load the supervisor root pointer 880 movl #0x80000002,a0@ | reinit upper half for CRP loads 881 jra Lstploaddone | done 882Lhpmmu2: 883 moveq #PGSHIFT,d2 884 lsrl d2,d1 | convert to page frame 885 movl d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register 886Lstploaddone: 887 lea MAXADDR,a2 | PA of last RAM page 888 RELOC(Lhighcode, a1) | addr of high code 889 RELOC(Lehighcode, a3) | end addr 890Lcodecopy: 891 movw a1@+,a2@+ | copy a word 892 cmpl a3,a1 | done yet? 893 jcs Lcodecopy | no, keep going 894 jmp MAXADDR | go for it! 895 896Lhighcode: 897 RELOC(_mmutype, a0) 898 tstl a0@ | HP MMU? 899 jeq Lhpmmu3 | yes, skip 900 cmpl #-2,a0@ | 68040? 901 jne Lmotommu2 | no, skip 902 movw #0,INTIOBASE+MMUBASE+MMUCMD+2 903 movw #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2 904 | enable FPU and caches 905 moveq #0,d0 | ensure TT regs are disabled 906 .long 0x4e7b0004 | movc d0,itt0 907 .long 0x4e7b0005 | movc d0,itt1 908 .long 0x4e7b0006 | movc d0,dtt0 909 .long 0x4e7b0007 | movc d0,dtt1 910 .word 0xf4d8 | cinva bc 911 .word 0xf518 | pflusha 912 movl #0x8000,d0 913 .long 0x4e7b0003 | movc d0,tc 914 movl #0x80008000,d0 915 movc d0,cacr | turn on both caches 916 jmp Lenab1 917Lmotommu2: 918 movl #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD 919 | enable 68881 and i-cache 920 movl #0x82c0aa00,a2@ | value to load TC with 921 pmove a2@,tc | load it 922 jmp Lenab1 923Lhpmmu3: 924 movl #0,INTIOBASE+MMUBASE+MMUCMD | clear external cache 925 movl #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU 926 jmp Lenab1 | jmp to mapped code 927Lehighcode: 928 929/* 930 * Should be running mapped from this point on 931 */ 932Lenab1: 933/* check for internal HP-IB in SYSFLAG */ 934 btst #5,0xfffffed2 | internal HP-IB? 935 jeq Lfinish | yes, have HP-IB just continue 936 clrl _internalhpib | no, clear associated address 937Lfinish: 938/* select the software page size now */ 939 lea tmpstk,sp | temporary stack 940 jbsr _vm_set_page_size | select software page size 941#ifdef BOOTDEBUG 942 movl a5,sp@- | phys load address (assumes VA 0) 943 movl a4,sp@- | first available PA 944 jbsr _Opmap_bootstrap | sync up pmap module 945 addql #8,sp 946#endif 947/* set kernel stack, user SP, and initial pcb */ 948 lea _kstack,a1 | proc0 kernel stack 949 lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area 950 movl #USRSTACK-4,a2 951 movl a2,usp | init user SP 952 movl _proc0paddr,a1 | get proc0 pcb addr 953 movl a1,_curpcb | proc0 is running 954 clrw a1@(PCB_FLAGS) | clear flags 955#ifdef FPCOPROC 956 clrl a1@(PCB_FPCTX) | ensure null FP context 957 movl a1,sp@- 958 jbsr _m68881_restore | restore it (does not kill a1) 959 addql #4,sp 960#endif 961/* flush TLB and turn on caches */ 962 jbsr _TBIA | invalidate TLB 963 cmpl #-2,_mmutype | 68040? 964 jeq Lnocache0 | yes, cache already on 965 movl #CACHE_ON,d0 966 movc d0,cacr | clear cache(s) 967 tstl _ectype 968 jeq Lnocache0 969 MMUADDR(a0) 970 orl #MMU_CEN,a0@(MMUCMD) | turn on external cache 971Lnocache0: 972/* final setup for C code */ 973 movw #PSL_LOWIPL,sr | lower SPL 974 movl d7,_boothowto | save reboot flags 975 movl d6,_bootdev | and boot device 976 jbsr _main | call main() 977 978/* proc[1] == init now running here; 979 * create a null exception frame and return to user mode in icode 980 */ 981 cmpl #-2,_mmutype | 68040? 982 jne Lnoflush | no, skip 983 .word 0xf478 | cpusha dc 984 .word 0xf498 | cinva ic 985Lnoflush: 986 clrw sp@- | vector offset/frame type 987 clrl sp@- | return to icode location 0 988 movw #PSL_USER,sp@- | in user mode 989 rte 990 991/* 992 * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig(). 993 * 994 * Stack looks like: 995 * 996 * sp+0 -> signal number 997 * sp+4 signal specific code 998 * sp+8 pointer to signal context frame (scp) 999 * sp+12 address of handler 1000 * sp+16 saved hardware state 1001 * . 1002 * . 1003 * scp+0-> beginning of signal context frame 1004 */ 1005 .globl _sigcode, _esigcode, _sigcodetrap 1006 .data 1007_sigcode: 1008 movl sp@(12),a0 | signal handler addr (4 bytes) 1009 jsr a0@ | call signal handler (2 bytes) 1010 addql #4,sp | pop signo (2 bytes) 1011_sigcodetrap: 1012 trap #1 | special syscall entry (2 bytes) 1013 movl d0,sp@(4) | save errno (4 bytes) 1014 moveq #1,d0 | syscall == exit (2 bytes) 1015 trap #0 | exit(errno) (2 bytes) 1016 .align 2 1017_esigcode: 1018 1019/* 1020 * Icode is copied out to process 1 to exec init. 1021 * If the exec fails, process 1 exits. 1022 */ 1023 .globl _icode,_szicode 1024 .text 1025_icode: 1026 clrl sp@- 1027 pea pc@((argv-.)+2) 1028 pea pc@((init-.)+2) 1029 clrl sp@- 1030 moveq #SYS_execve,d0 1031 trap #0 1032 moveq #SYS_exit,d0 1033 trap #0 1034init: 1035 .asciz "/sbin/init" 1036 .even 1037argv: 1038 .long init+6-_icode | argv[0] = "init" ("/sbin/init" + 6) 1039 .long eicode-_icode | argv[1] follows icode after copyout 1040 .long 0 1041eicode: 1042 1043_szicode: 1044 .long _szicode-_icode 1045 1046/* 1047 * Primitives 1048 */ 1049 1050#ifdef GPROF 1051#define ENTRY(name) \ 1052 .globl _/**/name; _/**/name: link a6,#0; jbsr mcount; unlk a6 1053#define ALTENTRY(name, rname) \ 1054 ENTRY(name); jra rname+12 1055#else 1056#define ENTRY(name) \ 1057 .globl _/**/name; _/**/name: 1058#define ALTENTRY(name, rname) \ 1059 .globl _/**/name; _/**/name: 1060#endif 1061 1062/* 1063 * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 1064 * 1065 * Copy a null terminated string from the user address space into 1066 * the kernel address space. 1067 * NOTE: maxlength must be < 64K 1068 */ 1069ENTRY(copyinstr) 1070 movl _curpcb,a0 | current pcb 1071 movl #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults 1072 movl sp@(4),a0 | a0 = fromaddr 1073 movl sp@(8),a1 | a1 = toaddr 1074 moveq #0,d0 1075 movw sp@(14),d0 | d0 = maxlength 1076 jlt Lcisflt1 | negative count, error 1077 jeq Lcisdone | zero count, all done 1078 subql #1,d0 | set up for dbeq 1079Lcisloop: 1080 movsb a0@+,d1 | grab a byte 1081 nop 1082 movb d1,a1@+ | copy it 1083 dbeq d0,Lcisloop | if !null and more, continue 1084 jne Lcisflt2 | ran out of room, error 1085 moveq #0,d0 | got a null, all done 1086Lcisdone: 1087 tstl sp@(16) | return length desired? 1088 jeq Lcisret | no, just return 1089 subl sp@(4),a0 | determine how much was copied 1090 movl sp@(16),a1 | return location 1091 movl a0,a1@ | stash it 1092Lcisret: 1093 movl _curpcb,a0 | current pcb 1094 clrl a0@(PCB_ONFAULT) | clear fault addr 1095 rts 1096Lcisflt1: 1097 moveq #EFAULT,d0 | copy fault 1098 jra Lcisdone 1099Lcisflt2: 1100 moveq #ENAMETOOLONG,d0 | ran out of space 1101 jra Lcisdone 1102 1103/* 1104 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 1105 * 1106 * Copy a null terminated string from the kernel 1107 * address space to the user address space. 1108 * NOTE: maxlength must be < 64K 1109 */ 1110ENTRY(copyoutstr) 1111 movl _curpcb,a0 | current pcb 1112 movl #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults 1113 movl sp@(4),a0 | a0 = fromaddr 1114 movl sp@(8),a1 | a1 = toaddr 1115 moveq #0,d0 1116 movw sp@(14),d0 | d0 = maxlength 1117 jlt Lcosflt1 | negative count, error 1118 jeq Lcosdone | zero count, all done 1119 subql #1,d0 | set up for dbeq 1120Lcosloop: 1121 movb a0@+,d1 | grab a byte 1122 movsb d1,a1@+ | copy it 1123 nop 1124 dbeq d0,Lcosloop | if !null and more, continue 1125 jne Lcosflt2 | ran out of room, error 1126 moveq #0,d0 | got a null, all done 1127Lcosdone: 1128 tstl sp@(16) | return length desired? 1129 jeq Lcosret | no, just return 1130 subl sp@(4),a0 | determine how much was copied 1131 movl sp@(16),a1 | return location 1132 movl a0,a1@ | stash it 1133Lcosret: 1134 movl _curpcb,a0 | current pcb 1135 clrl a0@(PCB_ONFAULT) | clear fault addr 1136 rts 1137Lcosflt1: 1138 moveq #EFAULT,d0 | copy fault 1139 jra Lcosdone 1140Lcosflt2: 1141 moveq #ENAMETOOLONG,d0 | ran out of space 1142 jra Lcosdone 1143 1144/* 1145 * copystr(fromaddr, toaddr, maxlength, &lencopied) 1146 * 1147 * Copy a null terminated string from one point to another in 1148 * the kernel address space. 1149 * NOTE: maxlength must be < 64K 1150 */ 1151ENTRY(copystr) 1152 movl sp@(4),a0 | a0 = fromaddr 1153 movl sp@(8),a1 | a1 = toaddr 1154 moveq #0,d0 1155 movw sp@(14),d0 | d0 = maxlength 1156 jlt Lcsflt1 | negative count, error 1157 jeq Lcsdone | zero count, all done 1158 subql #1,d0 | set up for dbeq 1159Lcsloop: 1160 movb a0@+,a1@+ | copy a byte 1161 dbeq d0,Lcsloop | if !null and more, continue 1162 jne Lcsflt2 | ran out of room, error 1163 moveq #0,d0 | got a null, all done 1164Lcsdone: 1165 tstl sp@(16) | return length desired? 1166 jeq Lcsret | no, just return 1167 subl sp@(4),a0 | determine how much was copied 1168 movl sp@(16),a1 | return location 1169 movl a0,a1@ | stash it 1170Lcsret: 1171 rts 1172Lcsflt1: 1173 moveq #EFAULT,d0 | copy fault 1174 jra Lcsdone 1175Lcsflt2: 1176 moveq #ENAMETOOLONG,d0 | ran out of space 1177 jra Lcsdone 1178 1179/* 1180 * Copyin(from, to, len) 1181 * 1182 * Copy specified amount of data from user space into the kernel. 1183 * NOTE: len must be < 64K 1184 */ 1185ENTRY(copyin) 1186 movl d2,sp@- | scratch register 1187 movl _curpcb,a0 | current pcb 1188 movl #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults 1189 movl sp@(16),d2 | check count 1190 jlt Lciflt | negative, error 1191 jeq Lcidone | zero, done 1192 movl sp@(8),a0 | src address 1193 movl sp@(12),a1 | dest address 1194 movl a0,d0 1195 btst #0,d0 | src address odd? 1196 jeq Lcieven | no, go check dest 1197 movsb a0@+,d1 | yes, get a byte 1198 nop 1199 movb d1,a1@+ | put a byte 1200 subql #1,d2 | adjust count 1201 jeq Lcidone | exit if done 1202Lcieven: 1203 movl a1,d0 1204 btst #0,d0 | dest address odd? 1205 jne Lcibyte | yes, must copy by bytes 1206 movl d2,d0 | no, get count 1207 lsrl #2,d0 | convert to longwords 1208 jeq Lcibyte | no longwords, copy bytes 1209 subql #1,d0 | set up for dbf 1210Lcilloop: 1211 movsl a0@+,d1 | get a long 1212 nop 1213 movl d1,a1@+ | put a long 1214 dbf d0,Lcilloop | til done 1215 andl #3,d2 | what remains 1216 jeq Lcidone | all done 1217Lcibyte: 1218 subql #1,d2 | set up for dbf 1219Lcibloop: 1220 movsb a0@+,d1 | get a byte 1221 nop 1222 movb d1,a1@+ | put a byte 1223 dbf d2,Lcibloop | til done 1224Lcidone: 1225 moveq #0,d0 | success 1226Lciexit: 1227 movl _curpcb,a0 | current pcb 1228 clrl a0@(PCB_ONFAULT) | clear fault catcher 1229 movl sp@+,d2 | restore scratch reg 1230 rts 1231Lciflt: 1232 moveq #EFAULT,d0 | got a fault 1233 jra Lciexit 1234 1235/* 1236 * Copyout(from, to, len) 1237 * 1238 * Copy specified amount of data from kernel to the user space 1239 * NOTE: len must be < 64K 1240 */ 1241ENTRY(copyout) 1242 movl d2,sp@- | scratch register 1243 movl _curpcb,a0 | current pcb 1244 movl #Lcoflt,a0@(PCB_ONFAULT) | catch faults 1245 movl sp@(16),d2 | check count 1246 jlt Lcoflt | negative, error 1247 jeq Lcodone | zero, done 1248 movl sp@(8),a0 | src address 1249 movl sp@(12),a1 | dest address 1250 movl a0,d0 1251 btst #0,d0 | src address odd? 1252 jeq Lcoeven | no, go check dest 1253 movb a0@+,d1 | yes, get a byte 1254 movsb d1,a1@+ | put a byte 1255 nop 1256 subql #1,d2 | adjust count 1257 jeq Lcodone | exit if done 1258Lcoeven: 1259 movl a1,d0 1260 btst #0,d0 | dest address odd? 1261 jne Lcobyte | yes, must copy by bytes 1262 movl d2,d0 | no, get count 1263 lsrl #2,d0 | convert to longwords 1264 jeq Lcobyte | no longwords, copy bytes 1265 subql #1,d0 | set up for dbf 1266Lcolloop: 1267 movl a0@+,d1 | get a long 1268 movsl d1,a1@+ | put a long 1269 nop 1270 dbf d0,Lcolloop | til done 1271 andl #3,d2 | what remains 1272 jeq Lcodone | all done 1273Lcobyte: 1274 subql #1,d2 | set up for dbf 1275Lcobloop: 1276 movb a0@+,d1 | get a byte 1277 movsb d1,a1@+ | put a byte 1278 nop 1279 dbf d2,Lcobloop | til done 1280Lcodone: 1281 moveq #0,d0 | success 1282Lcoexit: 1283 movl _curpcb,a0 | current pcb 1284 clrl a0@(PCB_ONFAULT) | clear fault catcher 1285 movl sp@+,d2 | restore scratch reg 1286 rts 1287Lcoflt: 1288 moveq #EFAULT,d0 | got a fault 1289 jra Lcoexit 1290 1291/* 1292 * non-local gotos 1293 */ 1294ENTRY(setjmp) 1295 movl sp@(4),a0 | savearea pointer 1296 moveml #0xFCFC,a0@ | save d2-d7/a2-a7 1297 movl sp@,a0@(48) | and return address 1298 moveq #0,d0 | return 0 1299 rts 1300 1301ENTRY(qsetjmp) 1302 movl sp@(4),a0 | savearea pointer 1303 lea a0@(40),a0 | skip regs we do not save 1304 movl a6,a0@+ | save FP 1305 movl sp,a0@+ | save SP 1306 movl sp@,a0@ | and return address 1307 moveq #0,d0 | return 0 1308 rts 1309 1310ENTRY(longjmp) 1311 movl sp@(4),a0 1312 moveml a0@+,#0xFCFC 1313 movl a0@,sp@ 1314 moveq #1,d0 1315 rts 1316 1317/* 1318 * The following primitives manipulate the run queues. 1319 * _whichqs tells which of the 32 queues _qs 1320 * have processes in them. Setrq puts processes into queues, Remrq 1321 * removes them from queues. The running process is on no queue, 1322 * other processes are on a queue related to p->p_pri, divided by 4 1323 * actually to shrink the 0-127 range of priorities into the 32 available 1324 * queues. 1325 */ 1326 1327 .globl _whichqs,_qs,_cnt,_panic 1328 .globl _curproc,_want_resched 1329 1330/* 1331 * Setrq(p) 1332 * 1333 * Call should be made at spl6(), and p->p_stat should be SRUN 1334 */ 1335ENTRY(setrq) 1336 movl sp@(4),a0 1337 tstl a0@(P_RLINK) 1338 jeq Lset1 1339 movl #Lset2,sp@- 1340 jbsr _panic 1341Lset1: 1342 clrl d0 1343 movb a0@(P_PRI),d0 1344 lsrb #2,d0 1345 movl _whichqs,d1 1346 bset d0,d1 1347 movl d1,_whichqs 1348 lslb #3,d0 1349 addl #_qs,d0 1350 movl d0,a0@(P_LINK) 1351 movl d0,a1 1352 movl a1@(P_RLINK),a0@(P_RLINK) 1353 movl a0,a1@(P_RLINK) 1354 movl a0@(P_RLINK),a1 1355 movl a0,a1@(P_LINK) 1356 rts 1357 1358Lset2: 1359 .asciz "setrq" 1360 .even 1361 1362/* 1363 * Remrq(p) 1364 * 1365 * Call should be made at spl6(). 1366 */ 1367ENTRY(remrq) 1368 movl sp@(4),a0 1369 clrl d0 1370 movb a0@(P_PRI),d0 1371 lsrb #2,d0 1372 movl _whichqs,d1 1373 bclr d0,d1 1374 jne Lrem1 1375 movl #Lrem3,sp@- 1376 jbsr _panic 1377Lrem1: 1378 movl d1,_whichqs 1379 movl a0@(P_LINK),a1 1380 movl a0@(P_RLINK),a1@(P_RLINK) 1381 movl a0@(P_RLINK),a1 1382 movl a0@(P_LINK),a1@(P_LINK) 1383 movl #_qs,a1 1384 movl d0,d1 1385 lslb #3,d1 1386 addl d1,a1 1387 cmpl a1@(P_LINK),a1 1388 jeq Lrem2 1389 movl _whichqs,d1 1390 bset d0,d1 1391 movl d1,_whichqs 1392Lrem2: 1393 clrl a0@(P_RLINK) 1394 rts 1395 1396Lrem3: 1397 .asciz "remrq" 1398Lsw0: 1399 .asciz "swtch" 1400 .even 1401 1402 .globl _curpcb 1403 .globl _masterpaddr | XXX compatibility (debuggers) 1404 .data 1405_masterpaddr: | XXX compatibility (debuggers) 1406_curpcb: 1407 .long 0 1408pcbflag: 1409 .byte 0 | copy of pcb_flags low byte 1410 .align 2 1411 .comm nullpcb,SIZEOF_PCB 1412 .text 1413 1414/* 1415 * At exit of a process, do a swtch for the last time. 1416 * The mapping of the pcb at p->p_addr has already been deleted, 1417 * and the memory for the pcb+stack has been freed. 1418 * The ipl is high enough to prevent the memory from being reallocated. 1419 */ 1420ENTRY(swtch_exit) 1421 movl #nullpcb,_curpcb | save state into garbage pcb 1422 lea tmpstk,sp | goto a tmp stack 1423 jra _cpu_swtch 1424 1425/* 1426 * When no processes are on the runq, Swtch branches to idle 1427 * to wait for something to come ready. 1428 */ 1429 .globl Idle 1430Lidle: 1431 stop #PSL_LOWIPL 1432Idle: 1433idle: 1434 movw #PSL_HIGHIPL,sr 1435 tstl _whichqs 1436 jeq Lidle 1437 movw #PSL_LOWIPL,sr 1438 jra Lsw1 1439 1440Lbadsw: 1441 movl #Lsw0,sp@- 1442 jbsr _panic 1443 /*NOTREACHED*/ 1444 1445/* 1446 * cpu_swtch() 1447 * 1448 * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the 1449 * entire ATC. The effort involved in selective flushing may not be 1450 * worth it, maybe we should just flush the whole thing? 1451 * 1452 * NOTE 2: With the new VM layout we now no longer know if an inactive 1453 * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag 1454 * bit). For now, we just always flush the full ATC. 1455 */ 1456ENTRY(cpu_swtch) 1457 movl _curpcb,a0 | current pcb 1458 movw sr,a0@(PCB_PS) | save sr before changing ipl 1459#ifdef notyet 1460 movl _curproc,sp@- | remember last proc running 1461#endif 1462 clrl _curproc 1463 addql #1,_cnt+V_SWTCH 1464 1465Lsw1: 1466 /* 1467 * Find the highest-priority queue that isn't empty, 1468 * then take the first proc from that queue. 1469 */ 1470 clrl d0 1471 lea _whichqs,a0 1472 movl a0@,d1 1473Lswchk: 1474 btst d0,d1 1475 jne Lswfnd 1476 addqb #1,d0 1477 cmpb #32,d0 1478 jne Lswchk 1479 jra idle 1480Lswfnd: 1481 movw #PSL_HIGHIPL,sr | lock out interrupts 1482 movl a0@,d1 | and check again... 1483 bclr d0,d1 1484 jeq Lsw1 | proc moved, rescan 1485 movl d1,a0@ | update whichqs 1486 moveq #1,d1 | double check for higher priority 1487 lsll d0,d1 | process (which may have snuck in 1488 subql #1,d1 | while we were finding this one) 1489 andl a0@,d1 1490 jeq Lswok | no one got in, continue 1491 movl a0@,d1 1492 bset d0,d1 | otherwise put this one back 1493 movl d1,a0@ 1494 jra Lsw1 | and rescan 1495Lswok: 1496 movl d0,d1 1497 lslb #3,d1 | convert queue number to index 1498 addl #_qs,d1 | locate queue (q) 1499 movl d1,a1 1500 cmpl a1@(P_LINK),a1 | anyone on queue? 1501 jeq Lbadsw | no, panic 1502 movl a1@(P_LINK),a0 | p = q->p_link 1503 movl a0@(P_LINK),a1@(P_LINK) | q->p_link = p->p_link 1504 movl a0@(P_LINK),a1 | q = p->p_link 1505 movl a0@(P_RLINK),a1@(P_RLINK) | q->p_rlink = p->p_rlink 1506 cmpl a0@(P_LINK),d1 | anyone left on queue? 1507 jeq Lsw2 | no, skip 1508 movl _whichqs,d1 1509 bset d0,d1 | yes, reset bit 1510 movl d1,_whichqs 1511Lsw2: 1512 movl a0,_curproc 1513 clrl _want_resched 1514#ifdef notyet 1515 movl sp@+,a1 1516 cmpl a0,a1 | switching to same proc? 1517 jeq Lswdone | yes, skip save and restore 1518#endif 1519 /* 1520 * Save state of previous process in its pcb. 1521 */ 1522 movl _curpcb,a1 1523 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1524 movl usp,a2 | grab USP (a2 has been saved) 1525 movl a2,a1@(PCB_USP) | and save it 1526#ifdef FPCOPROC 1527 lea a1@(PCB_FPCTX),a2 | pointer to FP save area 1528 fsave a2@ | save FP state 1529 tstb a2@ | null state frame? 1530 jeq Lswnofpsave | yes, all done 1531 fmovem fp0-fp7,a2@(216) | save FP general registers 1532 fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers 1533Lswnofpsave: 1534#endif 1535 1536#ifdef DIAGNOSTIC 1537 tstl a0@(P_WCHAN) 1538 jne Lbadsw 1539 cmpb #SRUN,a0@(P_STAT) 1540 jne Lbadsw 1541#endif 1542 clrl a0@(P_RLINK) | clear back link 1543 movl a0@(P_ADDR),a1 | get p_addr 1544 movl a1,_curpcb 1545 movb a1@(PCB_FLAGS+1),pcbflag | copy of pcb_flags low byte 1546 1547 /* see if pmap_activate needs to be called; should remove this */ 1548 movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace 1549#ifdef DIAGNOSTIC 1550 tstl a0 | map == VM_MAP_NULL? 1551 jeq Lbadsw | panic 1552#endif 1553 lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap 1554 tstl a0@(PM_STCHG) | pmap->st_changed? 1555 jeq Lswnochg | no, skip 1556 pea a1@ | push pcb (at p_addr) 1557 pea a0@ | push pmap 1558 jbsr _pmap_activate | pmap_activate(pmap, pcb) 1559 addql #8,sp 1560 movl _curpcb,a1 | restore p_addr 1561Lswnochg: 1562 1563 movl #PGSHIFT,d1 1564 movl a1,d0 1565 lsrl d1,d0 | convert p_addr to page number 1566 lsll #2,d0 | and now to Sysmap offset 1567 addl _Sysmap,d0 | add Sysmap base to get PTE addr 1568#ifdef notdef 1569 movw #PSL_HIGHIPL,sr | go crit while changing PTEs 1570#endif 1571 lea tmpstk,sp | now goto a tmp stack for NMI 1572 movl d0,a0 | address of new context 1573 movl _Umap,a2 | address of PTEs for kstack 1574 moveq #UPAGES-1,d0 | sizeof kstack 1575Lres1: 1576 movl a0@+,d1 | get PTE 1577 andl #~PG_PROT,d1 | mask out old protection 1578 orl #PG_RW+PG_V,d1 | ensure valid and writable 1579 movl d1,a2@+ | load it up 1580 dbf d0,Lres1 | til done 1581#if defined(HP380) 1582 cmpl #-2,_mmutype | 68040? 1583 jne Lres1a | no, skip 1584 .word 0xf518 | yes, pflusha 1585 movl a1@(PCB_USTP),d0 | get USTP 1586 moveq #PGSHIFT,d1 1587 lsll d1,d0 | convert to addr 1588 .long 0x4e7b0806 | movc d0,urp 1589 jra Lcxswdone 1590Lres1a: 1591#endif 1592 movl #CACHE_CLR,d0 1593 movc d0,cacr | invalidate cache(s) 1594#if defined(HP330) || defined(HP360) || defined(HP370) 1595 tstl _mmutype | HP MMU? 1596 jeq Lhpmmu4 | yes, skip 1597 pflusha | flush entire TLB 1598 movl a1@(PCB_USTP),d0 | get USTP 1599 moveq #PGSHIFT,d1 1600 lsll d1,d0 | convert to addr 1601 lea _protorp,a0 | CRP prototype 1602 movl d0,a0@(4) | stash USTP 1603 pmove a0@,crp | load new user root pointer 1604 jra Lcxswdone | thats it 1605Lhpmmu4: 1606#endif 1607#if defined(HP320) || defined(HP350) 1608 MMUADDR(a0) 1609 movl a0@(MMUTBINVAL),d1 | invalidate TLB 1610 tstl _ectype | got external VAC? 1611 jle Lnocache1 | no, skip 1612 andl #~MMU_CEN,a0@(MMUCMD) | toggle cache enable 1613 orl #MMU_CEN,a0@(MMUCMD) | to clear data cache 1614Lnocache1: 1615 movl a1@(PCB_USTP),a0@(MMUUSTP) | context switch 1616#endif 1617Lcxswdone: 1618 moveml a1@(PCB_REGS),#0xFCFC | and registers 1619 movl a1@(PCB_USP),a0 1620 movl a0,usp | and USP 1621#ifdef FPCOPROC 1622 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1623 tstb a0@ | null state frame? 1624 jeq Lresfprest | yes, easy 1625#if defined(HP380) 1626 cmpl #-2,_mmutype | 68040? 1627 jne Lresnot040 | no, skip 1628 clrl sp@- | yes... 1629 frestore sp@+ | ...magic! 1630Lresnot040: 1631#endif 1632 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 1633 fmovem a0@(216),fp0-fp7 | restore FP general registers 1634Lresfprest: 1635 frestore a0@ | restore state 1636#endif 1637 movw a1@(PCB_PS),sr | no, restore PS 1638 moveq #1,d0 | return 1 (for alternate returns) 1639 rts 1640 1641/* 1642 * savectx(pcb, altreturn) 1643 * Update pcb, saving current processor state and arranging 1644 * for alternate return ala longjmp in swtch if altreturn is true. 1645 */ 1646ENTRY(savectx) 1647 movl sp@(4),a1 1648 movw sr,a1@(PCB_PS) 1649 movl usp,a0 | grab USP 1650 movl a0,a1@(PCB_USP) | and save it 1651 moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers 1652#ifdef FPCOPROC 1653 lea a1@(PCB_FPCTX),a0 | pointer to FP save area 1654 fsave a0@ | save FP state 1655 tstb a0@ | null state frame? 1656 jeq Lsvnofpsave | yes, all done 1657 fmovem fp0-fp7,a0@(216) | save FP general registers 1658 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 1659Lsvnofpsave: 1660#endif 1661 tstl sp@(8) | altreturn? 1662 jeq Lsavedone 1663 movl sp,d0 | relocate current sp relative to a1 1664 subl #_kstack,d0 | (sp is relative to kstack): 1665 addl d0,a1 | a1 += sp - kstack; 1666 movl sp@,a1@ | write return pc at (relocated) sp@ 1667Lsavedone: 1668 moveq #0,d0 | return 0 1669 rts 1670 1671/* 1672 * {fu,su},{byte,sword,word} 1673 */ 1674ALTENTRY(fuiword, _fuword) 1675ENTRY(fuword) 1676 movl sp@(4),a0 | address to read 1677 movl _curpcb,a1 | current pcb 1678 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1679 movsl a0@,d0 | do read from user space 1680 nop 1681 jra Lfsdone 1682 1683ENTRY(fusword) 1684 movl sp@(4),a0 1685 movl _curpcb,a1 | current pcb 1686 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1687 moveq #0,d0 1688 movsw a0@,d0 | do read from user space 1689 nop 1690 jra Lfsdone 1691 1692/* Just like fusword, but tells trap code not to page in. */ 1693ENTRY(fuswintr) 1694 movl sp@(4),a0 1695 movl _curpcb,a1 1696 movl #_fswintr,a1@(PCB_ONFAULT) 1697 moveq #0,d0 1698 movsw a0@,d0 1699 nop 1700 jra Lfsdone 1701 1702ALTENTRY(fuibyte, _fubyte) 1703ENTRY(fubyte) 1704 movl sp@(4),a0 | address to read 1705 movl _curpcb,a1 | current pcb 1706 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1707 moveq #0,d0 1708 movsb a0@,d0 | do read from user space 1709 nop 1710 jra Lfsdone 1711 1712Lfserr: 1713 moveq #-1,d0 | error indicator 1714Lfsdone: 1715 clrl a1@(PCB_ONFAULT) | clear fault address 1716 rts 1717 1718/* Just like Lfserr, but the address is different (& exported). */ 1719 .globl _fswintr 1720_fswintr: 1721 moveq #-1,d0 1722 jra Lfsdone 1723 1724 1725/* 1726 * Write a longword in user instruction space. 1727 * Largely the same as suword but with a final i-cache purge on those 1728 * machines with split caches. 1729 */ 1730ENTRY(suiword) 1731 movl sp@(4),a0 | address to write 1732 movl sp@(8),d0 | value to put there 1733 movl _curpcb,a1 | current pcb 1734 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1735 movsl d0,a0@ | do write to user space 1736 nop 1737 moveq #0,d0 | indicate no fault 1738#if defined(HP380) 1739 cmpl #-2,_mmutype | 68040? 1740 jne Lsuicpurge | no, skip 1741 .word 0xf498 | cinva ic (XXX overkill) 1742 jra Lfsdone 1743Lsuicpurge: 1744#endif 1745 movl #IC_CLEAR,d1 1746 movc d1,cacr | invalidate i-cache 1747 jra Lfsdone 1748 1749ENTRY(suword) 1750 movl sp@(4),a0 | address to write 1751 movl sp@(8),d0 | value to put there 1752 movl _curpcb,a1 | current pcb 1753 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1754 movsl d0,a0@ | do write to user space 1755 nop 1756 moveq #0,d0 | indicate no fault 1757 jra Lfsdone 1758 1759ENTRY(susword) 1760 movl sp@(4),a0 | address to write 1761 movw sp@(10),d0 | value to put there 1762 movl _curpcb,a1 | current pcb 1763 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1764 movsw d0,a0@ | do write to user space 1765 nop 1766 moveq #0,d0 | indicate no fault 1767 jra Lfsdone 1768 1769ENTRY(suswintr) 1770 movl sp@(4),a0 1771 movw sp@(10),d0 1772 movl _curpcb,a1 1773 movl #_fswintr,a1@(PCB_ONFAULT) 1774 movsw d0,a0@ 1775 nop 1776 moveq #0,d0 1777 jra Lfsdone 1778 1779ALTENTRY(suibyte, _subyte) 1780ENTRY(subyte) 1781 movl sp@(4),a0 | address to write 1782 movb sp@(11),d0 | value to put there 1783 movl _curpcb,a1 | current pcb 1784 movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault 1785 movsb d0,a0@ | do write to user space 1786 nop 1787 moveq #0,d0 | indicate no fault 1788 jra Lfsdone 1789 1790#if defined(HP380) 1791ENTRY(suline) 1792 movl sp@(4),a0 | address to write 1793 movl _curpcb,a1 | current pcb 1794 movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault 1795 movl sp@(8),a1 | address of line 1796 movl a1@+,d0 | get lword 1797 movsl d0,a0@+ | put lword 1798 nop | sync 1799 movl a1@+,d0 | get lword 1800 movsl d0,a0@+ | put lword 1801 nop | sync 1802 movl a1@+,d0 | get lword 1803 movsl d0,a0@+ | put lword 1804 nop | sync 1805 movl a1@+,d0 | get lword 1806 movsl d0,a0@+ | put lword 1807 nop | sync 1808 moveq #0,d0 | indicate no fault 1809 jra Lsldone 1810Lslerr: 1811 moveq #-1,d0 1812Lsldone: 1813 movl _curpcb,a1 | current pcb 1814 clrl a1@(PCB_ONFAULT) | clear fault address 1815 rts 1816#endif 1817 1818/* 1819 * Invalidate entire TLB. 1820 */ 1821ENTRY(TBIA) 1822__TBIA: 1823#if defined(HP380) 1824 cmpl #-2,_mmutype | 68040? 1825 jne Lmotommu3 | no, skip 1826 .word 0xf518 | yes, pflusha 1827 rts 1828Lmotommu3: 1829#endif 1830#if defined(HP330) || defined(HP360) || defined(HP370) 1831 tstl _mmutype | HP MMU? 1832 jeq Lhpmmu6 | yes, skip 1833 pflusha | flush entire TLB 1834#if defined(HP360) || defined(HP370) 1835 jpl Lmc68851a | 68851 implies no d-cache 1836 movl #DC_CLEAR,d0 1837 movc d0,cacr | invalidate on-chip d-cache 1838Lmc68851a: 1839#endif 1840 rts 1841Lhpmmu6: 1842#endif 1843#if defined(HP320) || defined(HP350) 1844 MMUADDR(a0) 1845 movl a0@(MMUTBINVAL),sp@- | do not ask me, this 1846 addql #4,sp | is how hpux does it 1847#ifdef DEBUG 1848 tstl fullcflush 1849 jne __DCIA | XXX: invalidate entire cache 1850#endif 1851#endif 1852 rts 1853 1854/* 1855 * Invalidate any TLB entry for given VA (TB Invalidate Single) 1856 */ 1857ENTRY(TBIS) 1858#ifdef DEBUG 1859 tstl fulltflush | being conservative? 1860 jne __TBIA | yes, flush entire TLB 1861#endif 1862#if defined(HP380) 1863 cmpl #-2,_mmutype | 68040? 1864 jne Lmotommu4 | no, skip 1865 movl sp@(4),a0 1866 movc dfc,d1 1867 moveq #1,d0 | user space 1868 movc d0,dfc 1869 .word 0xf508 | pflush a0@ 1870 moveq #5,d0 | super space 1871 movc d0,dfc 1872 .word 0xf508 | pflush a0@ 1873 movc d1,dfc 1874 rts 1875Lmotommu4: 1876#endif 1877#if defined(HP330) || defined(HP360) || defined(HP370) 1878 tstl _mmutype | HP MMU? 1879 jeq Lhpmmu5 | yes, skip 1880 movl sp@(4),a0 | get addr to flush 1881#if defined(HP360) || defined(HP370) 1882 jpl Lmc68851b | is 68851? 1883 pflush #0,#0,a0@ | flush address from both sides 1884 movl #DC_CLEAR,d0 1885 movc d0,cacr | invalidate on-chip data cache 1886 rts 1887Lmc68851b: 1888#endif 1889 pflushs #0,#0,a0@ | flush address from both sides 1890 rts 1891Lhpmmu5: 1892#endif 1893#if defined(HP320) || defined(HP350) 1894 movl sp@(4),d0 | VA to invalidate 1895 bclr #0,d0 | ensure even 1896 movl d0,a0 1897 movw sr,d1 | go critical 1898 movw #PSL_HIGHIPL,sr | while in purge space 1899 moveq #FC_PURGE,d0 | change address space 1900 movc d0,dfc | for destination 1901 moveq #0,d0 | zero to invalidate? 1902 movsl d0,a0@ | hit it 1903 moveq #FC_USERD,d0 | back to old 1904 movc d0,dfc | address space 1905 movw d1,sr | restore IPL 1906#endif 1907 rts 1908 1909/* 1910 * Invalidate supervisor side of TLB 1911 */ 1912ENTRY(TBIAS) 1913#ifdef DEBUG 1914 tstl fulltflush | being conservative? 1915 jne __TBIA | yes, flush everything 1916#endif 1917#if defined(HP380) 1918 cmpl #-2,_mmutype | 68040? 1919 jne Lmotommu5 | no, skip 1920 .word 0xf518 | yes, pflusha (for now) XXX 1921 rts 1922Lmotommu5: 1923#endif 1924#if defined(HP330) || defined(HP360) || defined(HP370) 1925 tstl _mmutype | HP MMU? 1926 jeq Lhpmmu7 | yes, skip 1927#if defined(HP360) || defined(HP370) 1928 jpl Lmc68851c | 68851? 1929 pflush #4,#4 | flush supervisor TLB entries 1930 movl #DC_CLEAR,d0 1931 movc d0,cacr | invalidate on-chip d-cache 1932 rts 1933Lmc68851c: 1934#endif 1935 pflushs #4,#4 | flush supervisor TLB entries 1936 rts 1937Lhpmmu7: 1938#endif 1939#if defined(HP320) || defined(HP350) 1940 MMUADDR(a0) 1941 movl #0x8000,d0 | more 1942 movl d0,a0@(MMUTBINVAL) | HP magic 1943#ifdef DEBUG 1944 tstl fullcflush 1945 jne __DCIS | XXX: invalidate entire sup. cache 1946#endif 1947#endif 1948 rts 1949 1950/* 1951 * Invalidate user side of TLB 1952 */ 1953ENTRY(TBIAU) 1954#ifdef DEBUG 1955 tstl fulltflush | being conservative? 1956 jne __TBIA | yes, flush everything 1957#endif 1958#if defined(HP380) 1959 cmpl #-2,_mmutype | 68040? 1960 jne Lmotommu6 | no, skip 1961 .word 0xf518 | yes, pflusha (for now) XXX 1962 rts 1963Lmotommu6: 1964#endif 1965#if defined(HP330) || defined(HP360) || defined(HP370) 1966 tstl _mmutype | HP MMU? 1967 jeq Lhpmmu8 | yes, skip 1968#if defined(HP360) || defined(HP370) 1969 jpl Lmc68851d | 68851? 1970 pflush #0,#4 | flush user TLB entries 1971 movl #DC_CLEAR,d0 1972 movc d0,cacr | invalidate on-chip d-cache 1973 rts 1974Lmc68851d: 1975#endif 1976 pflushs #0,#4 | flush user TLB entries 1977 rts 1978Lhpmmu8: 1979#endif 1980#if defined(HP320) || defined(HP350) 1981 MMUADDR(a0) 1982 moveq #0,d0 | more 1983 movl d0,a0@(MMUTBINVAL) | HP magic 1984#ifdef DEBUG 1985 tstl fullcflush 1986 jne __DCIU | XXX: invalidate entire user cache 1987#endif 1988#endif 1989 rts 1990 1991/* 1992 * Invalidate instruction cache 1993 */ 1994ENTRY(ICIA) 1995#if defined(HP380) 1996ENTRY(ICPA) 1997 cmpl #-2,_mmutype | 68040 1998 jne Lmotommu7 | no, skip 1999 .word 0xf498 | cinva ic 2000 rts 2001Lmotommu7: 2002#endif 2003 movl #IC_CLEAR,d0 2004 movc d0,cacr | invalidate i-cache 2005 rts 2006 2007/* 2008 * Invalidate data cache. 2009 * HP external cache allows for invalidation of user/supervisor portions. 2010 * NOTE: we do not flush 68030 on-chip cache as there are no aliasing 2011 * problems with DC_WA. The only cases we have to worry about are context 2012 * switch and TLB changes, both of which are handled "in-line" in resume 2013 * and TBI*. 2014 */ 2015ENTRY(DCIA) 2016__DCIA: 2017#if defined(HP380) 2018 cmpl #-2,_mmutype | 68040 2019 jne Lmotommu8 | no, skip 2020 /* XXX implement */ 2021 rts 2022Lmotommu8: 2023#endif 2024#if defined(HP320) || defined(HP350) 2025 tstl _ectype | got external VAC? 2026 jle Lnocache2 | no, all done 2027 MMUADDR(a0) 2028 andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg 2029 orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control reg 2030Lnocache2: 2031#endif 2032 rts 2033 2034ENTRY(DCIS) 2035__DCIS: 2036#if defined(HP380) 2037 cmpl #-2,_mmutype | 68040 2038 jne Lmotommu9 | no, skip 2039 /* XXX implement */ 2040 rts 2041Lmotommu9: 2042#endif 2043#if defined(HP320) || defined(HP350) 2044 tstl _ectype | got external VAC? 2045 jle Lnocache3 | no, all done 2046 MMUADDR(a0) 2047 movl a0@(MMUSSTP),d0 | read the supervisor STP 2048 movl d0,a0@(MMUSSTP) | write it back 2049Lnocache3: 2050#endif 2051 rts 2052 2053ENTRY(DCIU) 2054__DCIU: 2055#if defined(HP380) 2056 cmpl #-2,_mmutype | 68040 2057 jne LmotommuA | no, skip 2058 /* XXX implement */ 2059 rts 2060LmotommuA: 2061#endif 2062#if defined(HP320) || defined(HP350) 2063 tstl _ectype | got external VAC? 2064 jle Lnocache4 | no, all done 2065 MMUADDR(a0) 2066 movl a0@(MMUUSTP),d0 | read the user STP 2067 movl d0,a0@(MMUUSTP) | write it back 2068Lnocache4: 2069#endif 2070 rts 2071 2072#if defined(HP380) 2073ENTRY(ICPL) 2074 movl sp@(4),a0 | address 2075 .word 0xf488 | cinvl ic,a0@ 2076 rts 2077ENTRY(ICPP) 2078 movl sp@(4),a0 | address 2079 .word 0xf490 | cinvp ic,a0@ 2080 rts 2081ENTRY(DCPL) 2082 movl sp@(4),a0 | address 2083 .word 0xf448 | cinvl dc,a0@ 2084 rts 2085ENTRY(DCPP) 2086 movl sp@(4),a0 | address 2087 .word 0xf450 | cinvp dc,a0@ 2088 rts 2089ENTRY(DCPA) 2090 .word 0xf458 | cinva dc 2091 rts 2092ENTRY(DCFL) 2093 movl sp@(4),a0 | address 2094 .word 0xf468 | cpushl dc,a0@ 2095 rts 2096ENTRY(DCFP) 2097 movl sp@(4),a0 | address 2098 .word 0xf470 | cpushp dc,a0@ 2099 rts 2100#endif 2101 2102ENTRY(PCIA) 2103#if defined(HP380) 2104ENTRY(DCFA) 2105 cmpl #-2,_mmutype | 68040 2106 jne LmotommuB | no, skip 2107 .word 0xf478 | cpusha dc 2108 rts 2109LmotommuB: 2110#endif 2111#if defined(HP360) || defined(HP370) 2112 movl #DC_CLEAR,d0 2113 movc d0,cacr | invalidate on-chip d-cache 2114 tstl _ectype | got external PAC? 2115 jge Lnocache6 | no, all done 2116 MMUADDR(a0) 2117 andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg 2118 orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control reg 2119Lnocache6: 2120#endif 2121 rts 2122 2123ENTRY(ecacheon) 2124 tstl _ectype 2125 jeq Lnocache7 2126 MMUADDR(a0) 2127 orl #MMU_CEN,a0@(MMUCMD) 2128Lnocache7: 2129 rts 2130 2131ENTRY(ecacheoff) 2132 tstl _ectype 2133 jeq Lnocache8 2134 MMUADDR(a0) 2135 andl #~MMU_CEN,a0@(MMUCMD) 2136Lnocache8: 2137 rts 2138 2139/* 2140 * Get callers current SP value. 2141 * Note that simply taking the address of a local variable in a C function 2142 * doesn't work because callee saved registers may be outside the stack frame 2143 * defined by A6 (e.g. GCC generated code). 2144 */ 2145 .globl _getsp 2146_getsp: 2147 movl sp,d0 | get current SP 2148 addql #4,d0 | compensate for return address 2149 rts 2150 2151 .globl _getsfc, _getdfc 2152_getsfc: 2153 movc sfc,d0 2154 rts 2155_getdfc: 2156 movc dfc,d0 2157 rts 2158 2159/* 2160 * Load a new user segment table pointer. 2161 */ 2162ENTRY(loadustp) 2163#if defined(HP330) || defined(HP360) || defined(HP370) || defined(HP380) 2164 tstl _mmutype | HP MMU? 2165 jeq Lhpmmu9 | yes, skip 2166 movl sp@(4),d0 | new USTP 2167 moveq #PGSHIFT,d1 2168 lsll d1,d0 | convert to addr 2169#if defined(HP380) 2170 cmpl #-2,_mmutype | 68040? 2171 jne LmotommuC | no, skip 2172 .long 0x4e7b0806 | movc d0,urp 2173 rts 2174LmotommuC: 2175#endif 2176 lea _protorp,a0 | CRP prototype 2177 movl d0,a0@(4) | stash USTP 2178 pmove a0@,crp | load root pointer 2179 movl #DC_CLEAR,d0 2180 movc d0,cacr | invalidate on-chip d-cache 2181 rts | since pmove flushes TLB 2182Lhpmmu9: 2183#endif 2184#if defined(HP320) || defined(HP350) 2185 MMUADDR(a0) 2186 movl sp@(4),a0@(MMUUSTP) | load a new USTP 2187#endif 2188 rts 2189 2190/* 2191 * Flush any hardware context associated with given USTP. 2192 * Only does something for HP330 where we must flush RPT 2193 * and ATC entries in PMMU. 2194 */ 2195ENTRY(flushustp) 2196#if defined(HP330) 2197 tstl _mmutype | 68851 PMMU? 2198 jle Lnot68851 | no, nothing to do 2199 movl sp@(4),d0 | get USTP to flush 2200 moveq #PGSHIFT,d1 2201 lsll d1,d0 | convert to address 2202 movl d0,_protorp+4 | stash USTP 2203 pflushr _protorp | flush RPT/TLB entries 2204Lnot68851: 2205#endif 2206 rts 2207 2208ENTRY(ploadw) 2209#if defined(HP330) || defined(HP360) || defined(HP370) 2210 movl sp@(4),a0 | address to load 2211 ploadw #1,a0@ | pre-load translation 2212#endif 2213 rts 2214 2215/* 2216 * Set processor priority level calls. Most are implemented with 2217 * inline asm expansions. However, spl0 requires special handling 2218 * as we need to check for our emulated software interrupts. 2219 */ 2220 2221ENTRY(spl0) 2222 moveq #0,d0 2223 movw sr,d0 | get old SR for return 2224 movw #PSL_LOWIPL,sr | restore new SR 2225 tstb _ssir | software interrupt pending? 2226 jeq Lspldone | no, all done 2227 subql #4,sp | make room for RTE frame 2228 movl sp@(4),sp@(2) | position return address 2229 clrw sp@(6) | set frame type 0 2230 movw #PSL_LOWIPL,sp@ | and new SR 2231 jra Lgotsir | go handle it 2232Lspldone: 2233 rts 2234 2235ENTRY(_insque) 2236 movw sr,d0 2237 movw #PSL_HIGHIPL,sr | atomic 2238 movl sp@(8),a0 | where to insert (after) 2239 movl sp@(4),a1 | element to insert (e) 2240 movl a0@,a1@ | e->next = after->next 2241 movl a0,a1@(4) | e->prev = after 2242 movl a1,a0@ | after->next = e 2243 movl a1@,a0 2244 movl a1,a0@(4) | e->next->prev = e 2245 movw d0,sr 2246 rts 2247 2248ENTRY(_remque) 2249 movw sr,d0 2250 movw #PSL_HIGHIPL,sr | atomic 2251 movl sp@(4),a0 | element to remove (e) 2252 movl a0@,a1 2253 movl a0@(4),a0 2254 movl a0,a1@(4) | e->next->prev = e->prev 2255 movl a1,a0@ | e->prev->next = e->next 2256 movw d0,sr 2257 rts 2258 2259/* 2260 * bzero(addr, count) 2261 */ 2262ALTENTRY(blkclr, _bzero) 2263ENTRY(bzero) 2264 movl sp@(4),a0 | address 2265 movl sp@(8),d0 | count 2266 jeq Lbzdone | if zero, nothing to do 2267 movl a0,d1 2268 btst #0,d1 | address odd? 2269 jeq Lbzeven | no, can copy words 2270 clrb a0@+ | yes, zero byte to get to even boundary 2271 subql #1,d0 | decrement count 2272 jeq Lbzdone | none left, all done 2273Lbzeven: 2274 movl d0,d1 2275 andl #31,d0 2276 lsrl #5,d1 | convert count to 8*longword count 2277 jeq Lbzbyte | no such blocks, zero byte at a time 2278Lbzloop: 2279 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2280 clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; 2281 subql #1,d1 | one more block zeroed 2282 jne Lbzloop | more to go, do it 2283 tstl d0 | partial block left? 2284 jeq Lbzdone | no, all done 2285Lbzbyte: 2286 clrb a0@+ 2287 subql #1,d0 | one more byte cleared 2288 jne Lbzbyte | more to go, do it 2289Lbzdone: 2290 rts 2291 2292/* 2293 * strlen(str) 2294 */ 2295ENTRY(strlen) 2296 moveq #-1,d0 2297 movl sp@(4),a0 | string 2298Lslloop: 2299 addql #1,d0 | increment count 2300 tstb a0@+ | null? 2301 jne Lslloop | no, keep going 2302 rts 2303 2304/* 2305 * bcmp(s1, s2, len) 2306 * 2307 * WARNING! This guy only works with counts up to 64K 2308 */ 2309ENTRY(bcmp) 2310 movl sp@(4),a0 | string 1 2311 movl sp@(8),a1 | string 2 2312 moveq #0,d0 2313 movw sp@(14),d0 | length 2314 jeq Lcmpdone | if zero, nothing to do 2315 subqw #1,d0 | set up for DBcc loop 2316Lcmploop: 2317 cmpmb a0@+,a1@+ | equal? 2318 dbne d0,Lcmploop | yes, keep going 2319 addqw #1,d0 | +1 gives zero on match 2320Lcmpdone: 2321 rts 2322 2323/* 2324 * {ov}bcopy(from, to, len) 2325 * 2326 * Works for counts up to 128K. 2327 */ 2328ALTENTRY(ovbcopy, _bcopy) 2329ENTRY(bcopy) 2330 movl sp@(12),d0 | get count 2331 jeq Lcpyexit | if zero, return 2332 movl sp@(4),a0 | src address 2333 movl sp@(8),a1 | dest address 2334 cmpl a1,a0 | src before dest? 2335 jlt Lcpyback | yes, copy backwards (avoids overlap) 2336 movl a0,d1 2337 btst #0,d1 | src address odd? 2338 jeq Lcfeven | no, go check dest 2339 movb a0@+,a1@+ | yes, copy a byte 2340 subql #1,d0 | update count 2341 jeq Lcpyexit | exit if done 2342Lcfeven: 2343 movl a1,d1 2344 btst #0,d1 | dest address odd? 2345 jne Lcfbyte | yes, must copy by bytes 2346 movl d0,d1 | no, get count 2347 lsrl #2,d1 | convert to longwords 2348 jeq Lcfbyte | no longwords, copy bytes 2349 subql #1,d1 | set up for dbf 2350Lcflloop: 2351 movl a0@+,a1@+ | copy longwords 2352 dbf d1,Lcflloop | til done 2353 andl #3,d0 | get remaining count 2354 jeq Lcpyexit | done if none 2355Lcfbyte: 2356 subql #1,d0 | set up for dbf 2357Lcfbloop: 2358 movb a0@+,a1@+ | copy bytes 2359 dbf d0,Lcfbloop | til done 2360Lcpyexit: 2361 rts 2362Lcpyback: 2363 addl d0,a0 | add count to src 2364 addl d0,a1 | add count to dest 2365 movl a0,d1 2366 btst #0,d1 | src address odd? 2367 jeq Lcbeven | no, go check dest 2368 movb a0@-,a1@- | yes, copy a byte 2369 subql #1,d0 | update count 2370 jeq Lcpyexit | exit if done 2371Lcbeven: 2372 movl a1,d1 2373 btst #0,d1 | dest address odd? 2374 jne Lcbbyte | yes, must copy by bytes 2375 movl d0,d1 | no, get count 2376 lsrl #2,d1 | convert to longwords 2377 jeq Lcbbyte | no longwords, copy bytes 2378 subql #1,d1 | set up for dbf 2379Lcblloop: 2380 movl a0@-,a1@- | copy longwords 2381 dbf d1,Lcblloop | til done 2382 andl #3,d0 | get remaining count 2383 jeq Lcpyexit | done if none 2384Lcbbyte: 2385 subql #1,d0 | set up for dbf 2386Lcbbloop: 2387 movb a0@-,a1@- | copy bytes 2388 dbf d0,Lcbbloop | til done 2389 rts 2390 2391/* 2392 * Emulate fancy VAX string operations: 2393 * scanc(count, startc, table, mask) 2394 * skpc(mask, count, startc) 2395 * locc(mask, count, startc) 2396 */ 2397ENTRY(scanc) 2398 movl sp@(4),d0 | get length 2399 jeq Lscdone | nothing to do, return 2400 movl sp@(8),a0 | start of scan 2401 movl sp@(12),a1 | table to compare with 2402 movb sp@(19),d1 | and mask to use 2403 movw d2,sp@- | need a scratch register 2404 clrw d2 | clear it out 2405 subqw #1,d0 | adjust for dbra 2406Lscloop: 2407 movb a0@+,d2 | get character 2408 movb a1@(0,d2:w),d2 | get table entry 2409 andb d1,d2 | mask it 2410 dbne d0,Lscloop | keep going til no more or non-zero 2411 addqw #1,d0 | overshot by one 2412 movw sp@+,d2 | restore scratch 2413Lscdone: 2414 rts 2415 2416ENTRY(skpc) 2417 movl sp@(8),d0 | get length 2418 jeq Lskdone | nothing to do, return 2419 movb sp@(7),d1 | mask to use 2420 movl sp@(12),a0 | where to start 2421 subqw #1,d0 | adjust for dbcc 2422Lskloop: 2423 cmpb a0@+,d1 | compate with mask 2424 dbne d0,Lskloop | keep going til no more or zero 2425 addqw #1,d0 | overshot by one 2426Lskdone: 2427 rts 2428 2429ENTRY(locc) 2430 movl sp@(8),d0 | get length 2431 jeq Llcdone | nothing to do, return 2432 movb sp@(7),d1 | mask to use 2433 movl sp@(12),a0 | where to start 2434 subqw #1,d0 | adjust for dbcc 2435Llcloop: 2436 cmpb a0@+,d1 | compate with mask 2437 dbeq d0,Llcloop | keep going til no more or non-zero 2438 addqw #1,d0 | overshot by one 2439Llcdone: 2440 rts 2441 2442/* 2443 * Emulate VAX FFS (find first set) instruction. 2444 */ 2445ENTRY(ffs) 2446 moveq #-1,d0 2447 movl sp@(4),d1 2448 jeq Lffsdone 2449Lffsloop: 2450 addql #1,d0 2451 btst d0,d1 2452 jeq Lffsloop 2453Lffsdone: 2454 addql #1,d0 2455 rts 2456 2457#ifdef FPCOPROC 2458/* 2459 * Save and restore 68881 state. 2460 * Pretty awful looking since our assembler does not 2461 * recognize FP mnemonics. 2462 */ 2463ENTRY(m68881_save) 2464 movl sp@(4),a0 | save area pointer 2465 fsave a0@ | save state 2466 tstb a0@ | null state frame? 2467 jeq Lm68881sdone | yes, all done 2468 fmovem fp0-fp7,a0@(216) | save FP general registers 2469 fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers 2470Lm68881sdone: 2471 rts 2472 2473ENTRY(m68881_restore) 2474 movl sp@(4),a0 | save area pointer 2475 tstb a0@ | null state frame? 2476 jeq Lm68881rdone | yes, easy 2477 fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers 2478 fmovem a0@(216),fp0-fp7 | restore FP general registers 2479Lm68881rdone: 2480 frestore a0@ | restore state 2481 rts 2482#endif 2483 2484/* 2485 * Handle the nitty-gritty of rebooting the machine. 2486 * Basically we just turn off the MMU and jump to the appropriate ROM routine. 2487 * Note that we must be running in an address range that is mapped one-to-one 2488 * logical to physical so that the PC is still valid immediately after the MMU 2489 * is turned off. We have conveniently mapped the last page of physical 2490 * memory this way. 2491 */ 2492 .globl _doboot 2493_doboot: 2494#if defined(HP380) 2495 cmpl #-2,_mmutype | 68040? 2496 jeq Lnocache5 | yes, skip 2497#endif 2498 movl #CACHE_OFF,d0 2499 movc d0,cacr | disable on-chip cache(s) 2500#if defined(HP320) || defined(HP350) || defined(HP370) 2501 tstl _ectype 2502 jeq Lnocache5 2503 MMUADDR(a0) 2504 andl #~MMU_CEN,a0@(MMUCMD) | disable external cache 2505#endif 2506Lnocache5: 2507 lea MAXADDR,a0 | last page of physical memory 2508 movl _boothowto,a0@+ | store howto 2509 movl _bootdev,a0@+ | and devtype 2510 lea Lbootcode,a1 | start of boot code 2511 lea Lebootcode,a3 | end of boot code 2512Lbootcopy: 2513 movw a1@+,a0@+ | copy a word 2514 cmpl a3,a1 | done yet? 2515 jcs Lbootcopy | no, keep going 2516#if defined(HP380) 2517 cmpl #-2,_mmutype | 68040? 2518 jne LmotommuE | no, skip 2519 .word 0xf4f8 | cpusha bc 2520LmotommuE: 2521#endif 2522 jmp MAXADDR+8 | jump to last page 2523 2524Lbootcode: 2525 lea MAXADDR+0x800,sp | physical SP in case of NMI 2526#if defined(HP380) 2527 cmpl #-2,_mmutype | 68040? 2528 jne LmotommuF | no, skip 2529 movl #0,d0 2530 movc d0,cacr | caches off 2531 .long 0x4e7b0003 | movc d0,tc 2532 movl d2,MAXADDR+NBPG-4 | restore old high page contents 2533 jmp 0x1A4 | goto REQ_REBOOT 2534LmotommuF: 2535#endif 2536#if defined(HP330) || defined(HP360) || defined(HP370) 2537 tstl _mmutype | HP MMU? 2538 jeq LhpmmuB | yes, skip 2539 movl #0,a0@ | value for pmove to TC (turn off MMU) 2540 pmove a0@,tc | disable MMU 2541 jmp 0x1A4 | goto REQ_REBOOT 2542LhpmmuB: 2543#endif 2544#if defined(HP320) || defined(HP350) 2545 MMUADDR(a0) 2546 movl #0xFFFF0000,a0@(MMUCMD) | totally disable MMU 2547 movl d2,MAXADDR+NBPG-4 | restore old high page contents 2548 jmp 0x1A4 | goto REQ_REBOOT 2549#endif 2550Lebootcode: 2551 2552 .data 2553 .space NBPG 2554tmpstk: 2555 .globl _machineid 2556_machineid: 2557 .long 0 | default to 320 2558 .globl _mmutype,_protorp 2559_mmutype: 2560 .long 0 | default to HP MMU 2561_protorp: 2562 .long 0,0 | prototype root pointer 2563 .globl _ectype 2564_ectype: 2565 .long 0 | external cache type, default to none 2566 .globl _internalhpib 2567_internalhpib: 2568 .long 1 | has internal HP-IB, default to yes 2569 .globl _cold 2570_cold: 2571 .long 1 | cold start flag 2572 .globl _want_resched 2573_want_resched: 2574 .long 0 2575 .globl _intiobase, _intiolimit, _extiobase, _CLKbase, _MMUbase 2576 .globl _proc0paddr 2577_proc0paddr: 2578 .long 0 | KVA of proc0 u-area 2579_intiobase: 2580 .long 0 | KVA of base of internal IO space 2581_intiolimit: 2582 .long 0 | KVA of end of internal IO space 2583_extiobase: 2584 .long 0 | KVA of base of external IO space 2585_CLKbase: 2586 .long 0 | KVA of base of clock registers 2587_MMUbase: 2588 .long 0 | KVA of base of HP MMU registers 2589#ifdef DEBUG 2590 .globl fulltflush, fullcflush 2591fulltflush: 2592 .long 0 2593fullcflush: 2594 .long 0 2595 .globl timebomb 2596timebomb: 2597 .long 0 2598#endif 2599#ifdef HPFPLIB 2600/* 2601 * Undefined symbols from hpux_float.o: 2602 * 2603 * kdb_printf: A kernel debugger print routine, we just use printf instead. 2604 * processor: HP-UX equiv. of machineid, set to 3 if it is a 68040. 2605 * u: Ye ole u-area. The code wants to grab the first longword 2606 * indirect off of that and clear the 0x40000 bit there. 2607 * Oddly enough this was incorrect even in HP-UX! 2608 * runrun: Old name for want_resched. 2609 */ 2610 .globl _kdb_printf,_processor,_u,_runrun 2611_kdb_printf: 2612 .long _printf 2613_processor: 2614 .long 0 2615_u: 2616 .long .+4 2617 .long 0 2618 .set _runrun,_want_resched 2619#endif 2620/* interrupt counters */ 2621 .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames 2622_intrnames: 2623 .asciz "spur" 2624 .asciz "hil" 2625 .asciz "lev2" 2626 .asciz "lev3" 2627 .asciz "lev4" 2628 .asciz "lev5" 2629 .asciz "dma" 2630 .asciz "clock" 2631 .asciz "statclock" 2632 .asciz "nmi" 2633_eintrnames: 2634 .even 2635_intrcnt: 2636 .long 0,0,0,0,0,0,0,0,0,0 2637_eintrcnt: 2638