|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)machdep.c 1.1 86/02/03 Copyr 1986 Sun Micro";
3: #endif lint
4:
5: /*
6: * Copyright (c) 1986 by Sun Microsystems, Inc.
7: */
8:
9: #include "../h/param.h"
10: #include "../h/systm.h"
11: #include "../h/dir.h"
12: #include "../h/user.h"
13: #include "../h/map.h"
14: #include "../h/vm.h"
15: #include "../h/lnode.h"
16: #include "../h/proc.h"
17: #include "../h/msgbuf.h"
18: #include "../h/buf.h"
19: #include "../h/inode.h"
20: #include "../h/file.h"
21: #include "../h/text.h"
22: #include "../h/callout.h"
23: #include "../h/cmap.h"
24: #include "../h/reboot.h"
25:
26: #include "../machine/mbvar.h"
27: #include "../machine/psl.h"
28: #include "../machine/reg.h"
29: #include "../machine/clock.h"
30: #include "../machine/pte.h"
31: #include "../machine/scb.h"
32: #include "../machine/mmu.h"
33: #include "../machine/cpu.h"
34: #include "../machine/eeprom.h"
35: #include "../machine/interreg.h"
36: #include "../machine/memerr.h"
37: #include "../machine/eccreg.h"
38: #include "../machine/frame.h"
39:
40: /*
41: * Declare these as initialized data so we can patch them.
42: */
43: int nbuf = 0;
44: int nswbuf = 0;
45: int bufpages = 0;
46: int physmem = 0; /* memory size in pages, patch if you want less */
47: int kernprot = 1; /* write protect kernel text */
48: int msgbufinit = 0; /* message buffer has been initialized, ok to printf */
49: dev_t consdev = 0;
50:
51: int (*exit_vector)() = (int (*)())0; /* Where to go when halting UNIX */
52:
53: #define TESTVAL 0xA55A /* memory test value */
54:
55: u_char getsegmap(), pmegallocres();
56: long getpgmap();
57:
58: #ifdef SUN3_260
59: /*
60: * Since there is no implied ordering of the memory cards, we store
61: * a zero terminated list of pointers to eccreg's that are active so
62: * that we only look at existent memory cards during softecc() handling.
63: */
64: struct eccreg *ecc_alive[MAX_ECC+1];
65: #endif SUN3_260
66:
67: /*
68: * We make use of CMAPn (the pte address)
69: * and CADDRn (the virtual address)
70: * which are both temporaries defined in locore.s,
71: * not preserved across context switches,
72: * and not to be used in interrupt routines
73: */
74:
75: /*
76: * Machine-dependent startup code
77: */
78: startup()
79: {
80: register int unixsize, dvmapage;
81: register unsigned i;
82: register int c;
83: register struct pte *pte;
84: register caddr_t v;
85: u_int firstaddr; /* next free physical page number */
86: extern char start[], etext[], end[], CADDR1[], Syslimit[];
87: u_char oc, u_pmeg;
88: u_int mapaddr;
89: caddr_t zmemall();
90: void v_handler();
91: int mon_mem;
92:
93: initscb(); /* set trap vectors */
94: *INTERREG |= IR_ENA_INT; /* make sure interrupts can occur */
95: firstaddr = btoc((int)end - KERNELBASE) + UPAGES;
96:
97: /*
98: * Initialize map of allocated page map groups.
99: * Must be done before mapin of unallocated segments.
100: */
101: pmeginit(); /* init list of pmeg data structures */
102: ctxinit(); /* init context data structures */
103:
104: /*
105: * Reserve necessary pmegs and set segment mapping.
106: * It is assumed here that the pmegs for low
107: * memory have already been duplicated for the
108: * segments up in the kernel virtual address space.
109: */
110:
111: /*
112: * invalidate to start of high mapping
113: */
114: for (i = 0; i < KERNELBASE >> SGSHIFT; i++)
115: setsegmap(i, (u_char)SEGINV);
116:
117: /* reserve kernel pmegs */
118: for (; i < ptos(NPAGSEG - 1 + btoc(end)); i++)
119: pmegreserve(getsegmap(i));
120:
121: for (; i < (MONSTART >> SGSHIFT); i++) /* invalidate to mon start */
122: setsegmap(i, (u_char)SEGINV);
123:
124: for (; i < (MONEND >> SGSHIFT); i++) /* reserve monitor pmegs */
125: if ((oc = getsegmap(i)) != (u_char)SEGINV)
126: pmegreserve(oc);
127:
128: for (; i < NSEGMAP - 1; i++) /* invalid until last seg */
129: setsegmap(i, (u_char)SEGINV);
130:
131: /*
132: * Last segment contains the u area itself,
133: * the pmeg here is reserved for all contexts.
134: * We also reserve the invalid pmeg itself.
135: */
136: u_pmeg = getsegmap(NSEGMAP - 1);
137: pmegreserve(u_pmeg);
138: pmegreserve((u_char)SEGINV);
139:
140: setcputype(); /* sets cpu and dvmasize variables */
141:
142: /*
143: * Make sure the memory error register is
144: * set up to generate interrupts on error.
145: */
146: #if defined(SUN3_160) || defined(SUN3_50)
147: if (cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50)
148: MEMREG->mr_per = PER_INTENA | PER_CHECK;
149: #endif defined(SUN3_160) || defined(SUN3_50)
150:
151: #ifdef SUN3_260
152: if (cpu == CPU_SUN3_260) {
153: register struct eccreg **ecc_nxt = ecc_alive;
154: register struct eccreg *ecc;
155:
156: /*
157: * Go probe for all memory cards and perform initialization.
158: * The address of the cards found is stashed in ecc_alive[].
159: * We assume that the cards are already enabled and the
160: * base addresses have been set correctly by the monitor.
161: */
162: for (ecc = ECCREG; ecc < &ECCREG[MAX_ECC]; ecc++) {
163: if (peekc((char *)ecc) == -1)
164: continue;
165: ecc->eccena.ena_scrub = 1;
166: ecc->eccena.ena_busena = 1;
167: *ecc_nxt++ = ecc;
168: }
169: *ecc_nxt = (struct eccreg *)0; /* terminate list */
170:
171: MEMREG->mr_eer = EER_INTENA | EER_CE_ENA;
172: }
173: #endif SUN3_260
174:
175: /*
176: * Allocate pmegs for DVMA space
177: */
178: for (i = ptos(btop(DVMA)); i < ptos(btop(DVMA) + dvmasize); i++) {
179: u_char pm = pmegallocres();
180:
181: setsegmap(i, pm);
182: for (v = (caddr_t)ctob(NPAGSEG * i);
183: v < (caddr_t)ctob(NPAGSEG * (i+1));
184: v += NBPG)
185: setpgmap(v, (long)0);
186: }
187:
188: /*
189: * Now go through all the other contexts and set up the segment
190: * maps so that all segments are mapped the same.
191: * We have to use a PROM routine to do this since we don't want
192: * to switch to a new (unmapped) context to call setsegmap()!
193: */
194: for (c = 0; c < NCONTEXT; c++) {
195: if (c == KCONTEXT)
196: continue;
197:
198: for (v = (caddr_t)0, i = 0;
199: v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBSG, i++)
200: (*romp->v_setcxsegmap)(c, v, getsegmap(i));
201: }
202:
203: /*
204: * Initialize kernel page table entries.
205: */
206: pte = &Sysmap[0];
207:
208: /* invalid until start except scb page which is kernel writable */
209: for (v = (caddr_t)KERNELBASE; v < (caddr_t)start; v += NBPG) {
210: if (v == (caddr_t)&scb)
211: *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
212: else
213: *(int *)pte = 0;
214: setpgmap(v, *(long *)pte++);
215: }
216:
217: /* set up kernel text pages */
218: for (; v < (caddr_t)etext; v += NBPG) {
219: if (kernprot) /* is kernel to be protected? */
220: *(int *)pte = PG_V | PG_KR | getpgmap(v) & PG_PFNUM;
221: else
222: *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
223: setpgmap(v, *(long *)pte++);
224: }
225:
226: /* set up kernel data/bss pages to be writeable */
227: for (; v < (caddr_t)end; v += NBPG) {
228: *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
229: setpgmap(v, *(long *)pte++);
230: }
231:
232: /* invalid until end of this segment */
233: i = ((u_int)end + SGOFSET) & ~SGOFSET;
234: for (; v < (caddr_t)i; v += NBPG)
235: setpgmap(v, (long)0);
236:
237: /*
238: * Remove user access to monitor-set-up maps.
239: */
240: for (i = MONSTART>>SGSHIFT; i < MONEND>>SGSHIFT; i++) {
241: if (getsegmap(i) == SEGINV)
242: continue;
243: for (v = (caddr_t)ctob(NPAGSEG * i);
244: v < (caddr_t)ctob(NPAGSEG * (i+1));
245: v += NBPG)
246: setpgmap(v, (long)(((getpgmap(v) & ~PG_PROT) | PG_KW)));
247: }
248:
249: /*
250: * Invalidate any other pages in last segment
251: * besides the u area, EEPROM_ADDR, CLKADDR,
252: * MEMREG, INTERREG and MONSHORTPAGE. This sets
253: * up the kernel redzone below the u area. We
254: * get interrupt redzone for free when the kernel
255: * is write protected as the interrupt stack is
256: * the first thing in the data area. Since u
257: * and MONSHORTPAGE are defined as 32 bit virtual
258: * addresses (to get short references to work),
259: * we must mask to get only the 28 bits we really
260: * want to look at.
261: */
262: for (v = (caddr_t)ctob(NPAGSEG * (NSEGMAP - 1));
263: v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBPG) {
264: if (((u_int)v < ((u_int)&u & 0x0FFFFFFF) ||
265: (u_int)v >= (((u_int)&u & 0x0FFFFFFF) + UPAGES*NBPG)) &&
266: (u_int)v != ((u_int)MONSHORTPAGE & 0x0FFFFFFF) &&
267: (u_int)v != (u_int)EEPROM_ADDR &&
268: (u_int)v != (u_int)CLKADDR &&
269: (u_int)v != (u_int)MEMREG &&
270: (u_int)v != (u_int)INTERREG)
271: setpgmap(v, (long)0);
272: }
273:
274: /*
275: * v_memorysize is the amount of physical memory while
276: * v_memoryavail is the amount of usable memory in versions
277: * equal or greater to 1. Mon_mem is the difference which
278: * is the number of pages hidden by the monitor.
279: */
280: if (romp->v_romvec_version >= 1)
281: mon_mem = btop(*romp->v_memorysize - *romp->v_memoryavail);
282: else
283: mon_mem = 0;
284: /*
285: * If physmem is patched to be non-zero, use it instead of
286: * the monitor value unless physmem is larger than the total
287: * amount of memory on hand.
288: */
289: if (physmem == 0 || physmem > btop(*romp->v_memorysize))
290: physmem = btop(*romp->v_memorysize);
291: /*
292: * Adjust physmem down for the pages stolen by the monitor.
293: */
294: physmem -= mon_mem;
295: maxmem = physmem;
296:
297: /*
298: * v_vector_cmd is the handler for new monitor vector
299: * command in versions equal or greater to 2.
300: * We install v_handler() there for Unix.
301: */
302: if (romp->v_romvec_version >= 2)
303: *romp->v_vector_cmd = v_handler;
304:
305: #include "bwtwo.h"
306: #if NBWTWO > 0
307: if (physmem > btop(OBFBADDR + FBSIZE))
308: fbobmemavail = 1;
309: else
310: fbobmemavail = 0;
311: #else
312: fbobmemavail = 0;
313: #endif
314:
315: /*
316: * Determine if anything lives in DVMA bus space.
317: * We're paranoid and go through both the 16 bit
318: * and 32 bit device types.
319: */
320: disable_dvma();
321: for (dvmapage = 0; dvmapage < btoc(dvmasize); dvmapage++) {
322: mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D16),
323: 1, PG_V | PG_KW);
324: if (poke((short *)CADDR1, TESTVAL) == 0)
325: break;
326: mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D32),
327: 1, PG_V | PG_KW);
328: if (poke((short *)CADDR1, TESTVAL) == 0)
329: break;
330: }
331: enable_dvma();
332:
333: /*
334: * Initialize error message buffer (in low real memory before start).
335: * Printf's which occur prior to this will not be captured.
336: */
337: mapin(msgbufmap, (u_int)btop(&msgbuf),
338: (u_int)btop((int)start - sizeof (struct msgbuf) - KERNELBASE),
339: (int)btoc(sizeof (struct msgbuf)), PG_V | PG_KW);
340: msgbufinit = 1;
341:
342: /*
343: * Allocate IOPB memory space just below the message
344: * buffer and map it to the first pages of DVMA space.
345: */
346: maxmem -= IOPBMEM;
347: for (v = (caddr_t)DVMA, i = maxmem; i < maxmem + IOPBMEM;
348: v += NBPG, i++) {
349: struct pte tmp; /* scratch pte */
350:
351: mapin(&tmp, btop(v), i, 1, PG_V | PG_KW);
352: }
353:
354: /*
355: * Good {morning,afternoon,evening,night}.
356: * When printing memory, use the total including
357: * those hidden by the monitor (mon_mem).
358: */
359: printf(version);
360:
361: if (dvmapage < btoc(dvmasize)) {
362: printf("CAN'T HAVE PERIPHERALS IN RANGE 0 - %dKB\n",
363: ctob(dvmasize) / 1024);
364: panic("dvma collision");
365: }
366:
367: #ifndef lint
368: if ((int)start - (int)ctob(btoc(sizeof (struct msgbuf))) <= (int)&scb)
369: panic("msgbuf too large");
370:
371: if (sizeof (struct user) > UPAGES * NBPG)
372: panic("user area too large");
373: #endif lint
374:
375: if ((int)Syslimit > (CSEG << SGSHIFT))
376: panic("system map tables too large");
377:
378: /*
379: * Determine how many buffers to allocate.
380: * Use 10% of memory (not counting 512K for kernel), with min of 16.
381: * We allocate 1/4 as many swap buffer headers as file i/o buffers.
382: */
383: if (bufpages == 0)
384: bufpages = (physmem * NBPG - 512 * 1024) / 10 / CLBYTES;
385: if (nbuf == 0) {
386: nbuf = bufpages;
387: if (nbuf < 16)
388: nbuf = 16;
389: }
390: if (bufpages > nbuf * (BUFSIZE / CLBYTES))
391: bufpages = nbuf * (BUFSIZE / CLBYTES);
392: if (nswbuf == 0) {
393: nswbuf = (nbuf / 4) &~ 1; /* force even */
394: if (nswbuf > 32)
395: nswbuf = 32; /* sanity */
396: }
397: printf("real mem = %d nbuf = %d nswbuf = %d\n",
398: ctob(physmem + mon_mem), nbuf, nswbuf);
399:
400: /*
401: * Allocate space for system data structures.
402: * The first available real memory address is in "firstaddr".
403: * The first available kernel virtual address is in "v".
404: * As pages of kernel virtual memory are allocated, "v" is incremented.
405: * "mapaddr" is the real memory address where the tables start.
406: * It is used when remapping the tables later.
407: * In order to support the frame buffer which might appear in
408: * the middle of contiguous memory we adjust the map address to
409: * start after the end of the frame buffer. Later we will adjust
410: * the core map to take this hole into account. The reason for
411: * this is to keep all the kernel tables contiguous in virtual space.
412: */
413: if (fbobmemavail)
414: mapaddr = btoc(OBFBADDR + FBSIZE);
415: else
416: mapaddr = firstaddr;
417: v = (caddr_t)(ctob(firstaddr) + KERNELBASE);
418: #define valloc(name, type, num) \
419: (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
420: #define valloclim(name, type, num, lim) \
421: (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
422: valloc(swbuf, struct buf, nswbuf);
423: valloclim(inode, struct inode, ninode, inodeNINODE);
424: valloclim(file, struct file, nfile, fileNFILE);
425: valloclim(proc, struct proc, nproc, procNPROC);
426: valloclim(text, struct text, ntext, textNTEXT);
427: valloclim(lnodes, struct kern_lnode, maxusers, lnodesMAXUSERS);
428: valloc(callout, struct callout, ncallout);
429: valloc(swapmap, struct map, nswapmap = nproc * 2);
430: valloc(argmap, struct map, ARGMAPSIZE);
431: valloc(kernelmap, struct map, nproc);
432: valloc(iopbmap, struct map, IOPBMAPSIZE);
433: valloc(mb_hd.mh_map, struct map, DVMAMAPSIZE);
434:
435: /*
436: * Now allocate space for core map
437: * Allow space for all of physical memory minus the amount
438: * dedicated to the system. The amount of physical memory
439: * dedicated to the system is the total virtual memory of
440: * the system minus the space in the buffers which is not
441: * allocated real memory.
442: */
443: ncmap = physmem - firstaddr;
444: valloclim(cmap, struct cmap, ncmap, ecmap);
445: unixsize = btoc((int)(ecmap+1) - KERNELBASE);
446:
447: if ((int)unixsize > SYSPTSIZE)
448: panic("sys pt too small");
449:
450: /*
451: * Clear allocated space, and make r/w entries
452: * for the space in the kernel map.
453: */
454: if (unixsize >= physmem - 8*UPAGES)
455: panic("no memory");
456:
457: pte = &Sysmap[firstaddr];
458: for (i = firstaddr + btop(KERNELBASE); i < btoc(v); i++) {
459: mapin(pte++, i, mapaddr, 1, PG_V | PG_KW);
460: clearseg(mapaddr++);
461: }
462:
463: /*
464: * Initialize callouts.
465: */
466: callfree = callout;
467: for (i = 1; i < ncallout; i++)
468: callout[i-1].c_next = &callout[i];
469:
470: /*
471: * Initialize memory allocator and swap
472: * and user page table maps.
473: */
474: if (fbobmemavail) {
475: meminit((int)firstaddr, maxmem);
476: memialloc((int)firstaddr, (int)btop(OBFBADDR));
477: memialloc((int)(1 + mapaddr), maxmem);
478: } else {
479: meminit((int)mapaddr, maxmem);
480: memialloc((int)mapaddr, maxmem);
481: }
482: maxmem = freemem;
483: printf("avail mem = %d\n", ctob(maxmem));
484: rminit(kernelmap, (long)(USRPTSIZE - CLSIZE), (long)CLSIZE,
485: "usrpt", nproc);
486: rminit(iopbmap, (long)ctob(IOPBMEM), (long)DVMA,
487: "IOPB space", IOPBMAPSIZE);
488: rminit(mb_hd.mh_map, (long)(dvmasize - IOPBMEM), (long)IOPBMEM,
489: "DVMA map space", DVMAMAPSIZE);
490:
491: /*
492: * Configure the system.
493: */
494: bootflags(); /* get the boot options */
495: configure(); /* set up devices */
496: if (fbobmemavail) {
497: /*
498: * Onboard frame buffer memory still
499: * available, put back onto the free list.
500: */
501: memialloc((int)btop(OBFBADDR), (int)btop(OBFBADDR + FBSIZE));
502: fbobmemavail = 0;
503: }
504: bufmemall();
505: uinit(); /* initialize the u area */
506: (void) spl0(); /* drop priority */
507: }
508:
509: /*
510: * set up a physical address
511: * into users virtual address space.
512: */
513: sysphys()
514: {
515:
516: if(!suser())
517: return;
518: u.u_error = EINVAL;
519: }
520:
521: /*
522: * This system call sets the time of year clock without touching
523: * the software clock. It returns the previous clock value. If
524: * the argument is zero or the caller is not the super-user, it
525: * does not change the clock.
526: * Since the clocks are the same on the SUN, it just calls stime.
527: */
528: settod()
529: {
530: register struct a {
531: long unsigned tod;
532: } *uap;
533:
534: u.u_r.r_time = time;
535: if (uap->tod != 0 && suser())
536: stime();
537: }
538:
539: /*
540: * Allocate physical memory for system buffers
541: * In Ethernet memory if the right board exists &
542: * the root device is ND & there are no block I/O DMA devices
543: */
544: bufmemall()
545: {
546: struct pte *pte;
547: long a, va;
548: int npages;
549: int i, j, base, residual;
550:
551: a = rmalloc(kernelmap, (long)(nbuf*BUFSIZE/NBPG));
552: if (a == 0)
553: panic("no vmem for buffers");
554: buffers = (caddr_t)kmxtob(a);
555: pte = &Usrptmap[a];
556: base = bufpages / nbuf;
557: residual = bufpages % nbuf;
558: for (i = 0; i < nbuf; i++) {
559: if (i < residual)
560: npages = base+1;
561: else
562: npages = base;
563: /* XXX - this loop only works if CLSIZE == 1 */
564: for (j = 0; j < npages; j += CLSIZE) {
565: if (memall(pte+j, CLSIZE, &proc[0], CSYS) == 0)
566: panic("no mem for buffers");
567: *(int *)(pte+j) |= PG_V|PG_KW;
568: va = (int)kmxtob(a+j);
569: vmaccess(pte+j, (caddr_t)va, 1);
570: bzero((caddr_t)va, CLBYTES);
571: }
572: pte += BUFSIZE/CLBYTES;
573: a += BUFSIZE/CLBYTES;
574: }
575: /*
576: * Double map and then unmap the last page of the last
577: * buffer to insure the presence of a pmeg.
578: * AARRRGGGHHH. Kludge away.
579: */
580: if (base < BUFSIZE/CLBYTES) {
581: pte -= BUFSIZE/CLBYTES;
582: va = (int)kmxtob(a-1);
583: pte[BUFSIZE/CLBYTES - 1] = pte[0];
584: vmaccess(&pte[BUFSIZE/CLBYTES - 1], (caddr_t)va, 1);
585: /* now unmap without disturbing the pmeg */
586: *(int *)&pte[BUFSIZE/CLBYTES - 1] = 0;
587: setpgmap((caddr_t)va, (long)0);
588: }
589: buf = (struct buf *)zmemall(memall, nbuf * sizeof(struct buf));
590: if (buf == 0)
591: panic("no mem for buf headers");
592: }
593:
594: struct bootf {
595: char let;
596: short bit;
597: } bootf[] = {
598: 'a', RB_ASKNAME,
599: 's', RB_SINGLE,
600: 'i', RB_INITNAME,
601: 'h', RB_HALT,
602: 0, 0,
603: };
604: char *initname = "/etc/init";
605:
606: /*
607: * Parse the boot line to determine boot flags .
608: */
609: bootflags()
610: {
611: register struct bootparam *bp = (*romp->v_bootparam);
612: register char *cp;
613: register int i;
614:
615: cp = bp->bp_argv[1];
616: if (cp && *cp++ == '-')
617: do {
618: for (i = 0; bootf[i].let; i++) {
619: if (*cp == bootf[i].let) {
620: boothowto |= bootf[i].bit;
621: break;
622: }
623: }
624: cp++;
625: } while (bootf[i].let && *cp);
626: if (boothowto & RB_INITNAME)
627: initname = bp->bp_argv[2];
628: if (boothowto & RB_HALT)
629: halt("bootflags");
630: }
631:
632: /*
633: * Start the initial user process.
634: * The program [initname] is invoked with one argument
635: * containing the boot flags.
636: */
637: icode()
638: {
639: struct execa {
640: char *fname;
641: char **argp;
642: char **envp;
643: } *ap;
644: char *ucp, **uap, *arg0, *arg1;
645: int i;
646:
647: u.u_error = 0; /* paranoid */
648: /* Make a user stack (1 page) */
649: expand(1, 1);
650: (void) swpexpand(0, 1, &u.u_dmap, &u.u_smap);
651:
652: /* Move out the boot flag argument */
653: ucp = (char *)USRSTACK;
654: (void) subyte(--ucp, 0); /* trailing zero */
655: for (i = 0; bootf[i].let; i++) {
656: if (boothowto & bootf[i].bit)
657: (void) subyte(--ucp, bootf[i].let);
658: }
659: (void) subyte(--ucp, '-'); /* leading hyphen */
660: arg1 = ucp;
661:
662: /* Move out the file name (also arg 0) */
663: for (i = 0; initname[i]; i++)
664: ; /* size the name */
665: for (; i >= 0; i--)
666: (void) subyte(--ucp, initname[i]);
667: arg0 = ucp;
668:
669: /* Move out the arg pointers */
670: uap = (char **) ((int)ucp & ~(NBPW-1));
671: (void) suword((caddr_t)--uap, 0); /* terminator */
672: (void) suword((caddr_t)--uap, (int)arg1);
673: (void) suword((caddr_t)--uap, (int)arg0);
674:
675: /* Point at the arguments */
676: u.u_ap = u.u_arg;
677: ap = (struct execa *)u.u_ap;
678: ap->fname = arg0;
679: ap->argp = uap;
680: ap->envp = 0;
681: u.u_dirp = (caddr_t)u.u_arg[0];
682:
683: /* Now let exec do the hard work */
684: exece();
685: if (u.u_error) {
686: printf("Can't invoke %s, error %d\n", initname, u.u_error);
687: panic("icode");
688: }
689: }
690:
691: /*
692: * Set up page tables for process 0 U pages.
693: * This is closely related to way the code
694: * in locore.s sets things up.
695: */
696: uinit()
697: {
698: register struct pte *pte;
699: u_int page;
700: register int i;
701: extern char end[];
702:
703: /*
704: * main() will initialize proc[0].p_p0br to u.u_pcb.pcb_p0br
705: * and proc[0].p_szpt to 1. All we have to do is set up
706: * the pcb_p{0,1}{b,l}r registers in the pcb for now.
707: */
708:
709: /* initialize base and length of P0 region */
710: u.u_pcb.pcb_p0br = usrpt;
711: u.u_pcb.pcb_p0lr = 0; /* no user text/data (P0) for proc 0 */
712:
713: /*
714: * initialize base and length of P1 region,
715: * where the length here is for invalid pages
716: */
717: u.u_pcb.pcb_p1br = initp1br(usrpt + 1 * NPTEPG);
718: u.u_pcb.pcb_p1lr = P1PAGES; /* no user stack (P1) for proc 0 */
719:
720: /*
721: * Doublely map the page containing the scb to contain the
722: * ptes whose virtual address is usrpt. Got that?
723: */
724: page = (u_int)(getpgmap((caddr_t)&scb) & PG_PFNUM);
725: mapin(&Usrptmap[0], btop(usrpt), page, 1, PG_V | PG_KW);
726:
727: /*
728: * Now build the software page maps to map virtual U to physical U.
729: * These pages have already been set up using the real pages beyond
730: * end by locore.s.
731: */
732: pte = usrpt + 1 * NPTEPG - UPAGES;
733: page = btop((int)end + (NBPG - 1) - KERNELBASE);
734: for (i = 0; i < UPAGES; i++)
735: *(int *)pte++ = PG_V | PG_KW | page++;
736: }
737:
738: struct sigcontext {
739: int sc_sp; /* sp to restore */
740: int sc_pc; /* pc to retore */
741: int sc_ps; /* psl to restore */
742: };
743: /*
744: * Send an interrupt to process.
745: *
746: * When using new signals user code must do a
747: * sys #139 to return from the signal, which
748: * calls sigcleanup below, which resets the
749: * signal mask and the notion of onsigstack,
750: * and returns from the signal handler.
751: */
752: sendsig(p, sig)
753: int (*p)(), sig;
754: {
755: register int usp, *regs, scp;
756: struct nframe {
757: int sig;
758: int code;
759: int scp;
760: } frame;
761: struct sigcontext sc;
762:
763: #define mask(s) (1<<((s)-1))
764: regs = u.u_ar0;
765:
766: usp = regs[SP];
767: usp -= sizeof (struct sigcontext);
768: scp = usp;
769: usp -= sizeof (frame);
770: if (usp <= USRSTACK - ctob(u.u_ssize))
771: (void) grow((unsigned)usp);
772: if (useracc((caddr_t)usp, sizeof(frame) + sizeof(sc), B_WRITE) == 0) {
773: /*
774: * Process has trashed its stack; give it an illegal
775: * instruction to halt it in its tracks.
776: */
777: u.u_signal[SIGILL] = SIG_DFL;
778: u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
779: u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
780: psignal(u.u_procp, SIGILL);
781: }
782: /*
783: * push sigcontext structure.
784: */
785: sc.sc_sp = regs[SP];
786: sc.sc_pc = regs[PC];
787: sc.sc_ps = regs[PS];
788: /*
789: * If trace mode was on for the user process
790: * when we came in here, it may have been because
791: * of an ast-induced trace on a trap instruction,
792: * in which case we do not want to restore the
793: * trace bit in the status register later on
794: * in sigcleanup(). If we were to restore it
795: * and another ast trap had been posted, we would
796: * end up marking the trace trap as a user-requested
797: * real trace trap and send a bogus "Trace/BPT" signal.
798: */
799: if ((sc.sc_ps & PSL_T) && (u.u_pcb.pcb_p0lr & TRACE_AST))
800: sc.sc_ps &= ~PSL_T;
801: (void) copyout((caddr_t)&sc, (caddr_t)scp, sizeof (sc));
802: /*
803: * push call frame.
804: */
805: frame.sig = sig;
806: if (sig == SIGILL || sig == SIGFPE || sig == SIGEMT) {
807: frame.code = u.u_code;
808: u.u_code = 0;
809: } else
810: frame.code = 0;
811: frame.scp = scp;
812: (void) copyout((caddr_t)&frame, (caddr_t)usp, sizeof (frame));
813: regs[SP] = usp;
814: regs[PC] = (int)p;
815: }
816:
817: /*
818: * Routine to cleanup state after a signal
819: * has been taken. Reset signal mask and
820: * notion of on signal stack from context
821: * left there by sendsig (above). Pop these
822: * values and perform rti.
823: */
824: sigcleanup()
825: {
826: struct sigcontext *scp, sc;
827:
828: scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP] + sizeof(int));
829: if ((int)scp == -1)
830: return;
831: if (copyin((caddr_t)scp, (caddr_t)&sc, sizeof (sc)))
832: return;
833: u.u_ar0[SP] = sc.sc_sp;
834: u.u_ar0[PC] = sc.sc_pc;
835: u.u_ar0[PS] = sc.sc_ps;
836: u.u_ar0[PS] &= ~PSL_USERCLR;
837: u.u_ar0[PS] |= PSL_USERSET;
838: u.u_eosys = REALLYRETURN;
839: }
840: #undef mask
841:
842: int waittime = -1;
843:
844: boot(arghowto)
845: int arghowto;
846: {
847: register int howto;
848: static int prevflag = 0;
849: register struct buf *bp;
850: int iter, nbusy;
851: int s;
852:
853: consdev = 0;
854: startnmi();
855: howto = arghowto;
856: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
857: waittime = 0;
858: update();
859: printf("syncing disks... ");
860: while (++waittime <= 5)
861: sleep((caddr_t)&lbolt, PZERO);
862: printf("done\n");
863: }
864: s = spl7(); /* extreme priority */
865: if (howto & RB_HALT) {
866: halt((char *)NULL);
867: /* MAYBE REACHED */
868: } else {
869: if ((howto & RB_PANIC) && prevflag == 0) {
870: prevflag = 1;
871: dumpsys();
872:
873: }
874: printf("Rebooting Unix...\n");
875: (*romp->v_boot_me)(howto & RB_SINGLE ? "-s" : "");
876: /*NOTREACHED*/
877: }
878: (void) splx(s);
879: }
880:
881: /*
882: * Initialize UNIX's vector table:
883: * Vectors are copied from protoscb unless
884: * they are zero; zero means preserve whatever the
885: * monitor put there. If the protoscb is zero,
886: * then the original contents are copied into
887: * the scb we are setting up.
888: */
889: initscb()
890: {
891: register int *s, *p, *f;
892: register int n;
893: struct scb *orig, *getvbr();
894:
895: orig = getvbr();
896: exit_vector = orig->scb_trap[14];
897: s = (int *)&scb;
898: p = (int *)&protoscb;
899: f = (int *)orig;
900: for (n = sizeof (struct scb)/sizeof (int); n--; s++, p++, f++) {
901: if (*p)
902: *s = *p;
903: else
904: *s = *f;
905: }
906: setvbr(&scb);
907: }
908:
909: /*
910: * Clear a segment (page (click)).
911: */
912: clearseg(pgno)
913: u_int pgno;
914: {
915: extern char CADDR1[];
916:
917: mapin(CMAP1, btop(CADDR1), pgno, 1, PG_V | PG_KW);
918: bzero(CADDR1, NBPG);
919: }
920:
921: /*
922: * Copy a segment (page) from a user virtual address
923: * to a physical page number.
924: */
925: copyseg(vaddr, pgno)
926: caddr_t vaddr;
927: int pgno;
928: {
929: register struct pte *pte;
930: register int lock;
931: extern char CADDR1[];
932:
933: /*
934: * Make sure the user's page is valid and locked.
935: */
936: pte = vtopte(u.u_procp, btop(vaddr));
937: if (lock = !pte->pg_v) {
938: pagein((u_int)vaddr, &u, 1); /* return it locked */
939: pte = vtopte(u.u_procp, btop(vaddr)); /* pte may move */
940: }
941: /*
942: * Map the destination page into kernel address space.
943: */
944: mapin(CMAP1, btop(CADDR1), (u_int)pgno, 1, PG_V | PG_KW);
945: (void) copyin(vaddr, CADDR1, CLBYTES);
946: if (lock)
947: munlock(pte->pg_pfnum);
948: }
949:
950: /*
951: * Handle "physical" block transfers.
952: */
953: physstrat(bp, strat, pri)
954: register struct buf *bp;
955: int (*strat)();
956: int pri;
957: {
958: register int npte, n;
959: register long a;
960: unsigned v;
961: register struct pte *pte, *kpte;
962: struct proc *rp;
963: int va, s, o;
964:
965: v = btop(bp->b_un.b_addr);
966: o = (int)bp->b_un.b_addr & PGOFSET;
967: npte = btoc(bp->b_bcount + o) + 1;
968: while ((a = rmalloc(kernelmap, (long)npte)) == NULL) {
969: kmapwnt++;
970: sleep((caddr_t)kernelmap, PSWP+4);
971: }
972: kpte = &Usrptmap[a];
973: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
974: if ((bp->b_flags & B_PHYS) == 0)
975: pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)];
976: else if (bp->b_flags & B_UAREA)
977: pte = &rp->p_addr[v];
978: else if (bp->b_flags & B_PAGET)
979: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
980: else
981: pte = vtopte(rp, v);
982: for (n = npte; --n != 0; kpte++, pte++)
983: *(int *)kpte = PG_V | PG_KW | (*(int *)pte & PG_PFNUM);
984: *(int *)kpte = 0;
985: va = (int)kmxtob(a);
986: vmaccess(&Usrptmap[a], (caddr_t)va, npte);
987: bp->b_saddr = bp->b_un.b_addr;
988: bp->b_un.b_addr = (caddr_t)(va | o);
989: bp->b_kmx = a;
990: bp->b_npte = npte;
991: (*strat)(bp);
992: if (bp->b_flags & B_DIRTY)
993: return;
994: s = spl6();
995: while ((bp->b_flags & B_DONE) == 0)
996: sleep((caddr_t)bp, pri);
997: (void) splx(s);
998: bp->b_un.b_addr = bp->b_saddr;
999: bp->b_kmx = 0;
1000: bp->b_npte = 0;
1001: mapout(&Usrptmap[a], npte);
1002: rmfree(kernelmap, (long)npte, a);
1003: }
1004:
1005: /*
1006: * Halt the machine and return to the monitor
1007: */
1008: halt(s)
1009: char *s;
1010: {
1011: extern struct scb *getvbr();
1012:
1013: if (s)
1014: (*romp->v_printf)("(%s) ", s);
1015: (*romp->v_printf)("Unix Halted\n\n");
1016: startnmi();
1017: if (exit_vector)
1018: getvbr()->scb_trap[14] = exit_vector;
1019: asm("trap #14");
1020: if (exit_vector)
1021: getvbr()->scb_trap[14] = protoscb.scb_trap[14];
1022: stopnmi();
1023: }
1024:
1025: /*
1026: * Print out a traceback for the caller - can be called anywhere
1027: * within the kernel or from the monitor by typing "g4" (for sun-2
1028: * compatibility) or "w trace". This causes the monitor to call
1029: * the v_handler() routine which will call tracedump() for these cases.
1030: */
1031: /*VARARGS0*/
1032: tracedump(x1)
1033: caddr_t x1;
1034: {
1035: struct frame *fp = (struct frame *)(&x1 - 2);
1036: u_int tospage = btoc(fp);
1037:
1038: (*romp->v_printf)("Begin traceback...fp = %x\n", fp);
1039: while (btoc(fp) == tospage) {
1040: if (fp == fp->fr_savfp) {
1041: (*romp->v_printf)("FP loop at %x", fp);
1042: break;
1043: }
1044: (*romp->v_printf)("Called from %x, fp=%x, args=%x %x %x %x\n",
1045: fp->fr_savpc, fp->fr_savfp,
1046: fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
1047: fp = fp->fr_savfp;
1048: }
1049: (*romp->v_printf)("End traceback...\n");
1050: }
1051:
1052: /*
1053: * Buscheck is called by mbsetup to check to see it the requested
1054: * setup is a valid busmem type (i.e. VMEbus). Returns 1 if ok
1055: * busmem type, returns 0 if not busmem type. This routine
1056: * make checks and panic's if an illegal busmem type request is detected.
1057: */
1058: buscheck(pte, npf)
1059: register struct pte *pte;
1060: register int npf;
1061: {
1062: register int i, pf;
1063: register int pt = *(int *)pte & PGT_MASK;
1064:
1065: if (pt == PGT_VME_D16 || pt == PGT_VME_D32) {
1066: pf = pte->pg_pfnum;
1067: if (pf < btoc(DVMASIZE))
1068: panic("buscheck: busmem in DVMA range");
1069: for (i = 0; i < npf; i++, pte++, pf++) {
1070: if ((*(int *)pte & PGT_MASK) != pt ||
1071: pte->pg_pfnum != pf)
1072: panic("buscheck: request not contiguous");
1073: }
1074: return (1);
1075: }
1076: return (0);
1077: }
1078:
1079: /*
1080: * Compute the address of an I/O device within standard address
1081: * ranges and return the result. This is used by DKIOCINFO
1082: * ioctl to get the best guess possible for the actual address
1083: * set on the card.
1084: */
1085: getdevaddr(addr)
1086: caddr_t addr;
1087: {
1088: int off = (int)addr & PGOFSET;
1089: int pte = getkpgmap(addr);
1090: int physaddr = ((pte & PG_PFNUM) & ~PGT_MASK) * NBPG;
1091:
1092: switch (pte & PGT_MASK) {
1093: case PGT_VME_D16:
1094: case PGT_VME_D32:
1095: if (physaddr > VME16_BASE) {
1096: /* 16 bit VMEbus address */
1097: physaddr -= VME16_BASE;
1098: } else if (physaddr > VME24_BASE) {
1099: /* 24 bit VMEbus address */
1100: physaddr -= VME24_BASE;
1101: }
1102: /*
1103: * else 32 bit VMEbus address,
1104: * physaddr doesn't require adjustments
1105: */
1106: break;
1107:
1108: case PGT_OBMEM:
1109: case PGT_OBIO:
1110: /* physaddr doesn't require adjustments */
1111: break;
1112: }
1113:
1114: return (physaddr + off);
1115: }
1116:
1117: static int (*mon_nmi)(); /* monitor's level 7 nmi routine */
1118: extern int level7(); /* Unix's level 7 nmi routine */
1119:
1120: stopnmi()
1121: {
1122: struct scb *vbr, *getvbr();
1123:
1124: vbr = getvbr();
1125: if (vbr->scb_autovec[7 - 1] != level7) {
1126: #ifndef GPROF
1127: set_clk_mode(0, IR_ENA_CLK7); /* disable level 7 clk intr */
1128: #endif !GPROF
1129: mon_nmi = vbr->scb_autovec[7 - 1]; /* save mon vec */
1130: vbr->scb_autovec[7 - 1] = level7; /* install Unix vec */
1131: }
1132: }
1133:
1134: startnmi()
1135: {
1136: struct scb *getvbr();
1137:
1138: if (mon_nmi) {
1139: getvbr()->scb_autovec[7 - 1] = mon_nmi; /* install mon vec */
1140: #ifndef GPROF
1141: set_clk_mode(IR_ENA_CLK7, 0); /* enable level 7 clk intr */
1142: #endif !GPROF
1143: }
1144: }
1145:
1146: /*
1147: * Handler for monitor vector cmd -
1148: * For now we just implement the old "g0" and "g4"
1149: * commands and a printf hack.
1150: */
1151: void
1152: v_handler(addr, str)
1153: int addr;
1154: char *str;
1155: {
1156:
1157: switch (*str) {
1158: case '\0':
1159: /*
1160: * No (non-hex) letter was specified on
1161: * command line, use only the number given
1162: */
1163: switch (addr) {
1164: case 0: /* old g0 */
1165: case 0xd: /* 'd'ump short hand */
1166: panic("zero");
1167: /*NOTREACHED*/
1168:
1169: case 4: /* old g4 */
1170: tracedump();
1171: break;
1172:
1173: default:
1174: goto err;
1175: }
1176: break;
1177:
1178: case 'p': /* 'p'rint string command */
1179: case 'P':
1180: (*romp->v_printf)("%s\n", (char *)addr);
1181: break;
1182:
1183: case '%': /* p'%'int anything a la printf */
1184: (*romp->v_printf)(str, addr);
1185: (*romp->v_printf)("\n");
1186: break;
1187:
1188: case 't': /* 't'race kernel stack */
1189: case 'T':
1190: tracedump();
1191: break;
1192:
1193: case 'u': /* d'u'mp hack ('d' look like hex) */
1194: case 'U':
1195: if (addr == 0xd) {
1196: panic("zero");
1197: } else
1198: goto err;
1199: break;
1200:
1201: default:
1202: err:
1203: (*romp->v_printf)("Don't understand 0x%x '%s'\n", addr, str);
1204: }
1205: }
1206:
1207: /*
1208: * Handle parity/ECC memory errors. XXX - use something like
1209: * vax to only look for soft ecc errors periodically?
1210: */
1211: memerr()
1212: {
1213: u_char per, eer;
1214: char *mess = 0;
1215: int c;
1216: long pme;
1217:
1218: eer = per = MEMREG->mr_er;
1219: #ifdef SUN3_260
1220: if (cpu == CPU_SUN3_260 && (eer & EER_ERR) == EER_CE) {
1221: softecc();
1222: MEMREG->mr_dvma = 1; /* clear latching */
1223: return;
1224: }
1225: #endif SUN3_260
1226:
1227: /*
1228: * Since we are going down in flames, disable further
1229: * memory error interrupts to prevent confusion.
1230: */
1231: MEMREG->mr_er &= ~ER_INTENA;
1232:
1233: #if defined(SUN3_160) || defined(SUN3_50)
1234: if ((cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50) &&
1235: (per & PER_ERR) != 0) {
1236: printf("Parity Error Register %b\n", per, PARERR_BITS);
1237: mess = "parity error";
1238: }
1239: #endif defined(SUN3_160) || defined(SUN3_50)
1240:
1241: #ifdef SUN3_260
1242: if ((cpu == CPU_SUN3_260) && (eer & EER_ERR) != 0) {
1243: printf("ECC Error Register %b\n", eer, ECCERR_BITS);
1244: mess = "uncorrectable ECC error";
1245: }
1246: #endif SUN3_260
1247:
1248: if (!mess) {
1249: printf("Memory Error Register %b %b\n",
1250: per, PARERR_BITS, eer, ECCERR_BITS);
1251: mess = "unknown memory error";
1252: }
1253:
1254: printf("DVMA = %x, context = %x, virtual address = %x\n",
1255: MEMREG->mr_dvma, MEMREG->mr_ctx, MEMREG->mr_vaddr);
1256:
1257: c = getcontext();
1258: setcontext((int)MEMREG->mr_ctx);
1259: pme = getpgmap((caddr_t)MEMREG->mr_vaddr);
1260: printf("pme = %x, physical address = %x\n", pme,
1261: ptob(((struct pte *)&pme)->pg_pfnum) + (MEMREG->mr_vaddr&PGOFSET));
1262: setcontext(c);
1263:
1264: /*
1265: * Clear the latching by writing to the top
1266: * nibble of the memory address register
1267: */
1268: MEMREG->mr_dvma = 1;
1269:
1270: panic(mess);
1271: /*NOTREACHED*/
1272: }
1273:
1274: #ifdef SUN3_260
1275: int prtsoftecc = 1;
1276:
1277: /*
1278: * Probe memory cards to find which one(s) had ecc error(s).
1279: * If prtsoftecc is non-zero, log messages regarding the failing
1280: * syndrome. Then clear the latching on the memory card.
1281: */
1282: softecc()
1283: {
1284: register struct eccreg **ecc_nxt, *ecc;
1285:
1286: for (ecc_nxt = ecc_alive; *ecc_nxt != (struct eccreg *)0; ecc_nxt++) {
1287: ecc = *ecc_nxt;
1288: if (ecc->syndrome.sy_ce) {
1289: if (prtsoftecc) {
1290: printf("mem%d: soft ecc addr %x+%x=%x syn %b\n",
1291: ecc - ECCREG,
1292: (ecc->eccena.ena_addr << 22),
1293: (ecc->syndrome.sy_addr << 3),
1294: (ecc->eccena.ena_addr << 22) +
1295: (ecc->syndrome.sy_addr << 3),
1296: ecc->syndrome.sy_synd, SYNDERR_BITS);
1297: }
1298: ecc->syndrome.sy_ce = 1; /* clear latching */
1299: }
1300: }
1301: }
1302: #endif SUN3_260
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.