|
|
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: #ifdef SYS5
29: #include "../h/msg.h"
30: #endif SYS5
31:
32: #include "../machine/mem.h"
33: #include "../machine/mtpr.h"
34: #include "../machine/cp.h"
35: #include "../vba/vbavar.h"
36:
37: #ifdef AUDITTRAIL
38: #include "../h/audit.h"
39: #endif AUDITTRAIL
40:
41: int icode[] =
42: /* pushab argp */
43: /* pushab file */
44: /* pushl $2 */
45: /* movab (sp),fp */
46: /* kcall $exec */
47: /* here: brb here */
48: /* .file: .ascii "/etc/" */
49: /* args: .ascii "init\0" */
50: /* .align 2 */
51: /* argp: .long args */
52: /* .long 0 */
53: {
54: 0xf9af19f9,
55: 0xaf09dd02,
56: 0xe96e5dcf,
57: 0x0b11fe2f,
58: 0x6574632f,
59: 0x696e6974,
60: 0x00000000,
61: 0x00000014,
62: 0x00000000,
63: };
64: int szicode = sizeof(icode);
65:
66: /*
67: * Declare these as initialized data so we can patch them.
68: */
69: int nbuf = 0;
70: int nswbuf = 0;
71: int bufpages = 0;
72:
73: /*
74: * Machine-dependent startup code
75: */
76: startup(firstaddr)
77: int firstaddr;
78: {
79: register int unixsize;
80: register unsigned i;
81: register struct pte *pte;
82: register int mapaddr, j;
83: register caddr_t v;
84: register int maxbufs, base, residual;
85: extern char etext;
86:
87: /*
88: * Initialize error message buffer (at end of core).
89: */
90: maxmem -= btoc(sizeof (struct msgbuf));
91: pte = msgbufmap;
92: for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
93: *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
94: mtpr(1,TBIA);
95:
96: /*
97: * Good {morning,afternoon,evening,night}.
98: */
99: printf(version);
100: printf("real mem = %d\n", ctob(maxmem));
101:
102: /*
103: * Determine how many buffers to allocate.
104: * Use 10% of memory, with min of 16.
105: * We allocate 1/2 as many swap buffer headers as file i/o buffers.
106: */
107: maxbufs = ((SYSPTSIZE * NBPG) - (5 * (int)(&etext - 0xc0000000))) /
108: MAXBSIZE;
109: if (bufpages == 0)
110: bufpages = (physmem * NBPG) / 10 / CLBYTES;
111: if (nbuf == 0) {
112: nbuf = bufpages / 2;
113: if (nbuf < 16)
114: nbuf = 16;
115: if (nbuf > maxbufs)
116: nbuf = maxbufs;
117: }
118: if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
119: bufpages = nbuf * (MAXBSIZE / CLBYTES);
120: if (nswbuf == 0) {
121: nswbuf = (nbuf / 2) &~ 1; /* force even */
122: if (nswbuf > 256)
123: nswbuf = 256; /* sanity */
124: }
125:
126: /*
127: * Allocate space for system data structures.
128: * The first available real memory address is in "firstaddr".
129: * As pages of memory are allocated, "firstaddr" is incremented.
130: * The first available kernel virtual address is in "v".
131: * As pages of kernel virtual memory are allocated, "v" is incremented.
132: * An index into the kernel page table corresponding to the
133: * virtual memory address maintained in "v" is kept in "mapaddr".
134: */
135: mapaddr = firstaddr;
136: v = (caddr_t)(0xc0000000 | (firstaddr * NBPG));
137: #define valloc(name, type, num) \
138: (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
139: #define valloclim(name, type, num, lim) \
140: (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
141: valloc(buffers, char, MAXBSIZE * nbuf);
142: base = bufpages / nbuf;
143: residual = bufpages % nbuf;
144: for (i = 0; i < residual; i++) {
145: for (j = 0; j < (base + 1) * CLSIZE; j++) {
146: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
147: clearseg((unsigned)firstaddr);
148: firstaddr++;
149: }
150: mapaddr += MAXBSIZE / NBPG;
151: }
152: for (i = residual; i < nbuf; i++) {
153: for (j = 0; j < base * CLSIZE; j++) {
154: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
155: clearseg((unsigned)firstaddr);
156: firstaddr++;
157: }
158: mapaddr += MAXBSIZE / NBPG;
159: }
160: valloc(buf, struct buf, nbuf);
161: valloc(swbuf, struct buf, nswbuf);
162: valloclim(inode, struct inode, ninode, inodeNINODE);
163: valloclim(file, struct file, nfile, fileNFILE);
164: valloclim(proc, struct proc, nproc, procNPROC);
165: valloclim(text, struct text, ntext, textNTEXT);
166: #ifdef SYS5
167: valloclim(shmem, struct shmid_ds, nshmem, shmemNSHMEM);
168: #endif SYS5
169: valloc(cfree, struct cblock, nclist);
170: valloc(callout, struct callout, ncallout);
171: valloc(swapmap, struct map, nswapmap = nproc * 2);
172: valloc(argmap, struct map, ARGMAPSIZE);
173: valloc(kernelmap, struct map, nproc);
174: valloc(mbmap, struct map, nmbclusters/4);
175: #ifdef SYS5
176: valloc(msgmap, struct map, MSGMAP);
177: #endif SYS5
178: #ifdef QUOTA
179: valloclim(quota, struct quota, nquota, quotaNQUOTA);
180: valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
181: #endif
182:
183: #ifdef AUDITTRAIL
184: valloc(audbuf, struct audbuf, naudbuf);
185: #endif AUDITTRAIL
186: /*
187: * Now allocate space for core map
188: * Allow space for all of phsical memory minus the amount
189: * dedicated to the system. The amount of physical memory
190: * dedicated to the system is the total virtual memory of
191: * the system minus the space in the buffers which is not
192: * allocated real memory.
193: */
194: ncmap = (physmem*NBPG - ((int)v &~ 0xc0000000) +
195: (nbuf * MAXBSIZE - bufpages * CLBYTES)) /
196: (NBPG*CLSIZE + sizeof (struct cmap));
197: valloclim(cmap, struct cmap, ncmap, ecmap);
198: if ((((int)(ecmap+1))&~0xc0000000) > SYSPTSIZE*NBPG)
199: panic("sys pt too small");
200:
201: /*
202: * Clear allocated space, and make r/w entries
203: * for the space in the kernel map.
204: */
205: unixsize = btoc((int)(ecmap+1) &~ 0xc0000000);
206: for (i = mapaddr; i < unixsize; i++) {
207: *(int *)(&Sysmap[i]) = PG_V | PG_KW | firstaddr;
208: clearseg((unsigned)firstaddr);
209: firstaddr++;
210: }
211: if (firstaddr >= physmem - 8*UPAGES)
212: panic("no memory");
213: mtpr(1,TBIA);
214:
215: /*
216: * Initialize callouts
217: */
218: callfree = callout;
219: for (i = 1; i < ncallout; i++)
220: callout[i-1].c_next = &callout[i];
221:
222: /*
223: * Initialize memory allocator and swap
224: * and user page table maps.
225: *
226: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
227: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
228: */
229: meminit(firstaddr, maxmem);
230: maxmem = freemem;
231: printf("avail mem = %d\n", ctob(maxmem));
232: printf("using %d buffers containing %d bytes of memory\n",
233: nbuf, bufpages * CLBYTES);
234: rminit(kernelmap, (long)USRPTSIZE, (long)1,
235: "usrpt", nproc);
236: rminit(mbmap, (long)((nmbclusters - 1) * CLSIZE), (long)CLSIZE,
237: "mbclusters", nmbclusters/4);
238: #ifdef SYS5
239: rminit(msgmap, (long)MSGSEG, (long)1, "msgmap", MSGMAP);
240: #endif SYS5
241: intenable = 1; /* Enable interrupts from now on */
242: /*
243: * Configure the system.
244: */
245: configure();
246: }
247:
248: #ifdef PGINPROF
249: /*
250: * Return the difference (in microseconds)
251: * between the current time and a previous
252: * time as represented by the arguments.
253: * If there is a pending clock interrupt
254: * which has not been serviced due to high
255: * ipl, return error code.
256: */
257: vmtime(otime, olbolt, oicr)
258: register int otime, olbolt, oicr;
259: {
260: return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
261: }
262: #endif
263:
264: /*
265: * Send an interrupt to process.
266: *
267: * Stack is set up to allow sigcode stored
268: * in u. to call routine, followed by chmk
269: * to sigcleanup routine below. After sigcleanup
270: * resets the signal mask and the stack, it
271: * returns to user who then unwinds with the
272: * rei at the bottom of sigcode.
273: */
274: sendsig(p, sig, sigmask)
275: int (*p)(), sig, sigmask;
276: {
277: register struct sigcontext *scp; /* know to be r12 */
278: register int *regs;
279: register struct sigframe {
280: int sf_signum;
281: int sf_code;
282: struct sigcontext *sf_scp;
283: int (*sf_handler)();
284: int r1;
285: int r0;
286: struct sigcontext *sf_scpcopy;
287: } *fp; /* known to be r10 */
288: int oonstack;
289:
290: regs = u.u_ar0;
291: oonstack = u.u_onstack;
292: scp = (struct sigcontext *)regs[SP] - 1;
293: #define mask(s) (1<<((s)-1))
294: if (!u.u_onstack && (u.u_sigonstack & mask(sig))) {
295: fp = (struct sigframe *)u.u_sigsp - 1;
296: u.u_onstack = 1;
297: } else
298: fp = (struct sigframe *)scp - 1;
299: /*
300: * Must build signal handler context on stack to be returned to
301: * so that rei instruction in sigcode will pop ps and pc
302: * off correct stack. The remainder of the signal state
303: * used in calling the handler must be placed on the stack
304: * on which the handler is to operate so that the calls
305: * in sigcode will save the registers and such correctly.
306: */
307: if (!oonstack && (int)fp <= USRSTACK - ctob(u.u_ssize))
308: grow((unsigned)fp);
309: ;
310: #ifndef lint
311: asm("probew $1,(r10),$7*4");
312: asm("jeql bad");
313: #else
314: if (useracc((caddr_t)fp, sizeof (struct sigframe), 1))
315: goto bad;
316: #endif
317: if (!u.u_onstack && (int)scp <= USRSTACK - ctob(u.u_ssize))
318: grow((unsigned)scp);
319: ; /* Avoid asm() label botch */
320: #ifndef lint
321: asm("probew $1,(r12),$5*4");
322: asm("beql bad");
323: #else
324: if (useracc((caddr_t)scp, sizeof (struct sigcontext), 1))
325: goto bad;
326: #endif
327: fp->sf_signum = sig;
328: if (sig == SIGILL || sig == SIGFPE) {
329: fp->sf_code = u.u_code;
330: u.u_code = 0;
331: } else
332: fp->sf_code = 0;
333: fp->sf_scp = scp;
334: fp->sf_handler = p;
335: fp->r1 = regs[R1]; /* These are not saved by the C compiler */
336: fp->r0 = regs[R0];
337: /*
338: * Duplicate the pointer to the sigcontext structure.
339: * This one doesn't get popped by the ret, and is used
340: * by sigcleanup to reset the signal state on inward return.
341: */
342: fp->sf_scpcopy = scp;
343: /* sigcontext goes on previous stack */
344: scp->sc_onstack = oonstack;
345: scp->sc_mask = sigmask;
346: /* setup rei */
347: scp->sc_sp = (int)&scp->sc_pc;
348: scp->sc_pc = regs[PC];
349: scp->sc_ps = regs[PS];
350: regs[SP] = (int)fp;
351: regs[PC] = (int)u.u_pcb.pcb_sigc;
352: return;
353:
354: asm("bad:");
355: bad:
356: /*
357: * Process has trashed its stack; give it an illegal
358: * instruction to halt it in its tracks.
359: */
360: u.u_signal[SIGILL] = SIG_DFL;
361: sig = mask(SIGILL);
362: u.u_procp->p_sigignore &= ~sig;
363: u.u_procp->p_sigcatch &= ~sig;
364: u.u_procp->p_sigmask &= ~sig;
365: psignal(u.u_procp, SIGILL);
366: }
367:
368: /*
369: * Routine to cleanup state after a signal
370: * has been taken. Reset signal mask and
371: * stack state from context left by sendsig (above).
372: * Pop these values in preparation for rei which
373: * follows return from this routine.
374: */
375: sigcleanup()
376: {
377: register struct sigcontext *scp; /* known as R12 */
378:
379: scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP]);
380: if ((int)scp == -1)
381: return;
382: #ifndef lint
383: ; /* Avoid asm() label botch */
384: /* only probe 12 here because that's all we need */
385: asm("prober $1,(r12),$12");
386: asm("bnequ 1f; ret; 1:");
387: #else
388: if (useracc((caddr_t)scp, sizeof (*scp), 0))
389: return;
390: #endif
391: u.u_onstack = scp->sc_onstack & 01;
392: u.u_procp->p_sigmask =
393: scp->sc_mask &~ (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP));
394: u.u_ar0[SP] = scp->sc_sp;
395: }
396: #undef mask
397:
398: int waittime = -1;
399:
400: boot(paniced, arghowto)
401: int paniced, arghowto;
402: {
403: register long dummy;
404: register int howto; /* r11 == how to boot */
405: register int devtype; /* r10 == major of root dev */
406:
407: #ifdef lint
408: howto = 0; devtype = 0;
409: printf("howto %d, devtype %d\n", arghowto, devtype);
410: #endif
411: if (paniced == RB_PANIC) {
412: register unsigned i, n, *fp, pc;
413: fp = (unsigned *)&paniced - 1;
414: while(((int)fp&03)==0 && ((pc = fp[-2])&0xc0000000)==0xc0000000) {
415: printf("%x (", fp);
416: if(fp[-1] == 0x1fff0004) /* trap */
417: n = 6;
418: else
419: n = (fp[-1]&0xffff)/4;
420: for(i=1; i<n; i++) {
421: if(i > 1)
422: printf(",");
423: printf("%x", fp[i]);
424: }
425: printf(") from %x\n", pc);
426: if(fp[-1] == 0x1fff0004) { /* trap */
427: printf("regs: ");
428: for(i= -15; i<=-3; i++) {
429: if(i > -15)
430: printf(",");
431: printf("%x", fp[i]);
432: }
433: printf("\n");
434: }
435: fp = *(unsigned **)fp;
436: if (fp == NULL) break;
437: }
438: }
439: (void) spl1();
440: howto = arghowto;
441: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
442: waittime = 0;
443: update();
444: printf("syncing disks... ");
445: #ifdef notdef
446: DELAY(10000000);
447: #else
448: { register struct buf *bp;
449: int iter, nbusy, oldnbusy;
450:
451: printf ("\tBlocks to sync : ");
452: oldnbusy = 0;
453: for (;;) {
454: DELAY(1000);
455: nbusy = 0;
456: for (bp = &buf[nbuf]; --bp >= buf; )
457: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
458: nbusy++;
459: if (nbusy == 0)
460: break;
461: if (nbusy != oldnbusy) {
462: iter = 0;
463: printf("%d ", nbusy);
464: oldnbusy = nbusy;
465: } else {
466: if (++iter >= 100) {
467: printf (" - disk I/O stopped (?), giving up\n");
468: DELAY(10000);
469: break;
470: }
471: }
472: }
473: }
474: #endif
475: printf("done\n\n");
476: }
477: splx(0x1f); /* extreme priority */
478: devtype = major(rootdev);
479: if (howto&RB_HALT) {
480: printf("halting (in tight loop); hit <return>~h\n\n");
481: mtpr(0x1f,IPL);
482: for (;;)
483: ;
484: } else {
485: if (paniced == RB_PANIC) {
486: doadump(); /* TXDB_BOOT's itsself */
487: /*NOTREACHED*/
488: }
489: tocons(CPBOOT);
490: }
491: for (;;)
492: asm("halt");
493: /*NOTREACHED*/
494: }
495:
496:
497:
498: /*
499: * Send the given comand ('c') to the console processor.
500: * Assumed to be one of the last things the OS does before
501: * halting or rebooting.
502: */
503:
504: struct cphdr *lasthdr; /* Available in "dev/cons.c" */
505:
506: struct cpdcb_o cpcontrol;
507:
508: tocons(command)
509: int command;
510: {
511:
512: int timeout;
513:
514: cpcontrol.cp_hdr.cp_unit = CPUNIT;
515: cpcontrol.cp_hdr.cp_comm = (char) command;
516: if (command != CPBOOT)
517: cpcontrol.cp_hdr.cp_count = 1; /* Just for sanity */
518: else {
519: cpcontrol.cp_hdr.cp_count = 4;
520: *(int *)cpcontrol.cp_buf = 0; /* r11 value for reboot */
521: }
522: timeout = 100000; /* Delay loop */
523: while (timeout-- && !(lasthdr->cp_unit & CPDONE))
524: uncache(&lasthdr->cp_unit);
525: /* Give up, force it to listen */
526: mtpr ( vtoph(0, &cpcontrol), CPMDCB);
527: }
528:
529: /*
530: * Invalidate single all pte's in a cluster
531: */
532: tbiscl(v)
533: unsigned v;
534: {
535: register caddr_t addr; /* must be first reg var */
536: register int i;
537:
538: addr = ptob(v);
539: for (i = 0; i < CLSIZE; i++) {
540: mtpr(addr, TBIS);
541: addr += NBPG;
542: }
543: }
544:
545: int dumpmag = 0x8fca0101; /* magic number for savecore */
546: int dumpsize = 0; /* also for savecore */
547: /*
548: * Doadump comes here after turning off memory management and
549: * getting on the dump stack, either when called above, or by
550: * the auto-restart code.
551: */
552: dumpsys()
553: {
554:
555: #ifdef notdef
556: if ((minor(dumpdev)&07) != 1)
557: return;
558: #endif
559: dumpsize = physmem;
560: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
561: printf("dump ");
562: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
563:
564: case ENXIO:
565: printf("device bad\n");
566: break;
567:
568: case EFAULT:
569: printf("device not ready\n");
570: break;
571:
572: case EINVAL:
573: printf("area improper\n");
574: break;
575:
576: case EIO:
577: printf("i/o error\n");
578: break;
579:
580: default:
581: printf("succeeded\n");
582: break;
583: }
584: printf("Rebooting the system ...\n\n");
585: tocons(CPBOOT);
586: }
587:
588:
589: /*
590: * Bus error 'recovery' code.
591: * Print out the buss frame and then give up.
592: * (More information from special registers can be printed here.)
593: *
594: */
595:
596: /*
597: * Frame for bus error
598: */
599: struct buserframe {
600: int which_bus; /* primary or secondary */
601: int memerreg; /* memory error register */
602: int trp_pc; /* trapped pc */
603: int trp_psl; /* trapped psl */
604: };
605:
606: buserror(busef)
607: caddr_t busef;
608: {
609: register struct buserframe *frameptr;
610: register long hardreg;
611:
612:
613: frameptr = (struct buserframe *)busef;
614: printf("bus error at address %x, psl = %x\n",
615: frameptr->trp_pc,frameptr->trp_psl);
616: hardreg = frameptr->memerreg;
617: printf("\tMEAR = %x\n",((hardreg&MEAR)>>16)&0xffff);
618: switch (hardreg & ERRCD){
619: case (APE): printf("\tAdress parity error.Should not reach this point!! \n");
620: break;
621: case (DPE): printf("\tData parity error.\n");
622: break;
623: case (DCE): printf("\tData check error.\n");
624: break;
625: case (VTO): printf("\tVersabus timeout.\n");
626: break;
627: case (VBE): printf("\tVersabus error.Should not reach this point!! \n");
628: break;
629: case (NEM): printf("\tNon existent memory.\n");
630: break;
631: default: printf("\tUnknown error code: %x\n",
632: hardreg&ERRCD);
633: }
634: if (hardreg&AXE) printf("\tAdapter external error\n");
635: printf ("\tError master : ");
636: if (hardreg&ERM) printf("Versabus\n");
637: else printf ("Tahoe\n");
638: if (hardreg&IVV)
639: printf("\tIllegal interrupt vector, from ipl %d\n",
640: (hardreg >> 2) & 7);
641:
642: hardreg = frameptr->which_bus;
643: printf("\tMCBR = %x\n", ((hardreg&MCBR)>>16)&0xffff);
644: printf("\tVersabus type : %x\n", hardreg&0xffc3);
645: if (frameptr->memerreg&IVV) return;
646: panic("buserror");
647: }
648:
649:
650: physstrat(bp, strat, prio)
651: struct buf *bp;
652: int (*strat)(), prio;
653: {
654: int s;
655:
656: (*strat)(bp);
657: /* pageout daemon doesn't wait for pushed pages */
658: if (bp->b_flags & B_DIRTY)
659: return;
660: s = spl8();
661: while ((bp->b_flags & B_DONE) == 0)
662: sleep((caddr_t)bp, prio);
663: splx(s);
664: }
665:
666:
667: /*ARGSUSED*/
668: mtpr (value, regno)
669: {
670: asm("mtpr 4(fp), 8(fp)");
671: }
672:
673: /*ARGSUSED*/
674: int
675: mfpr (regno)
676: {
677: asm("mfpr 4(fp),r0");
678: #ifdef lint
679: return(0);
680: #endif
681: }
682:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.