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