|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)machdep.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "reg.h"
10: #include "pte.h"
11: #include "psl.h"
12:
13: #include "param.h"
14: #include "systm.h"
15: #include "dir.h"
16: #include "user.h"
17: #include "kernel.h"
18: #include "map.h"
19: #include "vm.h"
20: #include "proc.h"
21: #include "buf.h"
22: #include "reboot.h"
23: #include "conf.h"
24: #include "inode.h"
25: #include "file.h"
26: #include "text.h"
27: #include "clist.h"
28: #include "callout.h"
29: #include "cmap.h"
30: #include "mbuf.h"
31: #include "msgbuf.h"
32: #include "quota.h"
33:
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: #include "../vaxuba/ubavar.h"
43: #include "../vaxuba/ubareg.h"
44:
45: /*
46: * Declare these as initialized data so we can patch them.
47: */
48: int nswbuf = 0;
49: #ifdef NBUF
50: int nbuf = NBUF;
51: #else
52: int nbuf = 0;
53: #endif
54: #ifdef BUFPAGES
55: int bufpages = BUFPAGES;
56: #else
57: int bufpages = 0;
58: #endif
59:
60: /*
61: * Machine-dependent startup code
62: */
63: startup(firstaddr)
64: int firstaddr;
65: {
66: register int unixsize;
67: register unsigned i;
68: register struct pte *pte;
69: int mapaddr, j;
70: register caddr_t v;
71: int maxbufs, base, residual;
72:
73: #if VAX630
74: /*
75: * Leave last 5k of phys. memory as console work area.
76: */
77: if (cpu == VAX_630)
78: maxmem -= 10;
79: #endif
80: /*
81: * Initialize error message buffer (at end of core).
82: */
83: maxmem -= btoc(sizeof (struct msgbuf));
84: pte = msgbufmap;
85: for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
86: *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
87: mtpr(TBIA, 0);
88:
89: /*
90: * Good {morning,afternoon,evening,night}.
91: */
92: printf(version);
93: printf("real mem = %d\n", ctob(physmem));
94:
95: /*
96: * Allocate space for system data structures.
97: * The first available real memory address is in "firstaddr".
98: * The first available kernel virtual address is in "v".
99: * As pages of kernel virtual memory are allocated, "v" is incremented.
100: * As pages of memory are allocated and cleared,
101: * "firstaddr" is incremented.
102: * An index into the kernel page table corresponding to the
103: * virtual memory address maintained in "v" is kept in "mapaddr".
104: */
105: v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
106: #define valloc(name, type, num) \
107: (name) = (type *)v; v = (caddr_t)((name)+(num))
108: #define valloclim(name, type, num, lim) \
109: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
110: valloclim(inode, struct inode, ninode, inodeNINODE);
111: valloclim(file, struct file, nfile, fileNFILE);
112: valloclim(proc, struct proc, nproc, procNPROC);
113: valloclim(text, struct text, ntext, textNTEXT);
114: valloc(cfree, struct cblock, nclist);
115: valloc(callout, struct callout, ncallout);
116: valloc(swapmap, struct map, nswapmap = nproc * 2);
117: valloc(argmap, struct map, ARGMAPSIZE);
118: valloc(kernelmap, struct map, nproc);
119: valloc(mbmap, struct map, nmbclusters/4);
120: valloc(namecache, struct namecache, nchsize);
121: #ifdef QUOTA
122: valloclim(quota, struct quota, nquota, quotaNQUOTA);
123: valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
124: #endif
125:
126: /*
127: * Determine how many buffers to allocate.
128: * Use 10% of memory for the first 2 Meg, 5% of the remaining
129: * memory. Insure a minimum of 16 buffers.
130: * We allocate 1/2 as many swap buffer headers as file i/o buffers.
131: */
132: if (bufpages == 0)
133: if (physmem < (2 * 1024 * CLSIZE))
134: bufpages = physmem / 10 / CLSIZE;
135: else
136: bufpages = ((2 * 1024 * CLSIZE + physmem) / 20) / CLSIZE;
137: if (nbuf == 0) {
138: nbuf = bufpages / 2;
139: if (nbuf < 16)
140: nbuf = 16;
141: }
142: if (nswbuf == 0) {
143: nswbuf = (nbuf / 2) &~ 1; /* force even */
144: if (nswbuf > 256)
145: nswbuf = 256; /* sanity */
146: }
147: valloc(swbuf, struct buf, nswbuf);
148:
149: /*
150: * Now the amount of virtual memory remaining for buffers
151: * can be calculated, estimating needs for the cmap.
152: */
153: ncmap = (maxmem*NBPG - ((int)v &~ 0x80000000)) /
154: (CLBYTES + sizeof(struct cmap)) + 2;
155: maxbufs = ((SYSPTSIZE * NBPG) -
156: ((int)(v + ncmap * sizeof(struct cmap)) - 0x80000000)) /
157: (MAXBSIZE + sizeof(struct buf));
158: if (maxbufs < 16)
159: panic("sys pt too small");
160: if (nbuf > maxbufs) {
161: printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
162: nbuf = maxbufs;
163: }
164: if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
165: bufpages = nbuf * (MAXBSIZE / CLBYTES);
166: valloc(buf, struct buf, nbuf);
167:
168: /*
169: * Allocate space for core map.
170: * Allow space for all of phsical memory minus the amount
171: * dedicated to the system. The amount of physical memory
172: * dedicated to the system is the total virtual memory of
173: * the system thus far, plus core map, buffer pages,
174: * and buffer headers not yet allocated.
175: * Add 2: 1 because the 0th entry is unused, 1 for rounding.
176: */
177: ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0x80000000)) /
178: (CLBYTES + sizeof(struct cmap)) + 2;
179: valloclim(cmap, struct cmap, ncmap, ecmap);
180:
181: /*
182: * Clear space allocated thus far, and make r/w entries
183: * for the space in the kernel map.
184: */
185: unixsize = btoc((int)v &~ 0x80000000);
186: while (firstaddr < unixsize) {
187: *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr;
188: clearseg((unsigned)firstaddr);
189: firstaddr++;
190: }
191:
192: /*
193: * Now allocate buffers proper. They are different than the above
194: * in that they usually occupy more virtual memory than physical.
195: */
196: v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
197: valloc(buffers, char, MAXBSIZE * nbuf);
198: base = bufpages / nbuf;
199: residual = bufpages % nbuf;
200: mapaddr = firstaddr;
201: for (i = 0; i < residual; i++) {
202: for (j = 0; j < (base + 1) * CLSIZE; j++) {
203: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
204: clearseg((unsigned)firstaddr);
205: firstaddr++;
206: }
207: mapaddr += MAXBSIZE / NBPG;
208: }
209: for (i = residual; i < nbuf; i++) {
210: for (j = 0; j < base * CLSIZE; j++) {
211: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
212: clearseg((unsigned)firstaddr);
213: firstaddr++;
214: }
215: mapaddr += MAXBSIZE / NBPG;
216: }
217:
218: unixsize = btoc((int)v &~ 0x80000000);
219: if (firstaddr >= physmem - 8*UPAGES)
220: panic("no memory");
221: mtpr(TBIA, 0); /* After we just cleared it all! */
222:
223: /*
224: * Initialize callouts
225: */
226: callfree = callout;
227: for (i = 1; i < ncallout; i++)
228: callout[i-1].c_next = &callout[i];
229:
230: /*
231: * Initialize memory allocator and swap
232: * and user page table maps.
233: *
234: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
235: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
236: */
237: meminit(firstaddr, maxmem);
238: maxmem = freemem;
239: printf("avail mem = %d\n", ctob(maxmem));
240: printf("using %d buffers containing %d bytes of memory\n",
241: nbuf, bufpages * CLBYTES);
242: rminit(kernelmap, (long)USRPTSIZE, (long)1,
243: "usrpt", nproc);
244: rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE,
245: "mbclusters", nmbclusters/4);
246:
247: /*
248: * Set up CPU-specific registers, cache, etc.
249: */
250: initcpu();
251:
252: /*
253: * Configure the system.
254: */
255: configure();
256:
257: /*
258: * Clear restart inhibit flags.
259: */
260: tocons(TXDB_CWSI);
261: tocons(TXDB_CCSI);
262: }
263:
264: #ifdef PGINPROF
265: /*
266: * Return the difference (in microseconds)
267: * between the current time and a previous
268: * time as represented by the arguments.
269: * If there is a pending clock interrupt
270: * which has not been serviced due to high
271: * ipl, return error code.
272: */
273: vmtime(otime, olbolt, oicr)
274: register int otime, olbolt, oicr;
275: {
276:
277: if (mfpr(ICCS)&ICCS_INT)
278: return(-1);
279: else
280: return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
281: }
282: #endif
283:
284: /*
285: * Clear registers on exec
286: */
287: setregs(entry)
288: u_long entry;
289: {
290: #ifdef notdef
291: register int *rp;
292:
293: /* should pass args to init on the stack */
294: /* should also fix this code before using it, it's wrong */
295: /* wanna clear the scb? */
296: for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
297: *rp++ = 0;
298: #endif
299: u.u_ar0[PC] = entry + 2;
300: }
301:
302: /*
303: * Send an interrupt to process.
304: *
305: * Stack is set up to allow sigcode stored
306: * in u. to call routine, followed by chmk
307: * to sigreturn routine below. After sigreturn
308: * resets the signal mask, the stack, the frame
309: * pointer, and the argument pointer, it returns
310: * to the user specified pc, psl.
311: */
312: sendsig(p, sig, mask)
313: int (*p)(), sig, mask;
314: {
315: register struct sigcontext *scp;
316: register int *regs;
317: register struct sigframe {
318: int sf_signum;
319: int sf_code;
320: struct sigcontext *sf_scp;
321: int (*sf_handler)();
322: int sf_argcount;
323: struct sigcontext *sf_scpcopy;
324: } *fp;
325: int oonstack;
326:
327: regs = u.u_ar0;
328: oonstack = u.u_onstack;
329: /*
330: * Allocate and validate space for the signal handler
331: * context. Note that if the stack is in P0 space, the
332: * call to grow() is a nop, and the useracc() check
333: * will fail if the process has not already allocated
334: * the space with a `brk'.
335: */
336: if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
337: scp = (struct sigcontext *)u.u_sigsp - 1;
338: u.u_onstack = 1;
339: } else
340: scp = (struct sigcontext *)regs[SP] - 1;
341: fp = (struct sigframe *)scp - 1;
342: if ((int)fp <= USRSTACK - ctob(u.u_ssize))
343: (void)grow((unsigned)fp);
344: if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) {
345: /*
346: * Process has trashed its stack; give it an illegal
347: * instruction to halt it in its tracks.
348: */
349: u.u_signal[SIGILL] = SIG_DFL;
350: sig = sigmask(SIGILL);
351: u.u_procp->p_sigignore &= ~sig;
352: u.u_procp->p_sigcatch &= ~sig;
353: u.u_procp->p_sigmask &= ~sig;
354: psignal(u.u_procp, SIGILL);
355: return;
356: }
357: /*
358: * Build the argument list for the signal handler.
359: */
360: fp->sf_signum = sig;
361: if (sig == SIGILL || sig == SIGFPE) {
362: fp->sf_code = u.u_code;
363: u.u_code = 0;
364: } else
365: fp->sf_code = 0;
366: fp->sf_scp = scp;
367: fp->sf_handler = p;
368: /*
369: * Build the calls argument frame to be used to call sigreturn
370: */
371: fp->sf_argcount = 1;
372: fp->sf_scpcopy = scp;
373: /*
374: * Build the signal context to be used by sigreturn.
375: */
376: scp->sc_onstack = oonstack;
377: scp->sc_mask = mask;
378: scp->sc_sp = regs[SP];
379: scp->sc_fp = regs[FP];
380: scp->sc_ap = regs[AP];
381: scp->sc_pc = regs[PC];
382: scp->sc_ps = regs[PS];
383: regs[SP] = (int)fp;
384: regs[PS] &= ~(PSL_CM|PSL_FPD);
385: regs[PC] = (int)u.u_pcb.pcb_sigc;
386: return;
387: }
388:
389: /*
390: * System call to cleanup state after a signal
391: * has been taken. Reset signal mask and
392: * stack state from context left by sendsig (above).
393: * Return to previous pc and psl as specified by
394: * context left by sendsig. Check carefully to
395: * make sure that the user has not modified the
396: * psl to gain improper priviledges or to cause
397: * a machine fault.
398: */
399: sigreturn()
400: {
401: struct a {
402: struct sigcontext *sigcntxp;
403: };
404: register struct sigcontext *scp;
405: register int *regs = u.u_ar0;
406:
407: scp = ((struct a *)(u.u_ap))->sigcntxp;
408: if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0)
409: return;
410: if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 ||
411: (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD) ||
412: ((scp->sc_ps & PSL_CM) &&
413: (scp->sc_ps & (PSL_FPD|PSL_DV|PSL_FU|PSL_IV)) != 0)) {
414: u.u_error = EINVAL;
415: return;
416: }
417: u.u_eosys = JUSTRETURN;
418: u.u_onstack = scp->sc_onstack & 01;
419: u.u_procp->p_sigmask = scp->sc_mask &~
420: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
421: regs[FP] = scp->sc_fp;
422: regs[AP] = scp->sc_ap;
423: regs[SP] = scp->sc_sp;
424: regs[PC] = scp->sc_pc;
425: regs[PS] = scp->sc_ps;
426: }
427:
428: /* XXX - BEGIN 4.2 COMPATIBILITY */
429: /*
430: * Compatibility with 4.2 chmk $139 used by longjmp()
431: */
432: osigcleanup()
433: {
434: register struct sigcontext *scp;
435: register int *regs = u.u_ar0;
436:
437: scp = (struct sigcontext *)fuword((caddr_t)regs[SP]);
438: if ((int)scp == -1)
439: return;
440: if (useracc((caddr_t)scp, 3 * sizeof (int), B_WRITE) == 0)
441: return;
442: u.u_onstack = scp->sc_onstack & 01;
443: u.u_procp->p_sigmask = scp->sc_mask &~
444: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
445: regs[SP] = scp->sc_sp;
446: }
447: /* XXX - END 4.2 COMPATIBILITY */
448:
449: #ifdef notdef
450: dorti()
451: {
452: struct frame frame;
453: register int sp;
454: register int reg, mask;
455: extern int ipcreg[];
456:
457: (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
458: sp = u.u_ar0[FP] + sizeof (frame);
459: u.u_ar0[PC] = frame.fr_savpc;
460: u.u_ar0[FP] = frame.fr_savfp;
461: u.u_ar0[AP] = frame.fr_savap;
462: mask = frame.fr_mask;
463: for (reg = 0; reg <= 11; reg++) {
464: if (mask&1) {
465: u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp);
466: sp += 4;
467: }
468: mask >>= 1;
469: }
470: sp += frame.fr_spa;
471: u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
472: if (frame.fr_s)
473: sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
474: /* phew, now the rei */
475: u.u_ar0[PC] = fuword((caddr_t)sp);
476: sp += 4;
477: u.u_ar0[PS] = fuword((caddr_t)sp);
478: sp += 4;
479: u.u_ar0[PS] |= PSL_USERSET;
480: u.u_ar0[PS] &= ~PSL_USERCLR;
481: u.u_ar0[SP] = (int)sp;
482: }
483: #endif
484:
485: /*
486: * Memenable enables the memory controlle corrected data reporting.
487: * This runs at regular intervals, turning on the interrupt.
488: * The interrupt is turned off, per memory controller, when error
489: * reporting occurs. Thus we report at most once per memintvl.
490: */
491: int memintvl = MEMINTVL;
492:
493: memenable()
494: {
495: register struct mcr *mcr;
496: register int m;
497:
498: #if VAX630
499: if (cpu == VAX_630)
500: return;
501: #endif
502: #ifdef VAX8600
503: if (cpu == VAX_8600) {
504: M8600_ENA;
505: } else
506: #endif
507: for (m = 0; m < nmcr; m++) {
508: mcr = mcraddr[m];
509: switch (mcrtype[m]) {
510: #if VAX780
511: case M780C:
512: M780C_ENA(mcr);
513: break;
514: case M780EL:
515: M780EL_ENA(mcr);
516: break;
517: case M780EU:
518: M780EU_ENA(mcr);
519: break;
520: #endif
521: #if VAX750
522: case M750:
523: M750_ENA(mcr);
524: break;
525: #endif
526: #if VAX730
527: case M730:
528: M730_ENA(mcr);
529: break;
530: #endif
531: }
532: }
533: if (memintvl > 0)
534: timeout(memenable, (caddr_t)0, memintvl*hz);
535: }
536:
537: /*
538: * Memerr is the interrupt routine for corrected read data
539: * interrupts. It looks to see which memory controllers have
540: * unreported errors, reports them, and disables further
541: * reporting for a time on those controller.
542: */
543: memerr()
544: {
545: #ifdef VAX8600
546: register int reg11; /* known to be r11 below */
547: #endif
548: register struct mcr *mcr;
549: register int m;
550:
551: #if VAX630
552: if (cpu == VAX_630)
553: return;
554: #endif
555: #ifdef VAX8600
556: if (cpu == VAX_8600) {
557: int mdecc, mear, mstat1, mstat2, array;
558:
559: /*
560: * Scratchpad registers in the Ebox must be read by
561: * storing their ID number in ESPA and then immediately
562: * reading ESPD's contents with no other intervening
563: * machine instructions!
564: *
565: * The asm's below have a number of constants which
566: * are defined correctly in mem.h and mtpr.h.
567: */
568: #ifdef lint
569: reg11 = 0;
570: #else
571: asm("mtpr $0x27,$0x4e; mfpr $0x4f,r11");
572: #endif
573: mdecc = reg11; /* must acknowledge interrupt? */
574: if (M8600_MEMERR(mdecc)) {
575: asm("mtpr $0x2a,$0x4e; mfpr $0x4f,r11");
576: mear = reg11;
577: asm("mtpr $0x25,$0x4e; mfpr $0x4f,r11");
578: mstat1 = reg11;
579: asm("mtpr $0x26,$0x4e; mfpr $0x4f,r11");
580: mstat2 = reg11;
581: array = M8600_ARRAY(mear);
582:
583: printf("mcr0: ecc error, addr %x (array %d) syn %x\n",
584: M8600_ADDR(mear), array, M8600_SYN(mdecc));
585: printf("\tMSTAT1 = %b\n\tMSTAT2 = %b\n",
586: mstat1, M8600_MSTAT1_BITS,
587: mstat2, M8600_MSTAT2_BITS);
588: M8600_INH;
589: }
590: } else
591: #endif
592: for (m = 0; m < nmcr; m++) {
593: mcr = mcraddr[m];
594: switch (mcrtype[m]) {
595: #if VAX780
596: case M780C:
597: if (M780C_ERR(mcr)) {
598: printf("mcr%d: soft ecc addr %x syn %x\n",
599: m, M780C_ADDR(mcr), M780C_SYN(mcr));
600: #ifdef TRENDATA
601: memlog(m, mcr);
602: #endif
603: M780C_INH(mcr);
604: }
605: break;
606:
607: case M780EL:
608: if (M780EL_ERR(mcr)) {
609: printf("mcr%d: soft ecc addr %x syn %x\n",
610: m, M780EL_ADDR(mcr), M780EL_SYN(mcr));
611: M780EL_INH(mcr);
612: }
613: break;
614:
615: case M780EU:
616: if (M780EU_ERR(mcr)) {
617: printf("mcr%d: soft ecc addr %x syn %x\n",
618: m, M780EU_ADDR(mcr), M780EU_SYN(mcr));
619: M780EU_INH(mcr);
620: }
621: break;
622: #endif
623: #if VAX750
624: case M750:
625: if (M750_ERR(mcr)) {
626: struct mcr amcr;
627: amcr.mc_reg[0] = mcr->mc_reg[0];
628: printf("mcr%d: %s",
629: m, (amcr.mc_reg[0] & M750_UNCORR) ?
630: "hard error" : "soft ecc");
631: printf(" addr %x syn %x\n",
632: M750_ADDR(&amcr), M750_SYN(&amcr));
633: M750_INH(mcr);
634: }
635: break;
636: #endif
637: #if VAX730
638: case M730: {
639: struct mcr amcr;
640:
641: /*
642: * Must be careful on the 730 not to use invalid
643: * instructions in I/O space, so make a copy;
644: */
645: amcr.mc_reg[0] = mcr->mc_reg[0];
646: amcr.mc_reg[1] = mcr->mc_reg[1];
647: if (M730_ERR(&amcr)) {
648: printf("mcr%d: %s",
649: m, (amcr.mc_reg[1] & M730_UNCORR) ?
650: "hard error" : "soft ecc");
651: printf(" addr %x syn %x\n",
652: M730_ADDR(&amcr), M730_SYN(&amcr));
653: M730_INH(mcr);
654: }
655: break;
656: }
657: #endif
658: }
659: }
660: }
661:
662: #ifdef TRENDATA
663: /*
664: * Figure out what chip to replace on Trendata boards.
665: * Assumes all your memory is Trendata or the non-Trendata
666: * memory never fails..
667: */
668: struct {
669: u_char m_syndrome;
670: char m_chip[4];
671: } memlogtab[] = {
672: 0x01, "C00", 0x02, "C01", 0x04, "C02", 0x08, "C03",
673: 0x10, "C04", 0x19, "L01", 0x1A, "L02", 0x1C, "L04",
674: 0x1F, "L07", 0x20, "C05", 0x38, "L00", 0x3B, "L03",
675: 0x3D, "L05", 0x3E, "L06", 0x40, "C06", 0x49, "L09",
676: 0x4A, "L10", 0x4c, "L12", 0x4F, "L15", 0x51, "L17",
677: 0x52, "L18", 0x54, "L20", 0x57, "L23", 0x58, "L24",
678: 0x5B, "L27", 0x5D, "L29", 0x5E, "L30", 0x68, "L08",
679: 0x6B, "L11", 0x6D, "L13", 0x6E, "L14", 0x70, "L16",
680: 0x73, "L19", 0x75, "L21", 0x76, "L22", 0x79, "L25",
681: 0x7A, "L26", 0x7C, "L28", 0x7F, "L31", 0x80, "C07",
682: 0x89, "U01", 0x8A, "U02", 0x8C, "U04", 0x8F, "U07",
683: 0x91, "U09", 0x92, "U10", 0x94, "U12", 0x97, "U15",
684: 0x98, "U16", 0x9B, "U19", 0x9D, "U21", 0x9E, "U22",
685: 0xA8, "U00", 0xAB, "U03", 0xAD, "U05", 0xAE, "U06",
686: 0xB0, "U08", 0xB3, "U11", 0xB5, "U13", 0xB6, "U14",
687: 0xB9, "U17", 0xBA, "U18", 0xBC, "U20", 0xBF, "U23",
688: 0xC1, "U25", 0xC2, "U26", 0xC4, "U28", 0xC7, "U31",
689: 0xE0, "U24", 0xE3, "U27", 0xE5, "U29", 0xE6, "U30"
690: };
691:
692: memlog (m, mcr)
693: int m;
694: struct mcr *mcr;
695: {
696: register i;
697:
698: switch (mcrtype[m]) {
699:
700: #if VAX780
701: case M780C:
702: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++)
703: if ((u_char)(M780C_SYN(mcr)) == memlogtab[i].m_syndrome) {
704: printf (
705: "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n",
706: m,
707: memlogtab[i].m_chip,
708: (M780C_ADDR(mcr) & 0x8000) ? "upper" : "lower",
709: (M780C_ADDR(mcr) >> 16));
710: return;
711: }
712: printf ("mcr%d: multiple errors, not traceable\n", m);
713: break;
714: #endif
715: }
716: }
717: #endif
718:
719: /*
720: * Invalidate single all pte's in a cluster
721: */
722: tbiscl(v)
723: unsigned v;
724: {
725: register caddr_t addr; /* must be first reg var */
726: register int i;
727:
728: asm(".set TBIS,58");
729: addr = ptob(v);
730: for (i = 0; i < CLSIZE; i++) {
731: #ifdef lint
732: mtpr(TBIS, addr);
733: #else
734: asm("mtpr r11,$TBIS");
735: #endif
736: addr += NBPG;
737: }
738: }
739:
740: int waittime = -1;
741:
742: boot(paniced, arghowto)
743: int paniced, arghowto;
744: {
745: register int howto; /* r11 == how to boot */
746: register int devtype; /* r10 == major of root dev */
747:
748: #ifdef lint
749: howto = 0; devtype = 0;
750: printf("howto %d, devtype %d\n", arghowto, devtype);
751: #endif
752: howto = arghowto;
753: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
754: waittime = 0;
755: (void) splnet();
756: printf("syncing disks... ");
757: /*
758: * Release inodes held by texts before update.
759: */
760: xumount(NODEV);
761: update();
762: { register struct buf *bp;
763: int iter, nbusy;
764:
765: for (iter = 0; iter < 20; iter++) {
766: nbusy = 0;
767: for (bp = &buf[nbuf]; --bp >= buf; )
768: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
769: nbusy++;
770: if (nbusy == 0)
771: break;
772: printf("%d ", nbusy);
773: DELAY(40000 * iter);
774: }
775: }
776: printf("done\n");
777: /*
778: * If we've been adjusting the clock, the todr
779: * will be out of synch; adjust it now.
780: */
781: resettodr();
782: }
783: splx(0x1f); /* extreme priority */
784: devtype = major(rootdev);
785: if (howto&RB_HALT) {
786: printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
787: mtpr(IPL, 0x1f);
788: for (;;)
789: ;
790: } else {
791: if (paniced == RB_PANIC) {
792: doadump(); /* TXDB_BOOT's itself */
793: /*NOTREACHED*/
794: }
795: tocons(TXDB_BOOT);
796: }
797: #if defined(VAX750) || defined(VAX730) || defined(VAX630)
798: if (cpu == VAX_750 || cpu == VAX_730 || cpu == VAX_630)
799: { asm("movl r11,r5"); } /* boot flags go in r5 */
800: #endif
801: for (;;)
802: asm("halt");
803: /*NOTREACHED*/
804: }
805:
806: tocons(c)
807: {
808: register oldmask;
809:
810: while (((oldmask = mfpr(TXCS)) & TXCS_RDY) == 0)
811: continue;
812:
813: switch (cpu) {
814:
815: #if VAX780 || VAX750 || VAX730 || VAX630
816: case VAX_780:
817: case VAX_750:
818: case VAX_730:
819: case VAX_630:
820: c |= TXDB_CONS;
821: break;
822: #endif
823:
824: #if VAX8600
825: case VAX_8600:
826: mtpr(TXCS, TXCS_LCONS | TXCS_WMASK);
827: while ((mfpr(TXCS) & TXCS_RDY) == 0)
828: continue;
829: break;
830: #endif
831: }
832:
833: mtpr(TXDB, c);
834:
835: #if VAX8600
836: switch (cpu) {
837:
838: case VAX_8600:
839: while ((mfpr(TXCS) & TXCS_RDY) == 0)
840: continue;
841: mtpr(TXCS, oldmask | TXCS_WMASK);
842: break;
843: }
844: #endif
845: }
846:
847: int dumpmag = 0x8fca0101; /* magic number for savecore */
848: int dumpsize = 0; /* also for savecore */
849: /*
850: * Doadump comes here after turning off memory management and
851: * getting on the dump stack, either when called above, or by
852: * the auto-restart code.
853: */
854: dumpsys()
855: {
856:
857: rpb.rp_flag = 1;
858: #ifdef notdef
859: if ((minor(dumpdev)&07) != 1)
860: return;
861: #endif
862: dumpsize = physmem;
863: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
864: printf("dump ");
865: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
866:
867: case ENXIO:
868: printf("device bad\n");
869: break;
870:
871: case EFAULT:
872: printf("device not ready\n");
873: break;
874:
875: case EINVAL:
876: printf("area improper\n");
877: break;
878:
879: case EIO:
880: printf("i/o error");
881: break;
882:
883: default:
884: printf("succeeded");
885: break;
886: }
887: }
888:
889: /*
890: * Machine check error recovery code.
891: * Print out the machine check frame and then give up.
892: */
893: #if VAX8600
894: #define NMC8600 7
895: char *mc8600[] = {
896: "unkn type", "fbox error", "ebox error", "ibox error",
897: "mbox error", "tbuf error", "mbox 1D error"
898: };
899: /* codes for above */
900: #define MC_FBOX 1
901: #define MC_EBOX 2
902: #define MC_IBOX 3
903: #define MC_MBOX 4
904: #define MC_TBUF 5
905: #define MC_MBOX1D 6
906:
907: /* error bits */
908: #define MBOX_FE 0x8000 /* Mbox fatal error */
909: #define FBOX_SERV 0x10000000 /* Fbox service error */
910: #define IBOX_ERR 0x2000 /* Ibox error */
911: #define EBOX_ERR 0x1e00 /* Ebox error */
912: #define MBOX_1D 0x81d0000 /* Mbox 1D error */
913: #define EDP_PE 0x200
914: #endif
915:
916: #if defined(VAX780) || defined(VAX750)
917: char *mc780[] = {
918: "cp read", "ctrl str par", "cp tbuf par", "cp cache par",
919: "cp rdtimo", "cp rds", "ucode lost", 0,
920: 0, 0, "ib tbuf par", 0,
921: "ib rds", "ib rd timo", 0, "ib cache par"
922: };
923: #define MC750_TBERR 2 /* type code of cp tbuf par */
924: #define MC750_TBPAR 4 /* tbuf par bit in mcesr */
925: #endif
926:
927: #if VAX730
928: #define NMC730 12
929: char *mc730[] = {
930: "tb par", "bad retry", "bad intr id", "cant write ptem",
931: "unkn mcr err", "iib rd err", "nxm ref", "cp rds",
932: "unalgn ioref", "nonlw ioref", "bad ioaddr", "unalgn ubaddr",
933: };
934: #endif
935: #if VAX630
936: #define NMC630 10
937: extern struct ka630cpu ka630cpu;
938: char *mc630[] = {
939: 0, "immcr (fsd)", "immcr (ssd)", "fpu err 0",
940: "fpu err 7", "mmu st(tb)", "mmu st(m=0)", "pte in p0",
941: "pte in p1", "un intr id",
942: };
943: #endif
944:
945: /*
946: * Frame for each cpu
947: */
948: struct mc780frame {
949: int mc8_bcnt; /* byte count == 0x28 */
950: int mc8_summary; /* summary parameter (as above) */
951: int mc8_cpues; /* cpu error status */
952: int mc8_upc; /* micro pc */
953: int mc8_vaviba; /* va/viba register */
954: int mc8_dreg; /* d register */
955: int mc8_tber0; /* tbuf error reg 0 */
956: int mc8_tber1; /* tbuf error reg 1 */
957: int mc8_timo; /* timeout address divided by 4 */
958: int mc8_parity; /* parity */
959: int mc8_sbier; /* sbi error register */
960: int mc8_pc; /* trapped pc */
961: int mc8_psl; /* trapped psl */
962: };
963: struct mc750frame {
964: int mc5_bcnt; /* byte count == 0x28 */
965: int mc5_summary; /* summary parameter (as above) */
966: int mc5_va; /* virtual address register */
967: int mc5_errpc; /* error pc */
968: int mc5_mdr;
969: int mc5_svmode; /* saved mode register */
970: int mc5_rdtimo; /* read lock timeout */
971: int mc5_tbgpar; /* tb group parity error register */
972: int mc5_cacherr; /* cache error register */
973: int mc5_buserr; /* bus error register */
974: int mc5_mcesr; /* machine check status register */
975: int mc5_pc; /* trapped pc */
976: int mc5_psl; /* trapped psl */
977: };
978: struct mc730frame {
979: int mc3_bcnt; /* byte count == 0xc */
980: int mc3_summary; /* summary parameter */
981: int mc3_parm[2]; /* parameter 1 and 2 */
982: int mc3_pc; /* trapped pc */
983: int mc3_psl; /* trapped psl */
984: };
985: struct mc630frame {
986: int mc63_bcnt; /* byte count == 0xc */
987: int mc63_summary; /* summary parameter */
988: int mc63_mrvaddr; /* most recent vad */
989: int mc63_istate; /* internal state */
990: int mc63_pc; /* trapped pc */
991: int mc63_psl; /* trapped psl */
992: };
993: struct mc8600frame {
994: int mc6_bcnt; /* byte count == 0x58 */
995: int mc6_ehmsts;
996: int mc6_evmqsav;
997: int mc6_ebcs;
998: int mc6_edpsr;
999: int mc6_cslint;
1000: int mc6_ibesr;
1001: int mc6_ebxwd1;
1002: int mc6_ebxwd2;
1003: int mc6_ivasav;
1004: int mc6_vibasav;
1005: int mc6_esasav;
1006: int mc6_isasav;
1007: int mc6_cpc;
1008: int mc6_mstat1;
1009: int mc6_mstat2;
1010: int mc6_mdecc;
1011: int mc6_merg;
1012: int mc6_cshctl;
1013: int mc6_mear;
1014: int mc6_medr;
1015: int mc6_accs;
1016: int mc6_cses;
1017: int mc6_pc; /* trapped pc */
1018: int mc6_psl; /* trapped psl */
1019: };
1020:
1021: machinecheck(cmcf)
1022: caddr_t cmcf;
1023: {
1024: register u_int type = ((struct mc780frame *)cmcf)->mc8_summary;
1025:
1026: printf("machine check %x: ", type);
1027: switch (cpu) {
1028: #if VAX8600
1029: case VAX_8600: {
1030: register struct mc8600frame *mcf = (struct mc8600frame *)cmcf;
1031:
1032: if (mcf->mc6_ebcs & MBOX_FE)
1033: mcf->mc6_ehmsts |= MC_MBOX;
1034: else if (mcf->mc6_ehmsts & FBOX_SERV)
1035: mcf->mc6_ehmsts |= MC_FBOX;
1036: else if (mcf->mc6_ebcs & EBOX_ERR) {
1037: if (mcf->mc6_ebcs & EDP_PE)
1038: mcf->mc6_ehmsts |= MC_MBOX;
1039: else
1040: mcf->mc6_ehmsts |= MC_EBOX;
1041: } else if (mcf->mc6_ehmsts & IBOX_ERR)
1042: mcf->mc6_ehmsts |= MC_IBOX;
1043: else if (mcf->mc6_mstat1 & M8600_TB_ERR)
1044: mcf->mc6_ehmsts |= MC_TBUF;
1045: else if ((mcf->mc6_cslint & MBOX_1D) == MBOX_1D)
1046: mcf->mc6_ehmsts |= MC_MBOX1D;
1047:
1048: type = mcf->mc6_ehmsts & 0x7;
1049: if (type < NMC8600)
1050: printf("machine check %x: %s", type, mc8600[type]);
1051: printf("\n");
1052: printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n",
1053: mcf->mc6_ehmsts, mcf->mc6_evmqsav, mcf->mc6_ebcs,
1054: mcf->mc6_edpsr, mcf->mc6_cslint);
1055: printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n",
1056: mcf->mc6_ibesr, mcf->mc6_ebxwd1, mcf->mc6_ebxwd2,
1057: mcf->mc6_ivasav, mcf->mc6_vibasav);
1058: printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n",
1059: mcf->mc6_esasav, mcf->mc6_isasav, mcf->mc6_cpc,
1060: mcf->mc6_mstat1, mcf->mc6_mstat2, mcf->mc6_mdecc);
1061: printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n",
1062: mcf->mc6_merg, mcf->mc6_cshctl, mcf->mc6_mear,
1063: mcf->mc6_medr, mcf->mc6_accs, mcf->mc6_cses);
1064: printf("\tpc %x psl %x\n", mcf->mc6_pc, mcf->mc6_psl);
1065: mtpr(EHSR, 0);
1066: break;
1067: };
1068: #endif
1069: #if VAX780
1070: case VAX_780: {
1071: register struct mc780frame *mcf = (struct mc780frame *)cmcf;
1072:
1073: register int sbifs;
1074: printf("%s%s\n", mc780[type&0xf],
1075: (type&0xf0) ? " abort" : " fault");
1076: printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
1077: mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
1078: mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
1079: sbifs = mfpr(SBIFS);
1080: printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
1081: mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
1082: mcf->mc8_pc, mcf->mc8_psl, sbifs);
1083: /* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */
1084: /* BOOK'' AND SHOULD BE PUT IN AN ``sbi.h'' */
1085: mtpr(SBIFS, sbifs &~ 0x2000000);
1086: mtpr(SBIER, mfpr(SBIER) | 0x70c0);
1087: break;
1088: }
1089: #endif
1090: #if VAX750
1091: case VAX_750: {
1092: register struct mc750frame *mcf = (struct mc750frame *)cmcf;
1093:
1094: int mcsr = mfpr(MCSR);
1095: printf("%s%s\n", mc780[type&0xf],
1096: (type&0xf0) ? " abort" : " fault");
1097: mtpr(TBIA, 0);
1098: mtpr(MCESR, 0xf);
1099: printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n",
1100: mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode,
1101: mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr);
1102: printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n",
1103: mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl,
1104: mcsr);
1105: if (type == MC750_TBERR && (mcf->mc5_mcesr&0xe) == MC750_TBPAR){
1106: printf("tbuf par: flushing and returning\n");
1107: return;
1108: }
1109: break;
1110: }
1111: #endif
1112: #if VAX730
1113: case VAX_730: {
1114: register struct mc730frame *mcf = (struct mc730frame *)cmcf;
1115:
1116: if (type < NMC730)
1117: printf("%s", mc730[type]);
1118: printf("\n");
1119: printf("params %x,%x pc %x psl %x mcesr %x\n",
1120: mcf->mc3_parm[0], mcf->mc3_parm[1],
1121: mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR));
1122: mtpr(MCESR, 0xf);
1123: break;
1124: }
1125: #endif
1126: #if VAX630
1127: case VAX_630: {
1128: register struct ka630cpu *ka630addr = &ka630cpu;
1129: register struct mc630frame *mcf = (struct mc630frame *)cmcf;
1130: printf("vap %x istate %x pc %x psl %x\n",
1131: mcf->mc63_mrvaddr, mcf->mc63_istate,
1132: mcf->mc63_pc, mcf->mc63_psl);
1133: if (ka630addr->ka630_mser & KA630MSER_MERR) {
1134: printf("mser=0x%x ",ka630addr->ka630_mser);
1135: if (ka630addr->ka630_mser & KA630MSER_CPUER)
1136: printf("page=%d",ka630addr->ka630_cear);
1137: if (ka630addr->ka630_mser & KA630MSER_DQPE)
1138: printf("page=%d",ka630addr->ka630_dear);
1139: printf("\n");
1140: }
1141: break;
1142: }
1143: #endif
1144: }
1145: memerr();
1146: panic("mchk");
1147: }
1148:
1149: /*
1150: * Return the best possible estimate of the time in the timeval
1151: * to which tvp points. We do this by reading the interval count
1152: * register to determine the time remaining to the next clock tick.
1153: * We must compensate for wraparound which is not yet reflected in the time
1154: * (which happens when the ICR hits 0 and wraps after the splhigh(),
1155: * but before the mfpr(ICR)). Also check that this time is no less than
1156: * any previously-reported time, which could happen around the time
1157: * of a clock adjustment. Just for fun, we guarantee that the time
1158: * will be greater than the value obtained by a previous call.
1159: */
1160: microtime(tvp)
1161: register struct timeval *tvp;
1162: {
1163: int s = splhigh();
1164: static struct timeval lasttime;
1165: register long t;
1166:
1167: *tvp = time;
1168: t = mfpr(ICR);
1169: if (t < -tick / 2 && (mfpr(ICCS) & ICCS_INT))
1170: t += tick;
1171: tvp->tv_usec += tick + t;
1172: if (tvp->tv_usec > 1000000) {
1173: tvp->tv_sec++;
1174: tvp->tv_usec -= 1000000;
1175: }
1176: if (tvp->tv_sec == lasttime.tv_sec &&
1177: tvp->tv_usec <= lasttime.tv_usec &&
1178: (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
1179: tvp->tv_sec++;
1180: tvp->tv_usec -= 1000000;
1181: }
1182: lasttime = *tvp;
1183: splx(s);
1184: }
1185:
1186: physstrat(bp, strat, prio)
1187: struct buf *bp;
1188: int (*strat)(), prio;
1189: {
1190: int s;
1191:
1192: (*strat)(bp);
1193: /* pageout daemon doesn't wait for pushed pages */
1194: if (bp->b_flags & B_DIRTY)
1195: return;
1196: s = splbio();
1197: while ((bp->b_flags & B_DONE) == 0)
1198: sleep((caddr_t)bp, prio);
1199: splx(s);
1200: }
1201:
1202: initcpu()
1203: {
1204: /*
1205: * Enable cache.
1206: */
1207: switch (cpu) {
1208:
1209: #if VAX780
1210: case VAX_780:
1211: mtpr(SBIMT, 0x200000);
1212: break;
1213: #endif
1214: #if VAX750
1215: case VAX_750:
1216: mtpr(CADR, 0);
1217: break;
1218: #endif
1219: #if VAX8600
1220: case VAX_8600:
1221: mtpr(CSWP, 3);
1222: break;
1223: #endif
1224: default:
1225: break;
1226: }
1227:
1228: /*
1229: * Enable floating point accelerator if it exists
1230: * and has control register.
1231: */
1232: switch(cpu) {
1233:
1234: #if VAX8600 || VAX780
1235: case VAX_780:
1236: case VAX_8600:
1237: if ((mfpr(ACCS) & 0xff) != 0) {
1238: printf("Enabling FPA\n");
1239: mtpr(ACCS, 0x8000);
1240: }
1241: #endif
1242: default:
1243: break;
1244: }
1245: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.