|
|
1.1 root 1: /* machdep.c 6.2 83/10/02 */
2:
3: #include "../machine/reg.h"
4: #include "../machine/pte.h"
5: #include "../machine/psl.h"
6:
7: #include "../h/param.h"
8: #include "../h/systm.h"
9: #include "../h/dir.h"
10: #include "../h/user.h"
11: #include "../h/kernel.h"
12: #include "../h/map.h"
13: #include "../h/vm.h"
14: #include "../h/proc.h"
15: #include "../h/buf.h"
16: #include "../h/reboot.h"
17: #include "../h/conf.h"
18: #include "../h/inode.h"
19: #include "../h/file.h"
20: #include "../h/text.h"
21: #include "../h/clist.h"
22: #include "../h/callout.h"
23: #include "../h/cmap.h"
24: #include "../h/mbuf.h"
25: #include "../h/msgbuf.h"
26: #include "../h/quota.h"
27:
28: #include "../vax/frame.h"
29: #include "../vax/cons.h"
30: #include "../vax/cpu.h"
31: #include "../vax/mem.h"
32: #include "../vax/mtpr.h"
33: #include "../vax/rpb.h"
34: #include "../vaxuba/ubavar.h"
35: #include "../vaxuba/ubareg.h"
36:
37: int icode[] =
38: {
39: 0x9f19af9f, /* pushab [&"init",0]; pushab */
40: 0x02dd09af, /* "/etc/init"; pushl $2 */
41: 0xbc5c5ed0, /* movl sp,ap; chmk */
42: 0x2ffe110b, /* $exec; brb .; "/ */
43: 0x2f637465, /* etc/ */
44: 0x74696e69, /* init" */
45: 0x00000000, /* \0\0\0"; 0 */
46: 0x00000014, /* [&"init", */
47: 0x00000000, /* 0] */
48: };
49: int szicode = sizeof(icode);
50:
51: /*
52: * Declare these as initialized data so we can patch them.
53: */
54: int nbuf = 0;
55: int nswbuf = 0;
56: int bufpages = 0;
57:
58: /*
59: * Machine-dependent startup code
60: */
61: startup(firstaddr)
62: int firstaddr;
63: {
64: register int unixsize;
65: register unsigned i;
66: register struct pte *pte;
67: int mapaddr, j;
68: register caddr_t v;
69: int maxbufs, base, residual;
70: extern char etext;
71:
72: /*
73: * Initialize error message buffer (at end of core).
74: */
75: maxmem -= btoc(sizeof (struct msgbuf));
76: pte = msgbufmap;
77: for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
78: *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
79: mtpr(TBIA, 1);
80:
81: /*
82: * Good {morning,afternoon,evening,night}.
83: */
84: printf(version);
85: printf("real mem = %d\n", ctob(maxmem));
86:
87: /*
88: * Determine how many buffers to allocate.
89: * Use 10% of memory, with min of 16.
90: * We allocate 1/2 as many swap buffer headers as file i/o buffers.
91: */
92: maxbufs = ((SYSPTSIZE * NBPG) - (5 * (int)(&etext - 0x80000000))) /
93: MAXBSIZE;
94: if (bufpages == 0)
95: bufpages = (physmem * NBPG) / 10 / CLBYTES;
96: if (nbuf == 0) {
97: nbuf = bufpages / 2;
98: if (nbuf < 16)
99: nbuf = 16;
100: if (nbuf > maxbufs)
101: nbuf = maxbufs;
102: }
103: if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
104: bufpages = nbuf * (MAXBSIZE / CLBYTES);
105: if (nswbuf == 0) {
106: nswbuf = (nbuf / 2) &~ 1; /* force even */
107: if (nswbuf > 256)
108: nswbuf = 256; /* sanity */
109: }
110:
111: /*
112: * Allocate space for system data structures.
113: * The first available real memory address is in "firstaddr".
114: * As pages of memory are allocated, "firstaddr" is incremented.
115: * The first available kernel virtual address is in "v".
116: * As pages of kernel virtual memory are allocated, "v" is incremented.
117: * An index into the kernel page table corresponding to the
118: * virtual memory address maintained in "v" is kept in "mapaddr".
119: */
120: mapaddr = firstaddr;
121: v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
122: #define valloc(name, type, num) \
123: (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
124: #define valloclim(name, type, num, lim) \
125: (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
126: valloc(buffers, char, MAXBSIZE * nbuf);
127: base = bufpages / nbuf;
128: residual = bufpages % nbuf;
129: for (i = 0; i < residual; i++) {
130: for (j = 0; j < (base + 1) * CLSIZE; j++) {
131: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
132: clearseg((unsigned)firstaddr);
133: firstaddr++;
134: }
135: mapaddr += MAXBSIZE / NBPG;
136: }
137: for (i = residual; i < nbuf; i++) {
138: for (j = 0; j < base * CLSIZE; j++) {
139: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
140: clearseg((unsigned)firstaddr);
141: firstaddr++;
142: }
143: mapaddr += MAXBSIZE / NBPG;
144: }
145: valloc(buf, struct buf, nbuf);
146: valloc(swbuf, struct buf, nswbuf);
147: valloclim(inode, struct inode, ninode, inodeNINODE);
148: valloclim(file, struct file, nfile, fileNFILE);
149: valloclim(proc, struct proc, nproc, procNPROC);
150: valloclim(text, struct text, ntext, textNTEXT);
151: valloc(cfree, struct cblock, nclist);
152: valloc(callout, struct callout, ncallout);
153: valloc(swapmap, struct map, nswapmap = nproc * 2);
154: valloc(argmap, struct map, ARGMAPSIZE);
155: valloc(kernelmap, struct map, nproc);
156: valloc(mbmap, struct map, nmbclusters/4);
157: #ifdef QUOTA
158: valloclim(quota, struct quota, nquota, quotaNQUOTA);
159: valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
160: #endif
161: /*
162: * Now allocate space for core map
163: * Allow space for all of phsical memory minus the amount
164: * dedicated to the system. The amount of physical memory
165: * dedicated to the system is the total virtual memory of
166: * the system minus the space in the buffers which is not
167: * allocated real memory.
168: */
169: ncmap = (physmem*NBPG - ((int)v &~ 0x80000000) +
170: (nbuf * (MAXBSIZE - 2 * CLBYTES))) /
171: (NBPG*CLSIZE + sizeof (struct cmap));
172: valloclim(cmap, struct cmap, ncmap, ecmap);
173: if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG)
174: panic("sys pt too small");
175:
176: /*
177: * Clear allocated space, and make r/w entries
178: * for the space in the kernel map.
179: */
180: unixsize = btoc((int)(ecmap+1) &~ 0x80000000);
181: for (i = mapaddr; i < unixsize; i++) {
182: *(int *)(&Sysmap[i]) = PG_V | PG_KW | firstaddr;
183: clearseg((unsigned)firstaddr);
184: firstaddr++;
185: }
186: if (firstaddr >= physmem - 8*UPAGES)
187: panic("no memory");
188: mtpr(TBIA, 1);
189:
190: /*
191: * Initialize callouts
192: */
193: callfree = callout;
194: for (i = 1; i < ncallout; i++)
195: callout[i-1].c_next = &callout[i];
196:
197: /*
198: * Initialize memory allocator and swap
199: * and user page table maps.
200: *
201: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
202: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
203: */
204: meminit(firstaddr, maxmem);
205: maxmem = freemem;
206: printf("avail mem = %d\n", ctob(maxmem));
207: printf("using %d buffers containing %d bytes of memory\n",
208: nbuf, bufpages * CLBYTES);
209: rminit(kernelmap, (long)USRPTSIZE, (long)1,
210: "usrpt", nproc);
211: rminit(mbmap, (long)((nmbclusters - 1) * CLSIZE), (long)CLSIZE,
212: "mbclusters", nmbclusters/4);
213:
214: /*
215: * Configure the system.
216: */
217: configure();
218:
219: /*
220: * Clear restart inhibit flags.
221: */
222: tocons(TXDB_CWSI);
223: tocons(TXDB_CCSI);
224: }
225:
226: #ifdef PGINPROF
227: /*
228: * Return the difference (in microseconds)
229: * between the current time and a previous
230: * time as represented by the arguments.
231: * If there is a pending clock interrupt
232: * which has not been serviced due to high
233: * ipl, return error code.
234: */
235: vmtime(otime, olbolt, oicr)
236: register int otime, olbolt, oicr;
237: {
238:
239: if (mfpr(ICCS)&ICCS_INT)
240: return(-1);
241: else
242: return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
243: }
244: #endif
245:
246: /*
247: * Send an interrupt to process.
248: *
249: * Stack is set up to allow sigcode stored
250: * in u. to call routine, followed by chmk
251: * to sigcleanup routine below. After sigcleanup
252: * resets the signal mask and the stack, it
253: * returns to user who then unwinds with the
254: * rei at the bottom of sigcode.
255: */
256: sendsig(p, sig, sigmask)
257: int (*p)(), sig, sigmask;
258: {
259: register struct sigcontext *scp; /* know to be r11 */
260: register int *regs;
261: register struct sigframe {
262: int sf_signum;
263: int sf_code;
264: struct sigcontext *sf_scp;
265: int (*sf_handler)();
266: struct sigcontext *sf_scpcopy;
267: } *fp; /* known to be r9 */
268: int oonstack;
269:
270: regs = u.u_ar0;
271: oonstack = u.u_onstack;
272: scp = (struct sigcontext *)regs[SP] - 1;
273: #define mask(s) (1<<((s)-1))
274: if (!u.u_onstack && (u.u_sigonstack & mask(sig))) {
275: fp = (struct sigframe *)u.u_sigsp - 1;
276: u.u_onstack = 1;
277: } else
278: fp = (struct sigframe *)scp - 1;
279: /*
280: * Must build signal handler context on stack to be returned to
281: * so that rei instruction in sigcode will pop ps and pc
282: * off correct stack. The remainder of the signal state
283: * used in calling the handler must be placed on the stack
284: * on which the handler is to operate so that the calls
285: * in sigcode will save the registers and such correctly.
286: */
287: if (!oonstack && (int)fp <= USRSTACK - ctob(u.u_ssize))
288: grow((unsigned)fp);
289: ;
290: #ifndef lint
291: asm("probew $3,$20,(r9)");
292: asm("jeql bad");
293: #else
294: if (useracc((caddr_t)fp, sizeof (struct sigframe), 1))
295: goto bad;
296: #endif
297: if (!u.u_onstack && (int)scp <= USRSTACK - ctob(u.u_ssize))
298: grow((unsigned)scp);
299: ; /* Avoid asm() label botch */
300: #ifndef lint
301: asm("probew $3,$20,(r11)");
302: asm("beql bad");
303: #else
304: if (useracc((caddr_t)scp, sizeof (struct sigcontext), 1))
305: goto bad;
306: #endif
307: fp->sf_signum = sig;
308: if (sig == SIGILL || sig == SIGFPE) {
309: fp->sf_code = u.u_code;
310: u.u_code = 0;
311: } else
312: fp->sf_code = 0;
313: fp->sf_scp = scp;
314: fp->sf_handler = p;
315: /*
316: * Duplicate the pointer to the sigcontext structure.
317: * This one doesn't get popped by the ret, and is used
318: * by sigcleanup to reset the signal state on inward return.
319: */
320: fp->sf_scpcopy = scp;
321: /* sigcontext goes on previous stack */
322: scp->sc_onstack = oonstack;
323: scp->sc_mask = sigmask;
324: /* setup rei */
325: scp->sc_sp = (int)&scp->sc_pc;
326: scp->sc_pc = regs[PC];
327: scp->sc_ps = regs[PS];
328: regs[SP] = (int)fp;
329: regs[PS] &= ~(PSL_CM|PSL_FPD);
330: regs[PC] = (int)u.u_pcb.pcb_sigc;
331: return;
332:
333: asm("bad:");
334: bad:
335: /*
336: * Process has trashed its stack; give it an illegal
337: * instruction to halt it in its tracks.
338: */
339: u.u_signal[SIGILL] = SIG_DFL;
340: sig = mask(SIGILL);
341: u.u_procp->p_sigignore &= ~sig;
342: u.u_procp->p_sigcatch &= ~sig;
343: u.u_procp->p_sigmask &= ~sig;
344: psignal(u.u_procp, SIGILL);
345: }
346:
347: /*
348: * Routine to cleanup state after a signal
349: * has been taken. Reset signal mask and
350: * stack state from context left by sendsig (above).
351: * Pop these values in preparation for rei which
352: * follows return from this routine.
353: */
354: sigcleanup()
355: {
356: register struct sigcontext *scp;
357:
358: scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP]);
359: if ((int)scp == -1)
360: return;
361: #ifndef lint
362: /* only probe 12 here because that's all we need */
363: asm("prober $3,$12,(r11)");
364: asm("bnequ 1f; ret; 1:");
365: #else
366: if (useracc((caddr_t)scp, sizeof (*scp), 0))
367: return;
368: #endif
369: u.u_onstack = scp->sc_onstack & 01;
370: u.u_procp->p_sigmask =
371: scp->sc_mask &~ (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP));
372: u.u_ar0[SP] = scp->sc_sp;
373: }
374: #undef mask
375:
376: #ifdef notdef
377: dorti()
378: {
379: struct frame frame;
380: register int sp;
381: register int reg, mask;
382: extern int ipcreg[];
383:
384: (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
385: sp = u.u_ar0[FP] + sizeof (frame);
386: u.u_ar0[PC] = frame.fr_savpc;
387: u.u_ar0[FP] = frame.fr_savfp;
388: u.u_ar0[AP] = frame.fr_savap;
389: mask = frame.fr_mask;
390: for (reg = 0; reg <= 11; reg++) {
391: if (mask&1) {
392: u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp);
393: sp += 4;
394: }
395: mask >>= 1;
396: }
397: sp += frame.fr_spa;
398: u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
399: if (frame.fr_s)
400: sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
401: /* phew, now the rei */
402: u.u_ar0[PC] = fuword((caddr_t)sp);
403: sp += 4;
404: u.u_ar0[PS] = fuword((caddr_t)sp);
405: sp += 4;
406: u.u_ar0[PS] |= PSL_USERSET;
407: u.u_ar0[PS] &= ~PSL_USERCLR;
408: u.u_ar0[SP] = (int)sp;
409: }
410: #endif
411:
412: /*
413: * Memenable enables the memory controlle corrected data reporting.
414: * This runs at regular intervals, turning on the interrupt.
415: * The interrupt is turned off, per memory controller, when error
416: * reporting occurs. Thus we report at most once per memintvl.
417: */
418: int memintvl = MEMINTVL;
419:
420: memenable()
421: {
422: register struct mcr *mcr;
423: register int m;
424:
425: for (m = 0; m < nmcr; m++) {
426: mcr = mcraddr[m];
427: switch (cpu) {
428: #if VAX780
429: case VAX_780:
430: M780_ENA(mcr);
431: break;
432: #endif
433: #if VAX750
434: case VAX_750:
435: M750_ENA(mcr);
436: break;
437: #endif
438: #if VAX730
439: case VAX_730:
440: M730_ENA(mcr);
441: break;
442: #endif
443: }
444: }
445: if (memintvl > 0)
446: timeout(memenable, (caddr_t)0, memintvl*hz);
447: }
448:
449: /*
450: * Memerr is the interrupt routine for corrected read data
451: * interrupts. It looks to see which memory controllers have
452: * unreported errors, reports them, and disables further
453: * reporting for a time on those controller.
454: */
455: memerr()
456: {
457: register struct mcr *mcr;
458: register int m;
459:
460: for (m = 0; m < nmcr; m++) {
461: mcr = mcraddr[m];
462: switch (cpu) {
463: #if VAX780
464: case VAX_780:
465: if (M780_ERR(mcr)) {
466: printf("mcr%d: soft ecc addr %x syn %x\n",
467: m, M780_ADDR(mcr), M780_SYN(mcr));
468: #ifdef TRENDATA
469: memlog(m, mcr);
470: #endif
471: M780_INH(mcr);
472: }
473: break;
474: #endif
475: #if VAX750
476: case VAX_750:
477: if (M750_ERR(mcr)) {
478: struct mcr amcr;
479: amcr.mc_reg[0] = mcr->mc_reg[0];
480: printf("mcr%d: soft ecc addr %x syn %x\n",
481: m, M750_ADDR(&amcr), M750_SYN(&amcr));
482: M750_INH(mcr);
483: }
484: break;
485: #endif
486: #if VAX730
487: case VAX_730: {
488: register int mcreg = mcr->mc_reg[1];
489:
490: if (mcreg & M730_CRD) {
491: struct mcr amcr;
492: amcr.mc_reg[0] = mcr->mc_reg[0];
493: printf("mcr%d: soft ecc addr %x syn %x\n",
494: m, M730_ADDR(&amcr), M730_SYN(&amcr));
495: M730_INH(mcr);
496: }
497: break;
498: }
499: #endif
500: }
501: }
502: }
503:
504: #ifdef TRENDATA
505: /*
506: * Figure out what chip to replace on Trendata boards.
507: * Assumes all your memory is Trendata or the non-Trendata
508: * memory never fails..
509: */
510: struct {
511: u_char m_syndrome;
512: char m_chip[4];
513: } memlogtab[] = {
514: 0x01, "C00", 0x02, "C01", 0x04, "C02", 0x08, "C03",
515: 0x10, "C04", 0x19, "L01", 0x1A, "L02", 0x1C, "L04",
516: 0x1F, "L07", 0x20, "C05", 0x38, "L00", 0x3B, "L03",
517: 0x3D, "L05", 0x3E, "L06", 0x40, "C06", 0x49, "L09",
518: 0x4A, "L10", 0x4c, "L12", 0x4F, "L15", 0x51, "L17",
519: 0x52, "L18", 0x54, "L20", 0x57, "L23", 0x58, "L24",
520: 0x5B, "L27", 0x5D, "L29", 0x5E, "L30", 0x68, "L08",
521: 0x6B, "L11", 0x6D, "L13", 0x6E, "L14", 0x70, "L16",
522: 0x73, "L19", 0x75, "L21", 0x76, "L22", 0x79, "L25",
523: 0x7A, "L26", 0x7C, "L28", 0x7F, "L31", 0x80, "C07",
524: 0x89, "U01", 0x8A, "U02", 0x8C, "U04", 0x8F, "U07",
525: 0x91, "U09", 0x92, "U10", 0x94, "U12", 0x97, "U15",
526: 0x98, "U16", 0x9B, "U19", 0x9D, "U21", 0x9E, "U22",
527: 0xA8, "U00", 0xAB, "U03", 0xAD, "U05", 0xAE, "U06",
528: 0xB0, "U08", 0xB3, "U11", 0xB5, "U13", 0xB6, "U14",
529: 0xB9, "U17", 0xBA, "U18", 0xBC, "U20", 0xBF, "U23",
530: 0xC1, "U25", 0xC2, "U26", 0xC4, "U28", 0xC7, "U31",
531: 0xE0, "U24", 0xE3, "U27", 0xE5, "U29", 0xE6, "U30"
532: };
533:
534: memlog (m, mcr)
535: int m;
536: struct mcr *mcr;
537: {
538: register i;
539:
540: switch (cpu) {
541:
542: #if VAX780
543: case VAX_780:
544: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++)
545: if ((u_char)(M780_SYN(mcr)) == memlogtab[i].m_syndrome) {
546: printf (
547: "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n",
548: m,
549: memlogtab[i].m_chip,
550: (M780_ADDR(mcr) & 0x8000) ? "upper" : "lower",
551: (M780_ADDR(mcr) >> 16));
552: return;
553: }
554: printf ("mcr%d: multiple errors, not traceable\n", m);
555: break;
556: #endif
557: }
558: }
559: #endif
560:
561: /*
562: * Invalidate single all pte's in a cluster
563: */
564: tbiscl(v)
565: unsigned v;
566: {
567: register caddr_t addr; /* must be first reg var */
568: register int i;
569:
570: asm(".set TBIS,58");
571: addr = ptob(v);
572: for (i = 0; i < CLSIZE; i++) {
573: #ifdef lint
574: mtpr(TBIS, addr);
575: #else
576: asm("mtpr r11,$TBIS");
577: #endif
578: addr += NBPG;
579: }
580: }
581:
582: int waittime = -1;
583:
584: boot(paniced, arghowto)
585: int paniced, arghowto;
586: {
587: register int howto; /* r11 == how to boot */
588: register int devtype; /* r10 == major of root dev */
589:
590: #ifdef lint
591: howto = 0; devtype = 0;
592: printf("howto %d, devtype %d\n", arghowto, devtype);
593: #endif
594: (void) spl1();
595: howto = arghowto;
596: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
597: waittime = 0;
598: update();
599: printf("syncing disks... ");
600: #ifdef notdef
601: DELAY(10000000);
602: #else
603: { register struct buf *bp;
604: int iter, nbusy;
605:
606: for (iter = 0; iter < 20; iter++) {
607: nbusy = 0;
608: for (bp = &buf[nbuf]; --bp >= buf; )
609: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
610: nbusy++;
611: if (nbusy == 0)
612: break;
613: printf("%d ", nbusy);
614: }
615: }
616: #endif
617: printf("done\n");
618: }
619: splx(0x1f); /* extreme priority */
620: devtype = major(rootdev);
621: if (howto&RB_HALT) {
622: printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
623: mtpr(IPL, 0x1f);
624: for (;;)
625: ;
626: } else {
627: if (paniced == RB_PANIC) {
628: doadump(); /* TXDB_BOOT's itsself */
629: /*NOTREACHED*/
630: }
631: tocons(TXDB_BOOT);
632: }
633: #if defined(VAX750) || defined(VAX730)
634: if (cpu != VAX_780)
635: { asm("movl r11,r5"); } /* boot flags go in r5 */
636: #endif
637: for (;;)
638: asm("halt");
639: /*NOTREACHED*/
640: }
641:
642: tocons(c)
643: {
644:
645: while ((mfpr(TXCS)&TXCS_RDY) == 0)
646: continue;
647: mtpr(TXDB, c);
648: }
649:
650: int dumpmag = 0x8fca0101; /* magic number for savecore */
651: int dumpsize = 0; /* also for savecore */
652: /*
653: * Doadump comes here after turning off memory management and
654: * getting on the dump stack, either when called above, or by
655: * the auto-restart code.
656: */
657: dumpsys()
658: {
659:
660: rpb.rp_flag = 1;
661: #ifdef notdef
662: if ((minor(dumpdev)&07) != 1)
663: return;
664: #endif
665: dumpsize = physmem;
666: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
667: printf("dump ");
668: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
669:
670: case ENXIO:
671: printf("device bad\n");
672: break;
673:
674: case EFAULT:
675: printf("device not ready\n");
676: break;
677:
678: case EINVAL:
679: printf("area improper\n");
680: break;
681:
682: case EIO:
683: printf("i/o error");
684: break;
685:
686: default:
687: printf("succeeded");
688: break;
689: }
690: }
691:
692: /*
693: * Machine check error recovery code.
694: * Print out the machine check frame and then give up.
695: */
696: #if defined(VAX780) || defined(VAX750)
697: char *mc780[] = {
698: "cp read", "ctrl str par", "cp tbuf par", "cp cache par",
699: "cp rdtimo", "cp rds", "ucode lost", 0,
700: 0, 0, "ib tbuf par", 0,
701: "ib rds", "ib rd timo", 0, "ib cache par"
702: };
703: #define MC750_TBPAR 4
704: #endif
705: #if VAX730
706: #define NMC730 12
707: char *mc730[] = {
708: "tb par", "bad retry", "bad intr id", "cant write ptem",
709: "unkn mcr err", "iib rd err", "nxm ref", "cp rds",
710: "unalgn ioref", "nonlw ioref", "bad ioaddr", "unalgn ubaddr",
711: };
712: #endif
713:
714: /*
715: * Frame for each cpu
716: */
717: struct mc780frame {
718: int mc8_bcnt; /* byte count == 0x28 */
719: int mc8_summary; /* summary parameter (as above) */
720: int mc8_cpues; /* cpu error status */
721: int mc8_upc; /* micro pc */
722: int mc8_vaviba; /* va/viba register */
723: int mc8_dreg; /* d register */
724: int mc8_tber0; /* tbuf error reg 0 */
725: int mc8_tber1; /* tbuf error reg 1 */
726: int mc8_timo; /* timeout address divided by 4 */
727: int mc8_parity; /* parity */
728: int mc8_sbier; /* sbi error register */
729: int mc8_pc; /* trapped pc */
730: int mc8_psl; /* trapped psl */
731: };
732: struct mc750frame {
733: int mc5_bcnt; /* byte count == 0x28 */
734: int mc5_summary; /* summary parameter (as above) */
735: int mc5_va; /* virtual address register */
736: int mc5_errpc; /* error pc */
737: int mc5_mdr;
738: int mc5_svmode; /* saved mode register */
739: int mc5_rdtimo; /* read lock timeout */
740: int mc5_tbgpar; /* tb group parity error register */
741: int mc5_cacherr; /* cache error register */
742: int mc5_buserr; /* bus error register */
743: int mc5_mcesr; /* machine check status register */
744: int mc5_pc; /* trapped pc */
745: int mc5_psl; /* trapped psl */
746: };
747: struct mc730frame {
748: int mc3_bcnt; /* byte count == 0xc */
749: int mc3_summary; /* summary parameter */
750: int mc3_parm[2]; /* parameter 1 and 2 */
751: int mc3_pc; /* trapped pc */
752: int mc3_psl; /* trapped psl */
753: };
754:
755: machinecheck(cmcf)
756: caddr_t cmcf;
757: {
758: register u_int type = ((struct mc780frame *)cmcf)->mc8_summary;
759:
760: printf("machine check %x: ", type);
761: switch (cpu) {
762: #if VAX780
763: case VAX_780:
764: #endif
765: #if VAX750
766: case VAX_750:
767: #endif
768: #if defined(VAX780) || defined(VAX750)
769: printf("%s%s\n", mc780[type&0xf],
770: (type&0xf0) ? " abort" : " fault");
771: break;
772: #endif
773: #if VAX730
774: case VAX_730:
775: if (type < NMC730)
776: printf("%s", mc730[type]);
777: printf("\n");
778: break;
779: #endif
780: }
781: switch (cpu) {
782: #if VAX780
783: case VAX_780: {
784: register struct mc780frame *mcf = (struct mc780frame *)cmcf;
785: register int sbifs;
786: printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
787: mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
788: mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
789: sbifs = mfpr(SBIFS);
790: printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
791: mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
792: mcf->mc8_pc, mcf->mc8_psl, sbifs);
793: /* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */
794: /* BOOK'' AND SHOULD BE PUT IN AN ``sbi.h'' */
795: mtpr(SBIFS, sbifs &~ 0x2000000);
796: mtpr(SBIER, mfpr(SBIER) | 0x70c0);
797: break;
798: }
799: #endif
800: #if VAX750
801: case VAX_750: {
802: register struct mc750frame *mcf = (struct mc750frame *)cmcf;
803: printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n",
804: mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode,
805: mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr);
806: printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n",
807: mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl,
808: mfpr(MCSR));
809: mtpr(MCESR, 0xf);
810: if ((mcf->mc5_mcesr&0xf) == MC750_TBPAR) {
811: printf("tbuf par: flushing and returning\n");
812: mtpr(TBIA, 0);
813: return;
814: }
815: break;
816: }
817: #endif
818: #if VAX730
819: case VAX_730: {
820: register struct mc730frame *mcf = (struct mc730frame *)cmcf;
821: printf("params %x,%x pc %x psl %x mcesr %x\n",
822: mcf->mc3_parm[0], mcf->mc3_parm[1],
823: mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR));
824: mtpr(MCESR, 0xf);
825: break;
826: }
827: #endif
828: }
829: memerr();
830: panic("mchk");
831: }
832:
833: #ifdef notdef
834: microtime(tvp)
835: struct timeval *tvp;
836: {
837: int s = spl7();
838:
839: tvp->tv_sec = time.tv_sec;
840: tvp->tv_usec = (lbolt+1)*16667 + mfpr(ICR);
841: while (tvp->tv_usec > 1000000) {
842: tvp->tv_sec++;
843: tvp->tv_usec -= 1000000;
844: }
845: splx(s);
846: }
847: #endif
848:
849: physstrat(bp, strat, prio)
850: struct buf *bp;
851: int (*strat)(), prio;
852: {
853: int s;
854:
855: (*strat)(bp);
856: /* pageout daemon doesn't wait for pushed pages */
857: if (bp->b_flags & B_DIRTY)
858: return;
859: s = spl6();
860: while ((bp->b_flags & B_DONE) == 0)
861: sleep((caddr_t)bp, prio);
862: splx(s);
863: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.