|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)locore.s 7.6 (Berkeley) 5/1/89 ! 7: * 9/8/89 (bostic) -- added delay in wbadaddr from 7.10 ! 8: * This had already been patched, but I have no idea by whom; the ! 9: * following lines had been added: ! 10: * ! 11: * #if NVX > 0 ! 12: * ADDMAP( NVX * 16384/NBPG ) ! 13: * #endif ! 14: */ ! 15: ! 16: #include "../tahoe/mtpr.h" ! 17: #include "../tahoe/trap.h" ! 18: #include "../tahoe/psl.h" ! 19: #include "../tahoe/pte.h" ! 20: #include "../tahoe/cp.h" ! 21: #include "../tahoe/mem.h" ! 22: #include "../tahoe/SYS.h" ! 23: ! 24: #include "../tahoemath/fp.h" ! 25: ! 26: #include "errno.h" ! 27: #include "syscall.h" ! 28: #include "cmap.h" ! 29: ! 30: .set HIGH,0x1f # mask for total disable ! 31: .set NISP,3 # number of interrupt stack pages ! 32: .set SYSTEM,0xC0000000 # virtual address of system start ! 33: .set PPAGES,0x100000 # possible pages in P0,P1, etc. ! 34: ! 35: /* ACBL for non-negative '_add' */ ! 36: #define ACBL(_limit,_add,_index,_displ) \ ! 37: addl2 _add,_index; \ ! 38: cmpl _index,_limit; \ ! 39: bleq _displ ! 40: ! 41: /* _ACBL for negative '_add' */ ! 42: #define _ACBL(_limit,_add,_index,_displ) \ ! 43: addl2 _add,_index; \ ! 44: cmpl _index,_limit; \ ! 45: bgeq _displ ! 46: ! 47: #define MOVC3(_srcaddr,_dstaddr,_len) \ ! 48: movl _srcaddr,r0; \ ! 49: movl _dstaddr,r1; \ ! 50: movl _len,r2; \ ! 51: movblk ! 52: ! 53: /* keep address of psl if coming from user mode */ ! 54: #define CHECK_SFE(_delta) \ ! 55: bitl $PSL_CURMOD,_delta(sp); \ ! 56: jeql 1f; \ ! 57: moval _delta(sp),_user_psl; \ ! 58: 1: ! 59: ! 60: /* ! 61: * User structure is UPAGES at top of user space. ! 62: */ ! 63: .globl _u ! 64: .set _u,SYSTEM - UPAGES*NBPG ! 65: ! 66: /* ! 67: * Restart stack. Used on power recovery or panic. ! 68: * Takes a core-dump and then halts. ! 69: */ ! 70: .globl _rsstk ! 71: .globl pwfl_stk ! 72: _rsstk: ! 73: .space 1024-8 ! 74: pwfl_stk: ! 75: .space 4 ! 76: dumpflag: ! 77: .space 4 ! 78: ! 79: .globl _intstack ! 80: _intstack: ! 81: .space NISP*NBPG ! 82: eintstack: ! 83: ! 84: /* ! 85: * Power failure storage block and ! 86: * macros for saving and restoring. ! 87: */ ! 88: #define POWERFAIL(id,longs) \ ! 89: .globl pwfl_/**/id \ ! 90: pwfl_/**/id: .space longs*4 ! 91: .data ! 92: POWERFAIL(r0, 14) # r0-r13 ! 93: POWERFAIL(sp, 1) # r14 ! 94: POWERFAIL(SCBB, 1) # system control block base ! 95: POWERFAIL(SBR, 1) # system pte base ! 96: POWERFAIL(SLR, 1) # system pte length ! 97: POWERFAIL(P0BR, 1) # p0 pte base ! 98: POWERFAIL(P0LR, 1) # p0 pte length ! 99: POWERFAIL(P1BR, 1) # p1 pte base ! 100: POWERFAIL(P1LR, 1) # p1 pte length ! 101: POWERFAIL(P2BR, 1) # p2 pte base ! 102: POWERFAIL(P2LR, 1) # p2 pte length ! 103: POWERFAIL(IPL, 1) # interrupt priority level ! 104: POWERFAIL(DCK, 1) # data cache key ! 105: POWERFAIL(CCK, 1) # code cache key ! 106: POWERFAIL(PCBB, 1) # process control block base ! 107: POWERFAIL(ISP, 1) # interrupt stack pointer ! 108: POWERFAIL(KSP, 1) # kernel mode stack pointer ! 109: POWERFAIL(USP, 1) # user mode stack pointer ! 110: POWERFAIL(MME, 1) # memory management enable ! 111: POWERFAIL(PSL, 1) # processor status longword ! 112: ! 113: /* ! 114: * Save current state in power fail storage block. ! 115: */ ! 116: #define SAVEpwfl() \ ! 117: movpsl pwfl_PSL # Keeps all flags, etc. \ ! 118: storer $0x3fff,pwfl_r0 # Saves r0-r13 \ ! 119: moval 0(sp),pwfl_sp # Saves sp (=r14) \ ! 120: mfpr $SBR,pwfl_SBR # Save all re_loadable registers \ ! 121: mfpr $SLR,pwfl_SLR \ ! 122: mfpr $P0BR,pwfl_P0BR \ ! 123: mfpr $P0LR,pwfl_P0LR \ ! 124: mfpr $P1BR,pwfl_P1BR \ ! 125: mfpr $P1LR,pwfl_P1LR \ ! 126: mfpr $P2BR,pwfl_P2BR \ ! 127: mfpr $P2LR,pwfl_P2LR \ ! 128: mfpr $IPL,pwfl_IPL \ ! 129: mfpr $MME,pwfl_MME \ ! 130: mfpr $DCK,pwfl_DCK \ ! 131: mfpr $CCK,pwfl_CCK \ ! 132: mfpr $PCBB,pwfl_PCBB \ ! 133: mfpr $ISP,pwfl_ISP \ ! 134: mfpr $SCBB,pwfl_SCBB \ ! 135: mfpr $KSP,pwfl_KSP \ ! 136: mfpr $USP,pwfl_USP ! 137: ! 138: /* ! 139: * Restore state saved in power fail block and ! 140: * jmp to location specified after (possibly) ! 141: * enabling memory management. ! 142: */ ! 143: #define RESTOREpwfl(loc) \ ! 144: loadr $0x3fff,pwfl_r0 # Restore r0-r13 \ ! 145: movl pwfl_sp,sp # Restore sp (=r14) \ ! 146: mtpr pwfl_SCBB,$SCBB \ ! 147: mtpr pwfl_SBR,$SBR # Restore all re_loadable registers \ ! 148: mtpr pwfl_SLR,$SLR \ ! 149: mtpr pwfl_P0BR,$P0BR \ ! 150: mtpr pwfl_P0LR,$P0LR \ ! 151: mtpr pwfl_P1BR,$P1BR \ ! 152: mtpr pwfl_P1LR,$P1LR \ ! 153: mtpr pwfl_P2BR,$P2BR \ ! 154: mtpr pwfl_P2LR,$P2LR \ ! 155: mtpr pwfl_IPL,$IPL \ ! 156: mtpr pwfl_DCK,$DCK \ ! 157: mtpr pwfl_CCK,$CCK \ ! 158: mtpr pwfl_PCBB,$PCBB \ ! 159: mtpr pwfl_ISP,$ISP \ ! 160: mtpr pwfl_KSP,$KSP \ ! 161: mtpr pwfl_USP,$USP \ ! 162: \ ! 163: bicpsw $0xff # Restore PSW. \ ! 164: bispsw pwfl_PSL+2 # Set original bits back (just in case..) \ ! 165: # now go to mapped mode \ ! 166: # Have to change PC to system addresses \ ! 167: mtpr $1,$PACC # Thoroughly clean up caches. \ ! 168: mtpr $1,$PADC \ ! 169: mtpr $1,$TBIA \ ! 170: mtpr pwfl_MME,$MME # Restore MME. Last thing to be done. \ ! 171: jmp loc ! 172: ! 173: /* ! 174: * Do a dump. ! 175: * Called by auto-restart. ! 176: * May be called manually. ! 177: */ ! 178: .align 2 ! 179: .text ! 180: .globl _Xdoadump ! 181: .globl _doadump ! 182: _Xdoadump: # CP comes here after power fail ! 183: RESTOREpwfl(*0f) # restore state ! 184: _doadump: ! 185: .word 0 ! 186: 0: mtpr $HIGH,$IPL ! 187: #define _rsstkmap _Sysmap+12 # powerfail storage, scb, rsstk, int stack ! 188: tstl dumpflag # dump only once! ! 189: bneq 1f ! 190: andl2 $~PG_PROT,_rsstkmap ! 191: orl2 $PG_KW,_rsstkmap # Make dump stack r/w ! 192: mtpr $0,$TBIA ! 193: movl $1,dumpflag ! 194: movab dumpflag,sp ! 195: callf $4,_dumpsys ! 196: 1: ! 197: halt ! 198: ! 199: /* ! 200: * Interrupt vector routines ! 201: */ ! 202: .globl _waittime ! 203: #define SCBVEC(name) \ ! 204: .align 2; \ ! 205: .globl _X/**/name; \ ! 206: _X/**/name ! 207: #define PANIC(msg) \ ! 208: clrl _waittime; pushab 1f; callf $8,_panic; 1: .asciz msg ! 209: #define PRINTF(n,msg) \ ! 210: pushab 1f; callf $(n+2)*4,_printf; MSG(msg) ! 211: #define MSG(msg) .data; 1: .asciz msg; .text ! 212: /* ! 213: * r0-r5 are saved across all faults and interrupts. ! 214: * Routines below and those hidden in vbglue.s (device ! 215: * interrupts) invoke the PUSHR/POPR macros to execute ! 216: * this. Also, certain stack frame offset calculations ! 217: * use this, using the REGSPC definition (and FPSPC defined below). ! 218: */ ! 219: #define REGSPC 6*4 ! 220: #define PUSHR movab -REGSPC(sp),sp; storer $0x3f,(sp) ! 221: #define POPR loadr $0x3f,(sp); movab REGSPC(sp),sp ! 222: ! 223: /* ! 224: * Floating point state is saved across faults and ! 225: * interrupts. The state occupies 4 longwords on ! 226: * the stack: ! 227: * precision indicator (single = 0/double = 1) ! 228: * double representation of accumulator ! 229: * save accumulator status flag (pcb_savacc) ! 230: */ ! 231: #define FPSPC (4*4) ! 232: ! 233: #define SAVE_FPSTAT(_delta) \ ! 234: bitl $PSL_DBL,_delta(sp); \ ! 235: beql 1f; \ ! 236: pushl $1; \ ! 237: pushd; \ ! 238: jmp 2f; \ ! 239: 1: pushl $0; \ ! 240: pushl $0; \ ! 241: stf -(sp); \ ! 242: 2: tstl _u+PCB_SAVACC; \ ! 243: bneq 3f; \ ! 244: moval 0(sp),_u+PCB_SAVACC; \ ! 245: orl2 $2,8(sp);\ ! 246: 3: pushl $0; ! 247: ! 248: #define REST_FPSTAT \ ! 249: tstl (sp)+; \ ! 250: bitl $2,8(sp);\ ! 251: beql 1f;\ ! 252: movl $0,_u+PCB_SAVACC; \ ! 253: 1: bitl $1,8(sp); \ ! 254: beql 2f; \ ! 255: ldd (sp); \ ! 256: jmp 3f; \ ! 257: 2: ldf (sp); \ ! 258: 3: moval 12(sp),sp; ! 259: ! 260: #define REST_ACC \ ! 261: tstl _u+PCB_SAVACC; \ ! 262: beql 2f; \ ! 263: movl _u+PCB_SAVACC,r1; \ ! 264: andl3 $(EXPMASK|SIGNBIT),(r1),-(sp); \ ! 265: cmpl $0x80000000,(sp)+; \ ! 266: bneq 3f; \ ! 267: clrl (r1); \ ! 268: 3: bitl $1,8(r1); \ ! 269: beql 1f; \ ! 270: ldd (r1); \ ! 271: jmp 2f; \ ! 272: 1: ldf (r1); \ ! 273: 2: ; ! 274: ! 275: .data ! 276: nofault: .space 4 # bus error non-local goto label ! 277: ! 278: .text ! 279: SCBVEC(buserr): ! 280: CHECK_SFE(12) ! 281: SAVE_FPSTAT(12) ! 282: incl _intrcnt+I_BUSERR # keep stats... ! 283: pushl r0 # must save ! 284: andl3 24(sp),$ERRCD,r0 # grab pushed MER value ! 285: cmpl r0,$APE # address parity error? ! 286: jneq 1f ! 287: halt ! 288: 1: cmpl r0,$VBE # versabus error? ! 289: jneq 2f ! 290: halt ! 291: 2: ! 292: movl (sp)+,r0 # restore r0 and... ! 293: bitl $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode? ! 294: jeql 3f # yes, then shift stack up for trap... ! 295: movl 12(sp),16(sp) # sorry, no space for which-buss... ! 296: movl 8(sp),12(sp) ! 297: movl 4(sp),8(sp) ! 298: movl 0(sp),4(sp) ! 299: movl $T_BUSERR,0(sp) # push trap type code and... ! 300: jbr alltraps # ...merge with all other traps ! 301: 3: # kernel mode, check to see if... ! 302: tstl nofault # ...doing peek/poke? ! 303: jeql 4f # nofault set? if so, jump to it... ! 304: movl nofault,4*4+2*4(sp) # ...setup for non-local goto ! 305: clrl nofault ! 306: jbr 5f ! 307: 4: ! 308: PUSHR ! 309: pushab 4*4+REGSPC(sp) # address of bus error parameters ! 310: callf $8,_buserror ! 311: POPR ! 312: 5: ! 313: REST_FPSTAT ! 314: movab 8(sp),sp # remove bus error parameters ! 315: rei ! 316: ! 317: SCBVEC(powfail): # We should be on interrupt stack now. ! 318: SAVEpwfl() # save machine state ! 319: moval _Xdoadump-SYSTEM,_scb+SCB_DOADUMP ! 320: halt ! 321: ! 322: SCBVEC(stray): ! 323: incl _cnt+V_INTR # add to statistics ! 324: rei ! 325: ! 326: #include "../net/netisr.h" ! 327: .globl _netisr ! 328: SCBVEC(netintr): ! 329: CHECK_SFE(4) ! 330: SAVE_FPSTAT(4); PUSHR ! 331: #include "imp.h" ! 332: #if NIMP > 0 ! 333: bbc $NETISR_IMP,_netisr,1f; ! 334: andl2 $~(1<<NETISR_IMP),_netisr ! 335: callf $4,_impintr; ! 336: 1: ! 337: #endif ! 338: #ifdef INET ! 339: bbc $NETISR_IP,_netisr,1f ! 340: andl2 $~(1<<NETISR_IP),_netisr ! 341: callf $4,_ipintr ! 342: 1: ! 343: #endif ! 344: #ifdef NS ! 345: bbc $NETISR_NS,_netisr,1f ! 346: andl2 $~(1<<NETISR_NS),_netisr ! 347: callf $4,_nsintr ! 348: 1: ! 349: #endif ! 350: bbc $NETISR_RAW,_netisr,1f ! 351: andl2 $~(1<<NETISR_RAW),_netisr ! 352: callf $4,_rawintr ! 353: 1: ! 354: incl _cnt+V_SOFT ! 355: POPR; REST_FPSTAT ! 356: rei ! 357: ! 358: SCBVEC(cnrint): ! 359: CHECK_SFE(4) ! 360: SAVE_FPSTAT(4); PUSHR; ! 361: pushl $CPCONS; callf $8,_cnrint; ! 362: incl _intrcnt+I_CNR ! 363: incl _cnt+V_INTR ! 364: POPR; REST_FPSTAT; ! 365: rei ! 366: SCBVEC(cnxint): ! 367: CHECK_SFE(4) ! 368: SAVE_FPSTAT(4); PUSHR; ! 369: pushl $CPCONS; callf $8,_cnxint; ! 370: incl _intrcnt+I_CNX ! 371: incl _cnt+V_INTR ! 372: POPR; REST_FPSTAT; ! 373: rei ! 374: SCBVEC(rmtrint): ! 375: CHECK_SFE(4) ! 376: SAVE_FPSTAT(4); PUSHR; ! 377: pushl $CPREMOT; callf $8,_cnrint; ! 378: incl _intrcnt+I_RMTR ! 379: incl _cnt+V_INTR ! 380: POPR; REST_FPSTAT; ! 381: rei ! 382: SCBVEC(rmtxint): ! 383: CHECK_SFE(4) ! 384: SAVE_FPSTAT(4); PUSHR; ! 385: pushl $CPREMOT; callf $8,_cnxint; ! 386: incl _intrcnt+I_RMTX ! 387: incl _cnt+V_INTR ! 388: POPR; REST_FPSTAT; ! 389: rei ! 390: ! 391: #define PUSHPCPSL pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp); ! 392: ! 393: SCBVEC(hardclock): ! 394: tstl _clk_enable ! 395: bneq 1f ! 396: rei ! 397: 1: ! 398: CHECK_SFE(4) ! 399: SAVE_FPSTAT(4); PUSHR ! 400: PUSHPCPSL # push pc and psl ! 401: callf $12,_hardclock # hardclock(pc,psl) ! 402: incl _intrcnt+I_CLOCK ! 403: incl _cnt+V_INTR ## temp so not to break vmstat -= HZ ! 404: POPR; REST_FPSTAT ! 405: rei ! 406: SCBVEC(softclock): ! 407: CHECK_SFE(4) ! 408: SAVE_FPSTAT(4); PUSHR; ! 409: PUSHPCPSL # push pc and psl ! 410: callf $12,_softclock # softclock(pc,psl) ! 411: incl _cnt+V_SOFT ! 412: POPR; REST_FPSTAT ! 413: rei ! 414: ! 415: /* ! 416: * Stray VERSAbus interrupt catch routines ! 417: */ ! 418: .data ! 419: #define PJ .align 2; callf $4,_Xvstray ! 420: .globl _catcher ! 421: _catcher: ! 422: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 423: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 424: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 425: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 426: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 427: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 428: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 429: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 430: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 431: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 432: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 433: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ ! 434: ! 435: .align 2 ! 436: .globl _cold ! 437: _cold: .long 0x3 ! 438: ! 439: .text ! 440: SCBVEC(vstray): ! 441: .word 0 ! 442: bbc $0,_cold,2f # system running? ! 443: bbc $1,_cold,1f # doing autoconfig? ! 444: jbr 3f # random interrupt, ignore ! 445: 1: ! 446: mfpr $IPL,r12 # ...setup br and cvec ! 447: subl3 $_catcher+7,-8(fp),r11; shar $3,r11,r11 ! 448: addl2 $SCB_DEVBASE,r11 ! 449: jbr 3f ! 450: 2: ! 451: PUSHR ! 452: subl3 $_catcher+7,-8(fp),r0; shar $3,r0,r0 ! 453: addl3 $SCB_DEVBASE,r0,-(sp); ! 454: mfpr $IPL,-(sp) ! 455: PRINTF(2, "stray intr ipl %x vec %x\n") ! 456: POPR ! 457: 3: moval 0f,-8(fp); ret # pop callf frame... ! 458: 0: rei # ...and return ! 459: ! 460: /* ! 461: * Trap and fault vector routines ! 462: */ ! 463: #define TRAP(a) pushl $T_/**/a; jbr alltraps ! 464: ! 465: /* ! 466: * Ast delivery (profiling and/or reschedule) ! 467: */ ! 468: ! 469: SCBVEC(kspnotval): ! 470: CHECK_SFE(4) ! 471: pushl $0; ! 472: SAVE_FPSTAT(8) ! 473: TRAP(KSPNOTVAL) ! 474: SCBVEC(privinflt): ! 475: CHECK_SFE(4) ! 476: pushl $0; ! 477: SAVE_FPSTAT(8) ! 478: TRAP(PRIVINFLT) ! 479: SCBVEC(resopflt): ! 480: CHECK_SFE(4) ! 481: pushl $0; ! 482: SAVE_FPSTAT(8) ! 483: TRAP(RESOPFLT) ! 484: SCBVEC(resadflt): ! 485: CHECK_SFE(4) ! 486: pushl $0; ! 487: SAVE_FPSTAT(8) ! 488: TRAP(RESADFLT) ! 489: SCBVEC(bptflt): ! 490: CHECK_SFE(4) ! 491: pushl $0; ! 492: SAVE_FPSTAT(8) ! 493: TRAP(BPTFLT) ! 494: SCBVEC(kdbintr): ! 495: CHECK_SFE(4); ! 496: pushl $0; ! 497: SAVE_FPSTAT(8); ! 498: TRAP(KDBTRAP); ! 499: SCBVEC(tracep): ! 500: CHECK_SFE(4) ! 501: pushl $0; ! 502: SAVE_FPSTAT(8) ! 503: TRAP(TRCTRAP) ! 504: SCBVEC(alignflt): ! 505: #ifdef ALIGN ! 506: bitl $PSL_CURMOD,4(sp) ! 507: jeql align_excp # Can't emulate for kernel mode ! ! 508: jbr non_aligned # Only emulated for user mode. ! 509: align_excp: ! 510: #else ! 511: CHECK_SFE(4) ! 512: #endif ! 513: pushl $0; ! 514: SAVE_FPSTAT(8) ! 515: TRAP(ALIGNFLT) ! 516: SCBVEC(arithtrap): ! 517: CHECK_SFE(8) ! 518: SAVE_FPSTAT(8) ! 519: TRAP(ARITHTRAP) ! 520: ! 521: SCBVEC(protflt): ! 522: CHECK_SFE(12) ! 523: bitl $1,(sp)+ ! 524: jneq segflt ! 525: SAVE_FPSTAT(8) ! 526: TRAP(PROTFLT) ! 527: segflt: ! 528: SAVE_FPSTAT(8) ! 529: TRAP(SEGFLT) ! 530: ! 531: SCBVEC(fpm): # Floating Point Emulation ! 532: #ifdef FPE ! 533: CHECK_SFE(16) ! 534: SAVE_FPSTAT(16) ! 535: incl _cnt+V_FPE # count emulation traps ! 536: callf $4,_fpemulate ! 537: REST_FPSTAT ! 538: #endif ! 539: moval 8(sp),sp # Pop operand ! 540: tstl (sp) # Stack= PSL, PC, return_code ! 541: jneq _Xarithtrap # If not OK, emulate F.P. exception ! 542: movab 4(sp),sp # Else remove return_code and ! 543: rei ! 544: ! 545: SCBVEC(sfexcep): ! 546: CHECK_SFE(4) ! 547: pushl $0 ! 548: SAVE_FPSTAT(8) ! 549: TRAP(ASTFLT) ! 550: ! 551: SCBVEC(transflt): ! 552: CHECK_SFE(12) ! 553: bitl $2,(sp)+ ! 554: bneq tableflt ! 555: pageflt: ! 556: SAVE_FPSTAT(8) ! 557: TRAP(PAGEFLT) ! 558: tableflt: ! 559: SAVE_FPSTAT(8) ! 560: TRAP(TABLEFLT) ! 561: ! 562: #define REST_STACK movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp ! 563: ! 564: alltraps: ! 565: mfpr $USP,-(sp); ! 566: callf $4,_trap; ! 567: mtpr (sp)+,$USP ! 568: incl _cnt+V_TRAP ! 569: REST_STACK # pop type, code, and fp stuff ! 570: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) ! 571: rei ! 572: ! 573: SCBVEC(syscall): ! 574: CHECK_SFE(8) ! 575: SAVE_FPSTAT(8) ! 576: pushl $T_SYSCALL ! 577: mfpr $USP,-(sp); ! 578: callf $4,_syscall; ! 579: mtpr (sp)+,$USP ! 580: incl _cnt+V_SYSCALL ! 581: REST_STACK # pop type, code, and fp stuff ! 582: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) ! 583: rei ! 584: ! 585: /* ! 586: * System page table. ! 587: * ! 588: * Mbmap and Usrptmap are enlarged by CLSIZE entries ! 589: * as they are managed by resource maps starting with index 1 or CLSIZE. ! 590: */ ! 591: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM) ! 592: #define SYSMAP(mname, vname, npte) \ ! 593: _/**/mname: .globl _/**/mname; \ ! 594: .space (npte)*4; \ ! 595: .globl _/**/vname; \ ! 596: .set _/**/vname,vaddr(_/**/mname) ! 597: #define ADDMAP(npte) .space (npte)*4 ! 598: ! 599: .data ! 600: .align 2 ! 601: SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE ) ! 602: SYSMAP(Forkmap ,forkutl ,UPAGES ) ! 603: SYSMAP(Xswapmap ,xswaputl ,UPAGES ) ! 604: SYSMAP(Xswap2map,xswap2utl ,UPAGES ) ! 605: SYSMAP(Swapmap ,swaputl ,UPAGES ) ! 606: SYSMAP(Pushmap ,pushutl ,UPAGES ) ! 607: SYSMAP(Vfmap ,vfutl ,UPAGES ) ! 608: SYSMAP(CMAP1 ,CADDR1 ,1 ) ! 609: SYSMAP(CMAP2 ,CADDR2 ,1 ) ! 610: SYSMAP(mmap ,vmmap ,1 ) ! 611: SYSMAP(alignmap ,alignutl ,1 ) /* XXX */ ! 612: SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT ) ! 613: SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE ) ! 614: SYSMAP(kmempt ,kmembase ,300*CLSIZE ) ! 615: #ifdef GPROF ! 616: SYSMAP(profmap ,profbase ,600*CLSIZE ) ! 617: #endif ! 618: /* ! 619: * Enlarge kmempt as needed for bounce buffers allocated ! 620: * by tahoe controllers. ! 621: */ ! 622: #include "hd.h" ! 623: #if NHD > 0 ! 624: ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) ) ! 625: #endif ! 626: #include "dk.h" ! 627: #if NDK > 0 ! 628: ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) ) ! 629: #endif ! 630: #include "yc.h" ! 631: #if NYC > 0 ! 632: ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) ) ! 633: #endif ! 634: #include "mp.h" ! 635: ADDMAP( NMP*14 ) ! 636: SYSMAP(ekmempt ,kmemlimit ,0 ) ! 637: ! 638: SYSMAP(VMEMbeg ,vmembeg ,0 ) ! 639: SYSMAP(VMEMmap ,vmem ,VBIOSIZE ) ! 640: SYSMAP(VMEMmap1 ,vmem1 ,0 ) ! 641: #include "ace.h" ! 642: #if NACE > 0 ! 643: ADDMAP( NACE*32 ) ! 644: #endif ! 645: #if NHD > 0 ! 646: ADDMAP( NHDC ) ! 647: #endif ! 648: #include "vx.h" ! 649: #if NVX > 0 ! 650: ADDMAP( NVX * 16384/NBPG ) ! 651: #endif ! 652: SYSMAP(VMEMend ,vmemend ,0 ) ! 653: ! 654: SYSMAP(VBmap ,vbbase ,CLSIZE ) ! 655: #if NHD > 0 ! 656: ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) ) ! 657: #endif ! 658: #if NDK > 0 ! 659: ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) ) ! 660: #endif ! 661: #if NYC > 0 ! 662: ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) ) ! 663: #endif ! 664: ADDMAP( NMP*14 ) ! 665: SYSMAP(eVBmap ,vbend ,0 ) ! 666: ! 667: SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE ) ! 668: eSysmap: ! 669: .globl _Syssize ! 670: .set _Syssize,(eSysmap-_Sysmap)/4 ! 671: ! 672: .text ! 673: /* ! 674: * Initialization ! 675: * ! 676: * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set ! 677: */ ! 678: .align 2 ! 679: .globl start ! 680: start: ! 681: .word 0 ! 682: /* set system control block base and system page table params */ ! 683: mtpr $_scb-SYSTEM,$SCBB ! 684: mtpr $_Sysmap-SYSTEM,$SBR ! 685: mtpr $_Syssize,$SLR ! 686: /* double map the kernel into the virtual user addresses of phys mem */ ! 687: mtpr $_Sysmap,$P0BR ! 688: mtpr $_Syssize,$P0LR ! 689: mtpr $_Sysmap,$P1BR # against Murphy ! 690: mtpr $_Syssize,$P1LR ! 691: /* set ISP */ ! 692: movl $_intstack-SYSTEM+NISP*NBPG,sp # still physical ! 693: mtpr $_intstack+NISP*NBPG,$ISP ! 694: /* count up memory */ ! 695: clrl r7 ! 696: 1: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f ! 697: ACBL($MAXMEM*1024-1,$64*1024,r7,1b) ! 698: 9: ! 699: /* clear memory from kernel bss and pages for proc 0 u. and page table */ ! 700: movab _edata,r6; andl2 $~SYSTEM,r6 ! 701: movab _end,r5; andl2 $~SYSTEM,r5 ! 702: #ifdef KADB ! 703: subl2 $4,r5 ! 704: 1: clrl (r6); ACBL(r5,$4,r6,1b) # clear just bss ! 705: addl2 $4,r5 ! 706: bbc $6,r11,0f # check RB_KDB ! 707: andl3 $~SYSTEM,r9,r5 # skip symbol & string tables ! 708: andl3 $~SYSTEM,r9,r6 ! 709: #endif ! 710: 0: orl3 $SYSTEM,r5,r9 # convert to virtual address ! 711: addl2 $NBPG-1,r9 # roundup to next page ! 712: addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 ! 713: 1: clrl (r6); ACBL(r5,$4,r6,1b) ! 714: /* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */ ! 715: orw2 $0x01fff,_trap ! 716: orw2 $0x01fff,_syscall ! 717: #ifdef FPE ! 718: orw2 $0x01fff,_fpemulate ! 719: #endif ! 720: orw2 $0x01ffc,_panic # for debugging (no r0|r1) ! 721: callf $4,_fixctlrmask # setup for autoconfig ! 722: /* initialize system page table: scb and int stack writeable */ ! 723: clrl r2 ! 724: movab eintstack,r1 ! 725: andl2 $~SYSTEM,r1 ! 726: shrl $PGSHIFT,r1,r1 # r1-page number of eintstack ! 727: /* make 1st page processor storage read/only, 2nd read/write */ ! 728: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2; ! 729: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; incl r2; ! 730: /* other parts of the system are read/write for kernel */ ! 731: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write+phys=virtual ! 732: aoblss r1,r2,1b ! 733: /* make rsstk read-only as red zone for interrupt stack */ ! 734: andl2 $~PG_PROT,_rsstkmap ! 735: orl2 $PG_V|PG_KR,_rsstkmap ! 736: /* make kernel text space read-only */ ! 737: movab _etext+NBPG-1,r1 ! 738: andl2 $~SYSTEM,r1 ! 739: shrl $PGSHIFT,r1,r1 ! 740: 1: orl3 $PG_V|PG_KR,r2,_Sysmap[r2] ! 741: aoblss r1,r2,1b ! 742: /* make kernel data, bss, read-write */ ! 743: andl3 $~SYSTEM,r9,r1 ! 744: shrl $PGSHIFT,r1,r1 ! 745: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2] ! 746: aoblss r1,r2,1b ! 747: /* go to mapped mode, have to change both pc and sp to system addresses */ ! 748: mtpr $1,$TBIA ! 749: mtpr $1,$PADC # needed by HW parity&ECC logic ! 750: mtpr $1,$PACC # just in case ! 751: mtpr $1,$MME ! 752: movab SYSTEM(sp),sp ! 753: jmp *$0f ! 754: 0: ! 755: /* disable any interrupts */ ! 756: movl $0,_intenable ! 757: /* init mem sizes */ ! 758: shrl $PGSHIFT,r7,_maxmem ! 759: movl _maxmem,_physmem ! 760: movl _maxmem,_freemem ! 761: /* setup context for proc[0] == scheduler */ ! 762: andl3 $~SYSTEM,r9,r6 # convert to physical ! 763: andl2 $~(NBPG-1),r6 # make page boundary ! 764: /* setup page table for proc[0] */ ! 765: shrl $PGSHIFT,r6,r3 # r3 = btoc(r6) ! 766: orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry ! 767: incl r3 # r3 - next page ! 768: movab _usrpt,r0 # r0 - first user page ! 769: mtpr r0,$TBIS ! 770: /* init p0br, p0lr */ ! 771: mtpr r0,$P0BR # no p0 for proc[0] ! 772: mtpr $0,$P0LR ! 773: mtpr r0,$P1BR # no p1 either ! 774: mtpr $0,$P1LR ! 775: /* init p2br, p2lr */ ! 776: movab NBPG(r0),r0 ! 777: movl $PPAGES-UPAGES,r1 ! 778: mtpr r1,$P2LR ! 779: moval -4*PPAGES(r0),r2 ! 780: mtpr r2,$P2BR ! 781: /* setup mapping for UPAGES of _u */ ! 782: clrl r2 ! 783: movl $SYSTEM,r1 ! 784: addl2 $UPAGES,r3 ! 785: jbr 2f ! 786: 1: decl r3 ! 787: moval -NBPG(r1),r1 # r1 = virtual add of next (downward) _u page ! 788: subl2 $4,r0 # r0 = pte address ! 789: orl3 $PG_V|PG_URKW,r3,(r0) ! 790: mtpr r1,$TBIS ! 791: 2: aobleq $UPAGES,r2,1b ! 792: /* initialize (slightly) the pcb */ ! 793: movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u ! 794: movl r1,PCB_USP(r1) # USP starts just below _u ! 795: mfpr $P0BR,PCB_P0BR(r1) ! 796: mfpr $P0LR,PCB_P0LR(r1) ! 797: mfpr $P1BR,PCB_P1BR(r1) ! 798: mfpr $P1LR,PCB_P1LR(r1) ! 799: mfpr $P2BR,PCB_P2BR(r1) ! 800: mfpr $P2LR,PCB_P2LR(r1) ! 801: movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt ! 802: movl r9,PCB_R9(r1) # r9 obtained from boot ! 803: movl r10,PCB_R10(r1) # r10 obtained from boot ! 804: movl r11,PCB_R11(r1) # r11 obtained from CP on boot ! 805: movab 1f,PCB_PC(r1) # initial pc ! 806: clrl PCB_PSL(r1) # kernel mode, ipl=0 ! 807: shll $PGSHIFT,r3,r3 ! 808: mtpr r3,$PCBB # first pcbb (physical) ! 809: /* go to kernel mode */ ! 810: ldpctx ! 811: rei # Actually next instruction: ! 812: /* put signal trampoline code in u. area */ ! 813: 1: movab sigcode,r0 ! 814: movab _u+PCB_SIGC,r1 ! 815: movl $19,r2 ! 816: movblk ! 817: /* save boot device in global _bootdev */ ! 818: movl r10,_bootdev ! 819: /* save reboot flags in global _boothowto */ ! 820: movl r11,_boothowto ! 821: #ifdef KADB ! 822: /* save end of symbol & string table in global _bootesym */ ! 823: subl3 $NBPG-1,r9,_bootesym ! 824: #endif ! 825: /* calculate firstaddr, and call main() */ ! 826: andl3 $~SYSTEM,r9,r0 ! 827: shrl $PGSHIFT,r0,-(sp) ! 828: addl2 $UPAGES+1,(sp) # first physical unused page ! 829: callf $8,_main ! 830: /* proc[1] == /etc/init now running here in kernel mode; run icode */ ! 831: pushl $PSL_CURMOD # User mode PSL ! 832: pushl $0 # PC = 0 (virtual now) ! 833: rei ! 834: ! 835: /* ! 836: * Mask for saving/restoring registers on entry to ! 837: * a user signal handler. Space for the registers ! 838: * is reserved in sendsig, so beware if you want ! 839: * to change the mask. ! 840: */ ! 841: #define SIGREGS (R0|R1|R2|R3|R4|R5) ! 842: .align 2 ! 843: .globl sigcode ! 844: sigcode: ! 845: storer $SIGREGS,16(sp) # save volatile registers ! 846: calls $4*3+4,*12(sp) # params pushed by sendsig for handler ! 847: loadr $SIGREGS,4(sp) # restore volatile registers ! 848: movab 24(sp),fp # use parameter list set up in sendsig ! 849: kcall $SYS_sigreturn # cleanup mask and onsigstack ! 850: halt # sigreturn does not return! ! 851: ! 852: .globl _icode ! 853: .globl _initflags ! 854: .globl _szicode ! 855: /* ! 856: * Icode is copied out to process 1 to exec /etc/init. ! 857: * If the exec fails, process 1 exits. ! 858: */ ! 859: .align 2 ! 860: _icode: ! 861: /* try /sbin/init */ ! 862: pushab b`argv1-l0(pc) ! 863: l0: pushab b`init1-l1(pc) ! 864: l1: pushl $2 ! 865: movab (sp),fp ! 866: kcall $SYS_execv ! 867: /* try /etc/init */ ! 868: pushab b`argv2-l2(pc) ! 869: l2: pushab b`init2-l3(pc) ! 870: l3: pushl $2 ! 871: movab (sp),fp ! 872: kcall $SYS_execv ! 873: /* give up */ ! 874: pushl r0 ! 875: pushl $1 ! 876: movab (sp),fp ! 877: kcall $SYS_exit ! 878: ! 879: init1: .asciz "/sbin/init" ! 880: init2: .asciz "/etc/init" ! 881: .align 2 ! 882: _initflags: ! 883: .long 0 ! 884: argv1: .long init1+6-_icode ! 885: .long _initflags-_icode ! 886: .long 0 ! 887: argv2: .long init2+5-_icode ! 888: .long _initflags-_icode ! 889: .long 0 ! 890: _szicode: ! 891: .long _szicode-_icode ! 892: ! 893: /* ! 894: * Primitives ! 895: */ ! 896: ! 897: /* ! 898: * badaddr(addr, len) ! 899: * see if access addr with a len type instruction causes a machine check ! 900: * len is length of access (1=byte, 2=short, 4=long) ! 901: * r0 = 0 means good(exists); r0 =1 means does not exist. ! 902: */ ! 903: ENTRY(badaddr, R3|R4) ! 904: mfpr $IPL,r1 ! 905: mtpr $HIGH,$IPL ! 906: movl _scb+SCB_BUSERR,r2 ! 907: movl 4(fp),r3 ! 908: movl 8(fp),r4 ! 909: movab 9f,_scb+SCB_BUSERR ! 910: bbc $0,r4,1f; tstb (r3) ! 911: 1: bbc $1,r4,1f; tstw (r3) ! 912: 1: bbc $2,r4,1f; tstl (r3) ! 913: 1: clrl r0 ! 914: 2: movl r2,_scb+SCB_BUSERR ! 915: mtpr r1,$IPL ! 916: ret ! 917: ! 918: /* ! 919: * wbadaddr(addr, len, value) ! 920: * see if write of value to addr with a len type instruction causes ! 921: * a machine check ! 922: * len is length of access (1=byte, 2=short, 4=long) ! 923: * r0 = 0 means good(exists); r0 =1 means does not exist. ! 924: */ ! 925: ENTRY(wbadaddr, R3|R4) ! 926: mfpr $IPL,r1 ! 927: mtpr $HIGH,$IPL ! 928: movl _scb+SCB_BUSERR,r2 ! 929: movl 4(fp),r3 ! 930: movl 8(fp),r4 ! 931: movab 9f,_scb+SCB_BUSERR ! 932: bbc $0,r4,1f; movb 15(fp), (r3) ! 933: 1: bbc $1,r4,1f; movw 14(fp), (r3) ! 934: 1: bbc $2,r4,1f; movl 12(fp), (r3) ! 935: 1: movl $30000,r0 # delay for error interrupt ! 936: 1: decl r0 ! 937: jneq 1b ! 938: 2: movl r2,_scb+SCB_BUSERR # made it w/o machine checks; r0 is 0 ! 939: mtpr r1,$IPL ! 940: ret ! 941: ! 942: .align 2 ! 943: 9: # catch buss error (if it comes) ! 944: andl3 4(sp),$ERRCD,r0 ! 945: cmpl r0,$APE ! 946: jneq 1f ! 947: halt # address parity error ! 948: 1: cmpl r0,$VBE ! 949: jneq 1f ! 950: halt # Versabus error ! 951: 1: ! 952: movl $1,r0 # Anything else = bad address ! 953: movab 8(sp),sp # discard buss error trash ! 954: movab 2b,(sp) # new program counter on stack. ! 955: rei ! 956: ! 957: /* ! 958: * badcyaddr(addr) ! 959: * see if access tape master controller addr causes a bus error ! 960: * r0 = 0: no error; r0 = 1: timeout error. ! 961: */ ! 962: ENTRY(badcyaddr, 0) ! 963: mfpr $IPL,r1 ! 964: mtpr $HIGH,$IPL ! 965: clrl r2 ! 966: movab 2f,nofault ! 967: movob $-1, *4(fp) ! 968: 1: aobleq $1000, r2, 1b ! 969: clrl nofault # made it w/o bus error ! 970: clrl r0 ! 971: jbr 3f ! 972: 2: movl $1,r0 ! 973: 3: mtpr r1,$IPL ! 974: ret ! 975: ! 976: /* ! 977: * peek(addr) ! 978: * fetch word and catch any bus error ! 979: */ ! 980: ENTRY(peek, 0) ! 981: mfpr $IPL,r1 ! 982: mtpr $0x18,$IPL # not reentrant ! 983: movl 4(fp),r2 ! 984: movab 1f,nofault ! 985: movw (r2),r0 ! 986: clrl nofault ! 987: andl2 $0xffff,r0 ! 988: jbr 2f ! 989: 1: movl $-1,r0 # bus error ! 990: 2: mtpr r1,$IPL ! 991: ret ! 992: ! 993: /* ! 994: * poke(addr, val) ! 995: * write word and catch any bus error ! 996: */ ! 997: ENTRY(poke, R3) ! 998: mfpr $IPL,r1 ! 999: mtpr $0x18,$IPL # not reentrant ! 1000: movl 4(fp),r2 ! 1001: movl 8(fp),r3 ! 1002: clrl r0 ! 1003: movab 1f,nofault ! 1004: movw r3,(r2) ! 1005: clrl nofault ! 1006: jbr 2f ! 1007: 1: movl $-1,r0 # bus error ! 1008: 2: mtpr r1,$IPL ! 1009: ret ! 1010: ! 1011: /* ! 1012: * Copy a potentially overlapping block of memory. ! 1013: * ! 1014: * ovbcopy(src, dst, count) ! 1015: * caddr_t src, dst; unsigned count; ! 1016: */ ! 1017: ENTRY(ovbcopy, R3|R4) ! 1018: movl 4(fp),r0 ! 1019: movl 8(fp),r1 ! 1020: movl 12(fp),r2 ! 1021: cmpl r0,r1 ! 1022: bgtru 1f # normal forward case ! 1023: beql 2f # equal, nothing to do ! 1024: addl2 r2,r0 # may be overlapping ! 1025: cmpl r0,r1 ! 1026: bgtru 3f ! 1027: subl2 r2,r0 # normal forward case ! 1028: 1: ! 1029: movblk ! 1030: 2: ! 1031: ret ! 1032: 3: ! 1033: addl2 r2,r1 # overlapping, must do backwards ! 1034: subl3 r0,r1,r3 ! 1035: movl r2,r4 ! 1036: jbr 5f ! 1037: 4: ! 1038: subl2 r3,r0 ! 1039: subl2 r3,r1 ! 1040: movl r3,r2 ! 1041: movblk ! 1042: subl2 r3,r0 ! 1043: subl2 r3,r1 ! 1044: subl2 r3,r4 ! 1045: 5: ! 1046: cmpl r4,r3 ! 1047: jgtr 4b ! 1048: movl r4,r2 ! 1049: subl2 r2,r0 ! 1050: subl2 r2,r1 ! 1051: movblk ! 1052: ret ! 1053: ! 1054: /* ! 1055: * Copy a null terminated string from the user address space into ! 1056: * the kernel address space. ! 1057: * ! 1058: * copyinstr(fromaddr, toaddr, maxlength, &lencopied) ! 1059: */ ! 1060: ENTRY(copyinstr, 0) ! 1061: movl 12(fp),r5 # r5 = max length ! 1062: jlss 5f ! 1063: movl 8(fp),r4 # r4 = kernel address ! 1064: movl 4(fp),r0 # r0 = user address ! 1065: andl3 $(NBPG*CLSIZE-1),r0,r2 # r2 = bytes on first page ! 1066: subl3 r2,$(NBPG*CLSIZE),r2 ! 1067: 1: ! 1068: cmpl r5,r2 # r2 = min(bytes on page, length left); ! 1069: jgeq 2f ! 1070: movl r5,r2 ! 1071: 2: ! 1072: prober $1,(r0),r2 # bytes accessible? ! 1073: jeql 5f ! 1074: subl2 r2,r5 # update bytes left count ! 1075: movl r2,r3 # r3 = saved count ! 1076: movl r0,r1 ! 1077: cmps3 # check for null ! 1078: tstl r2 ! 1079: jneq 3f ! 1080: subl2 r3,r0 # back up r0 ! 1081: movl r4,r1 ! 1082: movl r3,r2 ! 1083: movblk # copy in next piece ! 1084: movl r1,r4 ! 1085: movl $(NBPG*CLSIZE),r2 # check next page ! 1086: tstl r5 # run out of space? ! 1087: jneq 1b ! 1088: movl $ENOENT,r0 # set error code and return ! 1089: jbr 6f ! 1090: 3: ! 1091: tstl 16(fp) # return length? ! 1092: beql 4f ! 1093: subl3 r5,12(fp),r5 # actual len = maxlen - unused pages ! 1094: subl2 r2,r5 # - unused on this page ! 1095: addl3 $1,r5,*16(fp) # + the null byte ! 1096: 4: ! 1097: movl r4,r1 ! 1098: subl3 r2,r3,r2 # calc char cnt ! 1099: subl2 r2,r0 # back up r0 ! 1100: incl r2 # add on null byte ! 1101: movblk # copy last piece ! 1102: clrl r0 ! 1103: ret ! 1104: 5: ! 1105: movl $EFAULT,r0 ! 1106: 6: ! 1107: tstl 16(fp) ! 1108: beql 7f ! 1109: subl3 r5,12(fp),*16(fp) ! 1110: 7: ! 1111: ret ! 1112: ! 1113: /* ! 1114: * Copy a null terminated string from the kernel ! 1115: * address space to the user address space. ! 1116: * ! 1117: * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) ! 1118: */ ! 1119: ENTRY(copyoutstr, 0) ! 1120: movl 12(fp),r5 # r5 = max length ! 1121: jlss 5f ! 1122: movl 4(fp),r0 # r0 = kernel address ! 1123: movl 8(fp),r4 # r4 = user address ! 1124: andl3 $(NBPG*CLSIZE-1),r4,r2 # r2 = bytes on first page ! 1125: subl3 r2,$(NBPG*CLSIZE),r2 ! 1126: 1: ! 1127: cmpl r5,r2 # r2 = min(bytes on page, length left); ! 1128: jgeq 2f ! 1129: movl r5,r2 ! 1130: 2: ! 1131: probew $1,(r4),r2 # bytes accessible? ! 1132: jeql 5f ! 1133: subl2 r2,r5 # update bytes left count ! 1134: movl r2,r3 # r3 = saved count ! 1135: movl r0,r1 ! 1136: /* ! 1137: * This is a workaround for a microcode bug that causes ! 1138: * a trap type 9 when cmps3/movs3 touches the last byte ! 1139: * on a valid page immediately followed by an invalid page. ! 1140: */ ! 1141: #ifdef good_cmps3 ! 1142: cmps3 # check for null ! 1143: tstl r2 ! 1144: jneq 3b ! 1145: #else ! 1146: decl r2 ! 1147: beql 9f # cannot handle case of r2 == 0! ! 1148: cmps3 # check for null up to last byte ! 1149: 9: ! 1150: incl r2 ! 1151: cmpl $1,r2 # get to last byte on page? ! 1152: bneq 3b ! 1153: tstb (r0) # last byte on page null? ! 1154: beql 3b ! 1155: incl r0 # not null, so bump pointer ! 1156: #endif not good_cmps3 ! 1157: subl2 r3,r0 # back up r0 ! 1158: movl r4,r1 ! 1159: movl r3,r2 ! 1160: movblk # copy out next piece ! 1161: movl r1,r4 ! 1162: movl $(NBPG*CLSIZE),r2 # check next page ! 1163: tstl r5 # run out of space? ! 1164: jneq 1b ! 1165: movl $ENOENT,r0 # set error code and return ! 1166: jbr 6b ! 1167: 5: ! 1168: clrl *$0 # this should never execute, if it does ! 1169: movl $EFAULT,r0 # save me a core dump (mkm - 9/87) ! 1170: 6: ! 1171: tstl 16(fp) ! 1172: beql 7f ! 1173: subl3 r5,12(fp),*16(fp) ! 1174: 7: ! 1175: ret ! 1176: ! 1177: ! 1178: /* ! 1179: * Copy a null terminated string from one point to another in ! 1180: * the kernel address space. ! 1181: * ! 1182: * copystr(fromaddr, toaddr, maxlength, &lencopied) ! 1183: */ ! 1184: ENTRY(copystr, 0) ! 1185: movl 12(fp),r3 # r3 = max length ! 1186: jlss 5b ! 1187: movl 4(fp),r0 # r0 = src address ! 1188: movl 8(fp),r4 # r4 = dest address ! 1189: clrl r5 # r5 = bytes left ! 1190: movl r3,r2 # r2 = max bytes to copy ! 1191: movl r0,r1 ! 1192: cmps3 # check for null ! 1193: tstl r2 ! 1194: jneq 3b ! 1195: subl2 r3,r0 # back up r0 ! 1196: movl r4,r1 ! 1197: movl r3,r2 ! 1198: movblk # copy next piece ! 1199: movl $ENOENT,r0 # set error code and return ! 1200: jbr 6b ! 1201: ! 1202: /* ! 1203: * Copy a block of data from the user address space into ! 1204: * the kernel address space. ! 1205: * ! 1206: * copyin(fromaddr, toaddr, count) ! 1207: */ ! 1208: ENTRY(copyin, 0) ! 1209: movl 12(fp),r0 # copy length ! 1210: blss 9f ! 1211: movl 4(fp),r1 # copy user address ! 1212: cmpl $(CLSIZE*NBPG),r0 # probing one page or less ? ! 1213: bgeq 2f # yes ! 1214: 1: ! 1215: prober $1,(r1),$(CLSIZE*NBPG) # bytes accessible ? ! 1216: beql 9f # no ! 1217: addl2 $(CLSIZE*NBPG),r1 # incr user address ptr ! 1218: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop ! 1219: 2: ! 1220: prober $1,(r1),r0 # bytes accessible ? ! 1221: beql 9f # no ! 1222: MOVC3(4(fp),8(fp),12(fp)) ! 1223: clrl r0 ! 1224: ret ! 1225: 9: ! 1226: movl $EFAULT,r0 ! 1227: ret ! 1228: ! 1229: /* ! 1230: * Copy a block of data from the kernel ! 1231: * address space to the user address space. ! 1232: * ! 1233: * copyout(fromaddr, toaddr, count) ! 1234: */ ! 1235: ENTRY(copyout, 0) ! 1236: movl 12(fp),r0 # get count ! 1237: blss 9b ! 1238: movl 8(fp),r1 # get user address ! 1239: cmpl $(CLSIZE*NBPG),r0 # can do in one probew? ! 1240: bgeq 2f # yes ! 1241: 1: ! 1242: probew $1,(r1),$(CLSIZE*NBPG) # bytes accessible? ! 1243: beql 9b # no ! 1244: addl2 $(CLSIZE*NBPG),r1 # increment user address ! 1245: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop ! 1246: 2: ! 1247: probew $1,(r1),r0 # bytes accessible? ! 1248: beql 9b # no ! 1249: MOVC3(4(fp),8(fp),12(fp)) ! 1250: clrl r0 ! 1251: ret ! 1252: ! 1253: /* ! 1254: * non-local goto's ! 1255: */ ! 1256: #ifdef notdef ! 1257: ENTRY(setjmp, 0) ! 1258: movl 4(fp),r0 ! 1259: movl (fp),(r0); addl2 $4,r0 # save fp ! 1260: movl -8(fp),(r0) # save pc ! 1261: clrl r0 ! 1262: ret ! 1263: #endif ! 1264: ! 1265: ENTRY(longjmp, 0) ! 1266: movl 4(fp),r0 ! 1267: movl (r0),newfp; addl2 $4,r0 # must save parameters in memory ! 1268: movl (r0),newpc # as all regs may be clobbered. ! 1269: 1: ! 1270: cmpl fp,newfp # are we there yet? ! 1271: bgequ 2f # yes ! 1272: moval 1b,-8(fp) # redirect return pc to us! ! 1273: ret # pop next frame ! 1274: 2: ! 1275: beql 3f # did we miss our frame? ! 1276: pushab 4f # yep ?!? ! 1277: callf $8,_panic ! 1278: 3: ! 1279: movl newpc,r0 # all done, just return ! 1280: jmp (r0) # to setjmp `ret' ! 1281: ! 1282: .data ! 1283: newpc: .space 4 ! 1284: newfp: .space 4 ! 1285: 4: .asciz "longjmp" ! 1286: .text ! 1287: ! 1288: /* ! 1289: * setjmp that saves all registers as the call frame may not ! 1290: * be available to recover them in the usual manner by longjmp. ! 1291: * Called before swapping out the u. area, restored by resume() ! 1292: * below. ! 1293: */ ! 1294: ENTRY(savectx, 0) ! 1295: movl 4(fp),r2 ! 1296: storer $0x1ff8,(r2); addl2 $40,r2 # r3-r12 ! 1297: movl (fp),(r2); addl2 $4,r2 # fp ! 1298: movab 8(fp),(r2); addl2 $4,r2 # sp ! 1299: movl -8(fp),(r2) # pc ! 1300: clrl r0 ! 1301: ret ! 1302: ! 1303: #ifdef KADB ! 1304: /* ! 1305: * C library -- reset, setexit ! 1306: * ! 1307: * reset(x) ! 1308: * will generate a "return" from ! 1309: * the last call to ! 1310: * setexit() ! 1311: * by restoring r2 - r12, fp ! 1312: * and doing a return. ! 1313: * The returned value is x; on the original ! 1314: * call the returned value is 0. ! 1315: */ ! 1316: ENTRY(setexit, 0) ! 1317: movab setsav,r0 ! 1318: storer $0x1ffc, (r0) ! 1319: movl (fp),44(r0) # fp ! 1320: moval 4(fp),48(r0) # sp ! 1321: movl -8(fp),52(r0) # pc ! 1322: clrl r0 ! 1323: ret ! 1324: ! 1325: ENTRY(reset, 0) ! 1326: movl 4(fp),r0 # returned value ! 1327: movab setsav,r1 ! 1328: loadr $0x1ffc,(r1) ! 1329: movl 44(r1),fp ! 1330: movl 48(r1),sp ! 1331: jmp *52(r1) ! 1332: ! 1333: .data ! 1334: .align 2 ! 1335: setsav: .space 14*4 ! 1336: .text ! 1337: #endif ! 1338: ! 1339: .globl _whichqs ! 1340: .globl _qs ! 1341: .globl _cnt ! 1342: ! 1343: .globl _noproc ! 1344: .comm _noproc,4 ! 1345: .globl _runrun ! 1346: .comm _runrun,4 ! 1347: /* ! 1348: * The following primitives use the fancy TAHOE instructions. ! 1349: * _whichqs tells which of the 32 queues _qs ! 1350: * have processes in them. setrq puts processes into queues, remrq ! 1351: * removes them from queues. The running process is on no queue, ! 1352: * other processes are on a queue related to p->p_pri, divided by 4 ! 1353: * actually to shrink the 0-127 range of priorities into the 32 available ! 1354: * queues. ! 1355: */ ! 1356: ! 1357: /* ! 1358: * setrq(p), using fancy TAHOE instructions. ! 1359: * ! 1360: * Call should be made at spl8(), and p->p_stat should be SRUN ! 1361: */ ! 1362: ENTRY(setrq, 0) ! 1363: movl 4(fp),r0 ! 1364: tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0 ! 1365: beql set1 ## ! 1366: pushab set3 ## ! 1367: callf $8,_panic ## ! 1368: set1: ! 1369: movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4 ! 1370: shar $2,r1,r1 ! 1371: shal $1,r1,r2 ! 1372: moval _qs[r2],r2 ! 1373: insque (r0),*4(r2) # at end of queue ! 1374: shal r1,$1,r1 ! 1375: orl2 r1,_whichqs # mark queue non-empty ! 1376: ret ! 1377: ! 1378: set3: .asciz "setrq" ! 1379: ! 1380: /* ! 1381: * remrq(p), using fancy TAHOE instructions ! 1382: * ! 1383: * Call should be made at spl8(). ! 1384: */ ! 1385: ENTRY(remrq, 0) ! 1386: movl 4(fp),r0 ! 1387: movzbl P_PRI(r0),r1 ! 1388: shar $2,r1,r1 ! 1389: bbs r1,_whichqs,rem1 ! 1390: pushab rem3 # it wasn't recorded to be on its q ! 1391: callf $8,_panic ! 1392: rem1: ! 1393: remque (r0) ! 1394: bneq rem2 # q not empty yet ! 1395: shal r1,$1,r1 ! 1396: mcoml r1,r1 ! 1397: andl2 r1,_whichqs # mark queue empty ! 1398: rem2: ! 1399: clrl P_RLINK(r0) ## for firewall checking ! 1400: ret ! 1401: ! 1402: rem3: .asciz "remrq" ! 1403: ! 1404: /* ! 1405: * Masterpaddr is the p->p_addr of the running process on the master ! 1406: * processor. When a multiprocessor system, the slave processors will have ! 1407: * an array of slavepaddr's. ! 1408: */ ! 1409: .globl _masterpaddr ! 1410: .data ! 1411: .align 2 ! 1412: _masterpaddr: .long 0 ! 1413: ! 1414: .text ! 1415: sw0: .asciz "swtch" ! 1416: ! 1417: /* ! 1418: * When no processes are on the runq, swtch branches to idle ! 1419: * to wait for something to come ready. ! 1420: */ ! 1421: .globl Idle ! 1422: Idle: idle: ! 1423: movl $1,_noproc ! 1424: mtpr $0,$IPL # must allow interrupts here ! 1425: 1: ! 1426: tstl _whichqs # look for non-empty queue ! 1427: bneq sw1 ! 1428: brb 1b ! 1429: ! 1430: badsw: pushab sw0 ! 1431: callf $8,_panic ! 1432: /* NOTREACHED */ ! 1433: ! 1434: .align 2 ! 1435: /* ! 1436: * swtch(), using fancy tahoe instructions ! 1437: */ ! 1438: ENTRY(swtch, 0) ! 1439: movl (fp),fp # prepare for rei ! 1440: movl (sp),4(sp) # saved pc ! 1441: tstl (sp)+ ! 1442: movpsl 4(sp) ! 1443: incl _cnt+V_SWTCH ! 1444: sw1: ffs _whichqs,r0 # look for non-empty queue ! 1445: blss idle # if none, idle ! 1446: mtpr $0x18,$IPL # lock out all so _whichqs==_qs ! 1447: bbc r0,_whichqs,sw1 # proc moved via interrupt ! 1448: shal $1,r0,r1 ! 1449: moval _qs[r1],r1 ! 1450: movl (r1),r2 # r2 = p = highest pri process ! 1451: remque *(r1) ! 1452: bvs badsw # make sure something was there ! 1453: bneq sw2 ! 1454: shal r0,$1,r1 ! 1455: mcoml r1,r1 ! 1456: andl2 r1,_whichqs # no more procs in this queue ! 1457: sw2: ! 1458: clrl _noproc ! 1459: clrl _runrun ! 1460: #ifdef notdef ! 1461: tstl P_WCHAN(r2) ## firewalls ! 1462: bneq badsw ## ! 1463: cmpb P_STAT(r2),$SRUN ## ! 1464: bneq badsw ## ! 1465: #endif ! 1466: clrl P_RLINK(r2) ## ! 1467: movl *P_ADDR(r2),r0 ! 1468: #ifdef notdef ! 1469: cmpl r0,_masterpaddr # resume of current proc is easy ! 1470: beql res0 ! 1471: #endif ! 1472: movl r0,_masterpaddr ! 1473: shal $PGSHIFT,r0,r0 # r0 = pcbb(p) ! 1474: brb swresume ! 1475: ! 1476: /* ! 1477: * resume(pf) ! 1478: */ ! 1479: ENTRY(resume, 0) ! 1480: shal $PGSHIFT,4(fp),r0 # r0 = pcbb(pf) ! 1481: movl (fp),fp # prepare for rei ! 1482: movl (sp)+,4(sp) # saved pc ! 1483: tstl (sp)+ ! 1484: movpsl 4(sp) ! 1485: swresume: ! 1486: mtpr $0x18,$IPL # no interrupts, please ! 1487: movl _CMAP2,_u+PCB_CMAP2 # yech ! 1488: REST_ACC # restore original accumulator ! 1489: svpctx ! 1490: mtpr r0,$PCBB ! 1491: ldpctx ! 1492: movl _u+PCB_CMAP2,_CMAP2 # yech ! 1493: mtpr $_CADDR2,$TBIS ! 1494: res0: ! 1495: movl _u+U_PROCP,r2 # r2 = u.u_procp ! 1496: tstl P_CKEY(r2) # does proc have code key? ! 1497: bneq 1f ! 1498: callf $4,_getcodekey # no, give him one ! 1499: movl _u+U_PROCP,r2 # r2 = u.u_procp ! 1500: movl r0,P_CKEY(r2) ! 1501: 1: ! 1502: tstl P_DKEY(r2) # does proc have data key? ! 1503: bneq 1f ! 1504: callf $4,_getdatakey # no, give him one ! 1505: movl _u+U_PROCP,r2 # r2 = u.u_procp ! 1506: movl r0,P_DKEY(r2) ! 1507: 1: ! 1508: mtpr P_CKEY(r2),$CCK # set code cache key ! 1509: mtpr P_DKEY(r2),$DCK # set data cache key ! 1510: tstl _u+PCB_SSWAP ! 1511: bneq res1 ! 1512: rei ! 1513: res1: # longjmp to saved context ! 1514: movl _u+PCB_SSWAP,r2 ! 1515: clrl _u+PCB_SSWAP ! 1516: loadr $0x3ff8,(r2); addl2 $44,r2 # restore r3-r13 (r13=fp) ! 1517: movl (r2),r1; addl2 $4,r2 # fetch previous sp ... ! 1518: movab (sp),r0 # ... and current sp and ! 1519: cmpl r1,r0 # check for credibility, ! 1520: bgequ 1f # if further up stack ... ! 1521: pushab 2f; callf $8,_panic # ... panic ! 1522: /*NOTREACHED*/ ! 1523: 1: # sp ok, complete return ! 1524: movl r1,sp # restore sp ! 1525: pushl $PSL_PRVMOD # kernel mode, ipl 0 ! 1526: pushl (r2) # return address ! 1527: rei ! 1528: 2: .asciz "ldctx" ! 1529: ! 1530: /* ! 1531: * {fu,su},{byte,word} ! 1532: */ ! 1533: ENTRY(fuword, 0) ! 1534: movl 4(fp), r1 ! 1535: prober $1,(r1),$4 # check access ! 1536: beql fserr # page unreadable ! 1537: bitl $1,r1 # check byte alignment ! 1538: bneq 2f # odd, do byte-word-byte ! 1539: bitl $2,r1 # check word alignment ! 1540: bneq 1f # odd, do in 2 words ! 1541: movl (r1),r0 # move longword ! 1542: ret ! 1543: 1: ! 1544: movw (r1),r0 # move two words ! 1545: shal $16,r0,r0 ! 1546: movzwl 2(r1),r1 # orw2 sign extends ! 1547: orl2 r1,r0 ! 1548: ret ! 1549: 2: ! 1550: movb (r1),r0 # move byte-word-byte ! 1551: shal $24,r0,r0 ! 1552: movzwl 1(r1),r2 # orw2 sign extends ! 1553: shal $8,r2,r2 ! 1554: movzbl 3(r1),r1 # orb2 sign extends ! 1555: orl2 r2,r1 ! 1556: orl2 r1,r0 ! 1557: ret ! 1558: fserr: ! 1559: mnegl $1,r0 ! 1560: ret ! 1561: ! 1562: ENTRY(fubyte, 0) ! 1563: prober $1,*4(fp),$1 ! 1564: beql fserr ! 1565: movzbl *4(fp),r0 ! 1566: ret ! 1567: ! 1568: ENTRY(suword, 0) ! 1569: movl 4(fp), r0 ! 1570: probew $1,(r0),$4 # check access ! 1571: beql fserr # page unwritable ! 1572: bitl $1,r0 # check byte alignment ! 1573: bneq 1f # odd byte boundary ! 1574: bitl $2,r0 # check word alignment ! 1575: beql 2f # longword aligned ! 1576: movw 8(fp),(r0) # move two words ! 1577: movw 10(fp),2(r0) ! 1578: jbr 3f ! 1579: 1: ! 1580: movb 8(fp),(r0) ! 1581: movb 9(fp),1(r0) ! 1582: movb 10(fp),2(r0) ! 1583: movb 11(fp),3(r0) ! 1584: jbr 3f ! 1585: 2: ! 1586: movl 8(fp),(r0) ! 1587: 3: ! 1588: clrl r0 ! 1589: ret ! 1590: ! 1591: ENTRY(subyte, 0) ! 1592: probew $1,*4(fp),$1 ! 1593: beql fserr ! 1594: movb 11(fp),*4(fp) ! 1595: clrl r0 ! 1596: ret ! 1597: ! 1598: /* ! 1599: * Copy 1 relocation unit (NBPG bytes) ! 1600: * from user virtual address to physical address ! 1601: */ ! 1602: ENTRY(copyseg, 0) ! 1603: orl3 $PG_V|PG_KW,8(fp),_CMAP2 ! 1604: mtpr $_CADDR2,$TBIS # invalidate entry for copy ! 1605: MOVC3(4(fp),$_CADDR2,$NBPG) ! 1606: ret ! 1607: ! 1608: /* ! 1609: * Clear a page of memory. The page frame is specified. ! 1610: * ! 1611: * clearseg(pf); ! 1612: */ ! 1613: ENTRY(clearseg, 0) ! 1614: orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1 ! 1615: mtpr $_CADDR1,$TBIS ! 1616: movl $255,r0 # r0 = limit ! 1617: clrl r1 # r1 = index of cleared long ! 1618: 1: ! 1619: clrl _CADDR1[r1] ! 1620: aobleq r0,r1,1b ! 1621: ret ! 1622: ! 1623: /* ! 1624: * Check user mode read/write access. ! 1625: * ! 1626: * useracc(addr, count, mode) ! 1627: * caddr_t addr; int count, mode; ! 1628: * mode = 0 write access ! 1629: * mode = 1 read access ! 1630: */ ! 1631: ENTRY(useracc, 0) ! 1632: movl $1,r2 # r2 = 'user mode' for probew/probew ! 1633: probes: ! 1634: movl 4(fp),r0 # get va ! 1635: movl 8(fp),r1 # count ! 1636: tstl 12(fp) # test for read access ? ! 1637: bneq userar # yes ! 1638: cmpl $(CLSIZE*NBPG),r1 # can we do it in one probe ? ! 1639: bgeq uaw2 # yes ! 1640: uaw1: ! 1641: probew r2,(r0),$(CLSIZE*NBPG) ! 1642: beql uaerr # no access ! 1643: addl2 $(CLSIZE*NBPG),r0 ! 1644: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1) ! 1645: uaw2: ! 1646: probew r2,(r0),r1 ! 1647: beql uaerr ! 1648: movl $1,r0 ! 1649: ret ! 1650: userar: ! 1651: cmpl $(CLSIZE*NBPG),r1 ! 1652: bgeq uar2 ! 1653: uar1: ! 1654: prober r2,(r0),$(CLSIZE*NBPG) ! 1655: beql uaerr ! 1656: addl2 $(CLSIZE*NBPG),r0 ! 1657: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1) ! 1658: uar2: ! 1659: prober r2,(r0),r1 ! 1660: beql uaerr ! 1661: movl $1,r0 ! 1662: ret ! 1663: uaerr: ! 1664: clrl r0 ! 1665: ret ! 1666: ! 1667: /* ! 1668: * Check kernel mode read/write access. ! 1669: * ! 1670: * kernacc(addr, count, mode) ! 1671: * caddr_t addr; int count, mode; ! 1672: * mode = 0 write access ! 1673: * mode = 1 read access ! 1674: */ ! 1675: ENTRY(kernacc, 0) ! 1676: clrl r2 # r2 = 0 means kernel mode probe. ! 1677: jbr probes # Dijkstra would get gastric distress here. ! 1678: ! 1679: /* ! 1680: * addupc - increment some histogram counter ! 1681: * in the profiling buffer ! 1682: * ! 1683: * addupc(pc, prof, delta) ! 1684: * long pc; short delta; struct uprof *prof; ! 1685: * ! 1686: * struct uprof { # profile arguments ! 1687: * short *r_base; # buffer base ! 1688: * unsigned pr_size; # buffer size ! 1689: * unsigned pr_off; # pc offset ! 1690: * unsigned pr_scale; # pc scaling ! 1691: * } ! 1692: */ ! 1693: ENTRY(addupc, 0) ! 1694: movl 8(fp),r2 # r2 points to structure ! 1695: subl3 8(r2),4(fp),r0 # r0 = PC - lowpc ! 1696: jlss 9f # PC < lowpc , out of range ! ! 1697: shrl $1,r0,r0 # the unit is words ! 1698: shrl $1,12(r2),r1 # ditto for scale ! 1699: emul r1,r0,$0,r0 ! 1700: shrq $14,r0,r0 ! 1701: tstl r0 # too big ! 1702: jneq 9f ! 1703: cmpl r1,4(r2) # Check buffer overflow ! 1704: jgequ 9f ! 1705: probew $1,*0(r2)[r1],$2 # counter accessible? ! 1706: jeql 9f ! 1707: shrl $1,r1,r1 # make r1 word index ! 1708: addw2 14(fp),*0(r2)[r1] ! 1709: 9: ret ! 1710: ! 1711: /* ! 1712: * scanc(size, cp, table, mask) ! 1713: */ ! 1714: ENTRY(scanc, R3|R4) ! 1715: movl 8(fp),r0 # r0 = cp ! 1716: addl3 4(fp),r0,r2 # end = &cp[size] ! 1717: movl 12(fp),r1 # r1 = table ! 1718: movb 19(fp),r4 # r4 = mask ! 1719: decl r0 # --cp ! 1720: jbr 0f # just like Fortran... ! 1721: 1: # do { ! 1722: movzbl (r0),r3 ! 1723: bitb r4,(r1)[r3] # if (table[*cp] & mask) ! 1724: jneq 2f # break; ! 1725: 0: aoblss r2,r0,1b # } while (++cp < end); ! 1726: 2: ! 1727: subl3 r0,r2,r0; ret # return (end - cp); ! 1728: ! 1729: /* ! 1730: * skpc(mask, size, cp) ! 1731: */ ! 1732: ENTRY(skpc, 0) ! 1733: movl 12(fp),r0 # r0 = cp ! 1734: addl3 8(fp),r0,r1 # r1 = end = &cp[size]; ! 1735: movb 7(fp),r2 # r2 = mask ! 1736: decl r0 # --cp; ! 1737: jbr 0f ! 1738: 1: # do ! 1739: cmpb (r0),r2 # if (*cp != mask) ! 1740: jneq 2f # break; ! 1741: 0: aoblss r1,r0,1b # while (++cp < end); ! 1742: 2: ! 1743: subl3 r0,r1,r0; ret # return (end - cp); ! 1744: ! 1745: /* ! 1746: * locc(mask, size, cp) ! 1747: */ ! 1748: ENTRY(locc, 0) ! 1749: movl 12(fp),r0 # r0 = cp ! 1750: addl3 8(fp),r0,r1 # r1 = end = &cp[size] ! 1751: movb 7(fp),r2 # r2 = mask ! 1752: decl r0 # --cp; ! 1753: jbr 0f ! 1754: 1: # do ! 1755: cmpb (r0),r2 # if (*cp == mask) ! 1756: jeql 2f # break; ! 1757: 0: aoblss r1,r0,1b # while (++cp < end); ! 1758: 2: ! 1759: subl3 r0,r1,r0; ret # return (end - cp); ! 1760: ! 1761: #ifdef ALIGN ! 1762: #include "../tahoealign/align.h" ! 1763: ! 1764: .globl _alignment ! 1765: /* ! 1766: * There's an intimate relationship between this piece of code ! 1767: * and the alignment emulation code (especially the layout ! 1768: * of local variables in alignment.c! Don't change unless ! 1769: * you update both this, alignment.h and alignment.c !! ! 1770: */ ! 1771: non_aligned: ! 1772: orb2 $EMULATEALIGN,_u+U_EOSYS ! 1773: incl _cnt+V_TRAP ! 1774: incl _cnt+V_ALIGN # count emulated alignment traps ! 1775: moval 4(sp),_user_psl ! 1776: SAVE_FPSTAT(4) # Also zeroes out ret_exception ! ! 1777: pushl $0 # ret_addr ! 1778: pushl $0 # ret_code ! 1779: mfpr $USP,-(sp) # user sp ! 1780: callf $4,_alignment # call w/o parms so regs may be modified ! 1781: /* ! 1782: * We return here after a successful emulation or an exception. ! 1783: * The registers have been restored and we must not alter them ! 1784: * before returning to the user. ! 1785: */ ! 1786: 2: mtpr (sp)+,$USP # restore user sp ! 1787: tstl 8(sp) # Any exception ? ! 1788: bneq got_excp # Yes, reflect it back to user. ! 1789: moval 8(sp),sp # pop 2 zeroes pushed above ! 1790: REST_FPSTAT ! 1791: xorb2 $EMULATEALIGN,_u+U_EOSYS ! 1792: ! 1793: bitl $PSL_T,4(sp) # check for trace bit set ! 1794: beql 9f ! 1795: CHECK_SFE(4) ! 1796: pushl $0 ! 1797: SAVE_FPSTAT(8) ! 1798: TRAP(TRCTRAP) ! 1799: 9: rei ! 1800: ! 1801: got_excp: # decode exception ! 1802: casel 8(sp),$ILL_ADDRMOD,$ALIGNMENT ! 1803: .align 1 ! 1804: L1: ! 1805: .word ill_addrmod-L1 ! 1806: .word ill_access-L1 ! 1807: .word ill_oprnd-L1 ! 1808: .word arithmetic-L1 ! 1809: .word alignment-L1 ! 1810: brw alignment # default - shouldn't come here at all ! ! 1811: ! 1812: ill_addrmod: # No other parameters. Set up stack as ! 1813: moval 8(sp),sp # the HW would do it in a real case. ! 1814: REST_FPSTAT ! 1815: jbr _Xresadflt ! 1816: ill_oprnd: ! 1817: moval 8(sp),sp ! 1818: REST_FPSTAT ! 1819: jbr _Xresopflt ! 1820: alignment: ! 1821: moval 8(sp),sp ! 1822: REST_FPSTAT ! 1823: jbr align_excp # NB: going to _Xalignflt would cause loop ! 1824: ill_access: ! 1825: /* ! 1826: * Must restore accumulator w/o modifying sp and w/o using ! 1827: * registers. Solution: copy things needed by REST_FPSTAT. ! 1828: */ ! 1829: pushl 20(sp) # The flags longword ! 1830: pushl 20(sp) # acc_low ! 1831: pushl 20(sp) # acc_high ! 1832: pushl 20(sp) # ret_exception ignored by REST_FPSTAT ! 1833: REST_FPSTAT # Back where we were with the sp ! ! 1834: movl (sp),16(sp) # code for illegal access ! 1835: movl 4(sp),20(sp) # original virtual address ! 1836: moval 16(sp),sp # Just like the HW would set it up ! 1837: jbr _Xprotflt ! 1838: arithmetic: # same trickery as above ! 1839: pushl 20(sp) # The flags longword ! 1840: pushl 20(sp) # acc_low ! 1841: pushl 20(sp) # acc_high ! 1842: pushl 20(sp) # ret_exception ignored by REST_FPSTAT ! 1843: REST_FPSTAT # Back where we were with the sp ! ! 1844: movl (sp),20(sp) # code for arithmetic exception ! 1845: moval 20(sp),sp # Just like the HW would set it up ! 1846: jbr _Xarithtrap ! 1847: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.