|
|
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);
1.1.1.2 ! root 423: valloc(swsize, short, nswbuf); /* note: nswbuf is even */
! 424: valloc(swpf, int, nswbuf);
1.1 root 425: valloclim(inode, struct inode, ninode, inodeNINODE);
426: valloclim(file, struct file, nfile, fileNFILE);
427: valloclim(proc, struct proc, nproc, procNPROC);
428: valloclim(text, struct text, ntext, textNTEXT);
429: valloclim(lnodes, struct kern_lnode, maxusers, lnodesMAXUSERS);
430: valloc(callout, struct callout, ncallout);
431: valloc(swapmap, struct map, nswapmap = nproc * 2);
432: valloc(argmap, struct map, ARGMAPSIZE);
433: valloc(kernelmap, struct map, nproc);
434: valloc(iopbmap, struct map, IOPBMAPSIZE);
435: valloc(mb_hd.mh_map, struct map, DVMAMAPSIZE);
436:
437: /*
438: * Now allocate space for core map
439: * Allow space for all of physical memory minus the amount
440: * dedicated to the system. The amount of physical memory
441: * dedicated to the system is the total virtual memory of
442: * the system minus the space in the buffers which is not
443: * allocated real memory.
444: */
445: ncmap = physmem - firstaddr;
446: valloclim(cmap, struct cmap, ncmap, ecmap);
447: unixsize = btoc((int)(ecmap+1) - KERNELBASE);
448:
449: if ((int)unixsize > SYSPTSIZE)
450: panic("sys pt too small");
451:
452: /*
453: * Clear allocated space, and make r/w entries
454: * for the space in the kernel map.
455: */
456: if (unixsize >= physmem - 8*UPAGES)
457: panic("no memory");
458:
459: pte = &Sysmap[firstaddr];
460: for (i = firstaddr + btop(KERNELBASE); i < btoc(v); i++) {
461: mapin(pte++, i, mapaddr, 1, PG_V | PG_KW);
462: clearseg(mapaddr++);
463: }
464:
465: /*
466: * Initialize callouts.
467: */
468: callfree = callout;
469: for (i = 1; i < ncallout; i++)
470: callout[i-1].c_next = &callout[i];
471:
472: /*
473: * Initialize memory allocator and swap
474: * and user page table maps.
475: */
476: if (fbobmemavail) {
477: meminit((int)firstaddr, maxmem);
478: memialloc((int)firstaddr, (int)btop(OBFBADDR));
479: memialloc((int)(1 + mapaddr), maxmem);
480: } else {
481: meminit((int)mapaddr, maxmem);
482: memialloc((int)mapaddr, maxmem);
483: }
484: maxmem = freemem;
485: printf("avail mem = %d\n", ctob(maxmem));
486: rminit(kernelmap, (long)(USRPTSIZE - CLSIZE), (long)CLSIZE,
487: "usrpt", nproc);
488: rminit(iopbmap, (long)ctob(IOPBMEM), (long)DVMA,
489: "IOPB space", IOPBMAPSIZE);
490: rminit(mb_hd.mh_map, (long)(dvmasize - IOPBMEM), (long)IOPBMEM,
491: "DVMA map space", DVMAMAPSIZE);
492:
493: /*
494: * Configure the system.
495: */
496: bootflags(); /* get the boot options */
497: configure(); /* set up devices */
498: if (fbobmemavail) {
499: /*
500: * Onboard frame buffer memory still
501: * available, put back onto the free list.
502: */
503: memialloc((int)btop(OBFBADDR), (int)btop(OBFBADDR + FBSIZE));
504: fbobmemavail = 0;
505: }
506: bufmemall();
507: uinit(); /* initialize the u area */
508: (void) spl0(); /* drop priority */
509: }
510:
511: /*
512: * set up a physical address
513: * into users virtual address space.
514: */
515: sysphys()
516: {
517:
518: if(!suser())
519: return;
520: u.u_error = EINVAL;
521: }
522:
523: /*
524: * This system call sets the time of year clock without touching
525: * the software clock. It returns the previous clock value. If
526: * the argument is zero or the caller is not the super-user, it
527: * does not change the clock.
528: * Since the clocks are the same on the SUN, it just calls stime.
529: */
530: settod()
531: {
532: register struct a {
533: long unsigned tod;
534: } *uap;
535:
536: u.u_r.r_time = time;
537: if (uap->tod != 0 && suser())
538: stime();
539: }
540:
541: /*
542: * Allocate physical memory for system buffers
543: * In Ethernet memory if the right board exists &
544: * the root device is ND & there are no block I/O DMA devices
545: */
546: bufmemall()
547: {
548: struct pte *pte;
549: long a, va;
550: int npages;
551: int i, j, base, residual;
552:
553: a = rmalloc(kernelmap, (long)(nbuf*BUFSIZE/NBPG));
554: if (a == 0)
555: panic("no vmem for buffers");
556: buffers = (caddr_t)kmxtob(a);
557: pte = &Usrptmap[a];
558: base = bufpages / nbuf;
559: residual = bufpages % nbuf;
560: for (i = 0; i < nbuf; i++) {
561: if (i < residual)
562: npages = base+1;
563: else
564: npages = base;
565: /* XXX - this loop only works if CLSIZE == 1 */
566: for (j = 0; j < npages; j += CLSIZE) {
567: if (memall(pte+j, CLSIZE, &proc[0], CSYS) == 0)
568: panic("no mem for buffers");
569: *(int *)(pte+j) |= PG_V|PG_KW;
570: va = (int)kmxtob(a+j);
571: vmaccess(pte+j, (caddr_t)va, 1);
572: bzero((caddr_t)va, CLBYTES);
573: }
574: pte += BUFSIZE/CLBYTES;
575: a += BUFSIZE/CLBYTES;
576: }
577: /*
578: * Double map and then unmap the last page of the last
579: * buffer to insure the presence of a pmeg.
580: * AARRRGGGHHH. Kludge away.
581: */
582: if (base < BUFSIZE/CLBYTES) {
583: pte -= BUFSIZE/CLBYTES;
584: va = (int)kmxtob(a-1);
585: pte[BUFSIZE/CLBYTES - 1] = pte[0];
586: vmaccess(&pte[BUFSIZE/CLBYTES - 1], (caddr_t)va, 1);
587: /* now unmap without disturbing the pmeg */
588: *(int *)&pte[BUFSIZE/CLBYTES - 1] = 0;
589: setpgmap((caddr_t)va, (long)0);
590: }
591: buf = (struct buf *)zmemall(memall, nbuf * sizeof(struct buf));
592: if (buf == 0)
593: panic("no mem for buf headers");
594: }
595:
596: struct bootf {
597: char let;
598: short bit;
599: } bootf[] = {
600: 'a', RB_ASKNAME,
601: 's', RB_SINGLE,
602: 'i', RB_INITNAME,
603: 'h', RB_HALT,
604: 0, 0,
605: };
606: char *initname = "/etc/init";
607:
608: /*
609: * Parse the boot line to determine boot flags .
610: */
611: bootflags()
612: {
613: register struct bootparam *bp = (*romp->v_bootparam);
614: register char *cp;
615: register int i;
616:
617: cp = bp->bp_argv[1];
618: if (cp && *cp++ == '-')
619: do {
620: for (i = 0; bootf[i].let; i++) {
621: if (*cp == bootf[i].let) {
622: boothowto |= bootf[i].bit;
623: break;
624: }
625: }
626: cp++;
627: } while (bootf[i].let && *cp);
628: if (boothowto & RB_INITNAME)
629: initname = bp->bp_argv[2];
630: if (boothowto & RB_HALT)
631: halt("bootflags");
632: }
633:
634: /*
635: * Start the initial user process.
636: * The program [initname] is invoked with one argument
637: * containing the boot flags.
638: */
639: icode()
640: {
641: struct execa {
642: char *fname;
643: char **argp;
644: char **envp;
645: } *ap;
646: char *ucp, **uap, *arg0, *arg1;
647: int i;
648:
649: u.u_error = 0; /* paranoid */
650: /* Make a user stack (1 page) */
651: expand(1, 1);
652: (void) swpexpand(0, 1, &u.u_dmap, &u.u_smap);
653:
654: /* Move out the boot flag argument */
655: ucp = (char *)USRSTACK;
656: (void) subyte(--ucp, 0); /* trailing zero */
657: for (i = 0; bootf[i].let; i++) {
658: if (boothowto & bootf[i].bit)
659: (void) subyte(--ucp, bootf[i].let);
660: }
661: (void) subyte(--ucp, '-'); /* leading hyphen */
662: arg1 = ucp;
663:
664: /* Move out the file name (also arg 0) */
665: for (i = 0; initname[i]; i++)
666: ; /* size the name */
667: for (; i >= 0; i--)
668: (void) subyte(--ucp, initname[i]);
669: arg0 = ucp;
670:
671: /* Move out the arg pointers */
672: uap = (char **) ((int)ucp & ~(NBPW-1));
673: (void) suword((caddr_t)--uap, 0); /* terminator */
674: (void) suword((caddr_t)--uap, (int)arg1);
675: (void) suword((caddr_t)--uap, (int)arg0);
676:
677: /* Point at the arguments */
678: u.u_ap = u.u_arg;
679: ap = (struct execa *)u.u_ap;
680: ap->fname = arg0;
681: ap->argp = uap;
682: ap->envp = 0;
683: u.u_dirp = (caddr_t)u.u_arg[0];
684:
685: /* Now let exec do the hard work */
686: exece();
687: if (u.u_error) {
688: printf("Can't invoke %s, error %d\n", initname, u.u_error);
689: panic("icode");
690: }
691: }
692:
693: /*
694: * Set up page tables for process 0 U pages.
695: * This is closely related to way the code
696: * in locore.s sets things up.
697: */
698: uinit()
699: {
700: register struct pte *pte;
701: u_int page;
702: register int i;
703: extern char end[];
704:
705: /*
706: * main() will initialize proc[0].p_p0br to u.u_pcb.pcb_p0br
707: * and proc[0].p_szpt to 1. All we have to do is set up
708: * the pcb_p{0,1}{b,l}r registers in the pcb for now.
709: */
710:
711: /* initialize base and length of P0 region */
712: u.u_pcb.pcb_p0br = usrpt;
713: u.u_pcb.pcb_p0lr = 0; /* no user text/data (P0) for proc 0 */
714:
715: /*
716: * initialize base and length of P1 region,
717: * where the length here is for invalid pages
718: */
719: u.u_pcb.pcb_p1br = initp1br(usrpt + 1 * NPTEPG);
720: u.u_pcb.pcb_p1lr = P1PAGES; /* no user stack (P1) for proc 0 */
721:
722: /*
723: * Doublely map the page containing the scb to contain the
724: * ptes whose virtual address is usrpt. Got that?
725: */
726: page = (u_int)(getpgmap((caddr_t)&scb) & PG_PFNUM);
727: mapin(&Usrptmap[0], btop(usrpt), page, 1, PG_V | PG_KW);
728:
729: /*
730: * Now build the software page maps to map virtual U to physical U.
731: * These pages have already been set up using the real pages beyond
732: * end by locore.s.
733: */
734: pte = usrpt + 1 * NPTEPG - UPAGES;
735: page = btop((int)end + (NBPG - 1) - KERNELBASE);
736: for (i = 0; i < UPAGES; i++)
737: *(int *)pte++ = PG_V | PG_KW | page++;
738: }
739:
740: struct sigcontext {
741: int sc_sp; /* sp to restore */
742: int sc_pc; /* pc to retore */
743: int sc_ps; /* psl to restore */
744: };
745: /*
746: * Send an interrupt to process.
747: *
748: * When using new signals user code must do a
749: * sys #139 to return from the signal, which
750: * calls sigcleanup below, which resets the
751: * signal mask and the notion of onsigstack,
752: * and returns from the signal handler.
753: */
754: sendsig(p, sig)
755: int (*p)(), sig;
756: {
757: register int usp, *regs, scp;
758: struct nframe {
759: int sig;
760: int code;
761: int scp;
762: } frame;
763: struct sigcontext sc;
764:
765: #define mask(s) (1<<((s)-1))
766: regs = u.u_ar0;
767:
768: usp = regs[SP];
769: usp -= sizeof (struct sigcontext);
770: scp = usp;
771: usp -= sizeof (frame);
772: if (usp <= USRSTACK - ctob(u.u_ssize))
773: (void) grow((unsigned)usp);
774: if (useracc((caddr_t)usp, sizeof(frame) + sizeof(sc), B_WRITE) == 0) {
775: /*
776: * Process has trashed its stack; give it an illegal
777: * instruction to halt it in its tracks.
778: */
779: u.u_signal[SIGILL] = SIG_DFL;
780: u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
781: u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
782: psignal(u.u_procp, SIGILL);
783: }
784: /*
785: * push sigcontext structure.
786: */
787: sc.sc_sp = regs[SP];
788: sc.sc_pc = regs[PC];
789: sc.sc_ps = regs[PS];
790: /*
791: * If trace mode was on for the user process
792: * when we came in here, it may have been because
793: * of an ast-induced trace on a trap instruction,
794: * in which case we do not want to restore the
795: * trace bit in the status register later on
796: * in sigcleanup(). If we were to restore it
797: * and another ast trap had been posted, we would
798: * end up marking the trace trap as a user-requested
799: * real trace trap and send a bogus "Trace/BPT" signal.
800: */
801: if ((sc.sc_ps & PSL_T) && (u.u_pcb.pcb_p0lr & TRACE_AST))
802: sc.sc_ps &= ~PSL_T;
803: (void) copyout((caddr_t)&sc, (caddr_t)scp, sizeof (sc));
804: /*
805: * push call frame.
806: */
807: frame.sig = sig;
808: if (sig == SIGILL || sig == SIGFPE || sig == SIGEMT) {
809: frame.code = u.u_code;
810: u.u_code = 0;
811: } else
812: frame.code = 0;
813: frame.scp = scp;
814: (void) copyout((caddr_t)&frame, (caddr_t)usp, sizeof (frame));
815: regs[SP] = usp;
816: regs[PC] = (int)p;
817: }
818:
819: /*
820: * Routine to cleanup state after a signal
821: * has been taken. Reset signal mask and
822: * notion of on signal stack from context
823: * left there by sendsig (above). Pop these
824: * values and perform rti.
825: */
826: sigcleanup()
827: {
828: struct sigcontext *scp, sc;
829:
830: scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP] + sizeof(int));
831: if ((int)scp == -1)
832: return;
833: if (copyin((caddr_t)scp, (caddr_t)&sc, sizeof (sc)))
834: return;
835: u.u_ar0[SP] = sc.sc_sp;
836: u.u_ar0[PC] = sc.sc_pc;
837: u.u_ar0[PS] = sc.sc_ps;
838: u.u_ar0[PS] &= ~PSL_USERCLR;
839: u.u_ar0[PS] |= PSL_USERSET;
840: u.u_eosys = REALLYRETURN;
841: }
842: #undef mask
843:
844: int waittime = -1;
845:
846: boot(arghowto)
847: int arghowto;
848: {
849: register int howto;
850: static int prevflag = 0;
851: register struct buf *bp;
852: int iter, nbusy;
853: int s;
854:
855: consdev = 0;
856: startnmi();
857: howto = arghowto;
858: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
859: waittime = 0;
860: update();
861: printf("syncing disks... ");
862: while (++waittime <= 5)
863: sleep((caddr_t)&lbolt, PZERO);
864: printf("done\n");
865: }
866: s = spl7(); /* extreme priority */
867: if (howto & RB_HALT) {
868: halt((char *)NULL);
869: /* MAYBE REACHED */
870: } else {
871: if ((howto & RB_PANIC) && prevflag == 0) {
872: prevflag = 1;
873: dumpsys();
874:
875: }
876: printf("Rebooting Unix...\n");
877: (*romp->v_boot_me)(howto & RB_SINGLE ? "-s" : "");
878: /*NOTREACHED*/
879: }
880: (void) splx(s);
881: }
882:
883: /*
884: * Initialize UNIX's vector table:
885: * Vectors are copied from protoscb unless
886: * they are zero; zero means preserve whatever the
887: * monitor put there. If the protoscb is zero,
888: * then the original contents are copied into
889: * the scb we are setting up.
890: */
891: initscb()
892: {
893: register int *s, *p, *f;
894: register int n;
895: struct scb *orig, *getvbr();
896:
897: orig = getvbr();
898: exit_vector = orig->scb_trap[14];
899: s = (int *)&scb;
900: p = (int *)&protoscb;
901: f = (int *)orig;
902: for (n = sizeof (struct scb)/sizeof (int); n--; s++, p++, f++) {
903: if (*p)
904: *s = *p;
905: else
906: *s = *f;
907: }
908: setvbr(&scb);
909: }
910:
911: /*
912: * Clear a segment (page (click)).
913: */
914: clearseg(pgno)
915: u_int pgno;
916: {
917: extern char CADDR1[];
918:
919: mapin(CMAP1, btop(CADDR1), pgno, 1, PG_V | PG_KW);
920: bzero(CADDR1, NBPG);
921: }
922:
923: /*
924: * Copy a segment (page) from a user virtual address
925: * to a physical page number.
926: */
927: copyseg(vaddr, pgno)
928: caddr_t vaddr;
929: int pgno;
930: {
931: register struct pte *pte;
932: register int lock;
933: extern char CADDR1[];
934:
935: /*
936: * Make sure the user's page is valid and locked.
937: */
938: pte = vtopte(u.u_procp, btop(vaddr));
939: if (lock = !pte->pg_v) {
940: pagein((u_int)vaddr, &u, 1); /* return it locked */
941: pte = vtopte(u.u_procp, btop(vaddr)); /* pte may move */
942: }
943: /*
944: * Map the destination page into kernel address space.
945: */
946: mapin(CMAP1, btop(CADDR1), (u_int)pgno, 1, PG_V | PG_KW);
947: (void) copyin(vaddr, CADDR1, CLBYTES);
948: if (lock)
949: munlock(pte->pg_pfnum);
950: }
951:
952: /*
953: * Handle "physical" block transfers.
954: */
955: physstrat(bp, strat, pri)
956: register struct buf *bp;
957: int (*strat)();
958: int pri;
959: {
960: register int npte, n;
961: register long a;
962: unsigned v;
963: register struct pte *pte, *kpte;
964: struct proc *rp;
965: int va, s, o;
966:
967: v = btop(bp->b_un.b_addr);
968: o = (int)bp->b_un.b_addr & PGOFSET;
969: npte = btoc(bp->b_bcount + o) + 1;
970: while ((a = rmalloc(kernelmap, (long)npte)) == NULL) {
971: kmapwnt++;
972: sleep((caddr_t)kernelmap, PSWP+4);
973: }
974: kpte = &Usrptmap[a];
975: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
976: if ((bp->b_flags & B_PHYS) == 0)
977: pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)];
978: else if (bp->b_flags & B_UAREA)
979: pte = &rp->p_addr[v];
980: else if (bp->b_flags & B_PAGET)
981: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
982: else
983: pte = vtopte(rp, v);
984: for (n = npte; --n != 0; kpte++, pte++)
985: *(int *)kpte = PG_V | PG_KW | (*(int *)pte & PG_PFNUM);
986: *(int *)kpte = 0;
987: va = (int)kmxtob(a);
988: vmaccess(&Usrptmap[a], (caddr_t)va, npte);
989: bp->b_saddr = bp->b_un.b_addr;
990: bp->b_un.b_addr = (caddr_t)(va | o);
991: bp->b_kmx = a;
992: bp->b_npte = npte;
993: (*strat)(bp);
994: if (bp->b_flags & B_DIRTY)
995: return;
996: s = spl6();
997: while ((bp->b_flags & B_DONE) == 0)
998: sleep((caddr_t)bp, pri);
999: (void) splx(s);
1000: bp->b_un.b_addr = bp->b_saddr;
1001: bp->b_kmx = 0;
1002: bp->b_npte = 0;
1003: mapout(&Usrptmap[a], npte);
1004: rmfree(kernelmap, (long)npte, a);
1005: }
1006:
1007: /*
1008: * Halt the machine and return to the monitor
1009: */
1010: halt(s)
1011: char *s;
1012: {
1013: extern struct scb *getvbr();
1014:
1015: if (s)
1016: (*romp->v_printf)("(%s) ", s);
1017: (*romp->v_printf)("Unix Halted\n\n");
1018: startnmi();
1019: if (exit_vector)
1020: getvbr()->scb_trap[14] = exit_vector;
1021: asm("trap #14");
1022: if (exit_vector)
1023: getvbr()->scb_trap[14] = protoscb.scb_trap[14];
1024: stopnmi();
1025: }
1026:
1027: /*
1028: * Print out a traceback for the caller - can be called anywhere
1029: * within the kernel or from the monitor by typing "g4" (for sun-2
1030: * compatibility) or "w trace". This causes the monitor to call
1031: * the v_handler() routine which will call tracedump() for these cases.
1032: */
1033: /*VARARGS0*/
1034: tracedump(x1)
1035: caddr_t x1;
1036: {
1037: struct frame *fp = (struct frame *)(&x1 - 2);
1038: u_int tospage = btoc(fp);
1039:
1040: (*romp->v_printf)("Begin traceback...fp = %x\n", fp);
1041: while (btoc(fp) == tospage) {
1042: if (fp == fp->fr_savfp) {
1043: (*romp->v_printf)("FP loop at %x", fp);
1044: break;
1045: }
1046: (*romp->v_printf)("Called from %x, fp=%x, args=%x %x %x %x\n",
1047: fp->fr_savpc, fp->fr_savfp,
1048: fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
1049: fp = fp->fr_savfp;
1050: }
1051: (*romp->v_printf)("End traceback...\n");
1052: }
1053:
1054: /*
1055: * Buscheck is called by mbsetup to check to see it the requested
1056: * setup is a valid busmem type (i.e. VMEbus). Returns 1 if ok
1057: * busmem type, returns 0 if not busmem type. This routine
1058: * make checks and panic's if an illegal busmem type request is detected.
1059: */
1060: buscheck(pte, npf)
1061: register struct pte *pte;
1062: register int npf;
1063: {
1064: register int i, pf;
1065: register int pt = *(int *)pte & PGT_MASK;
1066:
1067: if (pt == PGT_VME_D16 || pt == PGT_VME_D32) {
1068: pf = pte->pg_pfnum;
1069: if (pf < btoc(DVMASIZE))
1070: panic("buscheck: busmem in DVMA range");
1071: for (i = 0; i < npf; i++, pte++, pf++) {
1072: if ((*(int *)pte & PGT_MASK) != pt ||
1073: pte->pg_pfnum != pf)
1074: panic("buscheck: request not contiguous");
1075: }
1076: return (1);
1077: }
1078: return (0);
1079: }
1080:
1081: /*
1082: * Compute the address of an I/O device within standard address
1083: * ranges and return the result. This is used by DKIOCINFO
1084: * ioctl to get the best guess possible for the actual address
1085: * set on the card.
1086: */
1087: getdevaddr(addr)
1088: caddr_t addr;
1089: {
1090: int off = (int)addr & PGOFSET;
1091: int pte = getkpgmap(addr);
1092: int physaddr = ((pte & PG_PFNUM) & ~PGT_MASK) * NBPG;
1093:
1094: switch (pte & PGT_MASK) {
1095: case PGT_VME_D16:
1096: case PGT_VME_D32:
1097: if (physaddr > VME16_BASE) {
1098: /* 16 bit VMEbus address */
1099: physaddr -= VME16_BASE;
1100: } else if (physaddr > VME24_BASE) {
1101: /* 24 bit VMEbus address */
1102: physaddr -= VME24_BASE;
1103: }
1104: /*
1105: * else 32 bit VMEbus address,
1106: * physaddr doesn't require adjustments
1107: */
1108: break;
1109:
1110: case PGT_OBMEM:
1111: case PGT_OBIO:
1112: /* physaddr doesn't require adjustments */
1113: break;
1114: }
1115:
1116: return (physaddr + off);
1117: }
1118:
1119: static int (*mon_nmi)(); /* monitor's level 7 nmi routine */
1120: extern int level7(); /* Unix's level 7 nmi routine */
1121:
1122: stopnmi()
1123: {
1124: struct scb *vbr, *getvbr();
1125:
1126: vbr = getvbr();
1127: if (vbr->scb_autovec[7 - 1] != level7) {
1128: #ifndef GPROF
1129: set_clk_mode(0, IR_ENA_CLK7); /* disable level 7 clk intr */
1130: #endif !GPROF
1131: mon_nmi = vbr->scb_autovec[7 - 1]; /* save mon vec */
1132: vbr->scb_autovec[7 - 1] = level7; /* install Unix vec */
1133: }
1134: }
1135:
1136: startnmi()
1137: {
1138: struct scb *getvbr();
1139:
1140: if (mon_nmi) {
1141: getvbr()->scb_autovec[7 - 1] = mon_nmi; /* install mon vec */
1142: #ifndef GPROF
1143: set_clk_mode(IR_ENA_CLK7, 0); /* enable level 7 clk intr */
1144: #endif !GPROF
1145: }
1146: }
1147:
1148: /*
1149: * Handler for monitor vector cmd -
1150: * For now we just implement the old "g0" and "g4"
1151: * commands and a printf hack.
1152: */
1153: void
1154: v_handler(addr, str)
1155: int addr;
1156: char *str;
1157: {
1158:
1159: switch (*str) {
1160: case '\0':
1161: /*
1162: * No (non-hex) letter was specified on
1163: * command line, use only the number given
1164: */
1165: switch (addr) {
1166: case 0: /* old g0 */
1167: case 0xd: /* 'd'ump short hand */
1168: panic("zero");
1169: /*NOTREACHED*/
1170:
1171: case 4: /* old g4 */
1172: tracedump();
1173: break;
1174:
1175: default:
1176: goto err;
1177: }
1178: break;
1179:
1180: case 'p': /* 'p'rint string command */
1181: case 'P':
1182: (*romp->v_printf)("%s\n", (char *)addr);
1183: break;
1184:
1185: case '%': /* p'%'int anything a la printf */
1186: (*romp->v_printf)(str, addr);
1187: (*romp->v_printf)("\n");
1188: break;
1189:
1190: case 't': /* 't'race kernel stack */
1191: case 'T':
1192: tracedump();
1193: break;
1194:
1195: case 'u': /* d'u'mp hack ('d' look like hex) */
1196: case 'U':
1197: if (addr == 0xd) {
1198: panic("zero");
1199: } else
1200: goto err;
1201: break;
1202:
1203: default:
1204: err:
1205: (*romp->v_printf)("Don't understand 0x%x '%s'\n", addr, str);
1206: }
1207: }
1208:
1209: /*
1210: * Handle parity/ECC memory errors. XXX - use something like
1211: * vax to only look for soft ecc errors periodically?
1212: */
1213: memerr()
1214: {
1215: u_char per, eer;
1216: char *mess = 0;
1217: int c;
1218: long pme;
1219:
1220: eer = per = MEMREG->mr_er;
1221: #ifdef SUN3_260
1222: if (cpu == CPU_SUN3_260 && (eer & EER_ERR) == EER_CE) {
1223: softecc();
1224: MEMREG->mr_dvma = 1; /* clear latching */
1225: return;
1226: }
1227: #endif SUN3_260
1228:
1229: /*
1230: * Since we are going down in flames, disable further
1231: * memory error interrupts to prevent confusion.
1232: */
1233: MEMREG->mr_er &= ~ER_INTENA;
1234:
1235: #if defined(SUN3_160) || defined(SUN3_50)
1236: if ((cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50) &&
1237: (per & PER_ERR) != 0) {
1238: printf("Parity Error Register %b\n", per, PARERR_BITS);
1239: mess = "parity error";
1240: }
1241: #endif defined(SUN3_160) || defined(SUN3_50)
1242:
1243: #ifdef SUN3_260
1244: if ((cpu == CPU_SUN3_260) && (eer & EER_ERR) != 0) {
1245: printf("ECC Error Register %b\n", eer, ECCERR_BITS);
1246: mess = "uncorrectable ECC error";
1247: }
1248: #endif SUN3_260
1249:
1250: if (!mess) {
1251: printf("Memory Error Register %b %b\n",
1252: per, PARERR_BITS, eer, ECCERR_BITS);
1253: mess = "unknown memory error";
1254: }
1255:
1256: printf("DVMA = %x, context = %x, virtual address = %x\n",
1257: MEMREG->mr_dvma, MEMREG->mr_ctx, MEMREG->mr_vaddr);
1258:
1259: c = getcontext();
1260: setcontext((int)MEMREG->mr_ctx);
1261: pme = getpgmap((caddr_t)MEMREG->mr_vaddr);
1262: printf("pme = %x, physical address = %x\n", pme,
1263: ptob(((struct pte *)&pme)->pg_pfnum) + (MEMREG->mr_vaddr&PGOFSET));
1264: setcontext(c);
1265:
1266: /*
1267: * Clear the latching by writing to the top
1268: * nibble of the memory address register
1269: */
1270: MEMREG->mr_dvma = 1;
1271:
1272: panic(mess);
1273: /*NOTREACHED*/
1274: }
1275:
1276: #ifdef SUN3_260
1277: int prtsoftecc = 1;
1278:
1279: /*
1280: * Probe memory cards to find which one(s) had ecc error(s).
1281: * If prtsoftecc is non-zero, log messages regarding the failing
1282: * syndrome. Then clear the latching on the memory card.
1283: */
1284: softecc()
1285: {
1286: register struct eccreg **ecc_nxt, *ecc;
1287:
1288: for (ecc_nxt = ecc_alive; *ecc_nxt != (struct eccreg *)0; ecc_nxt++) {
1289: ecc = *ecc_nxt;
1290: if (ecc->syndrome.sy_ce) {
1291: if (prtsoftecc) {
1292: printf("mem%d: soft ecc addr %x+%x=%x syn %b\n",
1293: ecc - ECCREG,
1294: (ecc->eccena.ena_addr << 22),
1295: (ecc->syndrome.sy_addr << 3),
1296: (ecc->eccena.ena_addr << 22) +
1297: (ecc->syndrome.sy_addr << 3),
1298: ecc->syndrome.sy_synd, SYNDERR_BITS);
1299: }
1300: ecc->syndrome.sy_ce = 1; /* clear latching */
1301: }
1302: }
1303: }
1304: #endif SUN3_260
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.