|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982,1986,1988 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)machdep.c 7.14 (Berkeley) 5/26/88 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "dir.h" ! 12: #include "user.h" ! 13: #include "kernel.h" ! 14: #include "malloc.h" ! 15: #include "map.h" ! 16: #include "vm.h" ! 17: #include "proc.h" ! 18: #include "buf.h" ! 19: #include "reboot.h" ! 20: #include "conf.h" ! 21: #include "inode.h" ! 22: #include "file.h" ! 23: #include "text.h" ! 24: #include "clist.h" ! 25: #include "callout.h" ! 26: #include "cmap.h" ! 27: #include "mbuf.h" ! 28: #include "msgbuf.h" ! 29: #include "quota.h" ! 30: ! 31: #include "reg.h" ! 32: #include "pte.h" ! 33: #include "psl.h" ! 34: #include "frame.h" ! 35: #include "clock.h" ! 36: #include "cons.h" ! 37: #include "cpu.h" ! 38: #include "mem.h" ! 39: #include "mtpr.h" ! 40: #include "rpb.h" ! 41: #include "ka630.h" ! 42: ! 43: #include "../vaxuba/ubavar.h" ! 44: #include "../vaxuba/ubareg.h" ! 45: ! 46: /* ! 47: * Declare these as initialized data so we can patch them. ! 48: */ ! 49: int nswbuf = 0; ! 50: #ifdef NBUF ! 51: int nbuf = NBUF; ! 52: #else ! 53: int nbuf = 0; ! 54: #endif ! 55: #ifdef BUFPAGES ! 56: int bufpages = BUFPAGES; ! 57: #else ! 58: int bufpages = 0; ! 59: #endif ! 60: int msgbufmapped; /* set when safe to use msgbuf */ ! 61: ! 62: /* ! 63: * Machine-dependent startup code ! 64: */ ! 65: startup(firstaddr) ! 66: int firstaddr; ! 67: { ! 68: register int unixsize; ! 69: register unsigned i; ! 70: register struct pte *pte; ! 71: int mapaddr, j, n; ! 72: register caddr_t v; ! 73: int maxbufs, base, residual; ! 74: ! 75: #if VAX630 ! 76: /* ! 77: * Leave last 5k of phys. memory as console work area. ! 78: */ ! 79: if (cpu == VAX_630) ! 80: maxmem -= 10; ! 81: #endif ! 82: /* ! 83: * Initialize error message buffer (at end of core). ! 84: */ ! 85: maxmem -= btoc(sizeof (struct msgbuf)); ! 86: pte = msgbufmap; ! 87: for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) ! 88: *(int *)pte++ = PG_V | PG_KW | (maxmem + i); ! 89: mtpr(TBIA, 0); ! 90: msgbufmapped = 1; ! 91: ! 92: #if VAX630 ! 93: #include "qv.h" ! 94: #if NQV > 0 ! 95: /* ! 96: * redirect console to qvss if it exists ! 97: */ ! 98: qvcons_init(); ! 99: #endif ! 100: #include "qd.h" ! 101: #if NQD > 0 ! 102: /* ! 103: * redirect console to qdss if it exists ! 104: */ ! 105: qdcons_init(); ! 106: #endif ! 107: #endif ! 108: ! 109: #ifdef KADB ! 110: kdb_init(); ! 111: #endif ! 112: /* ! 113: * Good {morning,afternoon,evening,night}. ! 114: */ ! 115: printf(version); ! 116: printf("real mem = %d\n", ctob(physmem)); ! 117: ! 118: /* ! 119: * Allocate space for system data structures. ! 120: * The first available real memory address is in "firstaddr". ! 121: * The first available kernel virtual address is in "v". ! 122: * As pages of kernel virtual memory are allocated, "v" is incremented. ! 123: * As pages of memory are allocated and cleared, ! 124: * "firstaddr" is incremented. ! 125: * An index into the kernel page table corresponding to the ! 126: * virtual memory address maintained in "v" is kept in "mapaddr". ! 127: */ ! 128: v = (caddr_t)(KERNBASE | (firstaddr * NBPG)); ! 129: #define valloc(name, type, num) \ ! 130: (name) = (type *)v; v = (caddr_t)((name)+(num)) ! 131: #define valloclim(name, type, num, lim) \ ! 132: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) ! 133: valloclim(inode, struct inode, ninode, inodeNINODE); ! 134: valloclim(file, struct file, nfile, fileNFILE); ! 135: valloclim(proc, struct proc, nproc, procNPROC); ! 136: valloclim(text, struct text, ntext, textNTEXT); ! 137: valloc(cfree, struct cblock, nclist); ! 138: valloc(callout, struct callout, ncallout); ! 139: valloc(swapmap, struct map, nswapmap = nproc * 2); ! 140: valloc(argmap, struct map, ARGMAPSIZE); ! 141: valloc(kernelmap, struct map, nproc); ! 142: valloc(mbmap, struct map, nmbclusters/4); ! 143: valloc(namecache, struct namecache, nchsize); ! 144: valloc(kmemmap, struct map, ekmempt - kmempt); ! 145: valloc(kmemusage, struct kmemusage, ekmempt - kmempt); ! 146: #ifdef QUOTA ! 147: valloclim(quota, struct quota, nquota, quotaNQUOTA); ! 148: valloclim(dquot, struct dquot, ndquot, dquotNDQUOT); ! 149: #endif ! 150: ! 151: /* ! 152: * Determine how many buffers to allocate. ! 153: * Use 10% of memory for the first 2 Meg, 5% of the remaining ! 154: * memory. Insure a minimum of 16 buffers. ! 155: * We allocate 1/2 as many swap buffer headers as file i/o buffers. ! 156: */ ! 157: if (bufpages == 0) ! 158: if (physmem < (2 * 1024 * CLSIZE)) ! 159: bufpages = physmem / 10 / CLSIZE; ! 160: else ! 161: bufpages = ((2 * 1024 * CLSIZE + physmem) / 20) / CLSIZE; ! 162: if (nbuf == 0) { ! 163: nbuf = bufpages / 2; ! 164: if (nbuf < 16) ! 165: nbuf = 16; ! 166: } ! 167: if (nswbuf == 0) { ! 168: nswbuf = (nbuf / 2) &~ 1; /* force even */ ! 169: if (nswbuf > 256) ! 170: nswbuf = 256; /* sanity */ ! 171: } ! 172: valloc(swbuf, struct buf, nswbuf); ! 173: ! 174: /* ! 175: * Now the amount of virtual memory remaining for buffers ! 176: * can be calculated, estimating needs for the cmap. ! 177: */ ! 178: ncmap = (maxmem*NBPG - ((int)v &~ KERNBASE)) / ! 179: (CLBYTES + sizeof(struct cmap)) + 2; ! 180: maxbufs = ((SYSPTSIZE * NBPG) - ! 181: ((int)(v + ncmap * sizeof(struct cmap)) - KERNBASE)) / ! 182: (MAXBSIZE + sizeof(struct buf)); ! 183: if (maxbufs < 16) ! 184: panic("sys pt too small"); ! 185: if (nbuf > maxbufs) { ! 186: printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs); ! 187: nbuf = maxbufs; ! 188: } ! 189: if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) ! 190: bufpages = nbuf * (MAXBSIZE / CLBYTES); ! 191: valloc(buf, struct buf, nbuf); ! 192: ! 193: /* ! 194: * Allocate space for core map. ! 195: * Allow space for all of phsical memory minus the amount ! 196: * dedicated to the system. The amount of physical memory ! 197: * dedicated to the system is the total virtual memory of ! 198: * the system thus far, plus core map, buffer pages, ! 199: * and buffer headers not yet allocated. ! 200: * Add 2: 1 because the 0th entry is unused, 1 for rounding. ! 201: */ ! 202: ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ KERNBASE)) / ! 203: (CLBYTES + sizeof(struct cmap)) + 2; ! 204: valloclim(cmap, struct cmap, ncmap, ecmap); ! 205: ! 206: /* ! 207: * Clear space allocated thus far, and make r/w entries ! 208: * for the space in the kernel map. ! 209: */ ! 210: unixsize = btoc((int)v &~ KERNBASE); ! 211: while (firstaddr < unixsize) { ! 212: *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr; ! 213: clearseg((unsigned)firstaddr); ! 214: firstaddr++; ! 215: } ! 216: ! 217: /* ! 218: * Now allocate buffers proper. They are different than the above ! 219: * in that they usually occupy more virtual memory than physical. ! 220: */ ! 221: v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET); ! 222: valloc(buffers, char, MAXBSIZE * nbuf); ! 223: base = bufpages / nbuf; ! 224: residual = bufpages % nbuf; ! 225: mapaddr = firstaddr; ! 226: for (i = 0; i < nbuf; i++) { ! 227: n = (i < residual ? base + 1 : base) * CLSIZE; ! 228: for (j = 0; j < n; j++) { ! 229: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; ! 230: clearseg((unsigned)firstaddr); ! 231: firstaddr++; ! 232: } ! 233: mapaddr += MAXBSIZE / NBPG; ! 234: } ! 235: ! 236: unixsize = btoc((int)v &~ KERNBASE); ! 237: if (firstaddr >= physmem - 8*UPAGES) ! 238: panic("no memory"); ! 239: mtpr(TBIA, 0); /* After we just cleared it all! */ ! 240: ! 241: /* ! 242: * Initialize callouts ! 243: */ ! 244: callfree = callout; ! 245: for (i = 1; i < ncallout; i++) ! 246: callout[i-1].c_next = &callout[i]; ! 247: ! 248: /* ! 249: * Initialize memory allocator and swap ! 250: * and user page table maps. ! 251: * ! 252: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' ! 253: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. ! 254: */ ! 255: meminit(firstaddr, maxmem); ! 256: maxmem = freemem; ! 257: printf("avail mem = %d\n", ctob(maxmem)); ! 258: printf("using %d buffers containing %d bytes of memory\n", ! 259: nbuf, bufpages * CLBYTES); ! 260: rminit(kernelmap, (long)USRPTSIZE, (long)1, ! 261: "usrpt", nproc); ! 262: rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE, ! 263: "mbclusters", nmbclusters/4); ! 264: kmeminit(); /* now safe to do malloc/free */ ! 265: ! 266: /* ! 267: * Set up CPU-specific registers, cache, etc. ! 268: */ ! 269: initcpu(); ! 270: ! 271: /* ! 272: * Set up buffers, so they can be used to read disk labels. ! 273: */ ! 274: bhinit(); ! 275: binit(); ! 276: ! 277: /* ! 278: * Configure the system. ! 279: */ ! 280: configure(); ! 281: ! 282: /* ! 283: * Clear restart inhibit flags. ! 284: */ ! 285: tocons(TXDB_CWSI); ! 286: tocons(TXDB_CCSI); ! 287: } ! 288: ! 289: #ifdef PGINPROF ! 290: /* ! 291: * Return the difference (in microseconds) ! 292: * between the current time and a previous ! 293: * time as represented by the arguments. ! 294: * If there is a pending clock interrupt ! 295: * which has not been serviced due to high ! 296: * ipl, return error code. ! 297: */ ! 298: vmtime(otime, olbolt, oicr) ! 299: register int otime, olbolt, oicr; ! 300: { ! 301: ! 302: if (mfpr(ICCS)&ICCS_INT) ! 303: return(-1); ! 304: else ! 305: return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr); ! 306: } ! 307: #endif ! 308: ! 309: /* ! 310: * Clear registers on exec ! 311: */ ! 312: setregs(entry) ! 313: u_long entry; ! 314: { ! 315: #ifdef notdef ! 316: register int *rp; ! 317: ! 318: /* should pass args to init on the stack */ ! 319: /* should also fix this code before using it, it's wrong */ ! 320: /* wanna clear the scb? */ ! 321: for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) ! 322: *rp++ = 0; ! 323: #endif ! 324: u.u_ar0[PC] = entry + 2; ! 325: } ! 326: ! 327: /* ! 328: * Send an interrupt to process. ! 329: * ! 330: * Stack is set up to allow sigcode stored ! 331: * in u. to call routine, followed by chmk ! 332: * to sigreturn routine below. After sigreturn ! 333: * resets the signal mask, the stack, the frame ! 334: * pointer, and the argument pointer, it returns ! 335: * to the user specified pc, psl. ! 336: */ ! 337: sendsig(p, sig, mask) ! 338: int (*p)(), sig, mask; ! 339: { ! 340: register struct sigcontext *scp; ! 341: register int *regs; ! 342: register struct sigframe { ! 343: int sf_signum; ! 344: int sf_code; ! 345: struct sigcontext *sf_scp; ! 346: int (*sf_handler)(); ! 347: int sf_argcount; ! 348: struct sigcontext *sf_scpcopy; ! 349: } *fp; ! 350: int oonstack; ! 351: ! 352: regs = u.u_ar0; ! 353: oonstack = u.u_onstack; ! 354: /* ! 355: * Allocate and validate space for the signal handler ! 356: * context. Note that if the stack is in P0 space, the ! 357: * call to grow() is a nop, and the useracc() check ! 358: * will fail if the process has not already allocated ! 359: * the space with a `brk'. ! 360: */ ! 361: if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) { ! 362: scp = (struct sigcontext *)u.u_sigsp - 1; ! 363: u.u_onstack = 1; ! 364: } else ! 365: scp = (struct sigcontext *)regs[SP] - 1; ! 366: fp = (struct sigframe *)scp - 1; ! 367: if ((int)fp <= USRSTACK - ctob(u.u_ssize)) ! 368: (void)grow((unsigned)fp); ! 369: if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) { ! 370: /* ! 371: * Process has trashed its stack; give it an illegal ! 372: * instruction to halt it in its tracks. ! 373: */ ! 374: u.u_signal[SIGILL] = SIG_DFL; ! 375: sig = sigmask(SIGILL); ! 376: u.u_procp->p_sigignore &= ~sig; ! 377: u.u_procp->p_sigcatch &= ~sig; ! 378: u.u_procp->p_sigmask &= ~sig; ! 379: psignal(u.u_procp, SIGILL); ! 380: return; ! 381: } ! 382: /* ! 383: * Build the argument list for the signal handler. ! 384: */ ! 385: fp->sf_signum = sig; ! 386: if (sig == SIGILL || sig == SIGFPE) { ! 387: fp->sf_code = u.u_code; ! 388: u.u_code = 0; ! 389: } else ! 390: fp->sf_code = 0; ! 391: fp->sf_scp = scp; ! 392: fp->sf_handler = p; ! 393: /* ! 394: * Build the calls argument frame to be used to call sigreturn ! 395: */ ! 396: fp->sf_argcount = 1; ! 397: fp->sf_scpcopy = scp; ! 398: /* ! 399: * Build the signal context to be used by sigreturn. ! 400: */ ! 401: scp->sc_onstack = oonstack; ! 402: scp->sc_mask = mask; ! 403: scp->sc_sp = regs[SP]; ! 404: scp->sc_fp = regs[FP]; ! 405: scp->sc_ap = regs[AP]; ! 406: scp->sc_pc = regs[PC]; ! 407: scp->sc_ps = regs[PS]; ! 408: regs[SP] = (int)fp; ! 409: regs[PS] &= ~(PSL_CM|PSL_FPD); ! 410: regs[PC] = (int)u.u_pcb.pcb_sigc; ! 411: return; ! 412: } ! 413: ! 414: /* ! 415: * System call to cleanup state after a signal ! 416: * has been taken. Reset signal mask and ! 417: * stack state from context left by sendsig (above). ! 418: * Return to previous pc and psl as specified by ! 419: * context left by sendsig. Check carefully to ! 420: * make sure that the user has not modified the ! 421: * psl to gain improper priviledges or to cause ! 422: * a machine fault. ! 423: */ ! 424: sigreturn() ! 425: { ! 426: struct a { ! 427: struct sigcontext *sigcntxp; ! 428: }; ! 429: register struct sigcontext *scp; ! 430: register int *regs = u.u_ar0; ! 431: ! 432: scp = ((struct a *)(u.u_ap))->sigcntxp; ! 433: if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0) ! 434: return; ! 435: if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 || ! 436: (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD) || ! 437: ((scp->sc_ps & PSL_CM) && ! 438: (scp->sc_ps & (PSL_FPD|PSL_DV|PSL_FU|PSL_IV)) != 0)) { ! 439: u.u_error = EINVAL; ! 440: return; ! 441: } ! 442: u.u_eosys = JUSTRETURN; ! 443: u.u_onstack = scp->sc_onstack & 01; ! 444: u.u_procp->p_sigmask = scp->sc_mask &~ ! 445: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); ! 446: regs[FP] = scp->sc_fp; ! 447: regs[AP] = scp->sc_ap; ! 448: regs[SP] = scp->sc_sp; ! 449: regs[PC] = scp->sc_pc; ! 450: regs[PS] = scp->sc_ps; ! 451: } ! 452: ! 453: /* XXX - BEGIN 4.2 COMPATIBILITY */ ! 454: /* ! 455: * Compatibility with 4.2 chmk $139 used by longjmp() ! 456: */ ! 457: osigcleanup() ! 458: { ! 459: register struct sigcontext *scp; ! 460: register int *regs = u.u_ar0; ! 461: ! 462: scp = (struct sigcontext *)fuword((caddr_t)regs[SP]); ! 463: if ((int)scp == -1) ! 464: return; ! 465: if (useracc((caddr_t)scp, 3 * sizeof (int), B_WRITE) == 0) ! 466: return; ! 467: u.u_onstack = scp->sc_onstack & 01; ! 468: u.u_procp->p_sigmask = scp->sc_mask &~ ! 469: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); ! 470: regs[SP] = scp->sc_sp; ! 471: } ! 472: /* XXX - END 4.2 COMPATIBILITY */ ! 473: ! 474: #ifdef notdef ! 475: dorti() ! 476: { ! 477: struct frame frame; ! 478: register int sp; ! 479: register int reg, mask; ! 480: extern int ipcreg[]; ! 481: ! 482: (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame)); ! 483: sp = u.u_ar0[FP] + sizeof (frame); ! 484: u.u_ar0[PC] = frame.fr_savpc; ! 485: u.u_ar0[FP] = frame.fr_savfp; ! 486: u.u_ar0[AP] = frame.fr_savap; ! 487: mask = frame.fr_mask; ! 488: for (reg = 0; reg <= 11; reg++) { ! 489: if (mask&1) { ! 490: u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp); ! 491: sp += 4; ! 492: } ! 493: mask >>= 1; ! 494: } ! 495: sp += frame.fr_spa; ! 496: u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw; ! 497: if (frame.fr_s) ! 498: sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff); ! 499: /* phew, now the rei */ ! 500: u.u_ar0[PC] = fuword((caddr_t)sp); ! 501: sp += 4; ! 502: u.u_ar0[PS] = fuword((caddr_t)sp); ! 503: sp += 4; ! 504: u.u_ar0[PS] |= PSL_USERSET; ! 505: u.u_ar0[PS] &= ~PSL_USERCLR; ! 506: if (u.u_ar0[PS] & PSL_CM) ! 507: u.u_ar0[PS] &= ~PSL_CM_CLR; ! 508: u.u_ar0[SP] = (int)sp; ! 509: } ! 510: #endif ! 511: ! 512: /* ! 513: * Memenable enables memory controller corrected data reporting. ! 514: * This runs at regular intervals, turning on the interrupt. ! 515: * The interrupt is turned off, per memory controller, when error ! 516: * reporting occurs. Thus we report at most once per memintvl. ! 517: */ ! 518: int memintvl = MEMINTVL; ! 519: ! 520: memenable() ! 521: { ! 522: ! 523: (*cpuops->cpu_memenable)(); ! 524: if (memintvl > 0) ! 525: timeout(memenable, (caddr_t)0, memintvl*hz); ! 526: } ! 527: ! 528: /* ! 529: * Memerr is the interrupt routine for corrected read data ! 530: * interrupts. It looks to see which memory controllers have ! 531: * unreported errors, reports them, and disables further ! 532: * reporting for a time on those controller. ! 533: */ ! 534: memerr() ! 535: { ! 536: ! 537: (*cpuops->cpu_memerr)(); ! 538: } ! 539: ! 540: /* ! 541: * Invalidate single all pte's in a cluster ! 542: */ ! 543: tbiscl(v) ! 544: unsigned v; ! 545: { ! 546: register caddr_t addr; /* must be first reg var */ ! 547: register int i; ! 548: ! 549: asm(".set TBIS,58"); ! 550: addr = ptob(v); ! 551: for (i = 0; i < CLSIZE; i++) { ! 552: #ifdef lint ! 553: mtpr(TBIS, addr); ! 554: #else ! 555: asm("mtpr r11,$TBIS"); ! 556: #endif ! 557: addr += NBPG; ! 558: } ! 559: } ! 560: ! 561: int waittime = -1; ! 562: ! 563: boot(howto) ! 564: register int howto; /* r11 == how to boot */ ! 565: { ! 566: register int devtype; /* r10 == major of root dev */ ! 567: extern char *panicstr; ! 568: ! 569: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { ! 570: register struct buf *bp; ! 571: int iter, nbusy; ! 572: ! 573: waittime = 0; ! 574: (void) splnet(); ! 575: printf("syncing disks... "); ! 576: /* ! 577: * Release inodes held by texts before update. ! 578: */ ! 579: if (panicstr == 0) ! 580: xumount(NODEV); ! 581: update(); ! 582: ! 583: for (iter = 0; iter < 20; iter++) { ! 584: nbusy = 0; ! 585: for (bp = &buf[nbuf]; --bp >= buf; ) ! 586: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) ! 587: nbusy++; ! 588: if (nbusy == 0) ! 589: break; ! 590: printf("%d ", nbusy); ! 591: DELAY(40000 * iter); ! 592: } ! 593: if (nbusy) ! 594: printf("giving up\n"); ! 595: else ! 596: printf("done\n"); ! 597: /* ! 598: * If we've been adjusting the clock, the todr ! 599: * will be out of synch; adjust it now. ! 600: */ ! 601: resettodr(); ! 602: } ! 603: splx(0x1f); /* extreme priority */ ! 604: devtype = major(rootdev); ! 605: if (howto&RB_HALT) { ! 606: /* 630 can be told to halt, but how? */ ! 607: printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n"); ! 608: for (;;) ! 609: ; ! 610: } else { ! 611: if (howto & RB_DUMP) ! 612: doadump(); ! 613: vaxboot(); ! 614: } ! 615: #ifdef lint ! 616: devtype = devtype; ! 617: #endif ! 618: /*NOTREACHED*/ ! 619: } ! 620: ! 621: /* ! 622: * Reboot after panic or via reboot system call. Note that r11 ! 623: * and r10 must already have the proper boot values (`call by voodoo'). ! 624: */ ! 625: vaxboot() ! 626: { ! 627: ! 628: switch (cpu) { ! 629: ! 630: #ifdef VAX8200 ! 631: case VAX_8200: ! 632: /* ! 633: * TXDB_BOOT erases memory! Instead we set the `did ! 634: * a dump' flag in the rpb. ! 635: */ ! 636: *(int *)&Sysmap[0] &= ~PG_PROT; ! 637: *(int *)&Sysmap[0] |= PG_KW; ! 638: mtpr(TBIS, &rpb); ! 639: rpb.rp_flag = 1; ! 640: break; ! 641: #endif ! 642: ! 643: default: ! 644: tocons(TXDB_BOOT); ! 645: } ! 646: ! 647: /* ! 648: * Except on 780s and 8600s, boot flags go in r5. SBI ! 649: * VAXen do not care, so copy boot flags to r5 always. ! 650: */ ! 651: asm("movl r11,r5"); ! 652: for (;;) { ! 653: asm("halt"); ! 654: } ! 655: } ! 656: ! 657: tocons(c) ! 658: { ! 659: register int oldmask; ! 660: ! 661: while (((oldmask = mfpr(TXCS)) & TXCS_RDY) == 0) ! 662: continue; ! 663: ! 664: switch (cpu) { ! 665: ! 666: #if VAX8200 || VAX780 || VAX750 || VAX730 || VAX630 ! 667: case VAX_8200: ! 668: case VAX_780: ! 669: case VAX_750: ! 670: case VAX_730: ! 671: case VAX_630: ! 672: c |= TXDB_CONS; ! 673: break; ! 674: #endif ! 675: ! 676: #if VAX8600 ! 677: case VAX_8600: ! 678: mtpr(TXCS, TXCS_LCONS | TXCS_WMASK); ! 679: while ((mfpr(TXCS) & TXCS_RDY) == 0) ! 680: continue; ! 681: break; ! 682: #endif ! 683: } ! 684: ! 685: mtpr(TXDB, c); ! 686: ! 687: #if VAX8600 ! 688: switch (cpu) { ! 689: ! 690: case VAX_8600: ! 691: while ((mfpr(TXCS) & TXCS_RDY) == 0) ! 692: continue; ! 693: mtpr(TXCS, oldmask | TXCS_WMASK); ! 694: break; ! 695: } ! 696: #endif ! 697: #ifdef lint ! 698: oldmask = oldmask; ! 699: #endif ! 700: } ! 701: ! 702: int dumpmag = 0x8fca0101; /* magic number for savecore */ ! 703: int dumpsize = 0; /* also for savecore */ ! 704: /* ! 705: * Doadump comes here after turning off memory management and ! 706: * getting on the dump stack, either when called above, or by ! 707: * the auto-restart code. ! 708: */ ! 709: dumpsys() ! 710: { ! 711: ! 712: rpb.rp_flag = 1; ! 713: msgbufmapped = 0; ! 714: if (dumpdev == NODEV) ! 715: return; ! 716: /* ! 717: * For dumps during autoconfiguration, ! 718: * if dump device has already configured... ! 719: */ ! 720: if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize) ! 721: dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem; ! 722: if (dumplo < 0) ! 723: dumplo = 0; ! 724: dumpsize = physmem; ! 725: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); ! 726: printf("dump "); ! 727: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { ! 728: ! 729: case ENXIO: ! 730: printf("device bad\n"); ! 731: break; ! 732: ! 733: case EFAULT: ! 734: printf("device not ready\n"); ! 735: break; ! 736: ! 737: case EINVAL: ! 738: printf("area improper\n"); ! 739: break; ! 740: ! 741: case EIO: ! 742: printf("i/o error"); ! 743: break; ! 744: ! 745: default: ! 746: printf("succeeded"); ! 747: break; ! 748: } ! 749: } ! 750: ! 751: /* ! 752: * Machine check error recovery code. ! 753: */ ! 754: machinecheck(cmcf) ! 755: caddr_t cmcf; ! 756: { ! 757: ! 758: if ((*cpuops->cpu_mchk)(cmcf) == MCHK_RECOVERED) ! 759: return; ! 760: (*cpuops->cpu_memerr)(); ! 761: panic("mchk"); ! 762: } ! 763: ! 764: #if defined(VAX780) || defined(VAX750) ! 765: /* ! 766: * These strings are shared between the 780 and 750 machine check code ! 767: * in ka780.c and ka730.c. ! 768: */ ! 769: char *mc780750[16] = { ! 770: "cp read", "ctrl str par", "cp tbuf par", "cp cache par", ! 771: "cp rdtimo", "cp rds", "ucode lost", 0, ! 772: 0, 0, "ib tbuf par", 0, ! 773: "ib rds", "ib rd timo", 0, "ib cache par" ! 774: }; ! 775: #endif ! 776: ! 777: /* ! 778: * Return the best possible estimate of the time in the timeval ! 779: * to which tvp points. We do this by reading the interval count ! 780: * register to determine the time remaining to the next clock tick. ! 781: * We must compensate for wraparound which is not yet reflected in the time ! 782: * (which happens when the ICR hits 0 and wraps after the splhigh(), ! 783: * but before the mfpr(ICR)). Also check that this time is no less than ! 784: * any previously-reported time, which could happen around the time ! 785: * of a clock adjustment. Just for fun, we guarantee that the time ! 786: * will be greater than the value obtained by a previous call. ! 787: */ ! 788: microtime(tvp) ! 789: register struct timeval *tvp; ! 790: { ! 791: int s = splhigh(); ! 792: static struct timeval lasttime; ! 793: register long t; ! 794: ! 795: *tvp = time; ! 796: t = mfpr(ICR); ! 797: if (t < -tick / 2 && (mfpr(ICCS) & ICCS_INT)) ! 798: t += tick; ! 799: tvp->tv_usec += tick + t; ! 800: if (tvp->tv_usec > 1000000) { ! 801: tvp->tv_sec++; ! 802: tvp->tv_usec -= 1000000; ! 803: } ! 804: if (tvp->tv_sec == lasttime.tv_sec && ! 805: tvp->tv_usec <= lasttime.tv_usec && ! 806: (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { ! 807: tvp->tv_sec++; ! 808: tvp->tv_usec -= 1000000; ! 809: } ! 810: lasttime = *tvp; ! 811: splx(s); ! 812: } ! 813: ! 814: initcpu() ! 815: { ! 816: /* ! 817: * Enable cache. ! 818: */ ! 819: switch (cpu) { ! 820: ! 821: #if VAX8600 ! 822: case VAX_8600: ! 823: mtpr(CSWP, 3); ! 824: break; ! 825: #endif ! 826: #if VAX8200 ! 827: case VAX_8200: ! 828: mtpr(CADR, 0); ! 829: break; ! 830: #endif ! 831: #if VAX780 ! 832: case VAX_780: ! 833: mtpr(SBIMT, 0x200000); ! 834: break; ! 835: #endif ! 836: #if VAX750 ! 837: case VAX_750: ! 838: mtpr(CADR, 0); ! 839: break; ! 840: #endif ! 841: default: ! 842: break; ! 843: } ! 844: ! 845: /* ! 846: * Enable floating point accelerator if it exists ! 847: * and has control register. ! 848: */ ! 849: switch(cpu) { ! 850: ! 851: #if VAX8600 || VAX780 ! 852: case VAX_8600: ! 853: case VAX_780: ! 854: if ((mfpr(ACCS) & 0xff) != 0) { ! 855: printf("Enabling FPA\n"); ! 856: mtpr(ACCS, 0x8000); ! 857: } ! 858: #endif ! 859: default: ! 860: break; ! 861: } ! 862: } ! 863: ! 864: /* ! 865: * Return a reasonable approximation of the time of day register. ! 866: * More precisely, return a number that increases by one about ! 867: * once every ten milliseconds. ! 868: */ ! 869: todr() ! 870: { ! 871: ! 872: switch (cpu) { ! 873: ! 874: #if VAX8600 || VAX8200 || VAX780 || VAX750 || VAX730 ! 875: case VAX_8600: ! 876: case VAX_8200: ! 877: case VAX_780: ! 878: case VAX_750: ! 879: case VAX_730: ! 880: return (mfpr(TODR)); ! 881: #endif ! 882: ! 883: #if VAX630 ! 884: case VAX_630: ! 885: /* XXX crude */ ! 886: { static int t; DELAY(10000); return (++t); } ! 887: #endif ! 888: ! 889: default: ! 890: panic("todr"); ! 891: } ! 892: /* NOTREACHED */ ! 893: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.