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