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