1: /* 2: * SCCS id @(#)machdep.c 2.1 (Berkeley) 11/20/83 3: */ 4: 5: #include "param.h" 6: #include <sys/systm.h> 7: #include <sys/acct.h> 8: #include <sys/dir.h> 9: #include <sys/user.h> 10: #include <sys/inode.h> 11: #include <sys/proc.h> 12: #include <sys/seg.h> 13: #include <sys/map.h> 14: #include <sys/reg.h> 15: #include <sys/buf.h> 16: #include <sys/tty.h> 17: #ifdef UCB_AUTOBOOT 18: #include <sys/reboot.h> 19: #endif 20: #include <sys/uba.h> 21: #include <sys/iopage.h> 22: 23: extern memaddr bpaddr; 24: 25: #ifndef NOKA5 26: segm seg5; /* filled in by initialization */ 27: #endif 28: 29: #ifdef UCB_CLIST 30: extern memaddr clststrt; 31: #else 32: extern struct cblock cfree[]; 33: #endif UCB_CLIST 34: extern ubadr_t clstaddr; 35: #ifdef UCB_NET 36: extern memaddr mbbase; 37: extern int mbsize; 38: #endif 39: 40: #ifdef UCB_AUTOBOOT 41: int bootflags, checkword; /* saved from r4, r2 by mch.s */ 42: #endif 43: 44: /* 45: * Icode is the octal bootstrap 46: * program executed in user mode 47: * to bring up the system. 48: */ 49: int icode[] = 50: { 51: #ifdef UCB_AUTOBOOT 52: 0104413, /* sys exec; init; initp */ 53: 0000016, 54: 0000010, 55: 0104401, /* sys exit */ 56: 0000016, /* initp: init; bootopts; 0 */ 57: 0000030, 58: 0000000, 59: 0062457, /* init: </etc/init\0> */ 60: 0061564, 61: 0064457, 62: 0064556, 63: 0000164, 64: RB_SINGLE, /* bootopts: RB_SINGLE */ 65: 0000000 66: #define ICODE_OPTS 12 /* location of bootopts in icode */ 67: #else 68: 0104413, /* sys exec; init; initp */ 69: 0000014, 70: 0000010, 71: 0104401, /* sys exit */ 72: 0000014, /* initp: init; 0 */ 73: 0000000, 74: 0062457, /* init: </etc/init\0> */ 75: 0061564, 76: 0064457, 77: 0064556, 78: 0000164, 79: #endif UCB_AUTOBOOT 80: }; 81: int szicode = sizeof (icode); 82: 83: size_t physmem; /* total amount of physical memory (for savecore) */ 84: 85: 86: /* 87: * Machine dependent startup code 88: */ 89: startup() 90: { 91: register memaddr i, freebase; 92: extern end; 93: 94: #ifndef NOKA5 95: saveseg5(seg5); /* must be done before clear() is called */ 96: if (&remap_area > SEG5) 97: panic("&remap_area > 0120000"); 98: #else 99: if (&end > SEG5) 100: panic("_end > 0120000"); 101: #endif 102: 103: /* 104: * zero and free all of core 105: */ 106: i = freebase = *ka6 + USIZE; 107: UISD[0] = ((stoc(1) - 1) << 8) | RW; 108: for (;;) { 109: UISA[0] = i; 110: if (fuibyte((caddr_t)0) < 0) 111: break; 112: maxmem++; 113: i++; 114: /* 115: * avoid testing locations on the IO page if possible, 116: * since some people have dz's at 0160000 (0760000). 117: * Note that more than 248K of memory is not currently 118: * supported without a Unibus map anyway. 119: * (3968 is btoc(248K); the macro doesn't do longs.) 120: */ 121: if (!ubmap && i >= 3968) 122: break; 123: } 124: clear(freebase, i - freebase); 125: mfree(coremap, i - freebase, freebase); 126: physmem = i; 127: #define B (size_t)(((long)nbuf * (bsize)) / ctob(1)) 128: if ((bpaddr = malloc(coremap, B)) == 0) 129: panic("buffers"); 130: maxmem -= B; 131: #undef B 132: 133: #ifdef UCB_CLIST 134: #define C (nclist * sizeof(struct cblock)) 135: if ((clststrt = malloc(coremap, btoc(C))) == 0) 136: panic("clists"); 137: maxmem -= btoc(C); 138: clstaddr = ((ubadr_t) clststrt) << 6; 139: #undef C 140: #else 141: clstaddr = (ubadr_t) &cfree; 142: #endif UCB_CLIST 143: 144: #if defined(PROFILE) && !defined(ENABLE34) 145: maxmem -= msprof(); 146: #endif defined(PROFILE) && !defined(ENABLE34) 147: 148: #ifdef UCB_NET 149: if ((mbbase = malloc(coremap, btoc(mbsize))) == 0) 150: panic("mbbase"); 151: maxmem -= btoc(mbsize); 152: #endif 153: 154: printf("mem = %D\n", ctob((long)maxmem)); 155: if (MAXMEM < maxmem) 156: maxmem = MAXMEM; 157: mfree(swapmap, nswap, 1); 158: swplo--; 159: 160: UISA[7] = ka6[1]; /* io segment */ 161: UISD[7] = ((stoc(1) - 1) << 8) | RW; 162: #ifdef UCB_AUTOBOOT 163: if (checkword == ~bootflags) 164: icode[ICODE_OPTS] = bootflags; 165: #endif UCB_AUTOBOOT 166: } 167: 168: #if defined(PROFILE) && !defined(ENABLE34) 169: /* 170: * Allocate memory for system profiling. Called 171: * once at boot time. Returns number of clicks 172: * used by profiling. 173: * 174: * The system profiler uses supervisor I space registers 2 and 3 175: * (virtual addresses 040000 through 0100000) to hold the profile. 176: */ 177: 178: static int nproclicks; 179: memaddr proloc; 180: 181: msprof() 182: { 183: nproclicks = btoc(8192*2); 184: proloc = malloc(coremap, nproclicks); 185: if (proloc == 0) 186: panic("msprof"); 187: 188: *SISA2 = proloc; 189: *SISA3 = proloc + btoc(8192); 190: *SISD2 = 077400|RW; 191: *SISD3 = 077400|RW; 192: *SISD0 = RW; 193: *SISD1 = RW; 194: 195: esprof(); 196: return (nproclicks); 197: } 198: 199: /* 200: * Enable system profiling. 201: * Zero out the profile buffer and then turn the 202: * clock (KW11-P) on. 203: */ 204: esprof() 205: { 206: clear(proloc, nproclicks); 207: isprof(); 208: printf("profiling on\n"); 209: } 210: #endif defined(PROFILE) && !defined(ENABLE34) 211: 212: #ifdef UNIBUS_MAP 213: /* 214: * Re-initialize the Unibus map registers to statically map 215: * the clists and buffers. Free the remaining registers for 216: * physical I/O. 217: */ 218: void 219: ubinit() 220: { 221: long paddr; 222: register i, ub_nreg; 223: extern struct map ub_map[]; 224: #ifdef UCB_NET 225: extern int ub_inited; 226: #endif 227: 228: if (!ubmap) 229: return; 230: #ifdef UCB_NET 231: ub_inited++; 232: #endif 233: /* 234: * Clists start at UNIBUS virtual address 0. The size of 235: * the clist segment can be no larger than UBPAGE bytes. 236: * Clstaddt was the physical address of clists. 237: */ 238: if (nclist * sizeof (struct cblock) > ctob(stoc(1))) 239: panic("clist area too large"); 240: setubregno(0, clstaddr); 241: clstaddr = (ubadr_t) 0; 242: 243: /* 244: * Buffers start at UNIBUS virtual address BUF_UBADDR. 245: */ 246: paddr = ((long) bpaddr) << 6; 247: ub_nreg = nubreg(nbuf, bsize); 248: for (i = BUF_UBADDR / UBPAGE; i < ub_nreg + (BUF_UBADDR/UBPAGE); i++) { 249: setubregno(i, paddr); 250: paddr += (long) UBPAGE; 251: } 252: mfree(ub_map, 31 - ub_nreg - 1, 1 + ub_nreg); 253: } 254: #endif UNIBUS_MAP 255: 256: /* 257: * set up a physical address 258: * into users virtual address space. 259: */ 260: sysphys() 261: { 262: int d; 263: register i, s; 264: register struct a { 265: int segno; 266: int size; 267: int phys; 268: } *uap; 269: 270: if (!suser()) 271: return; 272: uap = (struct a *)u.u_ap; 273: i = uap->segno; 274: if (i < 0 || i >= 8) 275: goto bad; 276: s = uap->size; 277: if (s < 0 || s > 128) 278: goto bad; 279: #ifdef NONSEPARATE 280: d = u.u_uisd[i]; 281: #else 282: d = u.u_uisd[i + 8]; 283: #endif NONSEPARATE 284: if (d != 0 && (d & ABS) == 0) 285: goto bad; 286: #ifdef NONSEPARATE 287: u.u_uisd[i] = 0; 288: u.u_uisa[i] = 0; 289: #else 290: u.u_uisd[i + 8] = 0; 291: u.u_uisa[i + 8] = 0; 292: if (!u.u_sep) { 293: u.u_uisd[i] = 0; 294: u.u_uisa[i] = 0; 295: } 296: #endif NONSEPARATE 297: if (s) { 298: #ifdef NONSEPARATE 299: u.u_uisd[i] = ((s - 1) << 8) | RW | ABS; 300: u.u_uisa[i] = uap->phys; 301: #else 302: u.u_uisd[i + 8] = ((s - 1) << 8) | RW | ABS; 303: u.u_uisa[i + 8] = uap->phys; 304: if (!u.u_sep) { 305: u.u_uisa[i] = u.u_uisa[i + 8]; 306: u.u_uisd[i] = u.u_uisd[i + 8]; 307: } 308: #endif NONSEPARATE 309: } 310: sureg(); 311: return; 312: 313: bad: 314: u.u_error = EINVAL; 315: } 316: 317: /* 318: * Determine whether clock is attached. If so, start it. 319: */ 320: clkstart() 321: { 322: lks = LKS; 323: if (fioword((caddr_t)lks) == -1) { 324: lks = KW11P_CSR; 325: if (fioword((caddr_t)lks) == -1) { 326: printf("no clock??\n"); 327: lks = 0; 328: } 329: } 330: if (lks) 331: *lks = 0115; 332: } 333: 334: #ifndef ENABLE34 335: /* 336: * Fetch a word from an address on the I/O page, 337: * returning -1 if address does not exist. 338: */ 339: fioword(addr) 340: { 341: register val, saveUI7, saveUD7; 342: 343: saveUI7 = UISA[7]; 344: saveUD7 = UISD[7]; 345: UISA[7] = ka6[1]; /* io segment */ 346: UISD[7] = ((stoc(1) - 1) << 8) | RW; 347: val = fuiword(addr); 348: UISA[7] = saveUI7; 349: UISD[7] = saveUD7; 350: return(val); 351: } 352: #endif 353: 354: /* 355: * Let a process handle a signal by simulating an interrupt 356: */ 357: sendsig(p) 358: caddr_t p; 359: { 360: register unsigned n; 361: 362: n = u.u_ar0[R6] - 4; 363: if (n >= -ctob(u.u_ssize) || grow(n)) { 364: suword((caddr_t)n + 2, u.u_ar0[RPS]); 365: suword((caddr_t)n, u.u_ar0[R7]); 366: u.u_ar0[R6] = n; 367: u.u_ar0[RPS] &= ~PS_T; 368: u.u_ar0[R7] = (int)p; 369: } else { 370: /* 371: * Process has trashed its stack. 372: * Blow him away. 373: */ 374: u.u_signal[SIGSEGV] = SIG_DFL; 375: #ifdef MENLO_JCL 376: u.u_procp->p_cursig = SIGSEGV; 377: psig(); 378: #else 379: psignal(u.u_procp, SIGSEGV); 380: #endif 381: } 382: } 383: 384: #ifdef MENLO_JCL 385: /* 386: * Simulate a return from interrupt on return from the syscall. 387: * after popping n words of the users stack. 388: */ 389: dorti(n) 390: { 391: register int opc, ops; 392: 393: u.u_ar0[R6] += n * sizeof(int); 394: 395: if (((opc = fuword((caddr_t)u.u_ar0[R6])) == -1) 396: || ((ops = fuword((caddr_t)(u.u_ar0[R6] + sizeof(int)))) == -1)) 397: psignal(u.u_procp, SIGSEGV); 398: else { 399: u.u_ar0[R6] += 2 * sizeof(int); 400: u.u_ar0[PC] = opc; 401: ops |= PS_CURMOD | PS_PRVMOD; /* assure user space */ 402: ops &= ~PS_USERCLR; /* priority 0 */ 403: u.u_ar0[RPS] = ops; 404: } 405: } 406: #endif MENLO_JCL 407: 408: #ifdef UNIBUS_MAP 409: 410: int ub_wantmr; 411: 412: #define UMAPSIZ 10 413: struct mapent _ubmap[UMAPSIZ]; 414: struct map ub_map[1] = { 415: &_ubmap[0], &_ubmap[UMAPSIZ], "ub_map" 416: }; 417: 418: #ifdef UCB_METER 419: struct ubmeter { 420: long ub_requests; /* total # of calls to mapalloc */ 421: long ub_remaps; /* total # of buffer remappings */ 422: long ub_failures; /* total # of allocation failures */ 423: long ub_pages; /* total # of pages allocated */ 424: 425: } ub_meter; 426: #endif 427: 428: /* 429: * Routine to allocate the UNIBUS map 430: * and initialize for a UNIBUS device. 431: * For buffers already mapped by the UNIBUS map, 432: * perform the physical-to-UNIBUS-virtual address translation. 433: */ 434: mapalloc(bp) 435: register struct buf *bp; 436: { 437: long paddr; 438: ubadr_t ubaddr; 439: int s, ub_nregs; 440: register ub_first; 441: register struct ubmap *ubp; 442: extern memaddr bpaddr; 443: 444: if (!ubmap) 445: return; 446: #if defined(UNIBUS_MAP) && defined(UCB_METER) 447: ub_meter.ub_requests++; 448: #endif 449: paddr = ((long) ((unsigned) bp->b_xmem)) << 16 450: | ((long) ((unsigned) bp->b_un.b_addr)); 451: if ((bp->b_flags & B_PHYS) == 0) { 452: /* 453: * Transfer in the buffer cache. 454: * Change the buffer's physical address 455: * into a UNIBUS address for the driver. 456: */ 457: #if defined(UNIBUS_MAP) && defined(UCB_METER) 458: ub_meter.ub_remaps++; 459: #endif 460: ubaddr = paddr - (((ubadr_t) bpaddr) << 6) + BUF_UBADDR; 461: bp->b_un.b_addr = loint(ubaddr); 462: bp->b_xmem = hiint(ubaddr); 463: bp->b_flags |= B_UBAREMAP; 464: } else { 465: /* 466: * Physical I/O. 467: * Allocate a section of the UNIBUS map. 468: */ 469: ub_nregs = (int) btoub(bp->b_bcount); 470: #if defined(UNIBUS_MAP) && defined(UCB_METER) 471: ub_meter.ub_pages += ub_nregs; 472: #endif 473: s = spl6(); 474: while ((ub_first = malloc(ub_map, ub_nregs)) == NULL) { 475: ub_wantmr = 1; 476: #if defined(UNIBUS_MAP) && defined(UCB_METER) 477: ub_meter.ub_failures++; 478: #endif 479: sleep(ub_map, PSWP + 1); 480: } 481: splx(s); 482: 483: ubp = &UBMAP[ub_first]; 484: bp->b_xmem = ub_first >> 3; 485: bp->b_un.b_addr = (ub_first & 07) << 13; 486: bp->b_flags |= B_MAP; 487: 488: while (ub_nregs--) { 489: ubp->ub_lo = loint(paddr); 490: ubp->ub_hi = hiint(paddr); 491: ubp++; 492: paddr += (ubadr_t) UBPAGE; 493: } 494: } 495: } 496: 497: mapfree(bp) 498: register struct buf *bp; 499: { 500: register s; 501: extern memaddr bpaddr; 502: long paddr; 503: ubadr_t ubaddr; 504: 505: if (bp->b_flags & B_MAP) { 506: /* 507: * Free the UNIBUS map registers 508: * allocated to this buffer. 509: */ 510: s = spl6(); 511: mfree(ub_map, (int) btoub(bp->b_bcount), 512: (bp->b_xmem << 3) | ((bp->b_un.b_addr >> 13) & 07)); 513: splx(s); 514: bp->b_flags &= ~B_MAP; 515: if (ub_wantmr) 516: wakeup((caddr_t) ub_map); 517: ub_wantmr = 0; 518: } else if (bp->b_flags & B_UBAREMAP) { 519: /* 520: * Translate the UNIBUS virtual address of this buffer 521: * back to a physical memory address. 522: */ 523: ubaddr = ((long) ((unsigned) bp->b_xmem)) << 16 524: | ((long) ((unsigned) bp->b_un.b_addr)); 525: paddr = ubaddr - (long) BUF_UBADDR 526: + (((long) bpaddr) << 6); 527: bp->b_un.b_addr = loint(paddr); 528: bp->b_xmem = hiint(paddr); 529: bp->b_flags &= ~B_UBAREMAP; 530: } 531: } 532: #endif UNIBUS_MAP 533: 534: #ifndef NOKA5 535: /* 536: * Save the current kernel mapping and set it to the normal map. 537: * Called at interrupt time to access proc, text or file structures 538: * or the user structure. 539: * Called only if *KDSA5 != seg5.se_addr from the macro savemap. 540: * If NOKA5 is defined, the macro does the whole job. 541: */ 542: Savemap(map) 543: register mapinfo map; 544: { 545: map[0].se_addr = *KDSA5; 546: map[0].se_desc = *KDSD5; 547: if (kdsa6) { 548: map[1].se_addr = *KDSA6; 549: map[1].se_desc = *KDSD6; 550: *KDSD6 = KD6; 551: *KDSA6 = kdsa6; 552: } else 553: map[1].se_desc = NOMAP; 554: restorseg5(seg5); 555: } 556: 557: /* 558: * Restore the mapping information saved above. 559: * Called only if map[0].se_desc != NOMAP (from macro restormap). 560: */ 561: Restormap(map) 562: register mapinfo map; 563: { 564: *KDSA5 = map[0].se_addr; 565: *KDSD5 = map[0].se_desc; 566: if (map[1].se_desc != NOMAP) { 567: *KDSD6 = map[1].se_desc; 568: *KDSA6 = map[1].se_addr; 569: } 570: } 571: #endif NOKA5 572: 573: #if !defined(NOKA5) && defined(DIAGNOSTIC) 574: struct buf *hasmap; 575: #endif 576: 577: /* 578: * Map in an out-of-address space buffer. 579: * If this is done from interrupt level, 580: * the previous map must be saved before mapin, 581: * and restored after mapout; e.g. 582: * segm save; 583: * saveseg5(save); 584: * mapin(bp); 585: * ... 586: * mapout(bp); 587: * restorseg5(save); 588: */ 589: #ifdef UCB_NET 590: segm Bmapsave; 591: # ifdef NOKA5 592: ERROR! /* NOKA5 must not be defined with the net for now. */ 593: # endif 594: #endif 595: caddr_t 596: mapin(bp) 597: register struct buf *bp; 598: { 599: register caddr_t paddr; 600: register caddr_t offset; 601: 602: #ifdef UCB_NET 603: saveseg5(Bmapsave); 604: #endif 605: #if !defined(NOKA5) && defined(DIAGNOSTIC) 606: if (hasmap != (struct buf *) 0) { 607: printf("mapping %o over %o\n", bp, hasmap); 608: panic("mapin"); 609: } 610: hasmap = bp; 611: #endif 612: offset = bp->b_un.b_addr & 077; 613: paddr = (bp->b_un.b_addr >> 6) & 01777; 614: paddr |= bp->b_xmem << 10; 615: mapseg5(paddr, (BSIZE << 2) | RW); 616: return(SEG5 + offset); 617: } 618: 619: #ifndef NOKA5 620: void 621: mapout(bp) 622: register struct buf *bp; 623: { 624: #ifdef DIAGNOSTIC 625: if (bp != hasmap) { 626: printf("unmapping %o, not %o\n", bp, hasmap); 627: panic("mapout"); 628: } 629: hasmap = (struct buf *) NULL; 630: #endif 631: #ifndef UCB_NET 632: normalseg5(); 633: #else 634: restorseg5(Bmapsave); 635: #endif 636: } 637: #endif NOKA5 638: 639: #ifdef UCB_AUTOBOOT 640: void 641: boot(dev, howto) 642: dev_t dev; 643: int howto; 644: { 645: if ((howto & RB_NOSYNC) == 0 && bfreelist.b_forw) { 646: printf("syncing disks ... "); 647: update(); 648: delay(5); 649: printf("done\n\n"); 650: } 651: (void) _spl7(); 652: if (howto & RB_HALT) { 653: printf("halting\n"); 654: halt(); 655: /*NOTREACHED*/ 656: } else { 657: if (howto & RB_DUMP) { 658: /* 659: * save the registers in low core. 660: */ 661: saveregs(); 662: dumpsys(); 663: } 664: doboot(dev, howto); 665: /*NOTREACHED*/ 666: } 667: } 668: 669: /* 670: * wait for time "del", approximately in seconds. 671: * Used to avoid rescheduling from sleep(). 672: */ 673: delay(del) 674: int del; 675: { 676: register i, j; 677: 678: while (del--) { 679: for (i=10; i>0; --i) 680: for (j=32000; j>0; --j) 681: ; 682: } 683: } 684: 685: /* 686: * Dumpsys takes a dump of memory by calling (*dump)(), which must 687: * correspond to dumpdev. *(dump)() should dump from dumplo blocks 688: * to the end of memory or to the end of the logical device. 689: */ 690: dumpsys() 691: { 692: extern int (*dump)(); 693: 694: if (dumpdev != NODEV) { 695: printf("\ndumping to dev %o, offset %D\n", dumpdev, dumplo); 696: printf("dump "); 697: switch ((*dump)(dumpdev)) { 698: 699: case EFAULT: 700: printf("device not ready\n"); 701: break; 702: case EINVAL: 703: printf("arguments invalid\n"); 704: break; 705: case EIO: 706: printf("I/O error\n"); 707: break; 708: default: 709: printf("error(?)\n"); 710: break; 711: case 0: 712: printf("succeeded\n"); 713: return (1); 714: } 715: } 716: return (0); /* failure */ 717: } 718: #endif UCB_AUTOBOOT 719: 720: /* 721: * lock user into core as much 722: * as possible. swapping may still 723: * occur if core grows. 724: */ 725: syslock() 726: { 727: register struct proc *p; 728: struct a { 729: int flag; 730: }; 731: 732: if (suser()) { 733: p = u.u_procp; 734: p->p_flag &= ~SULOCK; 735: if (((struct a *)u.u_ap)->flag) 736: p->p_flag |= SULOCK; 737: } 738: }