1: /* 2: * Copyright (c) 1980, 1986 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.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "psl.h" 10: #include "pte.h" 11: 12: #include "errno.h" 13: #include "cmap.h" 14: 15: #include "mtpr.h" 16: #include "trap.h" 17: #include "cpu.h" 18: #include "nexus.h" 19: #include "cons.h" 20: #include "clock.h" 21: #include "ioa.h" 22: #include "ka630.h" 23: #include "../vaxuba/ubareg.h" 24: 25: #include "dz.h" 26: #include "uu.h" 27: #include "ps.h" 28: #include "mba.h" 29: #include "uba.h" 30: 31: .set HIGH,0x1f # mask for total disable 32: .set MCKVEC,4 # offset into scb of machine check vector 33: .set NBPG,512 34: .set PGSHIFT,9 35: 36: .set NISP,3 # number of interrupt stack pages 37: 38: /* 39: * User structure is UPAGES at top of user space. 40: */ 41: .globl _u 42: .set _u,0x80000000 - UPAGES*NBPG 43: 44: .globl _intstack 45: _intstack: 46: .space NISP*NBPG 47: eintstack: 48: 49: /* 50: * Do a dump. 51: * Called by auto-restart. 52: * May be called manually. 53: */ 54: .align 2 55: .globl _doadump 56: _doadump: 57: nop; nop # .word 0x0101 58: #define _rpbmap _Sysmap # rpb, scb, UNI*vec, istack*4 59: bicl2 $PG_PROT,_rpbmap 60: bisl2 $PG_KW,_rpbmap 61: mtpr $0,$TBIA 62: tstl _rpb+RP_FLAG # dump only once! 63: bneq 1f 64: incl _rpb+RP_FLAG 65: movl sp,erpb 66: movab erpb,sp 67: mfpr $PCBB,-(sp) 68: mfpr $MAPEN,-(sp) 69: mfpr $IPL,-(sp) 70: mtpr $0,$MAPEN 71: mtpr $HIGH,$IPL 72: pushr $0x3fff 73: calls $0,_dumpsys 74: 1: 75: pushl $TXDB_BOOT 76: calls $1,_tocons 77: halt 78: 79: /* 80: * Interrupt vector routines 81: */ 82: .globl _waittime 83: 84: #define SCBVEC(name) .align 2; .globl _X/**/name; _X/**/name 85: #define PANIC(msg) clrl _waittime; pushab 1f; \ 86: calls $1,_panic; 1: .asciz msg 87: #define PRINTF(n,msg) pushab 1f; calls $n+1,_printf; MSG(msg) 88: #define MSG(msg) .data; 1: .asciz msg; .text 89: #define PUSHR pushr $0x3f 90: #define POPR popr $0x3f 91: 92: .data 93: nofault: .long 0 # where to go on predicted machcheck 94: .text 95: SCBVEC(machcheck): 96: tstl nofault 97: bneq 1f 98: PUSHR; pushab 6*4(sp); calls $1,_machinecheck; POPR; 99: addl2 (sp)+,sp; rei 100: .align 2 101: 1: 102: casel _cpu,$1,$VAX_MAX 103: 0: 104: .word 8f-0b # 1 is 780 105: .word 5f-0b # 2 is 750 106: .word 5f-0b # 3 is 730 107: .word 7f-0b # 4 is 8600 108: .word 1f-0b # ??? 109: .word 1f-0b # ??? 110: .word 1f-0b # ??? 111: .word 1f-0b # 8 is 630 112: 5: 113: #if defined(VAX750) || defined(VAX730) 114: mtpr $0xf,$MCESR 115: #endif 116: brb 1f 117: 7: 118: #if VAX8600 119: mtpr $0,$EHSR 120: #endif 121: brb 1f 122: 8: 123: #if VAX780 124: mtpr $0,$SBIFS 125: #endif 126: 1: 127: addl2 (sp)+,sp # discard mchchk trash 128: movl nofault,(sp) 129: rei 130: SCBVEC(kspnotval): 131: PUSHR; PANIC("KSP not valid"); 132: SCBVEC(powfail): 133: halt 134: SCBVEC(chme): SCBVEC(chms): SCBVEC(chmu): 135: PUSHR; PANIC("CHM? in kernel"); 136: SCBVEC(stray): 137: PUSHR; PRINTF(0, "stray scb interrupt\n"); POPR; 138: rei 139: SCBVEC(nexzvec): 140: PUSHR; mfpr $IPL,-(sp); PRINTF(1, "nexus stray intr ipl%x\n"); POPR; rei 141: SCBVEC(cmrd): 142: PUSHR; calls $0,_memerr; POPR; rei 143: SCBVEC(wtime): 144: PUSHR; pushl 6*4(sp); PRINTF(1,"write timeout %x\n"); POPR; 145: PANIC("wtimo"); 146: 147: #if NMBA > 0 148: SCBVEC(mba3int): 149: PUSHR; incl _intrcnt+I_MBA3; pushl $3; brb 1f 150: SCBVEC(mba2int): 151: PUSHR; incl _intrcnt+I_MBA2; pushl $2; brb 1f 152: SCBVEC(mba1int): 153: PUSHR; incl _intrcnt+I_MBA1; pushl $1; brb 1f 154: SCBVEC(mba0int): 155: PUSHR; incl _intrcnt+I_MBA0; pushl $0 156: 1: calls $1,_mbintr 157: POPR 158: incl _cnt+V_INTR 159: rei 160: #endif 161: 162: #if defined(VAX780) || defined(VAX8600) 163: /* 164: * Registers for the uba handling code 165: */ 166: #define rUBANUM r0 167: #define rUBAHD r1 168: #define rUVEC r3 169: #define rUBA r4 170: /* r2,r5 are scratch */ 171: 172: #define I_UBA I_UBA0 /* base of UBA interrupt counters */ 173: 174: #if NUBA > 4 175: SCBVEC(ua7int): 176: PUSHR; movl $7,rUBANUM; moval _uba_hd+(7*UH_SIZE),rUBAHD; brb 1f 177: SCBVEC(ua6int): 178: PUSHR; movl $6,rUBANUM; moval _uba_hd+(6*UH_SIZE),rUBAHD; brb 1f 179: SCBVEC(ua5int): 180: PUSHR; movl $5,rUBANUM; moval _uba_hd+(5*UH_SIZE),rUBAHD; brb 1f 181: SCBVEC(ua4int): 182: PUSHR; movl $4,rUBANUM; moval _uba_hd+(4*UH_SIZE),rUBAHD; brb 1f 183: #endif 184: SCBVEC(ua3int): 185: PUSHR; movl $3,rUBANUM; moval _uba_hd+(3*UH_SIZE),rUBAHD; brb 1f 186: SCBVEC(ua2int): 187: PUSHR; movl $2,rUBANUM; moval _uba_hd+(2*UH_SIZE),rUBAHD; brb 1f 188: SCBVEC(ua1int): 189: PUSHR; movl $1,rUBANUM; moval _uba_hd+(1*UH_SIZE),rUBAHD; brb 1f 190: SCBVEC(ua0int): 191: PUSHR; movl $0,rUBANUM; moval _uba_hd+(0*UH_SIZE),rUBAHD; 192: 1: 193: mfpr $IPL,r2 /* r2 = mfpr(IPL); */ 194: movl UH_UBA(rUBAHD),rUBA /* uba = uhp->uh_uba; */ 195: movl UBA_BRRVR-0x14*4(rUBA)[r2],rUVEC 196: /* uvec = uba->uba_brrvr[r2-0x14] */ 197: ubanorm: 198: bleq ubaerror 199: addl2 UH_VEC(rUBAHD),rUVEC /* uvec += uh->uh_vec */ 200: bicl3 $3,(rUVEC),r1 201: jmp 2(r1) /* 2 skips ``pushr $0x3f'' */ 202: ubaerror: 203: PUSHR; calls $0,_ubaerror; POPR /* ubaerror r/w's r0-r5 */ 204: tstl rUVEC; jneq ubanorm /* rUVEC contains result */ 205: incl _intrcnt+I_UBA[rUBANUM] 206: incl _cnt+V_INTR 207: POPR 208: rei 209: #endif 210: SCBVEC(cnrint): 211: PUSHR; calls $0,_cnrint; POPR 212: incl _cnt+V_INTR 213: incl _intrcnt+I_CNR 214: rei 215: SCBVEC(cnxint): 216: PUSHR; calls $0,_cnxint; POPR 217: incl _cnt+V_INTR 218: incl _intrcnt+I_CNX 219: rei 220: SCBVEC(hardclock): 221: PUSHR 222: mtpr $ICCS_RUN|ICCS_IE|ICCS_INT|ICCS_ERR,$ICCS 223: #if NPS > 0 224: pushl 4+6*4(sp); pushl 4+6*4(sp); 225: calls $2,_psextsync 226: #endif 227: pushl 4+6*4(sp); pushl 4+6*4(sp); 228: calls $2,_hardclock # hardclock(pc,psl) 229: POPR; 230: incl _cnt+V_INTR 231: incl _intrcnt+I_CLOCK 232: rei 233: SCBVEC(softclock): 234: PUSHR 235: pushl 4+6*4(sp); pushl 4+6*4(sp); 236: calls $2,_softclock # softclock(pc,psl) 237: POPR; 238: incl _cnt+V_SOFT 239: rei 240: 241: #include "../net/netisr.h" 242: .globl _netisr 243: SCBVEC(netintr): 244: PUSHR 245: #include "imp.h" 246: #if NIMP > 0 247: bbcc $NETISR_IMP,_netisr,1f; calls $0,_impintr; 1: 248: #endif 249: #ifdef INET 250: bbcc $NETISR_IP,_netisr,1f; calls $0,_ipintr; 1: 251: #endif 252: #ifdef NS 253: bbcc $NETISR_NS,_netisr,1f; calls $0,_nsintr; 1: 254: #endif 255: bbcc $NETISR_RAW,_netisr,1f; calls $0,_rawintr; 1: 256: POPR 257: incl _cnt+V_SOFT 258: rei 259: 260: #if defined(VAX750) || defined(VAX730) || defined(VAX8600) 261: SCBVEC(consdin): 262: PUSHR; 263: incl _intrcnt+I_TUR 264: casel _cpu,$VAX_750,$VAX_8600 265: 0: 266: .word 5f-0b # 2 is VAX_750 267: .word 3f-0b # 3 is VAX_730 268: .word 6f-0b # 4 is VAX_8600 269: halt 270: 5: 271: #if defined(VAX750) && !defined(MRSP) 272: jsb tudma 273: #endif 274: 3: 275: #if defined(VAX750) || defined(VAX730) 276: calls $0,_turintr 277: brb 2f 278: #else 279: halt 280: #endif 281: 6: 282: #if VAX8600 283: calls $0, _crlintr 284: #else 285: halt 286: #endif 287: 2: 288: POPR; 289: incl _cnt+V_INTR; 290: rei 291: #else 292: SCBVEC(consdin): 293: halt 294: #endif 295: 296: #if defined(VAX750) || defined(VAX730) 297: SCBVEC(consdout): 298: PUSHR; calls $0,_tuxintr; POPR 299: incl _cnt+V_INTR 300: incl _intrcnt+I_TUX 301: rei 302: #else 303: SCBVEC(consdout): 304: halt 305: #endif 306: 307: #if NDZ > 0 308: /* 309: * DZ pseudo dma routine: 310: * r0 - controller number 311: */ 312: .align 1 313: .globl dzdma 314: dzdma: 315: mull2 $8*20,r0 316: movab _dzpdma(r0),r3 # pdma structure base 317: # for this controller 318: dzploop: 319: movl r3,r0 320: movl (r0)+,r1 # device register address 321: movzbl 1(r1),r2 # get line number 322: bitb $0x80,r2 # TRDY on? 323: beql dzprei # no 324: bicb2 $0xf8,r2 # clear garbage bits 325: mull2 $20,r2 326: addl2 r2,r0 # point at line's pdma structure 327: movl (r0)+,r2 # p_mem 328: cmpl r2,(r0)+ # p_mem < p_end ? 329: bgequ dzpcall # no, go call dzxint 330: movb (r2)+,6(r1) # dztbuf = *p_mem++ 331: movl r2,-8(r0) 332: brb dzploop # check for another line 333: dzprei: 334: POPR 335: incl _cnt+V_PDMA 336: rei 337: 338: dzpcall: 339: pushl r3 340: pushl (r0)+ # push tty address 341: calls $1,*(r0) # call interrupt rtn 342: movl (sp)+,r3 343: brb dzploop # check for another line 344: #endif 345: 346: #if NUU > 0 && defined(UUDMA) 347: /* 348: * Pseudo DMA routine for tu58 (on DL11) 349: * r0 - controller number 350: */ 351: .align 1 352: .globl uudma 353: uudma: 354: movl _uudinfo[r0],r2 355: movl 16(r2),r2 # r2 = uuaddr 356: mull3 $48,r0,r3 357: movab _uu_softc(r3),r5 # r5 = uuc 358: 359: cvtwl 2(r2),r1 # c = uuaddr->rdb 360: bbc $15,r1,1f # if (c & UUDB_ERROR) 361: movl $13,16(r5) # uuc->tu_state = TUC_RCVERR; 362: rsb # let uurintr handle it 363: 1: 364: tstl 4(r5) # if (uuc->tu_rcnt) { 365: beql 1f 366: movb r1,*0(r5) # *uuc->tu_rbptr++ = r1 367: incl (r5) 368: decl 4(r5) # if (--uuc->tu_rcnt) 369: beql 2f # done 370: tstl (sp)+ 371: POPR # registers saved in ubglue.s 372: rei # } 373: 2: 374: cmpl 16(r5),$8 # if (uuc->tu_state != TUS_GETH) 375: beql 2f # let uurintr handle it 376: 1: 377: rsb 378: 2: 379: mull2 $14,r0 # sizeof(uudata[ctlr]) = 14 380: movab _uudata(r0),r4 # data = &uudata[ctlr]; 381: cmpb $1,(r4) # if (data->pk_flag != TUF_DATA) 382: bneq 1b 383: #ifdef notdef 384: /* this is for command packets */ 385: beql 1f # r0 = uuc->tu_rbptr 386: movl (r5),r0 387: brb 2f 388: 1: # else 389: #endif 390: movl 24(r5),r0 # r0 = uuc->tu_addr 391: 2: 392: movzbl 1(r4),r3 # counter to r3 (data->pk_count) 393: movzwl (r4),r1 # first word of checksum (=header) 394: mfpr $IPL,-(sp) # s = spl5(); 395: mtpr $0x15,$IPL # to keep disk interrupts out 396: clrw (r2) # disable receiver interrupts 397: 3: bbc $7,(r2),3b # while ((uuaddr->rcs & UUCS_READY)==0); 398: cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff 399: sobgtr r3,1f # continue with next byte ... 400: addw2 2(r2),r1 # unless this was the last (odd count) 401: brb 2f 402: 403: 1: bbc $7,(r2),1b # while ((uuaddr->rcs & UUCS_READY)==0); 404: cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff 405: addw2 -2(r0),r1 # add to checksum.. 406: 2: 407: adwc $0,r1 # get the carry 408: sobgtr r3,3b # loop while r3 > 0 409: /* 410: * We're ready to get the checksum 411: */ 412: 1: bbc $7,(r2),1b # while ((uuaddr->rcs & UUCS_READY)==0); 413: cvtwb 2(r2),12(r4) # get first (lower) byte 414: 1: bbc $7,(r2),1b 415: cvtwb 2(r2),13(r4) # ..and second 416: cmpw 12(r4),r1 # is checksum ok? 417: beql 1f 418: movl $14,16(r5) # uuc->tu_state = TUS_CHKERR 419: brb 2f # exit 420: 1: 421: movl $11,16(r5) # uuc->tu_state = TUS_GET (ok) 422: 2: 423: movw $0x40,(r2) # enable receiver interrupts 424: mtpr (sp)+,$IPL # splx(s); 425: rsb # continue processing in uurintr 426: #endif 427: 428: #if defined(VAX750) && !defined(MRSP) 429: /* 430: * Pseudo DMA routine for VAX-11/750 console tu58 431: * (without MRSP) 432: */ 433: .align 1 434: .globl tudma 435: tudma: 436: movab _tu,r5 # r5 = tu 437: tstl 4(r5) # if (tu.tu_rcnt) { 438: beql 3f 439: mfpr $CSRD,r1 # get data from tu58 440: movb r1,*0(r5) # *tu.tu_rbptr++ = r1 441: incl (r5) 442: decl 4(r5) # if (--tu.tu_rcnt) 443: beql 1f # done 444: tstl (sp)+ 445: POPR # registers saved in ubglue.s 446: rei # data handled, done 447: 1: # } 448: cmpl 16(r5),$8 # if (tu.tu_state != TUS_GETH) 449: beql 2f # let turintr handle it 450: 3: 451: rsb 452: 2: 453: movab _tudata,r4 # r4 = tudata 454: cmpb $1,(r4) # if (tudata.pk_flag != TUF_DATA) 455: bneq 3b # let turintr handle it 456: 1: # else 457: movl 24(r5),r1 # get buffer pointer to r1 458: movzbl 1(r4),r3 # counter to r3 459: movzwl (r4),r0 # first word of checksum (=header) 460: mtpr $0,$CSRS # disable receiver interrupts 461: 3: 462: bsbw 5f # wait for next byte 463: mfpr $CSRD,r5 464: movb r5,(r1)+ # *buffer = rdb 465: sobgtr r3,1f # continue with next byte ... 466: mfpr $CSRD,r2 # unless this was the last (odd count) 467: brb 2f 468: 469: 1: bsbw 5f # wait for next byte 470: mfpr $CSRD,r5 471: movb r5,(r1)+ # *buffer = rdb 472: movzwl -2(r1),r2 # get the last word back from memory 473: 2: 474: addw2 r2,r0 # add to checksum.. 475: adwc $0,r0 # get the carry 476: sobgtr r3,3b # loop while r3 > 0 477: /* 478: * We're ready to get the checksum. 479: */ 480: bsbw 5f 481: movab _tudata,r4 482: mfpr $CSRD,r5 483: movb r5,12(r4) # get first (lower) byte 484: bsbw 5f 485: mfpr $CSRD,r5 486: movb r5,13(r4) # ..and second 487: movab _tu,r5 488: cmpw 12(r4),r0 # is checksum ok? 489: beql 1f 490: movl $14,16(r5) # tu.tu_state = TUS_CHKERR 491: brb 2f # exit 492: 1: 493: movl $11,16(r5) # tu.tu_state = TUS_GET 494: 2: 495: mtpr $0x40,$CSRS # enable receiver interrupts 496: rsb # continue processing in turintr 497: /* 498: * Loop until a new byte is ready from 499: * the tu58, make sure we don't loop forever 500: */ 501: 5: 502: movl $5000,r5 # loop max 5000 times 503: 1: 504: mfpr $CSRS,r2 505: bbs $7,r2,1f 506: sobgtr r5,1b 507: movab _tu,r5 508: movl $13,16(r5) # return TUS_RCVERR 509: tstl (sp)+ # and let turintr handle it 510: 1: 511: rsb 512: #endif 513: 514: /* 515: * Stray UNIBUS interrupt catch routines 516: */ 517: .data 518: .align 2 519: #define PJ PUSHR;jsb _Xustray 520: .globl _catcher 521: _catcher: 522: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 523: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 524: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 525: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 526: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 527: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 528: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 529: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 530: 531: .globl _cold 532: _cold: .long 1 533: .data 534: 535: .text 536: SCBVEC(ustray): 537: blbc _cold,1f 538: mfpr $IPL,r11 539: subl3 $_catcher+8,(sp)+,r10 540: ashl $-1,r10,r10 541: POPR 542: rei 543: 1: 544: subl3 $_catcher+8,(sp)+,r0 545: ashl $-1,r0,-(sp) 546: mfpr $IPL,-(sp) 547: PRINTF(2, "uba?: stray intr ipl %x vec %o\n") 548: POPR 549: rei 550: 551: #ifdef VAX630 552: /* 553: * Emulation OpCode jump table: 554: * ONLY GOES FROM 0xf8 (-8) TO 0x3B (59) 555: */ 556: #define EMUTABLE 0x43 557: #define NOEMULATE .long noemulate 558: #define EMULATE(a) .long _EM/**/a 559: .globl _emJUMPtable 560: _emJUMPtable: 561: /* f8 */ EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE 562: /* fc */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 563: /* 00 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 564: /* 04 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 565: /* 08 */ EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc) 566: /* 0c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 567: /* 10 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 568: /* 14 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 569: /* 18 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 570: /* 1c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 571: /* 20 */ EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6) 572: /* 24 */ EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp) 573: /* 28 */ NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc) 574: /* 2c */ NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc) 575: /* 30 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 576: /* 34 */ EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4) 577: /* 38 */ EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc) 578: #endif 579: 580: /* 581: * Trap and fault vector routines 582: */ 583: #define TRAP(a) pushl $T_/**/a; jbr alltraps 584: 585: /* 586: * Ast delivery (profiling and/or reschedule) 587: */ 588: SCBVEC(astflt): 589: pushl $0; TRAP(ASTFLT) 590: SCBVEC(privinflt): 591: pushl $0; TRAP(PRIVINFLT) 592: SCBVEC(xfcflt): 593: pushl $0; TRAP(XFCFLT) 594: SCBVEC(resopflt): 595: pushl $0; TRAP(RESOPFLT) 596: SCBVEC(resadflt): 597: pushl $0; TRAP(RESADFLT) 598: SCBVEC(bptflt): 599: pushl $0; TRAP(BPTFLT) 600: SCBVEC(compatflt): 601: TRAP(COMPATFLT); 602: SCBVEC(tracep): 603: pushl $0; TRAP(TRCTRAP) 604: SCBVEC(arithtrap): 605: TRAP(ARITHTRAP) 606: SCBVEC(protflt): 607: blbs (sp)+,segflt 608: TRAP(PROTFLT) 609: segflt: 610: TRAP(SEGFLT) 611: 612: /* 613: * The following is called with the stack set up as follows: 614: * 615: * (sp): Opcode 616: * 4(sp): Instruction PC 617: * 8(sp): Operand 1 618: * 12(sp): Operand 2 619: * 16(sp): Operand 3 620: * 20(sp): Operand 4 621: * 24(sp): Operand 5 622: * 28(sp): Operand 6 623: * 32(sp): Operand 7 (unused) 624: * 36(sp): Operand 8 (unused) 625: * 40(sp): Return PC 626: * 44(sp): Return PSL 627: * 48(sp): TOS before instruction 628: * 629: * Each individual routine is called with the stack set up as follows: 630: * 631: * (sp): Return address of trap handler 632: * 4(sp): Opcode (will get return PSL) 633: * 8(sp): Instruction PC 634: * 12(sp): Operand 1 635: * 16(sp): Operand 2 636: * 20(sp): Operand 3 637: * 24(sp): Operand 4 638: * 28(sp): Operand 5 639: * 32(sp): Operand 6 640: * 36(sp): saved register 11 641: * 40(sp): saved register 10 642: * 44(sp): Return PC 643: * 48(sp): Return PSL 644: * 52(sp): TOS before instruction 645: */ 646: 647: SCBVEC(emulate): 648: #ifdef VAX630 649: movl r11,32(sp) # save register r11 in unused operand 650: movl r10,36(sp) # save register r10 in unused operand 651: cvtbl (sp),r10 # get opcode 652: addl2 $8,r10 # shift negative opcodes 653: subl3 r10,$EMUTABLE,r11 # forget it if opcode is out of range 654: bcs noemulate 655: movl _emJUMPtable[r10],r10 # call appropriate emulation routine 656: jsb (r10) # routines put return values into regs 0-5 657: movl 32(sp),r11 # restore register r11 658: movl 36(sp),r10 # restore register r10 659: insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot 660: addl2 $40,sp # adjust stack for return 661: rei 662: noemulate: 663: addl2 $48,sp # adjust stack for 664: #endif VAX630 665: .word 0xffff # "reserved instruction fault" 666: SCBVEC(emulateFPD): 667: .word 0xffff # "reserved instruction fault" 668: SCBVEC(transflt): 669: bitl $2,(sp)+ 670: bnequ tableflt 671: jsb Fastreclaim # try and avoid pagein 672: TRAP(PAGEFLT) 673: tableflt: 674: TRAP(TABLEFLT) 675: 676: alltraps: 677: mfpr $USP,-(sp); calls $0,_trap; mtpr (sp)+,$USP 678: incl _cnt+V_TRAP 679: addl2 $8,sp # pop type, code 680: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 681: rei 682: 683: SCBVEC(syscall): 684: pushl $T_SYSCALL 685: mfpr $USP,-(sp); calls $0,_syscall; mtpr (sp)+,$USP 686: incl _cnt+V_SYSCALL 687: addl2 $8,sp # pop type, code 688: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 689: rei 690: 691: /* 692: * System page table 693: * Mbmap and Usrptmap are enlarged by CLSIZE entries 694: * as they are managed by resource maps starting with index 1 or CLSIZE. 695: */ 696: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+0x80000000) 697: #define SYSMAP(mname, vname, npte) \ 698: _/**/mname: .globl _/**/mname; \ 699: .space (npte)*4; \ 700: .globl _/**/vname; \ 701: .set _/**/vname,vaddr(_/**/mname) 702: 703: .data 704: .align 2 705: SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE ) 706: SYSMAP(Forkmap ,forkutl ,UPAGES ) 707: SYSMAP(Xswapmap ,xswaputl ,UPAGES ) 708: SYSMAP(Xswap2map,xswap2utl ,UPAGES ) 709: SYSMAP(Swapmap ,swaputl ,UPAGES ) 710: SYSMAP(Pushmap ,pushutl ,UPAGES ) 711: SYSMAP(Vfmap ,vfutl ,UPAGES ) 712: SYSMAP(CMAP1 ,CADDR1 ,1 ) 713: SYSMAP(CMAP2 ,CADDR2 ,1 ) 714: SYSMAP(mmap ,vmmap ,1 ) 715: SYSMAP(alignmap ,alignutl ,1 ) /* XXX */ 716: SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT ) 717: SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*CLSIZE+CLSIZE ) 718: SYSMAP(camap ,cabase ,16*CLSIZE ) 719: #ifdef GPROF 720: SYSMAP(profmap ,profbase ,600*CLSIZE ) 721: #endif 722: SYSMAP(ecamap ,calimit ,0 ) 723: 724: SYSMAP(UMBAbeg ,umbabeg ,0 ) 725: SYSMAP(Nexmap ,nexus ,16*MAXNNEXUS ) 726: SYSMAP(UMEMmap ,umem ,UBAPAGES*NUBA ) 727: SYSMAP(Ioamap ,ioa ,MAXNIOA*IOAMAPSIZ/NBPG ) 728: SYSMAP(UMBAend ,umbaend ,0 ) 729: #if VAX630 730: SYSMAP(Clockmap ,cldevice ,1 ) 731: SYSMAP(Ka630map ,ka630cpu ,1 ) 732: #endif 733: 734: SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE ) 735: 736: eSysmap: 737: .globl _Syssize 738: .set _Syssize,(eSysmap-_Sysmap)/4 739: .text 740: 741: /* 742: * Initialization 743: * 744: * ipl 0x1f; mapen 0; scbb, pcbb, sbr, slr, isp, ksp not set 745: */ 746: .data 747: .globl _cpu 748: _cpu: .long 0 749: .text 750: .globl start 751: start: 752: .word 0 753: mtpr $0,$ICCS 754: /* set system control block base and system page table params */ 755: mtpr $_scb-0x80000000,$SCBB 756: mtpr $_Sysmap-0x80000000,$SBR 757: mtpr $_Syssize,$SLR 758: /* double map the kernel into the virtual user addresses of phys mem */ 759: mtpr $_Sysmap,$P0BR 760: mtpr $_Syssize,$P0LR 761: /* set ISP and get cpu type */ 762: movl $_intstack+NISP*NBPG,sp 763: mfpr $SID,r0 764: movab _cpu,r1 765: extzv $24,$8,r0,(r1) 766: /* init RPB */ 767: movab _rpb,r0 768: movl r0,(r0)+ # rp_selfref 769: movab _doadump,r1 770: movl r1,(r0)+ # rp_dumprout 771: movl $0x1f,r2 772: clrl r3 773: 1: addl2 (r1)+,r3; sobgtr r2,1b 774: movl r3,(r0)+ # rp_chksum 775: /* count up memory */ 776: clrl r7 777: 1: pushl $4; pushl r7; calls $2,_badaddr; tstl r0; bneq 9f 778: acbl $MAXMEM*1024-1,$64*1024,r7,1b 779: 9: 780: #ifdef VAX630 781: /* leave an area for uVAX II console scratch pad at the top */ 782: cmpb _cpu,$VAX_630 783: bneq 1f 784: subl2 $4096,r7 785: 1: 786: #endif 787: /* clear memory from kernel bss and pages for proc 0 u. and page table */ 788: movab _edata,r6 789: movab _end,r5 790: bbcc $31,r5,0f; 0: 791: addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 792: 1: clrq (r6); acbl r5,$8,r6,1b 793: /* trap() and syscall() save r0-r11 in the entry mask (per ../h/reg.h) */ 794: /* panic() is convenient place to save all for debugging */ 795: bisw2 $0x0fff,_trap 796: bisw2 $0x0fff,_syscall 797: bisw2 $0x0fff,_panic 798: calls $0,_fixctlrmask 799: /* initialize system page table: uba vectors and int stack writeable */ 800: clrl r2 801: movab eintstack,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1 802: 1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b 803: /* make rpb, scb read-only as red zone for interrupt stack */ 804: bicl2 $PG_PROT,_rpbmap 805: bisl2 $PG_KR,_rpbmap 806: /* make kernel text space read-only */ 807: movab _etext+NBPG-1,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1 808: 1: bisl3 $PG_V|PG_URKR,r2,_Sysmap[r2]; aoblss r1,r2,1b 809: /* make kernel data, bss, read-write */ 810: movab _end+NBPG-1,r1; bbcc $31,r1,0f; 0:; ashl $-PGSHIFT,r1,r1 811: 1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b 812: /* now go to mapped mode */ 813: mtpr $0,$TBIA; mtpr $1,$MAPEN; jmp *$0f; 0: 814: /* init mem sizes */ 815: ashl $-PGSHIFT,r7,_maxmem 816: movl _maxmem,_physmem 817: movl _maxmem,_freemem 818: /* setup context for proc[0] == Scheduler */ 819: movab _end+NBPG-1,r6 820: bicl2 $NBPG-1,r6 # make page boundary 821: /* setup page table for proc[0] */ 822: bbcc $31,r6,0f; 0: 823: ashl $-PGSHIFT,r6,r3 # r3 = btoc(r6) 824: bisl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry 825: incl r3 826: movab _usrpt,r0 827: mtpr r0,$TBIS 828: /* init p0br, p0lr */ 829: mtpr r0,$P0BR 830: mtpr $0,$P0LR 831: /* init p1br, p1lr */ 832: movab NBPG(r0),r0 833: movl $0x200000-UPAGES,r1 834: mtpr r1,$P1LR 835: mnegl r1,r1 836: moval -4*UPAGES(r0)[r1],r2 837: mtpr r2,$P1BR 838: /* setup mapping for UPAGES of _u */ 839: movl $UPAGES,r2; movab _u+NBPG*UPAGES,r1; addl2 $UPAGES,r3; jbr 2f 840: 1: decl r3 841: moval -NBPG(r1),r1; 842: bisl3 $PG_V|PG_URKW,r3,-(r0) 843: mtpr r1,$TBIS 844: 2: sobgeq r2,1b 845: /* initialize (slightly) the pcb */ 846: movab UPAGES*NBPG(r1),PCB_KSP(r1) 847: mnegl $1,PCB_ESP(r1) 848: mnegl $1,PCB_SSP(r1) 849: movl r1,PCB_USP(r1) 850: mfpr $P0BR,PCB_P0BR(r1) 851: mfpr $P0LR,PCB_P0LR(r1) 852: movb $4,PCB_P0LR+3(r1) # disable ast 853: mfpr $P1BR,PCB_P1BR(r1) 854: mfpr $P1LR,PCB_P1LR(r1) 855: movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt 856: movl r10,PCB_R10(r1) 857: movl r11,PCB_R11(r1) 858: movab 1f,PCB_PC(r1) # initial pc 859: clrl PCB_PSL(r1) # mode(k,k), ipl=0 860: ashl $PGSHIFT,r3,r3 861: mtpr r3,$PCBB # first pcbb 862: /* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */ 863: ldpctx 864: rei 865: /* put signal trampoline code in u. area */ 866: 1: movab _u,r0 867: movc3 $19,sigcode,PCB_SIGC(r0) 868: /* save boot device in global _bootdev */ 869: movl r10,_bootdev 870: /* save reboot flags in global _boothowto */ 871: movl r11,_boothowto 872: /* calculate firstaddr, and call main() */ 873: movab _end+NBPG-1,r0; bbcc $31,r0,0f; 0:; ashl $-PGSHIFT,r0,-(sp) 874: addl2 $UPAGES+1,(sp); calls $1,_main 875: /* proc[1] == /etc/init now running here; run icode */ 876: pushl $PSL_CURMOD|PSL_PRVMOD; pushl $0; rei 877: 878: /* signal trampoline code: it is known that this code takes exactly 19 bytes */ 879: /* in ../vax/pcb.h and in the movc3 above */ 880: sigcode: 881: calls $4,8(pc) # params pushed by sendsig 882: movl sp,ap # calls frame built by sendsig 883: chmk $103 # cleanup mask and onsigstack 884: halt # sigreturn() does not return! 885: .word 0x3f # registers 0-5 886: callg (ap),*16(ap) # call the signal handler 887: ret # return to code above 888: 889: .set exec,11 890: .set exit,1 891: .globl _icode 892: .globl _initflags 893: .globl _szicode 894: /* 895: * Icode is copied out to process 1 to exec /etc/init. 896: * If the exec fails, process 1 exits. 897: */ 898: _icode: 899: pushab b`argv-l0(pc) 900: l0: pushab b`init-l1(pc) 901: l1: pushl $2 902: movl sp,ap 903: chmk $exec 904: chmk $exit 905: 906: init: .asciz "/etc/init" 907: .align 2 908: _initflags: 909: .long 0 910: argv: .long init+5-_icode 911: .long _initflags-_icode 912: .long 0 913: _szicode: 914: .long _szicode-_icode 915: 916: /* 917: * Primitives 918: */ 919: 920: #ifdef GPROF 921: #define ENTRY(name, regs) \ 922: .globl _/**/name; .align 1; _/**/name: .word regs; jsb mcount 923: #define JSBENTRY(name, regs) \ 924: .globl _/**/name; _/**/name: \ 925: movl fp,-(sp); movab -12(sp),fp; pushr $(regs); jsb mcount; \ 926: popr $(regs); movl (sp)+,fp 927: #else 928: #define ENTRY(name, regs) \ 929: .globl _/**/name; .align 1; _/**/name: .word regs 930: #define JSBENTRY(name, regs) \ 931: .globl _/**/name; _/**/name: 932: #endif GPROF 933: #define R0 0x01 934: #define R1 0x02 935: #define R2 0x04 936: #define R3 0x08 937: #define R4 0x10 938: #define R5 0x20 939: #define R6 0x40 940: 941: /* 942: * badaddr(addr, len) 943: * see if access addr with a len type instruction causes a machine check 944: * len is length of access (1=byte, 2=short, 4=long) 945: */ 946: .globl _badaddr 947: _badaddr: 948: .word 0 949: movl $1,r0 950: mfpr $IPL,r1 951: mtpr $HIGH,$IPL 952: movl 4(ap),r3 953: movl 8(ap),r4 954: movab 2f,nofault # jump to 2f on machcheck 955: bbc $0,r4,1f; tstb (r3) 956: 1: bbc $1,r4,1f; tstw (r3) 957: 1: bbc $2,r4,1f; tstl (r3) 958: 1: clrl r0 # made it w/o machine checks 959: 2: clrl nofault 960: mtpr r1,$IPL 961: ret 962: 963: /* 964: * update profiling information for the user 965: * addupc(pc, &u.u_prof, ticks) 966: */ 967: ENTRY(addupc, 0) 968: movl 8(ap),r2 # &u.u_prof 969: subl3 8(r2),4(ap),r0 # corrected pc 970: blss 9f 971: extzv $1,$31,r0,r0 # logical right shift 972: extzv $1,$31,12(r2),r1 # ditto for scale 973: emul r1,r0,$0,r0 974: ashq $-14,r0,r0 975: tstl r1 976: bneq 9f 977: bicl2 $1,r0 978: cmpl r0,4(r2) # length 979: bgequ 9f 980: addl2 (r2),r0 # base 981: probew $3,$2,(r0) 982: beql 8f 983: addw2 12(ap),(r0) 984: 9: 985: ret 986: 8: 987: clrl 12(r2) 988: ret 989: 990: /* 991: * Copy a null terminated string from the user address space into 992: * the kernel address space. 993: * 994: * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 995: */ 996: ENTRY(copyinstr, R6) 997: movl 12(ap),r6 # r6 = max length 998: jlss 8f 999: movl 4(ap),r1 # r1 = user address 1000: bicl3 $~(NBPG*CLSIZE-1),r1,r2 # r2 = bytes on first page 1001: subl3 r2,$NBPG*CLSIZE,r2 1002: movl 8(ap),r3 # r3 = kernel address 1003: 1: 1004: cmpl r6,r2 # r2 = min(bytes on page, length left); 1005: jgeq 2f 1006: movl r6,r2 1007: 2: 1008: prober $3,r2,(r1) # bytes accessible? 1009: jeql 8f 1010: subl2 r2,r6 # update bytes left count 1011: #ifdef NOSUBSINST 1012: # fake the locc instr. for processors that don't have it 1013: movl r2,r0 1014: 6: 1015: tstb (r1)+ 1016: jeql 5f 1017: sobgtr r0,6b 1018: jbr 7f 1019: 5: 1020: decl r1 1021: jbr 3f 1022: 7: 1023: #else 1024: locc $0,r2,(r1) # null byte found? 1025: jneq 3f 1026: #endif 1027: subl2 r2,r1 # back up pointer updated by `locc' 1028: movc3 r2,(r1),(r3) # copy in next piece 1029: movl $(NBPG*CLSIZE),r2 # check next page 1030: tstl r6 # run out of space? 1031: jneq 1b 1032: movl $ENOENT,r0 # set error code and return 1033: jbr 9f 1034: 3: 1035: tstl 16(ap) # return length? 1036: beql 4f 1037: subl3 r6,12(ap),r6 # actual len = maxlen - unused pages 1038: subl2 r0,r6 # - unused on this page 1039: addl3 $1,r6,*16(ap) # + the null byte 1040: 4: 1041: subl2 r0,r2 # r2 = number of bytes to move 1042: subl2 r2,r1 # back up pointer updated by `locc' 1043: incl r2 # copy null byte as well 1044: movc3 r2,(r1),(r3) # copy in last piece 1045: clrl r0 # redundant 1046: ret 1047: 8: 1048: movl $EFAULT,r0 1049: 9: 1050: tstl 16(ap) 1051: beql 1f 1052: subl3 r6,12(ap),*16(ap) 1053: 1: 1054: ret 1055: 1056: /* 1057: * Copy a null terminated string from the kernel 1058: * address space to the user address space. 1059: * 1060: * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 1061: */ 1062: ENTRY(copyoutstr, R6) 1063: movl 12(ap),r6 # r6 = max length 1064: jlss 8b 1065: movl 4(ap),r1 # r1 = kernel address 1066: movl 8(ap),r3 # r3 = user address 1067: bicl3 $~(NBPG*CLSIZE-1),r3,r2 # r2 = bytes on first page 1068: subl3 r2,$NBPG*CLSIZE,r2 1069: 1: 1070: cmpl r6,r2 # r2 = min(bytes on page, length left); 1071: jgeq 2f 1072: movl r6,r2 1073: 2: 1074: probew $3,r2,(r3) # bytes accessible? 1075: jeql 8b 1076: subl2 r2,r6 # update bytes left count 1077: #ifdef NOSUBSINST 1078: # fake the locc instr. for processors that don't have it 1079: movl r2,r0 1080: 6: 1081: tstb (r1)+ 1082: jeql 5f 1083: sobgtr r0,6b 1084: jbr 7f 1085: 5: 1086: decl r1 1087: jbr 3b 1088: 7: 1089: #else 1090: locc $0,r2,(r1) # null byte found? 1091: jneq 3b 1092: #endif 1093: subl2 r2,r1 # back up pointer updated by `locc' 1094: movc3 r2,(r1),(r3) # copy in next piece 1095: movl $(NBPG*CLSIZE),r2 # check next page 1096: tstl r6 # run out of space? 1097: jneq 1b 1098: movl $ENOENT,r0 # set error code and return 1099: jbr 9b 1100: 1101: /* 1102: * Copy a null terminated string from one point to another in 1103: * the kernel address space. 1104: * 1105: * copystr(fromaddr, toaddr, maxlength, &lencopied) 1106: */ 1107: ENTRY(copystr, R6) 1108: movl 12(ap),r6 # r6 = max length 1109: jlss 8b 1110: movl 4(ap),r1 # r1 = src address 1111: movl 8(ap),r3 # r3 = dest address 1112: 1: 1113: movzwl $65535,r2 # r2 = bytes in first chunk 1114: cmpl r6,r2 # r2 = min(bytes in chunk, length left); 1115: jgeq 2f 1116: movl r6,r2 1117: 2: 1118: subl2 r2,r6 # update bytes left count 1119: #ifdef NOSUBSINST 1120: # fake the locc instr. for processors that don't have it 1121: movl r2,r0 1122: 6: 1123: tstb (r1)+ 1124: jeql 5f 1125: sobgtr r0,6b 1126: jbr 7f 1127: 5: 1128: decl r1 1129: jbr 3b 1130: 7: 1131: #else 1132: locc $0,r2,(r1) # null byte found? 1133: jneq 3b 1134: #endif 1135: subl2 r2,r1 # back up pointer updated by `locc' 1136: movc3 r2,(r1),(r3) # copy in next piece 1137: tstl r6 # run out of space? 1138: jneq 1b 1139: movl $ENOENT,r0 # set error code and return 1140: jbr 9b 1141: 1142: /* 1143: * Copy specified amount of data from user space into the kernel 1144: * Copyin(from, to, len) 1145: * r1 == from (user source address) 1146: * r3 == to (kernel destination address) 1147: * r5 == length 1148: */ 1149: .align 1 1150: JSBENTRY(Copyin, R1|R3|R5) 1151: cmpl r5,$(NBPG*CLSIZE) # probing one page or less ? 1152: bgtru 1f # no 1153: prober $3,r5,(r1) # bytes accessible ? 1154: beql ersb # no 1155: movc3 r5,(r1),(r3) 1156: /* clrl r0 # redundant */ 1157: rsb 1158: 1: 1159: blss ersb # negative length? 1160: pushl r6 # r6 = length 1161: movl r5,r6 1162: bicl3 $~(NBPG*CLSIZE-1),r1,r0 # r0 = bytes on first page 1163: subl3 r0,$(NBPG*CLSIZE),r0 1164: addl2 $(NBPG*CLSIZE),r0 # plus one additional full page 1165: jbr 2f 1166: 1167: ciloop: 1168: movc3 r0,(r1),(r3) 1169: movl $(2*NBPG*CLSIZE),r0 # next amount to move 1170: 2: 1171: cmpl r0,r6 1172: bleq 3f 1173: movl r6,r0 1174: 3: 1175: prober $3,r0,(r1) # bytes accessible ? 1176: beql ersb1 # no 1177: subl2 r0,r6 # last move? 1178: bneq ciloop # no 1179: 1180: movc3 r0,(r1),(r3) 1181: /* clrl r0 # redundant */ 1182: movl (sp)+,r6 # restore r6 1183: rsb 1184: 1185: ersb1: 1186: movl (sp)+,r6 # restore r6 1187: ersb: 1188: movl $EFAULT,r0 1189: rsb 1190: 1191: /* 1192: * Copy specified amount of data from kernel to the user space 1193: * Copyout(from, to, len) 1194: * r1 == from (kernel source address) 1195: * r3 == to (user destination address) 1196: * r5 == length 1197: */ 1198: .align 1 1199: JSBENTRY(Copyout, R1|R3|R5) 1200: cmpl r5,$(NBPG*CLSIZE) # moving one page or less ? 1201: bgtru 1f # no 1202: probew $3,r5,(r3) # bytes writeable? 1203: beql ersb # no 1204: movc3 r5,(r1),(r3) 1205: /* clrl r0 # redundant */ 1206: rsb 1207: 1: 1208: blss ersb # negative length? 1209: pushl r6 # r6 = length 1210: movl r5,r6 1211: bicl3 $~(NBPG*CLSIZE-1),r3,r0 # r0 = bytes on first page 1212: subl3 r0,$(NBPG*CLSIZE),r0 1213: addl2 $(NBPG*CLSIZE),r0 # plus one additional full page 1214: jbr 2f 1215: 1216: coloop: 1217: movc3 r0,(r1),(r3) 1218: movl $(2*NBPG*CLSIZE),r0 # next amount to move 1219: 2: 1220: cmpl r0,r6 1221: bleq 3f 1222: movl r6,r0 1223: 3: 1224: probew $3,r0,(r3) # bytes writeable? 1225: beql ersb1 # no 1226: subl2 r0,r6 # last move? 1227: bneq coloop # no 1228: 1229: movc3 r0,(r1),(r3) 1230: /* clrl r0 # redundant */ 1231: movl (sp)+,r6 # restore r6 1232: rsb 1233: 1234: /* 1235: * non-local goto's 1236: */ 1237: #ifdef notdef /* this is now expanded completely inline */ 1238: .align 1 1239: JSBENTRY(Setjmp, R0) 1240: movl fp,(r0)+ # current stack frame 1241: movl (sp),(r0) # resuming pc 1242: clrl r0 1243: rsb 1244: #endif 1245: 1246: #define PCLOC 16 /* location of pc in calls frame */ 1247: #define APLOC 8 /* location of ap,fp in calls frame */ 1248: .align 1 1249: JSBENTRY(Longjmp, R0) 1250: movl (r0)+,newfp # must save parameters in memory as all 1251: movl (r0),newpc # registers may be clobbered. 1252: 1: 1253: cmpl fp,newfp # are we there yet? 1254: bgequ 2f # yes 1255: moval 1b,PCLOC(fp) # redirect return pc to us! 1256: ret # pop next frame 1257: 2: 1258: beql 3f # did we miss our frame? 1259: pushab 4f # yep ?!? 1260: calls $1,_panic 1261: 3: 1262: movl newpc,r0 # all done, just return to the `setjmp' 1263: jmp (r0) # ``rsb'' 1264: 1265: .data 1266: newpc: .space 4 1267: newfp: .space 4 1268: 4: .asciz "longjmp" 1269: .text 1270: /* 1271: * setjmp that saves all registers as the call frame may not 1272: * be available to recover them in the usual mannor by longjmp. 1273: * Called before swapping out the u. area, restored by resume() 1274: * below. 1275: */ 1276: ENTRY(savectx, 0) 1277: movl 4(ap),r0 1278: movq r6,(r0)+ 1279: movq r8,(r0)+ 1280: movq r10,(r0)+ 1281: movq APLOC(fp),(r0)+ # save ap, fp 1282: addl3 $8,ap,(r0)+ # save sp 1283: movl PCLOC(fp),(r0) # save pc 1284: clrl r0 1285: ret 1286: 1287: .globl _whichqs 1288: .globl _qs 1289: .globl _cnt 1290: 1291: .globl _noproc 1292: .comm _noproc,4 1293: .globl _runrun 1294: .comm _runrun,4 1295: 1296: /* 1297: * The following primitives use the fancy VAX instructions 1298: * much like VMS does. _whichqs tells which of the 32 queues _qs 1299: * have processes in them. Setrq puts processes into queues, Remrq 1300: * removes them from queues. The running process is on no queue, 1301: * other processes are on a queue related to p->p_pri, divided by 4 1302: * actually to shrink the 0-127 range of priorities into the 32 available 1303: * queues. 1304: */ 1305: 1306: /* 1307: * Setrq(p), using fancy VAX instructions. 1308: * 1309: * Call should be made at splclock(), and p->p_stat should be SRUN 1310: */ 1311: .align 1 1312: JSBENTRY(Setrq, R0) 1313: tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0 1314: beql set1 ## 1315: pushab set3 ## 1316: calls $1,_panic ## 1317: set1: 1318: movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4 1319: ashl $-2,r1,r1 1320: movaq _qs[r1],r2 1321: insque (r0),*4(r2) # at end of queue 1322: bbss r1,_whichqs,set2 # mark queue non-empty 1323: set2: 1324: rsb 1325: 1326: set3: .asciz "setrq" 1327: 1328: /* 1329: * Remrq(p), using fancy VAX instructions 1330: * 1331: * Call should be made at splclock(). 1332: */ 1333: .align 1 1334: JSBENTRY(Remrq, R0) 1335: movzbl P_PRI(r0),r1 1336: ashl $-2,r1,r1 1337: bbsc r1,_whichqs,rem1 1338: pushab rem3 # it wasn't recorded to be on its q 1339: calls $1,_panic 1340: rem1: 1341: remque (r0),r2 1342: beql rem2 1343: bbss r1,_whichqs,rem2 1344: rem2: 1345: clrl P_RLINK(r0) ## for firewall checking 1346: rsb 1347: 1348: rem3: .asciz "remrq" 1349: 1350: /* 1351: * Masterpaddr is the p->p_addr of the running process on the master 1352: * processor. When a multiprocessor system, the slave processors will have 1353: * an array of slavepaddr's. 1354: */ 1355: .globl _masterpaddr 1356: .data 1357: _masterpaddr: 1358: .long 0 1359: 1360: .set ASTLVL_NONE,4 1361: .text 1362: sw0: .asciz "swtch" 1363: 1364: /* 1365: * When no processes are on the runq, Swtch branches to idle 1366: * to wait for something to come ready. 1367: */ 1368: .globl Idle 1369: Idle: idle: 1370: mtpr $0,$IPL # must allow interrupts here 1371: tstl _whichqs # look for non-empty queue 1372: bneq sw1 1373: brb idle 1374: 1375: badsw: pushab sw0 1376: calls $1,_panic 1377: /*NOTREACHED*/ 1378: 1379: /* 1380: * Swtch(), using fancy VAX instructions 1381: */ 1382: .align 1 1383: JSBENTRY(Swtch, 0) 1384: movl $1,_noproc 1385: incl _cnt+V_SWTCH 1386: sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue 1387: beql idle # if none, idle 1388: mtpr $0x18,$IPL # lock out all so _whichqs==_qs 1389: bbcc r0,_whichqs,sw1 # proc moved via lbolt interrupt 1390: movaq _qs[r0],r1 1391: remque *(r1),r2 # r2 = p = highest pri process 1392: bvs badsw # make sure something was there 1393: sw2: beql sw3 1394: insv $1,r0,$1,_whichqs # still more procs in this queue 1395: sw3: 1396: clrl _noproc 1397: clrl _runrun 1398: tstl P_WCHAN(r2) ## firewalls 1399: bneq badsw ## 1400: cmpb P_STAT(r2),$SRUN ## 1401: bneq badsw ## 1402: clrl P_RLINK(r2) ## 1403: movl *P_ADDR(r2),r0 1404: #ifdef notdef 1405: cmpl r0,_masterpaddr # resume of current proc is easy 1406: beql res0 1407: #endif 1408: movl r0,_masterpaddr 1409: ashl $PGSHIFT,r0,r0 # r0 = pcbb(p) 1410: /* fall into... */ 1411: 1412: /* 1413: * Resume(pf) 1414: */ 1415: JSBENTRY(Resume, R0) 1416: mtpr $HIGH,$IPL # no interrupts, please 1417: movl _CMAP2,_u+PCB_CMAP2 # yech 1418: svpctx 1419: mtpr r0,$PCBB 1420: ldpctx 1421: movl _u+PCB_CMAP2,_CMAP2 # yech 1422: mtpr $_CADDR2,$TBIS 1423: res0: 1424: tstl _u+PCB_SSWAP 1425: bneq res1 1426: rei 1427: res1: 1428: movl _u+PCB_SSWAP,r0 # longjmp to saved context 1429: clrl _u+PCB_SSWAP 1430: movq (r0)+,r6 1431: movq (r0)+,r8 1432: movq (r0)+,r10 1433: movq (r0)+,r12 1434: movl (r0)+,r1 1435: cmpl r1,sp # must be a pop 1436: bgequ 1f 1437: pushab 2f 1438: calls $1,_panic 1439: /* NOTREACHED */ 1440: 1: 1441: movl r1,sp 1442: movl (r0),(sp) # address to return to 1443: movl $PSL_PRVMOD,4(sp) # ``cheating'' (jfr) 1444: rei 1445: 1446: 2: .asciz "ldctx" 1447: 1448: /* 1449: * {fu,su},{byte,word}, all massaged by asm.sed to jsb's 1450: */ 1451: .align 1 1452: JSBENTRY(Fuword, R0) 1453: prober $3,$4,(r0) 1454: beql fserr 1455: movl (r0),r0 1456: rsb 1457: fserr: 1458: mnegl $1,r0 1459: rsb 1460: 1461: .align 1 1462: JSBENTRY(Fubyte, R0) 1463: prober $3,$1,(r0) 1464: beql fserr 1465: movzbl (r0),r0 1466: rsb 1467: 1468: .align 1 1469: JSBENTRY(Suword, R0|R1) 1470: probew $3,$4,(r0) 1471: beql fserr 1472: movl r1,(r0) 1473: clrl r0 1474: rsb 1475: 1476: .align 1 1477: JSBENTRY(Subyte, R0|R1) 1478: probew $3,$1,(r0) 1479: beql fserr 1480: movb r1,(r0) 1481: clrl r0 1482: rsb 1483: 1484: /* 1485: * Copy 1 relocation unit (NBPG bytes) 1486: * from user virtual address to physical address 1487: */ 1488: ENTRY(copyseg, 0) 1489: bisl3 $PG_V|PG_KW,8(ap),_CMAP2 1490: mtpr $_CADDR2,$TBIS # invalidate entry for copy 1491: movc3 $NBPG,*4(ap),_CADDR2 1492: ret 1493: 1494: /* 1495: * zero out physical memory 1496: * specified in relocation units (NBPG bytes) 1497: */ 1498: ENTRY(clearseg, 0) 1499: bisl3 $PG_V|PG_KW,4(ap),_CMAP1 1500: mtpr $_CADDR1,$TBIS 1501: movc5 $0,(sp),$0,$NBPG,_CADDR1 1502: ret 1503: 1504: /* 1505: * Check address. 1506: * Given virtual address, byte count, and rw flag 1507: * returns 0 on no access. 1508: */ 1509: ENTRY(useracc, 0) 1510: movl 4(ap),r0 # get va 1511: movl 8(ap),r1 # count 1512: tstl 12(ap) # test for read access ? 1513: bneq userar # yes 1514: cmpl $NBPG,r1 # can we do it in one probe ? 1515: bgeq uaw2 # yes 1516: uaw1: 1517: probew $3,$NBPG,(r0) 1518: beql uaerr # no access 1519: addl2 $NBPG,r0 1520: acbl $NBPG+1,$-NBPG,r1,uaw1 1521: uaw2: 1522: probew $3,r1,(r0) 1523: beql uaerr 1524: movl $1,r0 1525: ret 1526: 1527: userar: 1528: cmpl $NBPG,r1 1529: bgeq uar2 1530: uar1: 1531: prober $3,$NBPG,(r0) 1532: beql uaerr 1533: addl2 $NBPG,r0 1534: acbl $NBPG+1,$-NBPG,r1,uar1 1535: uar2: 1536: prober $3,r1,(r0) 1537: beql uaerr 1538: movl $1,r0 1539: ret 1540: uaerr: 1541: clrl r0 1542: ret 1543: 1544: /* 1545: * kernacc - check for kernel access privileges 1546: * 1547: * We can't use the probe instruction directly because 1548: * it ors together current and previous mode. 1549: */ 1550: ENTRY(kernacc, 0) 1551: movl 4(ap),r0 # virtual address 1552: bbcc $31,r0,kacc1 1553: bbs $30,r0,kacerr 1554: mfpr $SBR,r2 # address and length of page table (system) 1555: bbss $31,r2,0f; 0: 1556: mfpr $SLR,r3 1557: brb kacc2 1558: kacc1: 1559: bbsc $30,r0,kacc3 1560: mfpr $P0BR,r2 # user P0 1561: mfpr $P0LR,r3 1562: brb kacc2 1563: kacc3: 1564: mfpr $P1BR,r2 # user P1 (stack) 1565: mfpr $P1LR,r3 1566: kacc2: 1567: addl3 8(ap),r0,r1 # ending virtual address 1568: addl2 $NBPG-1,r1 1569: ashl $-PGSHIFT,r0,r0 1570: ashl $-PGSHIFT,r1,r1 1571: bbs $31,4(ap),kacc6 1572: bbc $30,4(ap),kacc6 1573: cmpl r0,r3 # user stack 1574: blss kacerr # address too low 1575: brb kacc4 1576: kacc6: 1577: cmpl r1,r3 # compare last page to P0LR or SLR 1578: bgtr kacerr # address too high 1579: kacc4: 1580: movl (r2)[r0],r3 1581: bbc $31,4(ap),kacc4a 1582: bbc $31,r3,kacerr # valid bit is off 1583: kacc4a: 1584: cmpzv $27,$4,r3,$1 # check protection code 1585: bleq kacerr # no access allowed 1586: tstb 12(ap) 1587: bneq kacc5 # only check read access 1588: cmpzv $27,$2,r3,$3 # check low 2 bits of prot code 1589: beql kacerr # no write access 1590: kacc5: 1591: aoblss r1,r0,kacc4 # next page 1592: movl $1,r0 # no errors 1593: ret 1594: kacerr: 1595: clrl r0 # error 1596: ret 1597: /* 1598: * Extracted and unrolled most common case of pagein (hopefully): 1599: * resident and not on free list (reclaim of page is purely 1600: * for the purpose of simulating a reference bit) 1601: * 1602: * Built in constants: 1603: * CLSIZE of 2, any bit fields in pte's 1604: */ 1605: .text 1606: .globl Fastreclaim 1607: Fastreclaim: 1608: PUSHR 1609: #ifdef GPROF 1610: movl fp,-(sp) 1611: movab 12(sp),fp 1612: jsb mcount 1613: movl (sp)+,fp 1614: #endif GPROF 1615: extzv $9,$23,28(sp),r3 # virtual address 1616: bicl2 $1,r3 # v = clbase(btop(virtaddr)); 1617: movl _u+U_PROCP,r5 # p = u.u_procp 1618: # from vtopte(p, v) ... 1619: movl $1,r2 # type = CTEXT; 1620: cmpl r3,P_TSIZE(r5) 1621: jlssu 1f # if (isatsv(p, v)) { 1622: addl3 P_TSIZE(r5),P_DSIZE(r5),r0 1623: cmpl r3,r0 1624: jgequ 2f 1625: clrl r2 # type = !CTEXT; 1626: 1: 1627: ashl $2,r3,r4 1628: addl2 P_P0BR(r5),r4 # tptopte(p, vtotp(p, v)); 1629: jbr 3f 1630: 2: 1631: cvtwl P_SZPT(r5),r4 # } else (isassv(p, v)) { 1632: ashl $7,r4,r4 1633: subl2 $0x400000,r4 1634: addl2 r3,r4 1635: ashl $2,r4,r4 1636: addl2 P_P0BR(r5),r4 # sptopte(p, vtosp(p, v)); 1637: clrl r2 # type = !CTEXT; 1638: 3: # } 1639: bitb $0x82,3(r4) 1640: beql 2f # if (pte->pg_v || pte->pg_fod) 1641: POPR; rsb # let pagein handle it 1642: 2: 1643: bicl3 $0xffe00000,(r4),r0 1644: jneq 2f # if (pte->pg_pfnum == 0) 1645: POPR; rsb # let pagein handle it 1646: 2: 1647: subl2 _firstfree,r0 1648: ashl $-1,r0,r0 1649: incl r0 # pgtocm(pte->pg_pfnum) 1650: mull2 $SZ_CMAP,r0 1651: addl2 _cmap,r0 # &cmap[pgtocm(pte->pg_pfnum)] 1652: tstl r2 1653: jeql 2f # if (type == CTEXT && 1654: jbc $C_INTRANS,(r0),2f # c_intrans) 1655: POPR; rsb # let pagein handle it 1656: 2: 1657: jbc $C_FREE,(r0),2f # if (c_free) 1658: POPR; rsb # let pagein handle it 1659: 2: 1660: bisb2 $0x80,3(r4) # pte->pg_v = 1; 1661: jbc $26,4(r4),2f # if (anycl(pte, pg_m) 1662: bisb2 $0x04,3(r4) # pte->pg_m = 1; 1663: 2: 1664: bicw3 $0x7f,2(r4),r0 1665: bicw3 $0xff80,6(r4),r1 1666: bisw3 r0,r1,6(r4) # distcl(pte); 1667: ashl $PGSHIFT,r3,r0 1668: mtpr r0,$TBIS 1669: addl2 $NBPG,r0 1670: mtpr r0,$TBIS # tbiscl(v); 1671: tstl r2 1672: jeql 2f # if (type == CTEXT) 1673: movl P_TEXTP(r5),r0 1674: movl X_CADDR(r0),r5 # for (p = p->p_textp->x_caddr; p; ) { 1675: jeql 2f 1676: ashl $2,r3,r3 1677: 3: 1678: addl3 P_P0BR(r5),r3,r0 # tpte = tptopte(p, tp); 1679: bisb2 $1,P_FLAG+3(r5) # p->p_flag |= SPTECHG; 1680: movl (r4),(r0)+ # for (i = 0; i < CLSIZE; i++) 1681: movl 4(r4),(r0) # tpte[i] = pte[i]; 1682: movl P_XLINK(r5),r5 # p = p->p_xlink; 1683: jneq 3b # } 1684: 2: # collect a few statistics... 1685: incl _u+U_RU+RU_MINFLT # u.u_ru.ru_minflt++; 1686: moval _cnt,r0 1687: incl V_FAULTS(r0) # cnt.v_faults++; 1688: incl V_PGREC(r0) # cnt.v_pgrec++; 1689: incl V_FASTPGREC(r0) # cnt.v_fastpgrec++; 1690: incl V_TRAP(r0) # cnt.v_trap++; 1691: POPR 1692: addl2 $8,sp # pop pc, code 1693: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 1694: rei