|
|
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
1.1.1.2 ! root 311: asm("probew $1,(r10),$1");
! 312: asm("jeql bad");
! 313: asm("probew $1,7*4-1(r10),$1");
1.1 root 314: asm("jeql bad");
315: #else
316: if (useracc((caddr_t)fp, sizeof (struct sigframe), 1))
317: goto bad;
318: #endif
319: if (!u.u_onstack && (int)scp <= USRSTACK - ctob(u.u_ssize))
320: grow((unsigned)scp);
321: ; /* Avoid asm() label botch */
322: #ifndef lint
1.1.1.2 ! root 323: asm("probew $1,(r12),$1");
! 324: asm("beql bad");
! 325: asm("probew $1,5*4-1(r12),$1");
1.1 root 326: asm("beql bad");
327: #else
328: if (useracc((caddr_t)scp, sizeof (struct sigcontext), 1))
329: goto bad;
330: #endif
331: fp->sf_signum = sig;
332: if (sig == SIGILL || sig == SIGFPE) {
333: fp->sf_code = u.u_code;
334: u.u_code = 0;
335: } else
336: fp->sf_code = 0;
337: fp->sf_scp = scp;
338: fp->sf_handler = p;
339: fp->r1 = regs[R1]; /* These are not saved by the C compiler */
340: fp->r0 = regs[R0];
341: /*
342: * Duplicate the pointer to the sigcontext structure.
343: * This one doesn't get popped by the ret, and is used
344: * by sigcleanup to reset the signal state on inward return.
345: */
346: fp->sf_scpcopy = scp;
347: /* sigcontext goes on previous stack */
348: scp->sc_onstack = oonstack;
349: scp->sc_mask = sigmask;
350: /* setup rei */
351: scp->sc_sp = (int)&scp->sc_pc;
352: scp->sc_pc = regs[PC];
353: scp->sc_ps = regs[PS];
354: regs[SP] = (int)fp;
355: regs[PC] = (int)u.u_pcb.pcb_sigc;
356: return;
357:
358: asm("bad:");
359: bad:
360: /*
361: * Process has trashed its stack; give it an illegal
362: * instruction to halt it in its tracks.
363: */
364: u.u_signal[SIGILL] = SIG_DFL;
365: sig = mask(SIGILL);
366: u.u_procp->p_sigignore &= ~sig;
367: u.u_procp->p_sigcatch &= ~sig;
368: u.u_procp->p_sigmask &= ~sig;
369: psignal(u.u_procp, SIGILL);
370: }
371:
372: /*
373: * Routine to cleanup state after a signal
374: * has been taken. Reset signal mask and
375: * stack state from context left by sendsig (above).
376: * Pop these values in preparation for rei which
377: * follows return from this routine.
378: */
379: sigcleanup()
380: {
381: register struct sigcontext *scp; /* known as R12 */
382:
383: scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP]);
384: if ((int)scp == -1)
385: return;
386: #ifndef lint
387: ; /* Avoid asm() label botch */
388: /* only probe 12 here because that's all we need */
1.1.1.2 ! root 389: asm("prober $1,(r12),$1");
1.1 root 390: asm("bnequ 1f; ret; 1:");
1.1.1.2 ! root 391: asm("prober $1,11(r12),$1");
! 392: asm("bnequ 2f; ret; 2:");
1.1 root 393: #else
394: if (useracc((caddr_t)scp, sizeof (*scp), 0))
395: return;
396: #endif
397: u.u_onstack = scp->sc_onstack & 01;
398: u.u_procp->p_sigmask =
399: scp->sc_mask &~ (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP));
400: u.u_ar0[SP] = scp->sc_sp;
401: }
402: #undef mask
403:
404: int waittime = -1;
405:
406: boot(paniced, arghowto)
407: int paniced, arghowto;
408: {
409: register long dummy;
410: register int howto; /* r11 == how to boot */
411: register int devtype; /* r10 == major of root dev */
412:
413: #ifdef lint
414: howto = 0; devtype = 0;
415: printf("howto %d, devtype %d\n", arghowto, devtype);
416: #endif
417: if (paniced == RB_PANIC) {
418: register unsigned i, n, *fp, pc;
419: fp = (unsigned *)&paniced - 1;
420: while(((int)fp&03)==0 && ((pc = fp[-2])&0xc0000000)==0xc0000000) {
421: printf("%x (", fp);
422: if(fp[-1] == 0x1fff0004) /* trap */
423: n = 6;
424: else
425: n = (fp[-1]&0xffff)/4;
426: for(i=1; i<n; i++) {
427: if(i > 1)
428: printf(",");
429: printf("%x", fp[i]);
430: }
431: printf(") from %x\n", pc);
432: if(fp[-1] == 0x1fff0004) { /* trap */
433: printf("regs: ");
434: for(i= -15; i<=-3; i++) {
435: if(i > -15)
436: printf(",");
437: printf("%x", fp[i]);
438: }
439: printf("\n");
440: }
441: fp = *(unsigned **)fp;
442: if (fp == NULL) break;
443: }
444: }
445: (void) spl1();
446: howto = arghowto;
447: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
448: waittime = 0;
449: update();
450: printf("syncing disks... ");
451: #ifdef notdef
452: DELAY(10000000);
453: #else
454: { register struct buf *bp;
455: int iter, nbusy, oldnbusy;
456:
457: printf ("\tBlocks to sync : ");
458: oldnbusy = 0;
459: for (;;) {
460: DELAY(1000);
461: nbusy = 0;
462: for (bp = &buf[nbuf]; --bp >= buf; )
463: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
464: nbusy++;
465: if (nbusy == 0)
466: break;
467: if (nbusy != oldnbusy) {
468: iter = 0;
469: printf("%d ", nbusy);
470: oldnbusy = nbusy;
471: } else {
472: if (++iter >= 100) {
473: printf (" - disk I/O stopped (?), giving up\n");
474: DELAY(10000);
475: break;
476: }
477: }
478: }
479: }
480: #endif
481: printf("done\n\n");
482: }
483: splx(0x1f); /* extreme priority */
484: devtype = major(rootdev);
485: if (howto&RB_HALT) {
486: printf("halting (in tight loop); hit <return>~h\n\n");
487: mtpr(0x1f,IPL);
488: for (;;)
489: ;
490: } else {
491: if (paniced == RB_PANIC) {
492: doadump(); /* TXDB_BOOT's itsself */
493: /*NOTREACHED*/
494: }
495: tocons(CPBOOT);
496: }
497: for (;;)
498: asm("halt");
499: /*NOTREACHED*/
500: }
501:
502:
503:
504: /*
505: * Send the given comand ('c') to the console processor.
506: * Assumed to be one of the last things the OS does before
507: * halting or rebooting.
508: */
509:
510: struct cphdr *lasthdr; /* Available in "dev/cons.c" */
511:
512: struct cpdcb_o cpcontrol;
513:
514: tocons(command)
515: int command;
516: {
517:
518: int timeout;
519:
520: cpcontrol.cp_hdr.cp_unit = CPUNIT;
521: cpcontrol.cp_hdr.cp_comm = (char) command;
522: if (command != CPBOOT)
523: cpcontrol.cp_hdr.cp_count = 1; /* Just for sanity */
524: else {
525: cpcontrol.cp_hdr.cp_count = 4;
526: *(int *)cpcontrol.cp_buf = 0; /* r11 value for reboot */
527: }
528: timeout = 100000; /* Delay loop */
529: while (timeout-- && !(lasthdr->cp_unit & CPDONE))
530: uncache(&lasthdr->cp_unit);
531: /* Give up, force it to listen */
532: mtpr ( vtoph(0, &cpcontrol), CPMDCB);
533: }
534:
535: /*
536: * Invalidate single all pte's in a cluster
537: */
538: tbiscl(v)
539: unsigned v;
540: {
541: register caddr_t addr; /* must be first reg var */
542: register int i;
543:
544: addr = ptob(v);
545: for (i = 0; i < CLSIZE; i++) {
546: mtpr(addr, TBIS);
547: addr += NBPG;
548: }
549: }
550:
551: int dumpmag = 0x8fca0101; /* magic number for savecore */
552: int dumpsize = 0; /* also for savecore */
553: /*
554: * Doadump comes here after turning off memory management and
555: * getting on the dump stack, either when called above, or by
556: * the auto-restart code.
557: */
558: dumpsys()
559: {
560:
561: #ifdef notdef
562: if ((minor(dumpdev)&07) != 1)
563: return;
564: #endif
565: dumpsize = physmem;
566: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
567: printf("dump ");
568: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
569:
570: case ENXIO:
571: printf("device bad\n");
572: break;
573:
574: case EFAULT:
575: printf("device not ready\n");
576: break;
577:
578: case EINVAL:
579: printf("area improper\n");
580: break;
581:
582: case EIO:
583: printf("i/o error\n");
584: break;
585:
586: default:
587: printf("succeeded\n");
588: break;
589: }
590: printf("Rebooting the system ...\n\n");
591: tocons(CPBOOT);
592: }
593:
594:
595: /*
596: * Bus error 'recovery' code.
597: * Print out the buss frame and then give up.
598: * (More information from special registers can be printed here.)
599: *
600: */
601:
602: /*
603: * Frame for bus error
604: */
605: struct buserframe {
606: int which_bus; /* primary or secondary */
607: int memerreg; /* memory error register */
608: int trp_pc; /* trapped pc */
609: int trp_psl; /* trapped psl */
610: };
611:
612: buserror(busef)
613: caddr_t busef;
614: {
615: register struct buserframe *frameptr;
616: register long hardreg;
617:
618:
619: frameptr = (struct buserframe *)busef;
620: printf("bus error at address %x, psl = %x\n",
621: frameptr->trp_pc,frameptr->trp_psl);
622: hardreg = frameptr->memerreg;
623: printf("\tMEAR = %x\n",((hardreg&MEAR)>>16)&0xffff);
624: switch (hardreg & ERRCD){
625: case (APE): printf("\tAdress parity error.Should not reach this point!! \n");
626: break;
627: case (DPE): printf("\tData parity error.\n");
628: break;
629: case (DCE): printf("\tData check error.\n");
630: break;
631: case (VTO): printf("\tVersabus timeout.\n");
632: break;
633: case (VBE): printf("\tVersabus error.Should not reach this point!! \n");
634: break;
635: case (NEM): printf("\tNon existent memory.\n");
636: break;
637: default: printf("\tUnknown error code: %x\n",
638: hardreg&ERRCD);
639: }
640: if (hardreg&AXE) printf("\tAdapter external error\n");
641: printf ("\tError master : ");
642: if (hardreg&ERM) printf("Versabus\n");
643: else printf ("Tahoe\n");
644: if (hardreg&IVV)
645: printf("\tIllegal interrupt vector, from ipl %d\n",
646: (hardreg >> 2) & 7);
647:
648: hardreg = frameptr->which_bus;
649: printf("\tMCBR = %x\n", ((hardreg&MCBR)>>16)&0xffff);
650: printf("\tVersabus type : %x\n", hardreg&0xffc3);
651: if (frameptr->memerreg&IVV) return;
652: panic("buserror");
653: }
654:
655:
656: physstrat(bp, strat, prio)
657: struct buf *bp;
658: int (*strat)(), prio;
659: {
660: int s;
661:
662: (*strat)(bp);
663: /* pageout daemon doesn't wait for pushed pages */
664: if (bp->b_flags & B_DIRTY)
665: return;
666: s = spl8();
667: while ((bp->b_flags & B_DONE) == 0)
668: sleep((caddr_t)bp, prio);
669: splx(s);
670: }
671:
672:
673: /*ARGSUSED*/
674: mtpr (value, regno)
675: {
676: asm("mtpr 4(fp), 8(fp)");
677: }
678:
679: /*ARGSUSED*/
680: int
681: mfpr (regno)
682: {
683: asm("mfpr 4(fp),r0");
684: #ifdef lint
685: return(0);
686: #endif
687: }
688:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.