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