|
|
1.1 ! root 1: .data ! 2: .asciz "@(#)locore.s 1.1 86/02/03 Copyr 1985 Sun Micro" ! 3: .even ! 4: .text ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: #include "../h/param.h" ! 10: #include "../h/vmparam.h" ! 11: #include "../h/errno.h" ! 12: /* ! 13: #include "../netinet/in_systm.h" ! 14: ! 15: #include "../sundev/mbvar.h" ! 16: */ ! 17: ! 18: #include "../machine/asm_linkage.h" ! 19: #include "../machine/buserr.h" ! 20: #include "../machine/clock.h" ! 21: #include "../machine/cpu.h" ! 22: #include "../machine/diag.h" ! 23: #include "../machine/enable.h" ! 24: #include "../machine/interreg.h" ! 25: #include "../machine/memerr.h" ! 26: #include "../machine/mmu.h" ! 27: #include "../machine/pcb.h" ! 28: #include "../machine/psl.h" ! 29: #include "../machine/pte.h" ! 30: #include "../machine/reg.h" ! 31: #include "../machine/trap.h" ! 32: ! 33: #include "assym.s" ! 34: ! 35: /* ! 36: * Absolute external symbols ! 37: */ ! 38: .globl _u, _DVMA ! 39: _u = UADDR | 32 bit virtual address for u-area ! 40: _DVMA = 0x0FF00000 | 28 bit virtual address for system DVMA ! 41: ! 42: /* ! 43: * The interrupt stack. This must be the first thing in the data ! 44: * segment (other than an sccs string) so that we don't stomp ! 45: * on anything important during interrupt handling. We get a ! 46: * red zone below this stack for free when the kernel text is ! 47: * write protected. Since the kernel is loaded with the "-N" ! 48: * flag, we pad this stack by a page because when the page ! 49: * level protection is done, we will lose part of this interrupt ! 50: * stack. Thus the true interrupt stack will be at least MIN_INTSTACK_SZ ! 51: * bytes and at most MIN_INTSTACK_SZ+NBPG bytes. The interrupt entry ! 52: * code assumes that the interrupt stack is at a lower address than ! 53: * both eintstack and the kernel stack in the u area. ! 54: */ ! 55: #define MIN_INTSTACK_SZ 0x800 ! 56: .data ! 57: .globl _intstack, eintstack ! 58: _intstack: | bottom of interrupt stack ! 59: . = . + NBPG + MIN_INTSTACK_SZ ! 60: eintstack: | end (top) of interrupt stack ! 61: ! 62: /* ! 63: * System software page tables ! 64: */ ! 65: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG + KERNELBASE) ! 66: #define SYSMAP(mname, vname, npte) \ ! 67: .globl mname; \ ! 68: mname: .=.+(4*npte); \ ! 69: .globl vname; \ ! 70: vname = vaddr(mname); ! 71: SYSMAP(_Sysmap ,_Sysbase ,SYSPTSIZE ) ! 72: SYSMAP(_Usrptmap ,_usrpt ,USRPTSIZE ) ! 73: SYSMAP(_Forkmap ,_forkutl ,UPAGES ) ! 74: SYSMAP(_Xswapmap ,_xswaputl ,UPAGES ) ! 75: SYSMAP(_Xswap2map,_xswap2utl ,UPAGES ) ! 76: SYSMAP(_Swapmap ,_swaputl ,UPAGES ) ! 77: SYSMAP(_Pushmap ,_pushutl ,UPAGES ) ! 78: SYSMAP(_Vfmap ,_vfutl ,UPAGES ) ! 79: SYSMAP(_CMAP1 ,_CADDR1 ,1 ) | local tmp ! 80: SYSMAP(_CMAP2 ,_CADDR2 ,1 ) | local tmp ! 81: SYSMAP(_mmap ,_vmmap ,1 ) ! 82: SYSMAP(_msgbufmap,_msgbuf ,MSGBUFPTECNT ) ! 83: /* ! 84: SYSMAP(_Mbmap ,_mbutl ,NMBCLUSTERS*CLSIZE) ! 85: */ ! 86: SYSMAP(_ESysmap ,_Syslimit ,0 ) | must be last ! 87: ! 88: .globl _Syssize ! 89: _Syssize = (_ESysmap-_Sysmap)/4 ! 90: ! 91: /* ! 92: * Software copy of system enable register ! 93: * This is always atomically updated ! 94: */ ! 95: .data ! 96: .globl _enablereg ! 97: _enablereg: .byte 0 | UNIX's system enable register ! 98: .even ! 99: .text ! 100: ! 101: /* ! 102: * Macro to save all registers and switch to kernel context ! 103: * 1: Save and switch context ! 104: * 2: Save all registers ! 105: * 3: Save user stack pointer ! 106: */ ! 107: #define SAVEALL() \ ! 108: clrw sp@-;\ ! 109: moveml #0xFFFF,sp@-;\ ! 110: movl usp,a0;\ ! 111: movl a0,sp@(R_SP) ! 112: ! 113: /* Normal trap sequence */ ! 114: #define TRAP(type) \ ! 115: SAVEALL();\ ! 116: movl #type,sp@-;\ ! 117: jra trap ! 118: ! 119: /* ! 120: * System initialization ! 121: * UNIX receives control at the label `_start' which ! 122: * must be at offset zero in this file; this file must ! 123: * be the first thing in the boot image. ! 124: */ ! 125: .text ! 126: .globl _start ! 127: _start: ! 128: /* ! 129: * We should reset the world here, but it screws the UART settings. ! 130: * ! 131: * Do a halfhearted job of setting up the mmu so that we can run out ! 132: * of the high address space. We do this by reading the current pmegs ! 133: * for the `real' locations and using them for the virtual relocation. ! 134: * NOTE - Assumes that the real and virtual locations have the same ! 135: * segment offsets from 0 and KERNELBASE!!! ! 136: * ! 137: * We make the following assumptions about our environment ! 138: * as set up by the monitor: ! 139: * ! 140: * - we have enough memory mapped for the entire kernel + some more ! 141: * - all pages are writable ! 142: * - the last pmeg [SEGINV] has no valid pme's ! 143: * - the highest virtual segment has a pmeg allocated to it ! 144: * - when the monitor's romp->v_memorybitmap points to a zero ! 145: * - each low segment i is mapped to use pmeg i ! 146: * - each page map entry i maps physical page i ! 147: * - the monitor's scb is NOT in low memory ! 148: * - on systems w/ ecc memory, that the monitor has set the base ! 149: * addresses and enabled all the memory cards correctly ! 150: * ! 151: * We will set the protection properly in startup(). ! 152: */ ! 153: ! 154: /* ! 155: * Before we set up the new mapping and start running with the correct ! 156: * addresses, all of the code must be carefully written to be position ! 157: * independent code, since we are linked for running out of high addresses, ! 158: * but we get control running in low addresses. We continue to run ! 159: * off the stack set up by the monitor until after we set up the u area. ! 160: */ ! 161: movw #SR_HIGH,sr | lock out interrupts ! 162: moveq #FC_MAP,d0 ! 163: movc d0,sfc | set default sfc to FC_MAP ! 164: movc d0,dfc | set default dfc to FC_MAP ! 165: moveq #KCONTEXT,d0 ! 166: movsb d0,CONTEXTBASE | now running in KCONTEXT ! 167: ! 168: leax: lea pc@(_start-(leax+2)),a2 | a2 = true current location of _start ! 169: movl a2,d2 | real start address ! 170: andl #SEGMENTADDRBITS,d2 | clear extraneous bits ! 171: orl #SEGMENTBASE,d2 | set to segment map offset ! 172: movl d2,a2 | a2 = real adddress map pointer ! 173: ! 174: movl #_start,d3 | virtual start address ! 175: andl #SEGMENTADDRBITS,d3 | clear extraneous bits ! 176: orl #SEGMENTBASE,d3 | set to segment map offset ! 177: movl d3,a3 | a3 = virtual address map pointer ! 178: ! 179: /* ! 180: * Compute the number used to control the dbra loop. ! 181: * By doing ((end - 1) - KERNELBASE) >> SGSHIFT we ! 182: * essentially get ctos(btoc(end - KERNELBASE)) - 1 ! 183: * where the - 1 is adjustment for the dbra loop. ! 184: */ ! 185: movl #_end-1,d1 | get virtual end ! 186: subl #KERNELBASE,d1 | subtract off base address ! 187: movl #SGSHIFT,d0 | load up segment shift value ! 188: lsrl d0,d1 | d1 = # of segments to map - 1 ! 189: ! 190: /* ! 191: * Now loop through the real addresses where we are loaded and set ! 192: * up the virtual segments for where we want to be virtually to be the same. ! 193: */ ! 194: 0: ! 195: movsb a2@,d0 | get real segno value ! 196: movsb d0,a3@ | set virtual segno value ! 197: addl #NBSG,a2 | bump real address map pointer ! 198: addl #NBSG,a3 | bump virtual address map pointer ! 199: dbra d1,0b | decrement count and loop ! 200: ! 201: movl #CACHE_CLEAR+CACHE_ENABLE,d0 ! 202: movc d0,cacr | clear (and enable) the cache ! 203: ! 204: jmp cont:l | force non-PC rel branch ! 205: cont: ! 206: ! 207: /* ! 208: * PHEW! Now we are running with correct addresses ! 209: * and can use non-position independent code. ! 210: */ ! 211: ! 212: /* ! 213: * Now map in our own copies of the eeprom, clock, memory error ! 214: * register, interrupt control register, and ecc regs into the ! 215: * last virtual segment which already has a pmeg allocated to it ! 216: * when we get control from the monitor. ! 217: */ ! 218: lea EEPROM_ADDR_MAPVAL,a0 | map in eeprom ! 219: movl #EEPROM_ADDR_PTE,d0 ! 220: movsl d0,a0@ ! 221: ! 222: lea CLKADDR_MAPVAL,a0 | map in clock ! 223: movl #CLKADDR_PTE,d0 ! 224: movsl d0,a0@ ! 225: ! 226: lea MEMREG_MAPVAL,a0 | map in memory error register ! 227: movl #MEMREG_PTE,d0 ! 228: movsl d0,a0@ ! 229: ! 230: lea INTERREG_MAPVAL,a0 | map in interrupt control reg ! 231: movl #INTERREG_PTE,d0 ! 232: movsl d0,a0@ ! 233: ! 234: lea ECCREG_MAPVAL,a0 | map in ecc regs ! 235: movl #ECCREG_PTE,d0 ! 236: movsl d0,a0@ ! 237: ! 238: /* ! 239: * Check to see if memory was all mapped in correctly. On versions >= 'N', ! 240: * if ROMP_ROMVEC_VERSION is greater than zero, then ROMP_MEMORYBITMAP ! 241: * contains the address of a pointer to an array of bits ! 242: * If this pointer is non-zero, then we had some bad pages ! 243: * Until we get smarter, we give up if we find this condition. ! 244: */ ! 245: tstl ROMP_ROMVEC_VERSION ! 246: ble 1f | field is <= zero, don't do next test ! 247: movl ROMP_MEMORYBITMAP,a0 ! 248: tstl a0@ ! 249: jeq 1f | pointer is zero, all ok ! 250: pea 0f ! 251: jsr _halt ! 252: addqw #4,sp | in case they really want to try this ! 253: .data ! 254: 0: .asciz "Memory bad" ! 255: .even ! 256: .text ! 257: 1: ! 258: ! 259: /* ! 260: * Set up mapping for the u page(s) now, using the physical page(s) ! 261: * after _end. This code and uinit() are closely related. ! 262: */ ! 263: movl #(UPAGES-1),d1 | dbra loop counter ! 264: pea _end-KERNELBASE+NBPG-1 | phys addr of starting page past end ! 265: jsr _getpgmap | getpgmap(end - KERNELBASE + NBPG - 1) ! 266: addqw #4,sp | pop argument ! 267: orl #(PG_S+PG_W),d0 | make a system writable page ! 268: lea _u,a0 | get addr of u area ! 269: 0: ! 270: movl d0,sp@- | push pte ! 271: pea a0@ | push addr ! 272: jsr _setpgmap | setpgmap(u + i*NBPG, pte + i) ! 273: addqw #8,sp | pop arguments ! 274: addql #1,d0 | bump pte to next phys page ! 275: addl #NBPG,a0 | bump addr ! 276: dbra d1,0b ! 277: ! 278: | zero first page which will be scb/usrpt page ! 279: movl #((NBPG-1)/4),d0 | dbra byte count ! 280: lea 0,a0 | start at zero ! 281: 0: clrl a0@+ | clear long word and increment ! 282: dbra d0,0b | decrement count and loop ! 283: ! 284: | zero bss + u page(s) (using low addresses) ! 285: movl #_end-KERNELBASE+(NBPG*(UPAGES+1))-1,d0 ! 286: andl #~(NBPG-1),d0 | mask off to page boundary ! 287: lea _edata-KERNELBASE,a0 | get bss start ! 288: subl a0,d0 | get bss length ! 289: lsrl #2,d0 | shift for long count ! 290: 0: clrl a0@+ | clear long word and increment ! 291: subql #1,d0 ! 292: jne 0b | decrement count and loop ! 293: ! 294: /* ! 295: * Set up the stack. From now we continue to use the 68020 ISP ! 296: * (interrupt stack pointer). This is because the MSP (master ! 297: * stack pointer) as implemented by Motorola is too painful to ! 298: * use since we have to play lots of games and add extra tests ! 299: * to set something in the master stack if we running on the ! 300: * interrupt stack and we are about to pop off a throw away ! 301: * stack frame. ! 302: * ! 303: * Thus it is possible to having naming conflicts. In general, ! 304: * when the term "interrupt stack" (no pointer) is used, it ! 305: * is referring to the software implemented interrupt stack ! 306: * and the "kernel stack" is the per user kernel stack in the ! 307: * user area. We handling switching between the two different ! 308: * address ranges upon interrupt entry/exit. We will use ISP ! 309: * and MSP if we are referring to the hardstack stack pointers. ! 310: */ ! 311: lea _u+U_STACK+KERNSTACK,sp | set to top of kernel stack ! 312: ! 313: /* ! 314: * See if we have a 68881 attached. ! 315: * _fppstate is 0 if no fpp, ! 316: * 1 if fpp is present and enabled, ! 317: * and -1 if fpp is present but disabled ! 318: * (not currently used). ! 319: */ ! 320: .data ! 321: .globl _fppstate ! 322: _fppstate: .word 1 | mark as present until we find out otherwise ! 323: .text ! 324: ! 325: flinevec = 0x2c ! 326: movsb ENABLEREG,d0 | get the current enable register ! 327: orb #ENA_FPP,d0 | or in FPP enable bit ! 328: movsb d0,ENABLEREG | set in the enable register ! 329: movl sp,a1 | save sp in case of fline fault ! 330: movc vbr,a0 | get vbr ! 331: movl a0@(flinevec),d1 | save old f line trap handler ! 332: movl #ffault,a0@(flinevec) | set up f line handler ! 333: frestore fnull ! 334: jra 1f ! 335: ! 336: fnull: .long 0 | null fpp internal state ! 337: ! 338: ffault: | handler for no fpp present ! 339: movw #0,_fppstate | set global to say no fpp ! 340: andb #~ENA_FPP,d0 | clear ENA_FPP enable bit ! 341: movl a1,sp | clean up stack ! 342: ! 343: 1: ! 344: movl d1,a0@(flinevec) | restore old f line trap handler ! 345: movsb d0,ENABLEREG | set up enable reg ! 346: movb d0,_enablereg | save soft copy of enable register ! 347: ! 348: | dummy up a stack so process 1 can find saved registers ! 349: movl #USRSTACK,a0 | init user stack pointer ! 350: movl a0,usp ! 351: clrw sp@- | dummy fmt & vor ! 352: movl #USRTEXT,sp@- | push pc ! 353: movw #SR_USER,sp@- | push sr ! 354: lea 0,a6 | stack frame link 0 in main ! 355: | invoke main, we will return as process 1 (init) ! 356: SAVEALL() ! 357: jsr _main | simulate interrupt -> main ! 358: clrl d0 | fake return value from trap ! 359: jra rei ! 360: ! 361: /* ! 362: * Entry points for interrupt and trap vectors ! 363: */ ! 364: .globl buserr, addrerr, coprocerr, fmterr, illinst, zerodiv, chkinst ! 365: .globl trapv, privvio, trace, emu1010, emu1111, spurious ! 366: .globl badtrap, brkpt, floaterr, level2, level3, level4, level5 ! 367: .globl _level7, errorvec ! 368: ! 369: buserr: ! 370: TRAP(T_BUSERR) ! 371: ! 372: addrerr: ! 373: TRAP(T_ADDRERR) ! 374: ! 375: coprocerr: ! 376: TRAP(T_COPROCERR) ! 377: ! 378: fmterr: ! 379: TRAP(T_FMTERR) ! 380: ! 381: illinst: ! 382: TRAP(T_ILLINST) ! 383: ! 384: zerodiv: ! 385: TRAP(T_ZERODIV) ! 386: ! 387: chkinst: ! 388: TRAP(T_CHKINST) ! 389: ! 390: trapv: ! 391: TRAP(T_TRAPV) ! 392: ! 393: privvio: ! 394: TRAP(T_PRIVVIO) ! 395: ! 396: trace: ! 397: TRAP(T_TRACE) ! 398: ! 399: emu1010: ! 400: TRAP(T_EMU1010) ! 401: ! 402: emu1111: ! 403: TRAP(T_EMU1111) ! 404: ! 405: spurious: ! 406: TRAP(T_SPURIOUS) ! 407: ! 408: badtrap: ! 409: TRAP(T_M_BADTRAP) ! 410: ! 411: brkpt: ! 412: TRAP(T_BRKPT) ! 413: ! 414: floaterr: ! 415: TRAP(T_M_FLOATERR) ! 416: ! 417: errorvec: ! 418: TRAP(T_M_ERRORVEC) ! 419: ! 420: level2: ! 421: IOINTR(2) ! 422: ! 423: level3: ! 424: IOINTR(3) ! 425: ! 426: level4: ! 427: IOINTR(4) ! 428: ! 429: .data ! 430: .globl _ledcnt ! 431: ledpat: ! 432: .byte ~0x80 ! 433: .byte ~0x40 ! 434: .byte ~0x20 ! 435: .byte ~0x10 ! 436: .byte ~0x08 ! 437: .byte ~0x04 ! 438: .byte ~0x02 ! 439: .byte ~0x01 ! 440: .byte ~0x02 ! 441: .byte ~0x04 ! 442: .byte ~0x08 ! 443: .byte ~0x10 ! 444: .byte ~0x20 ! 445: .byte ~0x40 ! 446: endpat: ! 447: .even ! 448: ledptr: .long ledpat ! 449: flag5: .word 0 ! 450: flag7: .word 0 ! 451: _ledcnt: .word 50 | once per second min LED update rate ! 452: ledcnt: .word 0 ! 453: .text ! 454: ! 455: /* ! 456: * This code assumes that the real time clock interrupts 100 times ! 457: * a second and that we want to only call hardclock 50 times/sec ! 458: * We update the LEDs with new values so at least a user can tell ! 459: * that something it still running before calling hardclock(). ! 460: */ ! 461: level5: | default clock interrupt ! 462: tstb CLKADDR+CLK_INTRREG | read CLKADDR->clk_intrreg to clear ! 463: andb #~IR_ENA_CLK5,INTERREG | clear interrupt request ! 464: orb #IR_ENA_CLK5,INTERREG | and re-enable ! 465: tstb CLKADDR+CLK_INTRREG | clear interrupt register again, ! 466: | if we lost interrupt we will ! 467: | resync later anyway. ! 468: | for 100 hz operation, comment out from here ... ! 469: notw flag5 | toggle flag ! 470: jeq 0f | if result zero skip ahead ! 471: rte ! 472: 0: ! 473: | ... to here ! 474: moveml #0xC0E0,sp@- | save d0,d1,a0,a1,a2 ! 475: ! 476: movl sp,a2 | save copy of previous sp ! 477: cmpl #eintstack,sp | on interrupt stack? ! 478: jls 1f | yes, skip ! 479: lea eintstack,sp | no, switch to interrupt stack ! 480: 1: ! 481: ! 482: /* check for LED update */ ! 483: movl a2@(5*4+2),a1 | get saved pc ! 484: cmpl #idle,a1 | were we idle? ! 485: beq 0f | yes, do LED update ! 486: subqw #1,ledcnt ! 487: bge 2f | if positive skip LED update ! 488: 0: ! 489: movw _ledcnt,ledcnt | reset counter ! 490: movl ledptr,a0 | get pointer ! 491: movb a0@+,d0 | get next byte ! 492: cmpl #endpat,a0 | are we at the end? ! 493: bne 1f | if not, skip ! 494: lea ledpat,a0 | reset pointer ! 495: 1: ! 496: movl a0,ledptr | save pointer ! 497: movsb d0,DIAGREG | d0 to diagnostic LEDs ! 498: ! 499: 2: | call hardclock ! 500: movw a2@(5*4),d0 | get saved sr ! 501: movl d0,sp@- | push it as a long ! 502: movl a1,sp@- | push saved pc ! 503: jsr _hardclock | call UNIX routine ! 504: movl a2,sp | restore old sp ! 505: moveml sp@+,#0x0703 | restore all saved regs ! 506: jra rei_io | all done ! 507: ! 508: /* ! 509: * Level 7 interrupts can be caused by parity/ECC errors or the ! 510: * clock chip. The clock chip is tied to level 7 interrupts ! 511: * only if we are profiling. Because of the way nmi's work, ! 512: * we clear the any level 7 clock interrupts first before ! 513: * checking the memory error register. ! 514: */ ! 515: _level7: ! 516: #ifdef GPROF ! 517: tstb CLKADDR+CLK_INTRREG | read CLKADDR->clk_intrreg to clear ! 518: andb #~IR_ENA_CLK7,INTERREG | clear interrupt request ! 519: orb #IR_ENA_CLK7,INTERREG | and re-enable ! 520: #endif GPROF ! 521: ! 522: moveml #0xC0C0,sp@- | save C regs ! 523: movb MEMREG,d0 | read memory error register ! 524: andb #ER_INTR,d0 | a parity/ECC interrupt pending? ! 525: jeq 0f | if not, jmp ! 526: jsr _memerr | dump memory error info ! 527: /*MAYBE REACHED*/ | if we do return to here, then ! 528: jra 1f | we had a non-fatal memory problem ! 529: 0: ! 530: ! 531: #ifdef GPROF ! 532: | for 100 hz profiling, comment out from here ... ! 533: notw flag7 | toggle flag ! 534: jne 1f | if result non-zero return ! 535: | ... to here ! 536: jsr kprof | do the profiling ! 537: #else GPROF ! 538: pea 0f | push message printf ! 539: jsr _printf | print the message ! 540: addqw #4,sp | pop argument ! 541: .data ! 542: 0: .asciz "stray level 7 interrupt\012" ! 543: .even ! 544: .text ! 545: #endif GPROF ! 546: 1: ! 547: moveml sp@+,#0x0303 | restore regs ! 548: rte ! 549: ! 550: /* ! 551: * Called by trap #2 to do an instruction cache flush operation ! 552: */ ! 553: .globl flush ! 554: flush: ! 555: movl #CACHE_CLEAR+CACHE_ENABLE,d0 ! 556: movc d0,cacr | clear (and enable) the cache ! 557: rte ! 558: ! 559: .globl syscall, trap, rei ! 560: /* ! 561: * Special case for syscall. ! 562: * Everything in line because this is by far the most ! 563: * common interrupt. ! 564: */ ! 565: syscall: ! 566: subqw #2,sp | empty space ! 567: moveml #0xFFFF,sp@- | save all regs ! 568: movl usp,a0 | get usp ! 569: movl a0,sp@(R_SP) | save usp ! 570: movl #syserr,_u+U_LOFAULT | catch a fault if and when ! 571: movl a0@,d0 | get the syscall code ! 572: syscont: ! 573: clrl _u+U_LOFAULT | clear lofault ! 574: movl d0,sp@- | push syscall code ! 575: jsr _syscall | go to C routine ! 576: addqw #4,sp | pop arg ! 577: orw #SR_INTPRI,sr | need to test atomicly, rte will lower ! 578: bclr #AST_STEP_BIT-24,_u+PCB_P0LR | need to single step? ! 579: jne 4f ! 580: bclr #AST_SCHED_BIT-24,_u+PCB_P0LR | need to reschedule? ! 581: jeq 3f | no, get out ! 582: 4: bset #TRACE_AST_BIT-24,_u+PCB_P0LR | say that we're tracing for AST ! 583: jne 3f | if already doing it, skip ! 584: bset #SR_TRACE_BIT-8,sp@(R_SR) | set trace mode ! 585: jeq 3f | if wasn't set, continue ! 586: bset #TRACE_USER_BIT-24,_u+PCB_P0LR | save fact that trace was set ! 587: 3: movl sp@(R_SP),a0 | restore user SP ! 588: movl a0,usp ! 589: movl #CACHE_CLEAR+CACHE_ENABLE,d0 ! 590: movc d0,cacr | clear (and enable) the cache ! 591: 1: ! 592: moveml sp@,#0x7FFF | restore all but SP ! 593: addw #R_SR,sp | pop all saved regs ! 594: rte | and return! ! 595: ! 596: syserr: ! 597: movl #-1,d0 | set err code ! 598: jra syscont | back to mainline ! 599: ! 600: /* ! 601: * We reset the sfc and dfc to FC_MAP in case we came in from ! 602: * a trap while in the monitor since the monitor uses movs ! 603: * instructions after dorking w/ sfc and dfc during its operation. ! 604: */ ! 605: trap: ! 606: moveq #FC_MAP,d0 ! 607: movc d0,sfc ! 608: movc d0,dfc ! 609: jsr _trap | Enter C trap routine ! 610: addqw #4,sp | Pop trap type ! 611: ! 612: /* ! 613: * Return from interrupt or trap, check for AST's. ! 614: * d0 contains the size of info to pop (if any) ! 615: */ ! 616: rei: ! 617: btst #SR_SMODE_BIT-8,sp@(R_SR) | SR_SMODE ? ! 618: bne 1f | skip if system ! 619: orw #SR_INTPRI,sr | need to test atomicly, rte will lower ! 620: bclr #AST_STEP_BIT-24,_u+PCB_P0LR | need to single step? ! 621: jne 4f ! 622: bclr #AST_SCHED_BIT-24,_u+PCB_P0LR | need to reschedule? ! 623: jeq 3f | no, get out ! 624: 4: bset #TRACE_AST_BIT-24,_u+PCB_P0LR | say that we're tracing for AST ! 625: bne 3f | if already doing it, skip ! 626: bset #SR_TRACE_BIT-8,sp@(R_SR) | set trace mode ! 627: jeq 3f | if wasn't set, continue ! 628: bset #TRACE_USER_BIT-24,_u+PCB_P0LR | save fact that trace was set ! 629: 3: movl sp@(R_SP),a0 | restore user SP ! 630: movl a0,usp ! 631: movl #CACHE_CLEAR+CACHE_ENABLE,a0 ! 632: movc a0,cacr | clear (and enable) the cache ! 633: 1: ! 634: tstl d0 | any cleanup needed? ! 635: beq 2f | no, skip ! 636: movl sp,a0 | get current sp ! 637: addw d0,a0 | pop off d0 bytes of crud ! 638: clrw a0@(R_VOR) | dummy VOR ! 639: movl sp@(R_PC),a0@(R_PC) | move PC ! 640: movw sp@(R_SR),a0@(R_SR) | move SR ! 641: movl a0,sp@(R_SP) | stash new sp value ! 642: moveml sp@,#0xFFFF | restore all including SP ! 643: addw #R_SR,sp | pop all saved regs ! 644: rte | and return! ! 645: 2: ! 646: moveml sp@,#0x7FFF | restore all but SP ! 647: addw #R_SR,sp | pop all saved regs ! 648: rte | and return! ! 649: ! 650: /* ! 651: * Return from I/O interrupt, check for AST's. ! 652: */ ! 653: .globl rei_io ! 654: rei_iop: ! 655: moveml sp@+,#0x0707 | pop regs <a2,a1,a0,d2,d1,d0> ! 656: rei_io: ! 657: addql #1,_cnt+V_INTR | increment io interrupt count ! 658: rei_si: ! 659: btst #SR_SMODE_BIT-8,sp@ | SR_SMODE? (SR is atop stack) ! 660: jne 3f | skip if system ! 661: orw #SR_INTPRI,sr | need to test atomicly, rte will lower ! 662: bclr #AST_STEP_BIT-24,_u+PCB_P0LR | need to single step? ! 663: jne 4f ! 664: bclr #AST_SCHED_BIT-24,_u+PCB_P0LR | need to reschedule? ! 665: jeq 3f | no, get out ! 666: 4: bset #TRACE_AST_BIT-24,_u+PCB_P0LR | say that we're tracing for AST ! 667: jne 3f | if already doing it, skip ! 668: bset #SR_TRACE_BIT-8,sp@ | set trace mode in SR atop stack ! 669: jeq 3f | if wasn't set, continue ! 670: bset #TRACE_USER_BIT-24,_u+PCB_P0LR | save fact that trace was set ! 671: 3: ! 672: rte | and return! ! 673: ! 674: /* ! 675: * Handle software interrupts ! 676: * Just call C routine ! 677: */ ! 678: .globl softint ! 679: softint: ! 680: moveml #0xC0E0,sp@- | save regs we trash <d0,d1,a0,a1,a2> ! 681: movl sp,a2 | save copy of previous sp ! 682: cmpl #eintstack,sp | on interrupt stack? ! 683: jls 0f | yes, skip ! 684: lea eintstack,sp | no, switch to interrupt stack ! 685: 0: ! 686: bclr #IR_SOFT_INT1_BIT,INTERREG| clear interrupt request ! 687: jsr _softint | Call C ! 688: movl a2,sp | restore old sp ! 689: moveml sp@+,#0x0703 | restore saved regs <a2,a1,a0,d1,d0> ! 690: jra rei_si ! 691: ! 692: /* ! 693: * Turn on a software interrupt (H/W level 1). ! 694: */ ! 695: ENTRY(siron) ! 696: bset #IR_SOFT_INT1_BIT,INTERREG | trigger level 1 intr ! 697: rts ! 698: ! 699: /* ! 700: * return 1 if an interrupt is being serviced (on interrupt stack), ! 701: * otherwise return 0. ! 702: */ ! 703: ENTRY(intsvc) ! 704: clrl d0 | assume false ! 705: cmpl #eintstack,sp | on interrupt stack? ! 706: bhi 1f | no, skip ! 707: movl #1,d0 | return true ! 708: 1: ! 709: rts ! 710: ! 711: /* ! 712: * Enable and disable DVMA. ! 713: */ ! 714: ENTRY(enable_dvma) ! 715: 1: ! 716: orb #ENA_SDVMA,_enablereg | enable System DVMA ! 717: movb _enablereg,d0 | get it in a register ! 718: movsb d0,ENABLEREG | put enable register back ! 719: cmpb _enablereg,d0 | see if someone higher changed it ! 720: bne 1b | if so, try again ! 721: rts ! 722: ! 723: ENTRY(disable_dvma) ! 724: 1: ! 725: andb #~ENA_SDVMA,_enablereg | disable System DVMA ! 726: movb _enablereg,d0 | get it in a register ! 727: movsb d0,ENABLEREG | put enable register back ! 728: cmpb _enablereg,d0 | see if someone higher changed it ! 729: bne 1b | if so, try again ! 730: rts ! 731: ! 732: /* ! 733: * Transfer data to and from user space - ! 734: * Note that these routines can cause faults ! 735: * It is assumed that the kernel has nothing at ! 736: * less than KERNELBASE in the virtual address space. ! 737: */ ! 738: | Return length of user string _fustrlen(address) ! 739: ENTRY(fustrlen) ! 740: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 741: movl sp@(4),a0 | get address ! 742: movl #KERNELBASE-1,a1 ! 743: 1: ! 744: cmpl a1,a0 | check address range ! 745: jhi fsuerr | jmp if greater than ! 746: tstb a0@+ | is it 0 ! 747: jne 1b ! 748: movl a0,d0 ! 749: subl sp@(4),d0 | compute difference ! 750: clrl _u+U_LOFAULT | clear lofault ! 751: rts ! 752: ! 753: | Fetch user byte _fubyte(address) ! 754: ENTRY2(fubyte,fuibyte) ! 755: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 756: movl sp@(4),a0 | get address ! 757: cmpl #KERNELBASE-1,a0 | check address range ! 758: jhi fsuerr | jmp if greater than ! 759: movb a0@,d0 | get the byte ! 760: andl #0xFF,d0 ! 761: clrl _u+U_LOFAULT | clear lofault ! 762: rts ! 763: ! 764: ! 765: | Fetch user (short) word: _fusword(address) ! 766: ENTRY(fusword) ! 767: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 768: movl sp@(4),a0 | get address ! 769: cmpl #KERNELBASE-2,a0 | check address range ! 770: jhi fsuerr | jmp if greater than ! 771: movw a0@,d0 | get the word ! 772: andl #0xFFFF,d0 ! 773: clrl _u+U_LOFAULT | clear lofault ! 774: rts ! 775: ! 776: | Fetch user (long) word: _fuword(address) ! 777: ENTRY2(fuword,fuiword) ! 778: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 779: movl sp@(4),a0 | get address ! 780: cmpl #KERNELBASE-4,a0 | check address range ! 781: jhi fsuerr | jmp if greater than ! 782: movl a0@,d0 | get the long word ! 783: clrl _u+U_LOFAULT | clear lofault ! 784: rts ! 785: ! 786: | Set user byte: _subyte(address, value) ! 787: ENTRY2(subyte,suibyte) ! 788: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 789: movl sp@(4),a0 | get address ! 790: cmpl #KERNELBASE-1,a0 | check address range ! 791: jhi fsuerr | jmp if greater than ! 792: movb sp@(8+3),a0@ | set the byte ! 793: clrl d0 | indicate success ! 794: clrl _u+U_LOFAULT | clear lofault ! 795: rts ! 796: ! 797: | Set user short word: _susword(address, value) ! 798: ENTRY(susword) ! 799: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 800: movl sp@(4),a0 | get address ! 801: cmpl #KERNELBASE-2,a0 | check address range ! 802: jhi fsuerr | jmp if greater than ! 803: movw sp@(8+2),a0@ | set the word ! 804: clrl d0 | indicate success ! 805: clrl _u+U_LOFAULT | clear lofault ! 806: rts ! 807: ! 808: | Set user (long) word: _suword(address, value) ! 809: ENTRY2(suword,suiword) ! 810: movl #fsuerr,_u+U_LOFAULT | catch a fault if and when ! 811: movl sp@(4),a0 | get address ! 812: cmpl #KERNELBASE-4,a0 | check address range ! 813: jhi fsuerr | jmp if greater than ! 814: movl sp@(8+0),a0@ | set the long word ! 815: clrl d0 | indicate success ! 816: clrl _u+U_LOFAULT | clear lofault ! 817: rts ! 818: ! 819: fsuerr: ! 820: movl #-1,d0 | return error ! 821: clrl _u+U_LOFAULT | clear lofault ! 822: rts ! 823: ! 824: /* ! 825: * copyout() - except for _u+U_LOFAULT and address ! 826: * checking this is just bcopy(). ! 827: */ ! 828: ENTRY(copyout) ! 829: movl #cpctxerr,_u+U_LOFAULT | catch faults ! 830: movl sp@(4),a0 ! 831: movl sp@(8),a1 ! 832: movl sp@(12),d0 ! 833: jle 7f | leave if ridiculous count ! 834: copyoutcheck: ! 835: movl a1,d1 | get starting address ! 836: cmpl #KERNELBASE,d1 | check starting address ! 837: jpl cpctxerr | jmp on error ! 838: addl d0,d1 | compute ending address ! 839: cmpl #KERNELBASE,d1 | check ending address ! 840: jhi cpctxerr | jmp on error ! 841: cmpl d1,a1 | check for wrap around ! 842: jhi cpctxerr | jmp on error ! 843: /* If from address is odd, move one byte to make it even */ ! 844: movl a0,d1 ! 845: btst #0,d1 ! 846: jeq 1f | even, skip ! 847: movb a0@+,a1@+ | move the byte ! 848: subql #1,d0 | decrement count ! 849: /* Now if to address is odd, we have to do byte-by-byte moves */ ! 850: 1: movl a1,d1 ! 851: btst #0,d1 ! 852: jne 2f | if odd go do bytes ! 853: /* Now both addresses are even and we can do long moves */ ! 854: rorl #2,d0 | get count as longs ! 855: jra 5f | enter loop at bottom ! 856: 4: movl a0@+,a1@+ | move a long ! 857: 5: dbra d0,4b | do until --longcount < 0 ! 858: roll #2,d0 ! 859: andl #3,d0 | count %= sizeof (long) ! 860: jra 2f ! 861: /* ! 862: * Here for the last 3 bytes or if we have to do byte-by-byte moves ! 863: * because the pointers were relatively odd ! 864: */ ! 865: 3: movb a0@+,a1@+ | move a byte ! 866: 2: dbra d0,3b | until --count < 0 ! 867: 7: clrl d0 | indicate success ! 868: clrl _u+U_LOFAULT ! 869: rts | and return ! 870: ! 871: /* ! 872: * copyin() - except for _u+U_LOFAULT and address ! 873: * checking this is just bcopy(). ! 874: */ ! 875: ENTRY(copyin) ! 876: movl #cpctxerr,_u+U_LOFAULT | catch faults ! 877: movl sp@(4),a0 ! 878: movl sp@(8),a1 ! 879: movl sp@(12),d0 ! 880: jle 7f | leave if ridiculous count ! 881: copyincheck: ! 882: movl a0,d1 | get starting address ! 883: cmpl #KERNELBASE,d1 | check starting address ! 884: jpl cpctxerr | jmp on error ! 885: addl d0,d1 | compute ending address ! 886: cmpl #KERNELBASE,d1 | check ending address ! 887: jhi cpctxerr | jmp on error ! 888: cmpl d1,a0 | check for wrap around ! 889: jhi cpctxerr | jmp on error ! 890: /* If from address is odd, move one byte to make it even */ ! 891: movl a0,d1 ! 892: btst #0,d1 ! 893: jeq 1f | even, skip ! 894: movb a0@+,a1@+ | move the byte ! 895: subql #1,d0 | decrement count ! 896: /* Now if to address is odd, we have to do byte-by-byte moves */ ! 897: 1: movl a1,d1 ! 898: btst #0,d1 ! 899: jne 2f | if odd go do bytes ! 900: /* Now both addresses are even and we can do long moves */ ! 901: rorl #2,d0 | get count as longs ! 902: jra 5f | enter loop at bottom ! 903: 4: movl a0@+,a1@+ | move a long ! 904: 5: dbra d0,4b | do until --longcount < 0 ! 905: roll #2,d0 ! 906: andl #3,d0 | count %= sizeof (long) ! 907: jra 2f ! 908: /* ! 909: * Here for the last 3 bytes or if we have to do byte-by-byte moves ! 910: * because the pointers were relatively odd ! 911: */ ! 912: 3: movb a0@+,a1@+ | move a byte ! 913: 2: dbra d0,3b | until --count < 0 ! 914: 7: clrl d0 | indicate success ! 915: clrl _u+U_LOFAULT ! 916: rts | and return ! 917: ! 918: cpctxerr: ! 919: movl #EFAULT,d0 | return error ! 920: clrl _u+U_LOFAULT | clear lofault ! 921: rts ! 922: ! 923: /* ! 924: * fetch user longwords -- used by syscall -- faster than copyin ! 925: * Doesn't worry about alignment of transfer, let the 68020 worry ! 926: * about that - we won't be doing more than 8 long words anyways. ! 927: * Use copyin to do more careful checking if we are real close. ! 928: * fulwds(uadd, sadd, nlwds) ! 929: */ ! 930: ENTRY(fulwds) ! 931: movl #cpctxerr,_u+U_LOFAULT | catch a fault if and when ! 932: movl sp@(4),a0 | user address ! 933: movl sp@(8),a1 | system address ! 934: movl sp@(12),d0 | number of words ! 935: cmpl #KERNELBASE-8*4,a0 | check starting address ! 936: jls 1f | enter loop at bottom if ok ! 937: lsll #2,d0 | convert to byte count ! 938: jra copyincheck | let copyin code handle ! 939: 2: movl a0@+,a1@+ | get longword ! 940: 1: dbra d0,2b | loop on count ! 941: clrl d0 | indicate success ! 942: clrl _u+U_LOFAULT | clear lofault ! 943: rts ! 944: ! 945: /* ! 946: * Get/Set vector base register ! 947: */ ! 948: ENTRY(getvbr) ! 949: movc vbr,d0 ! 950: rts ! 951: ! 952: ENTRY(setvbr) ! 953: movl sp@(4),d0 ! 954: movc d0,vbr ! 955: rts ! 956: ! 957: /* ! 958: * Enter the monitor -- called for console abort ! 959: */ ! 960: ENTRY(montrap) ! 961: jsr _startnmi | enable monitor nmi routine ! 962: movl sp@(4),a0 | address to trap to ! 963: clrw sp@- | dummy VOR ! 964: pea 0f | return address ! 965: movw sr,sp@- | current sr ! 966: jra a0@ | trap to monitor ! 967: 0: ! 968: jsr _stopnmi | disable monitor nmi routine ! 969: rts ! 970: ! 971: /* ! 972: * Read the ID prom. This is mapped from IDPROMBASE for IDPROMSIZE ! 973: * bytes in the FC_MAP address space for byte access only. Assumes ! 974: * that the sfc has already been set to FC_MAP. ! 975: */ ! 976: ENTRY(getidprom) ! 977: movl sp@(4),a0 | address to copy bytes to ! 978: lea IDPROMBASE,a1 | select id prom ! 979: movl #(IDPROMSIZE-1),d1 | byte loop counter ! 980: 0: movsb a1@+,d0 | get a byte ! 981: movb d0,a0@+ | save it ! 982: dbra d1,0b | and loop ! 983: rts ! 984: ! 985: /* ! 986: * Enable and disable video. ! 987: */ ! 988: ENTRY(setvideoenable) ! 989: 1: ! 990: tstl sp@(4) | is bit on or off ! 991: jeq 2f ! 992: orb #ENA_VIDEO,_enablereg | enable video ! 993: jra 3f ! 994: 2: ! 995: andb #~ENA_VIDEO,_enablereg | disable video ! 996: 3: ! 997: movb _enablereg,d0 | get it in a register ! 998: movsb d0,ENABLEREG | put enable register back ! 999: cmpb _enablereg,d0 | see if someone higher changed it ! 1000: bne 1b | if so, try again ! 1001: rts ! 1002: ! 1003: /* ! 1004: * Enable and disable video Copy. ! 1005: */ ! 1006: ENTRY(setcopyenable) ! 1007: 1: ! 1008: tstl sp@(4) | is bit on or off ! 1009: jeq 2f ! 1010: orb #ENA_COPY,_enablereg | enable video copy ! 1011: jra 3f ! 1012: 2: ! 1013: andb #~ENA_COPY,_enablereg | disable copy ! 1014: 3: ! 1015: movb _enablereg,d0 | get it in a register ! 1016: movsb d0,ENABLEREG | put enable register back ! 1017: cmpb _enablereg,d0 | see if someone higher changed it ! 1018: bne 1b | if so, try again ! 1019: rts ! 1020: ! 1021: /* ! 1022: * Enable and disable video interrupt. ! 1023: */ ! 1024: ENTRY(setintrenable) ! 1025: tstl sp@(4) | is bit on or off ! 1026: jeq 1f ! 1027: orb #IR_ENA_VID4,INTERREG | enable video interrupt ! 1028: rts ! 1029: 1: ! 1030: andb #~IR_ENA_VID4,INTERREG | disable ! 1031: rts ! 1032: ! 1033: /* ! 1034: * Read the bus error register ! 1035: */ ! 1036: ENTRY(getbuserr) ! 1037: clrl d0 ! 1038: movsb BUSERRREG,d0 | get the buserr register ! 1039: rts ! 1040: ! 1041: /* ! 1042: * Set the fpp registers to the u area values ! 1043: */ ! 1044: ENTRY(setfppregs) ! 1045: tstw _fppstate | is fpp present and enabled? ! 1046: jle 1f | branch if not ! 1047: fmovem _u+U_FPS_REGS,fp0-fp7 | set fp data registers ! 1048: fmovem _u+U_FPS_CTRL,fpc/fps/fpi | set control registers ! 1049: 1: ! 1050: rts ! 1051: ! 1052: /* ! 1053: * Define some variables used by post-modem debuggers ! 1054: * to help them work on kernels with changing structures. ! 1055: */ ! 1056: .globl UPAGES_DEBUG, KERNELBASE_DEBUG, VADDR_MASK_DEBUG ! 1057: .globl PGSHIFT_DEBUG, SLOAD_DEBUG ! 1058: ! 1059: UPAGES_DEBUG = UPAGES ! 1060: KERNELBASE_DEBUG = KERNELBASE ! 1061: VADDR_MASK_DEBUG = 0x0fffffff ! 1062: PGSHIFT_DEBUG = PGSHIFT ! 1063: SLOAD_DEBUG = SLOAD
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.