|
|
1.1 root 1: /*
2: * Copyright (c) 1982,1987,1988 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)machdep.c 7.1 (Berkeley) 5/26/88
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "dir.h"
12: #include "user.h"
13: #include "kernel.h"
14: #include "map.h"
15: #include "vm.h"
16: #include "proc.h"
17: #include "buf.h"
18: #include "reboot.h"
19: #include "conf.h"
20: #include "inode.h"
21: #include "file.h"
22: #include "text.h"
23: #include "clist.h"
24: #include "callout.h"
25: #include "cmap.h"
26: #include "malloc.h"
27: #include "mbuf.h"
28: #include "msgbuf.h"
29: #include "quota.h"
30:
31: #include "cpu.h"
32: #include "reg.h"
33: #include "pte.h"
34: #include "psl.h"
35: #include "mem.h"
36: #include "mtpr.h"
37: #include "cp.h"
38:
39: #include "../tahoevba/vbavar.h"
40:
41: /*
42: * Declare these as initialized data so we can patch them.
43: */
44: int nswbuf = 0;
45: #ifdef NBUF
46: int nbuf = NBUF;
47: #else
48: int nbuf = 0;
49: #endif
50: #ifdef BUFPAGES
51: int bufpages = BUFPAGES;
52: #else
53: int bufpages = 0;
54: #endif
55: #include "yc.h"
56: #if NCY > 0
57: #include "../tahoevba/cyreg.h"
58: #endif
59: int msgbufmapped; /* set when safe to use msgbuf */
60:
61: /*
62: * Machine-dependent startup code
63: */
64: startup(firstaddr)
65: int firstaddr;
66: {
67: register int unixsize;
68: register unsigned i;
69: register struct pte *pte;
70: int mapaddr, j;
71: register caddr_t v;
72: int maxbufs, base, residual;
73:
74: /*
75: * Initialize error message buffer (at end of core).
76: */
77: maxmem -= btoc(sizeof (struct msgbuf));
78: pte = msgbufmap;
79: for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
80: *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
81: mtpr(TBIA, 1);
82: msgbufmapped = 1;
83: #ifdef KADB
84: kdb_init(); /* startup kernel debugger */
85: #endif
86: /*
87: * Good {morning,afternoon,evening,night}.
88: */
89: printf(version);
90: printf("real mem = %d\n", ctob(physmem));
91:
92: /*
93: * Allocate space for system data structures.
94: * The first available real memory address is in "firstaddr".
95: * The first available kernel virtual address is in "v".
96: * As pages of kernel virtual memory are allocated, "v" is incremented.
97: * As pages of memory are allocated and cleared,
98: * "firstaddr" is incremented.
99: * An index into the kernel page table corresponding to the
100: * virtual memory address maintained in "v" is kept in "mapaddr".
101: */
102: v = (caddr_t)(0xc0000000 | (firstaddr * NBPG));
103: #define valloc(name, type, num) \
104: (name) = (type *)v; v = (caddr_t)((name)+(num))
105: #define valloclim(name, type, num, lim) \
106: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
107: #if NCY > 0
108: /*
109: * Allocate raw buffers for tapemaster controllers
110: * first, as they need buffers in the first megabyte.
111: */
112: valloc(cybuf, char, NCY * CYMAXIO);
113: #endif
114: valloclim(inode, struct inode, ninode, inodeNINODE);
115: valloclim(file, struct file, nfile, fileNFILE);
116: valloclim(proc, struct proc, nproc, procNPROC);
117: valloclim(text, struct text, ntext, textNTEXT);
118: valloc(cfree, struct cblock, nclist);
119: valloc(callout, struct callout, ncallout);
120: valloc(swapmap, struct map, nswapmap = nproc * 2);
121: valloc(argmap, struct map, ARGMAPSIZE);
122: valloc(kernelmap, struct map, nproc);
123: valloc(mbmap, struct map, nmbclusters/4);
124: valloc(namecache, struct namecache, nchsize);
125: valloc(kmemmap, struct map, ekmempt - kmempt);
126: valloc(kmemusage, struct kmemusage, ekmempt - kmempt);
127: #ifdef QUOTA
128: valloclim(quota, struct quota, nquota, quotaNQUOTA);
129: valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
130: #endif
131:
132: /*
133: * Determine how many buffers to allocate.
134: * Use 10% of memory for the first 2 Meg, 5% of the remaining
135: * memory. Insure a minimum of 16 buffers.
136: * We allocate 1/2 as many swap buffer headers as file i/o buffers.
137: */
138: if (bufpages == 0)
139: if (physmem < (2 * 1024 * 1024))
140: bufpages = physmem / 10 / CLSIZE;
141: else
142: bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
143: if (nbuf == 0) {
144: nbuf = bufpages / 2;
145: if (nbuf < 16)
146: nbuf = 16;
147: }
148: if (nswbuf == 0) {
149: nswbuf = (nbuf / 2) &~ 1; /* force even */
150: if (nswbuf > 256)
151: nswbuf = 256; /* sanity */
152: }
153: valloc(swbuf, struct buf, nswbuf);
154:
155: /*
156: * Now the amount of virtual memory remaining for buffers
157: * can be calculated, estimating needs for the cmap.
158: */
159: ncmap = (maxmem*NBPG - ((int)v &~ 0xc0000000)) /
160: (CLBYTES + sizeof(struct cmap)) + 2;
161: maxbufs = ((SYSPTSIZE * NBPG) -
162: ((int)(v + ncmap * sizeof(struct cmap)) - 0xc0000000)) /
163: (MAXBSIZE + sizeof(struct buf));
164: if (maxbufs < 16)
165: panic("sys pt too small");
166: if (nbuf > maxbufs) {
167: printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
168: nbuf = maxbufs;
169: }
170: if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
171: bufpages = nbuf * (MAXBSIZE / CLBYTES);
172: valloc(buf, struct buf, nbuf);
173:
174: /*
175: * Allocate space for core map.
176: * Allow space for all of phsical memory minus the amount
177: * dedicated to the system. The amount of physical memory
178: * dedicated to the system is the total virtual memory of
179: * the system thus far, plus core map, buffer pages,
180: * and buffer headers not yet allocated.
181: * Add 2: 1 because the 0th entry is unused, 1 for rounding.
182: */
183: ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0xc0000000)) /
184: (CLBYTES + sizeof(struct cmap)) + 2;
185: valloclim(cmap, struct cmap, ncmap, ecmap);
186:
187: /*
188: * Clear space allocated thus far, and make r/w entries
189: * for the space in the kernel map.
190: */
191: unixsize = btoc((int)v &~ 0xc0000000);
192: while (firstaddr < unixsize) {
193: *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr;
194: clearseg((unsigned)firstaddr);
195: firstaddr++;
196: }
197:
198: /*
199: * Now allocate buffers proper. They are different than the above
200: * in that they usually occupy more virtual memory than physical.
201: */
202: v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
203: valloc(buffers, char, MAXBSIZE * nbuf);
204: base = bufpages / nbuf;
205: residual = bufpages % nbuf;
206: mapaddr = firstaddr;
207: for (i = 0; i < residual; i++) {
208: for (j = 0; j < (base + 1) * CLSIZE; j++) {
209: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
210: clearseg((unsigned)firstaddr);
211: firstaddr++;
212: }
213: mapaddr += MAXBSIZE / NBPG;
214: }
215: for (i = residual; i < nbuf; i++) {
216: for (j = 0; j < base * CLSIZE; j++) {
217: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
218: clearseg((unsigned)firstaddr);
219: firstaddr++;
220: }
221: mapaddr += MAXBSIZE / NBPG;
222: }
223:
224: unixsize = btoc((int)v &~ 0xc0000000);
225: if (firstaddr >= physmem - 8*UPAGES)
226: panic("no memory");
227: mtpr(TBIA, 1); /* After we just cleared it all! */
228:
229: /*
230: * Initialize callouts
231: */
232: callfree = callout;
233: for (i = 1; i < ncallout; i++)
234: callout[i-1].c_next = &callout[i];
235:
236: /*
237: * Initialize memory allocator and swap
238: * and user page table maps.
239: *
240: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
241: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
242: */
243: meminit(firstaddr, maxmem);
244: maxmem = freemem;
245: printf("avail mem = %d\n", ctob(maxmem));
246: printf("using %d buffers containing %d bytes of memory\n",
247: nbuf, bufpages * CLBYTES);
248: rminit(kernelmap, (long)USRPTSIZE, (long)1,
249: "usrpt", nproc);
250: rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE,
251: "mbclusters", nmbclusters/4);
252: kmeminit(); /* now safe to do malloc/free */
253: intenable = 1; /* Enable interrupts from now on */
254:
255: /*
256: * Set up CPU-specific registers, cache, etc.
257: */
258: initcpu();
259:
260: /*
261: * Set up buffers, so they can be used to read disk labels.
262: */
263: bhinit();
264: binit();
265:
266: /*
267: * Configure the system.
268: */
269: configure();
270: }
271:
272: #ifdef PGINPROF
273: /*
274: * Return the difference (in microseconds)
275: * between the current time and a previous
276: * time as represented by the arguments.
277: * If there is a pending clock interrupt
278: * which has not been serviced due to high
279: * ipl, return error code.
280: */
281: /*ARGSUSED*/
282: vmtime(otime, olbolt, oicr)
283: register int otime, olbolt, oicr;
284: {
285:
286: return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
287: }
288: #endif
289:
290: /*
291: * Send an interrupt to process.
292: *
293: * Stack is set up to allow sigcode stored
294: * in u. to call routine, followed by kcall
295: * to sigreturn routine below. After sigreturn
296: * resets the signal mask, the stack, and the
297: * frame pointer, it returns to the user
298: * specified pc, psl.
299: */
300: sendsig(p, sig, mask)
301: int (*p)(), sig, mask;
302: {
303: register struct sigcontext *scp;
304: register int *regs;
305: register struct sigframe {
306: int sf_signum;
307: int sf_code;
308: struct sigcontext *sf_scp;
309: int (*sf_handler)();
310: int sf_regs[6]; /* r0-r5 */
311: struct sigcontext *sf_scpcopy;
312: } *fp;
313: int oonstack;
314:
315: regs = u.u_ar0;
316: oonstack = u.u_onstack;
317: /*
318: * Allocate and validate space for the signal handler
319: * context. Note that if the stack is in P0 space, the
320: * call to grow() is a nop, and the useracc() check
321: * will fail if the process has not already allocated
322: * the space with a `brk'.
323: */
324: if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
325: scp = (struct sigcontext *)u.u_sigsp - 1;
326: u.u_onstack = 1;
327: } else
328: scp = (struct sigcontext *)regs[SP] - 1;
329: fp = (struct sigframe *)scp - 1;
330: if ((int)fp <= USRSTACK - ctob(u.u_ssize))
331: (void) grow((unsigned)fp);
332: if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) {
333: /*
334: * Process has trashed its stack; give it an illegal
335: * instruction to halt it in its tracks.
336: */
337: u.u_signal[SIGILL] = SIG_DFL;
338: sig = sigmask(SIGILL);
339: u.u_procp->p_sigignore &= ~sig;
340: u.u_procp->p_sigcatch &= ~sig;
341: u.u_procp->p_sigmask &= ~sig;
342: psignal(u.u_procp, SIGILL);
343: return;
344: }
345: /*
346: * Build the argument list for the signal handler.
347: */
348: fp->sf_signum = sig;
349: if (sig == SIGILL || sig == SIGFPE) {
350: fp->sf_code = u.u_code;
351: u.u_code = 0;
352: } else
353: fp->sf_code = 0;
354: fp->sf_scp = scp;
355: fp->sf_handler = p;
356: /*
357: * Build the callf argument frame to be used to call sigreturn.
358: */
359: fp->sf_scpcopy = scp;
360: /*
361: * Build the signal context to be used by sigreturn.
362: */
363: scp->sc_onstack = oonstack;
364: scp->sc_mask = mask;
365: scp->sc_sp = regs[SP];
366: scp->sc_fp = regs[FP];
367: scp->sc_pc = regs[PC];
368: scp->sc_ps = regs[PS];
369: regs[SP] = (int)fp;
370: regs[PC] = (int)u.u_pcb.pcb_sigc;
371: }
372:
373: /*
374: * System call to cleanup state after a signal
375: * has been taken. Reset signal mask and
376: * stack state from context left by sendsig (above).
377: * Return to previous pc and psl as specified by
378: * context left by sendsig. Check carefully to
379: * make sure that the user has not modified the
380: * psl to gain improper priviledges or to cause
381: * a machine fault.
382: */
383: sigreturn()
384: {
385: struct a {
386: struct sigcontext *sigcntxp;
387: };
388: register struct sigcontext *scp;
389: register int *regs = u.u_ar0;
390:
391: scp = ((struct a *)(u.u_ap))->sigcntxp;
392: if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) {
393: u.u_error = EINVAL;
394: return;
395: }
396: if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 ||
397: (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD)) {
398: u.u_error = EINVAL;
399: return;
400: }
401: u.u_eosys = JUSTRETURN;
402: u.u_onstack = scp->sc_onstack & 01;
403: u.u_procp->p_sigmask = scp->sc_mask &~
404: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
405: regs[FP] = scp->sc_fp;
406: regs[SP] = scp->sc_sp;
407: regs[PC] = scp->sc_pc;
408: regs[PS] = scp->sc_ps;
409: }
410:
411: /* XXX - BEGIN 4.2 COMPATIBILITY */
412: /*
413: * Compatibility with 4.2 kcall $139 used by longjmp()
414: */
415: osigcleanup()
416: {
417: register struct sigcontext *scp;
418: register int *regs = u.u_ar0;
419:
420: scp = (struct sigcontext *)fuword((caddr_t)regs[SP]);
421: if ((int)scp == -1)
422: return;
423: if (useracc((caddr_t)scp, 3 * sizeof (int), 0) == 0)
424: return;
425: u.u_onstack = scp->sc_onstack & 01;
426: u.u_procp->p_sigmask = scp->sc_mask &~
427: (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
428: regs[SP] = scp->sc_sp;
429: }
430: /* XXX - END 4.2 COMPATIBILITY */
431:
432: int waittime = -1;
433:
434: boot(arghowto)
435: int arghowto;
436: {
437: register long dummy; /* r12 is reserved */
438: register int howto; /* r11 == how to boot */
439: register int devtype; /* r10 == major of root dev */
440: extern char *panicstr;
441:
442: howto = arghowto;
443: if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
444: register struct buf *bp;
445: int iter, nbusy;
446:
447: waittime = 0;
448: (void) splnet();
449: printf("syncing disks... ");
450: /*
451: * Release inodes held by texts before update.
452: */
453: if (panicstr == 0)
454: xumount(NODEV);
455: update();
456:
457: for (iter = 0; iter < 20; iter++) {
458: nbusy = 0;
459: for (bp = &buf[nbuf]; --bp >= buf; )
460: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
461: nbusy++;
462: if (nbusy == 0)
463: break;
464: printf("%d ", nbusy);
465: DELAY(40000 * iter);
466: }
467: if (nbusy)
468: printf("giving up\n");
469: else
470: printf("done\n");
471: DELAY(10000); /* wait for printf to finish */
472: }
473: mtpr(IPL, 0x1f); /* extreme priority */
474: devtype = major(rootdev);
475: *(int *)CPBFLG = howto;
476: if (howto&RB_HALT) {
477: printf("halting (in tight loop); hit ~h\n\n");
478: mtpr(IPL, 0x1f);
479: for (;;)
480: ;
481: } else {
482: if (howto & RB_DUMP) {
483: doadump(); /* CPBOOT's itsself */
484: /*NOTREACHED*/
485: }
486: tocons(CPBOOT);
487: }
488: #ifdef lint
489: dummy = 0; dummy = dummy;
490: printf("howto %d, devtype %d\n", arghowto, devtype);
491: #endif
492: for (;;)
493: asm("halt");
494: /*NOTREACHED*/
495: }
496:
497: struct cpdcb_o cpcontrol;
498:
499: /*
500: * Send the given comand ('c') to the console processor.
501: * Assumed to be one of the last things the OS does before
502: * halting or rebooting.
503: */
504: tocons(c)
505: {
506: register timeout;
507:
508: cpcontrol.cp_hdr.cp_unit = CPUNIT;
509: cpcontrol.cp_hdr.cp_comm = (char)c;
510: if (c != CPBOOT)
511: cpcontrol.cp_hdr.cp_count = 1; /* Just for sanity */
512: else {
513: cpcontrol.cp_hdr.cp_count = 4;
514: *(int *)cpcontrol.cp_buf = 0; /* r11 value for reboot */
515: }
516: timeout = 100000; /* Delay loop */
517: while (timeout-- && (cnlast->cp_unit&CPDONE) == 0)
518: uncache(&cnlast->cp_unit);
519: /* give up, force it to listen */
520: mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&cpcontrol));
521: }
522:
523: #if CLSIZE != 1
524: /*
525: * Invalidate single all pte's in a cluster
526: */
527: tbiscl(v)
528: unsigned v;
529: {
530: register caddr_t addr; /* must be first reg var */
531: register int i;
532:
533: addr = ptob(v);
534: for (i = 0; i < CLSIZE; i++) {
535: mtpr(TBIS, addr);
536: addr += NBPG;
537: }
538: }
539: #endif
540:
541: int dumpmag = 0x8fca0101; /* magic number for savecore */
542: int dumpsize = 0; /* also for savecore */
543: /*
544: * Doadump comes here after turning off memory management and
545: * getting on the dump stack, either when called above, or by
546: * the auto-restart code.
547: */
548: dumpsys()
549: {
550:
551: if (dumpdev == NODEV)
552: return;
553: #ifdef notdef
554: if ((minor(dumpdev)&07) != 1)
555: return;
556: #endif
557: dumpsize = physmem;
558: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
559: printf("dump ");
560: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
561:
562: case ENXIO:
563: printf("device bad\n");
564: break;
565:
566: case EFAULT:
567: printf("device not ready\n");
568: break;
569:
570: case EINVAL:
571: printf("area improper\n");
572: break;
573:
574: case EIO:
575: printf("i/o error\n");
576: break;
577:
578: default:
579: printf("succeeded\n");
580: break;
581: }
582: printf("\n\n");
583: DELAY(1000);
584: tocons(CPBOOT);
585: }
586:
587: /*
588: * Bus error 'recovery' code.
589: * Print out the buss frame and then give up.
590: * (More information from special registers can be printed here.)
591: */
592:
593: /*
594: * Frame for bus error
595: */
596: struct buserframe {
597: int which_bus; /* primary or secondary */
598: int memerreg; /* memory error register */
599: int trp_pc; /* trapped pc */
600: int trp_psl; /* trapped psl */
601: };
602:
603: char *mem_errcd[8] = {
604: "Unknown error code 0",
605: "Address parity error", /* APE */
606: "Data parity error", /* DPE */
607: "Data check error", /* DCE */
608: "Versabus timeout", /* VTO */
609: "Versabus error", /* VBE */
610: "Non-existent memory", /* NEM */
611: "Unknown error code 7",
612: };
613:
614: buserror(v)
615: caddr_t v;
616: {
617: register struct buserframe *busef = (struct buserframe *)v;
618: register long reg;
619:
620: printf("bus error, address %x, psl %x\n",
621: busef->trp_pc, busef->trp_psl);
622: reg = busef->memerreg;
623: printf("mear %x %s\n",
624: ((reg&MEAR)>>16)&0xffff, mem_errcd[reg & ERRCD]);
625: if (reg&AXE)
626: printf("adapter external error\n");
627: printf("error master: %s\n", reg&ERM ? "versabus" : "tahoe");
628: if (reg&IVV)
629: printf("illegal interrupt vector from ipl %d\n", (reg>>2)&7);
630: reg = busef->which_bus;
631: printf("mcbr %x versabus type %x\n",
632: ((reg&MCBR)>>16)&0xffff, reg & 0xffc3);
633: if ((busef->memerreg&IVV) == 0)
634: panic("buserror");
635: }
636:
637: microtime(tvp)
638: register struct timeval *tvp;
639: {
640: int s = splhigh();
641:
642: *tvp = time;
643: tvp->tv_usec += tick;
644: while (tvp->tv_usec > 1000000) {
645: tvp->tv_sec++;
646: tvp->tv_usec -= 1000000;
647: }
648: splx(s);
649: }
650:
651: initcpu()
652: {
653: register struct proc *p;
654:
655: p = &proc[0];
656: #define initkey(which, p, index) \
657: which/**/_cache[index] = 1, which/**/_cnt[index] = 1; \
658: p->p_/**/which = index;
659: initkey(ckey, p, MAXCKEY);
660: initkey(dkey, p, MAXDKEY);
661: }
662:
663: /*
664: * Clear registers on exec
665: */
666: setregs(entry)
667: u_long entry;
668: {
669:
670: #ifdef notdef
671: /* should pass args to init on the stack */
672: for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
673: *rp++ = 0;
674: #endif
675: u.u_ar0[FP] = 0; /* bottom of the fp chain */
676: u.u_ar0[PC] = entry + 2;
677: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.