|
|
1.1 root 1: /*
2: * machine-dependent init stuff;
3: * specific to VAX but general to all models
4: */
5:
6: #include "sys/param.h"
7: #include "sys/systm.h"
8: #include "sys/user.h"
9: #include "sys/proc.h"
10: #include "sys/map.h"
11: #include "sys/reg.h"
12: #include "sys/mtpr.h"
13: #include "sys/clock.h"
14: #include "sys/pte.h"
15: #include "sys/vm.h"
16: #include "sys/psl.h"
17: #include "sys/buf.h"
18: #include "sys/reboot.h"
19: #include "sys/conf.h"
20: #include "sys/text.h"
21: #include "sys/cmap.h"
22: #include "sys/msgbuf.h"
23:
24: /*
25: * table of little bits of page table needed
26: * by various bits of code
27: * the right way to do this would be
28: * to have a pool, and hand space out dynamically
29: */
30:
31: extern char *CADDR1, *CADDR2, *CADDR3;
32: extern struct pte *CMAP1, *CMAP2, *CMAP3, *mmap;
33: extern char *vmmap;
34: extern char *priobuf;
35: extern struct pte *Prbufmap;
36:
37: struct {
38: int npages;
39: struct pte **pmap;
40: caddr_t *pmem;
41: } mmlist[] = {
42: UPAGES, &Swapmap, (caddr_t *)&swaputl,
43: UPAGES, &Forkmap, (caddr_t *)&forkutl,
44: UPAGES, &Xswapmap, (caddr_t *)&xswaputl,
45: UPAGES, &Xswap2map, (caddr_t *)&xswap2utl,
46: UPAGES, &Pushmap, (caddr_t *)&pushutl,
47: UPAGES, &Prusrmap, (caddr_t *)&prusrutl,
48: CLSIZE, &Prbufmap, (caddr_t *)&priobuf,
49: CLSIZE, &msgbufmap, (caddr_t *)&msgbuf,
50: USRPTSIZE, &Usrptmap, (caddr_t *)&usrpt,
51: 1, &CMAP1, (caddr_t *)&CADDR1,
52: 1, &CMAP2, (caddr_t *)&CADDR2,
53: 1, &CMAP3, (caddr_t *)&CADDR3,
54: 1, &mmap, (caddr_t *)&vmmap,
55: -1
56: };
57:
58: struct pte *physspt;
59: struct pte *Sysmap;
60: struct pte *Usrptmap;
61: struct pte *usrpt;
62:
63: /*
64: * init the memory map
65: * called early on, well before main
66: * memory management is off
67: *
68: * the system page table is allocated here, out of free memory
69: * the theory is:
70: * map the static kernel first
71: * then any pseudo-dynamic data structures
72: * then the buffers
73: * then lay down the system page table
74: * then map io space
75: *
76: * subtlety: we generally want end and etext to be physical addresses.
77: * (long)&end & ~KSTART seems to be the only expression that is constant
78: * with and without the c optimizer.
79: */
80:
81: mmapinit(hiaddr)
82: long hiaddr;
83: {
84: extern int end, etext;
85: extern char *iospace;
86: register int i;
87: register long *p; /* pun; really struct pte * */
88: register long mtop; /* highest real memory address used */
89: register long ptop; /* highest virtual address used */
90: register long v;
91:
92: maxmem = physmem = btoc(hiaddr);
93: mtop = (long)&end & ~KSTART;
94: /*
95: * dynamic things: add to memtop, set addrs along the way
96: */
97: if (nbuf == 0) {
98: nbuf = 32 * physmem / btoc(1024*1024);
99: if (nbuf < 32)
100: nbuf = 32;
101: }
102: buf = (struct buf *)(KSTART+mtop);
103: mtop += nbuf * sizeof(struct buf);
104: mtop = (mtop + NBPG - 1) & ~PGOFSET;
105: buffers = (char *)(KSTART+mtop);
106: mtop += nbuf * BUFSIZE;
107: /*
108: * cmaps; we'll slightly overestimate; too bad
109: */
110: cmap = (struct cmap *)(KSTART+mtop);
111: ncmap = (physmem * NBPG - mtop)/(CLSIZE*NBPG + sizeof(struct cmap));
112: mtop += ncmap * sizeof(struct cmap);
113: ecmap = (struct cmap *)(KSTART+mtop);
114: /*
115: * clear all the memory we just handed out
116: */
117: p = (long *)((long)&end & ~KSTART);
118: while (p < (long *)mtop)
119: *p++ = 0;
120: /*
121: * now the things that aren't memory
122: * maps are relative to beginning of spt
123: */
124: mtop = (mtop + NBPG - 1) & ~PGOFSET;
125: ptop = mtop;
126: for (i = 0; mmlist[i].npages >= 0; i++) {
127: *mmlist[i].pmem = (caddr_t)(ptop + KSTART);
128: *mmlist[i].pmap = (struct pte *)(btoc(ptop) * sizeof(struct pte));
129: ptop += ctob(mmlist[i].npages);
130: }
131: iospace = (char *)(ptop + KSTART);
132: ptop += mchiopsize();
133: Sysmap = (struct pte *)(ptop + KSTART);
134: physspt = (struct pte *)mtop;
135: p = (long *)mtop;
136: i = (int)&etext & ~KSTART; /* not - KSTART; optimizer gets it wrong */
137: for (v = 0; v < mtop; v += NBPG) /* kernel text + data */
138: if (v < i)
139: *p++ = PG_V|PG_KR|btoc(v);
140: else
141: *p++ = PG_V|PG_KW|btoc(v);
142: for (; v < ptop; v += NBPG) /* mystery maps */
143: *p++ = 0;
144: ptop += (btoc(ptop) + btoc(btoc(ptop)*sizeof(struct pte)))*sizeof(struct pte);
145: for (i = btoc(mtop); v < ptop; v += NBPG, i++) /* spt */
146: *p++ = PG_V|PG_KW|i;
147: firstfree = i + 1;
148: /*
149: * fix the random maps
150: */
151: for (i = 0; mmlist[i].npages >= 0; i++)
152: *(long *)mmlist[i].pmap += (long)Sysmap;
153: mchiopinit(physspt + btoc(iospace - KSTART));
154: p = (long *)(physspt + (msgbufmap - Sysmap));
155: for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
156: *p++ = PG_V|PG_KW|(physmem - btoc(sizeof(struct msgbuf)) + i);
157: maxmem -= CLSIZE;
158: mtpr(SBR, mtop);
159: mtpr(SLR, btoc(ptop));
160: }
161:
162: /*
163: * set up context for process 0:
164: * first page of free memory becomes page table
165: * next UPAGES become user block
166: * init the process control block slightly
167: * called before memory mapping is turned on
168: */
169:
170: uctinit(kpc)
171: long kpc;
172: {
173: register long *p; /* pun: struct pte * */
174: register int i;
175: register struct pcb *pp;
176:
177: p = (long *)ctob(firstfree);
178: for (i = 0; i < (UPAGES+1)*NBPG; i += sizeof(long))
179: *p++ = 0;
180: p = (long *)(physspt + ((long)usrpt-KSTART)/NBPG);
181: *p = PG_V|PG_KW|firstfree; /* one page for first p0 page table */
182: p = (long *)ctob(firstfree+1);
183: for (i = UPAGES; i > 0; --i)
184: *--p = PG_V|PG_URKW|firstfree+i;
185: pp = (struct pcb *)ctob(firstfree+1);
186: pp->pcb_p0br = usrpt;
187: pp->pcb_p0lr = 0 + AST_NONE; /* no p0 space mapped */
188: pp->pcb_p1br = usrpt + NPTEPG - P1TOP;
189: pp->pcb_p1lr = P1TOP - UPAGES;
190: pp->pcb_ksp = KSTART;
191: pp->pcb_esp = pp->pcb_ssp = -1; /* something invalid */
192: pp->pcb_usp = USRSTACK;
193: pp->pcb_psl = 0; /* mode (kernel,kernel), ipl 0 */
194: pp->pcb_pc = kpc;
195: firstfree += UPAGES + 1;
196: mtpr(PCBB, pp);
197: }
198:
199: /*
200: * Machine-dependent startup code
201: * some of this is excessively specific to the paging code
202: */
203:
204: int dmmin, dmmax, dmtext;
205:
206: startup()
207: {
208: register long maxsz;
209: register unsigned i;
210: register struct proc *p;
211: extern struct map kernelmap[];
212: extern int kernelcnt;
213: extern char version[];
214:
215: setrestart();
216: printf("%s\n", version);
217: meminit(firstfree, maxmem);
218: maxmem = freemem;
219: printf("mem = %d\n", ctob(maxmem));
220: rminit(kernelmap, kernelcnt, USRPTSIZE-1, 1);
221: /*
222: * dmmin fixed for now
223: * dmmax == first power of 2 larger than max?size/(NDMAP-1)
224: */
225: dmmin = DMMIN;
226: maxsz = maxtsize / NXDAD;
227: for (i = 0x80000000; i; i >>= 1)
228: if (maxsz & i)
229: break;
230: i *= 2;
231: if (i < dmmin)
232: i = dmmin;
233: dmtext = i;
234: maxsz = maxdsize > maxssize ? maxdsize : maxssize;
235: maxsz /= NDMAP-1;
236: if (maxsz < dmtext)
237: maxsz = dmtext;
238: for (i = 0x80000000; i; i >>= 1)
239: if (maxsz & i)
240: break;
241: i *= 2;
242: if (i < dmmin)
243: i = dmmin;
244: dmmax = i;
245: maxpgio *= nswdevt;
246: /*
247: * set up vm aspects of first process
248: */
249: p = &proc[0];
250: p->p_p0br = (struct pte *)mfpr(P0BR);
251: p->p_szpt = 1;
252: p->p_addr = uaddr(p);
253: setredzone(p->p_addr, (caddr_t)&u);
254: u.u_pcb.pcb_szpt = CLSIZE;
255: }
256:
257: /*
258: * init unix time
259: * base is some nearly correct number, e.g. from a filesystem.
260: * try to get something better from the VAX time-of-year clock,
261: * which contains the number of .01-second clicks in the current year
262: */
263: clkinit(base)
264: time_t base;
265: {
266: register unsigned long todr;
267: int year = YRREF;
268:
269: todr = gettodr();
270: if (todr < TODRZERO) { /* too small; TODR was restarted */
271: time = base;
272: clkset(); /* so fix it */
273: }
274: else {
275: for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) {
276: if (LEAPYEAR(year))
277: time += SECDAY;
278: year++;
279: }
280: }
281: }
282:
283: /*
284: * once a day or so, set TOY clock to match system clock
285: */
286:
287: static time_t clknext;
288:
289: clkcheck()
290: {
291:
292: if (clknext == 0)
293: clknext = time + SECDAY;
294: if (clknext > time)
295: return;
296: clknext = time + SECDAY;
297: clkset();
298: }
299:
300: /*
301: * reset the TOY clock to match current unix time
302: */
303:
304: clkset()
305: {
306: int year = YRREF;
307: unsigned secyr;
308: unsigned yrtime = time;
309:
310: for (;;) {
311: secyr = SECYR;
312: if (LEAPYEAR(year))
313: secyr += SECDAY;
314: if (yrtime < secyr)
315: break;
316: yrtime -= secyr;
317: year++;
318: }
319: settodr(TODRZERO + yrtime*100);
320: }
321:
322: /*
323: * bias the clock to correct an error of `wrong' milliseconds
324: * -- just tick slightly slowly or quickly for a while
325: * MicroVAX has no NICR, but writing it is a no-op;
326: * let the clock interrupt code do the work
327: */
328:
329: int clockbias; /* number of ticks */
330: char clocksign; /* direction to correct */
331:
332: biasclock()
333: {
334: register struct a {
335: int wrong;
336: } *uap;
337: register long nticks;
338:
339: uap = (struct a *)u.u_ap;
340: if (!suser())
341: return;
342: nticks = (long)uap->wrong * 1000; /* microseconds */
343: nticks /= CLKBIAS; /* number of ticks to bias */
344: spl7();
345: if (nticks < 0) {
346: mtpr(NICR, CLK60HZ-CLKBIAS);
347: clockbias = -nticks;
348: clocksign = -1; /* -1 => clock must run slower */
349: }
350: else {
351: mtpr(NICR, CLK60HZ+CLKBIAS);
352: clockbias = nticks;
353: clocksign = 1;
354: }
355: spl0();
356: }
357:
358: /*
359: * Return the difference (in microseconds)
360: * between the current time and a previous
361: * time as represented by the arguments.
362: * If there is a pending clock interrupt
363: * which has not been serviced due to high
364: * ipl, return error code.
365: */
366: vmtime(otime, olbolt, oicr)
367: register int otime, olbolt, oicr;
368: {
369:
370: if (mfpr(ICCS)&ICCS_INT)
371: return(-1);
372: else
373: return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
374: }
375:
376: /*
377: * Send an interrupt to process
378: *
379: * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION
380: * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS.
381: */
382: sendsig(p, n)
383: int (*p)();
384: {
385: register int *usp, *regs;
386:
387: regs = u.u_ar0;
388: usp = (int *)regs[SP];
389: usp -= 5;
390: if ((int)usp <= USRSTACK - ctob(u.u_ssize))
391: (void) grow((unsigned)usp);
392: if (useracc((caddr_t)usp, 5*sizeof(int), B_WRITE) == 0)
393: goto bad;
394: *usp++ = n;
395: if (n == SIGILL || n == SIGFPE) {
396: *usp++ = u.u_code;
397: u.u_code = 0;
398: } else
399: *usp++ = 0;
400: *usp++ = (int)p;
401: *usp++ = regs[PC];
402: *usp++ = regs[PS];
403: regs[SP] = (int)(usp - 5);
404: regs[PS] &= ~(PSL_CM|PSL_FPD);
405: regs[PC] = (int)u.u_pcb.pcb_sigc;
406: return;
407:
408: bad:
409: /*
410: * Process has trashed its stack; give it an illegal
411: * instruction to halt it in its tracks.
412: */
413: u.u_signal[SIGILL] = SIG_DFL;
414: P_SETDFL(u.u_procp, SIGMASK(SIGILL));
415: psignal(u.u_procp, SIGILL);
416: }
417:
418: /*
419: * Invalidate single all pte's in a cluster
420: */
421: tbiscl(v)
422: unsigned v;
423: {
424: register caddr_t addr;
425: register int i;
426:
427: addr = ptob(v);
428: for (i = 0; i < CLSIZE; i++) {
429: mtpr(TBIS, addr);
430: addr += NBPG;
431: }
432: }
433:
434: /*
435: * sys reboot
436: * can this please go away?
437: */
438:
439: boot(howto)
440: int howto;
441: {
442:
443: if (howto&RB_HALT)
444: death();
445: reboot(1);
446: }
447:
448: /*
449: * freeze. can't just halt because
450: * on some machines that would cause a boot
451: */
452:
453: death()
454: {
455: splx(0x1f);
456: printf("death\n");
457: for (;;)
458: ;
459: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.