xref: /original-bsd/sys/vax/vax/machdep.c (revision ba72ef4c)
1 /*	machdep.c	3.28	10/11/80	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/map.h"
8 #include "../h/reg.h"
9 #include "../h/mtpr.h"
10 #include "../h/clock.h"
11 #include "../h/pte.h"
12 #include "../h/vm.h"
13 #include "../h/proc.h"
14 #include "../h/psl.h"
15 #include "../h/uba.h"
16 #include "../h/cons.h"
17 #include "../h/reboot.h"
18 
19 char	version[] = "VM/UNIX (Berkeley Version 3.28) 10/14/12 \n";
20 int	icode[] =
21 {
22 	0x9f19af9f,	/* pushab [&"init.vm",0]; pushab */
23 	0x02dd09af,	/* "/etc/init.vm"; pushl $2 */
24 	0xbc5c5ed0,	/* movl sp,ap; chmk */
25 	0x2ffe110b,	/* $exec; brb .; "/ */
26 	0x2f637465,	/* etc/ */
27 	0x74696e69,	/* init" */
28 	0x00000000,	/* \0\0\0";  0 */
29 	0x00000014,	/* [&"init", */
30 	0x00000000,	/* 0] */
31 };
32 int	szicode = sizeof(icode);
33 int	memchk();
34 
35 /*
36  * Machine-dependent startup code
37  */
38 startup(firstaddr)
39 {
40 	register int unixsize;
41 	register int i;
42 	register struct pte *pte;
43 
44 	/*
45 	 * Good {morning,afternoon,evening,night}.
46 	 */
47 
48 	printf(version);
49 	printf("real mem  = %d\n", ctob(maxmem));
50 
51 	/*
52 	 * Allow for the u. area of process 0 and its (single)
53 	 * page of page tables.
54 	 */
55 	unixsize = (firstaddr+UPAGES+1);
56 
57 	/*
58 	 * Initialze buffers
59 	 */
60 	pte = bufmap;
61 	for (i = 0; i < NBUF * CLSIZE; i++)
62 		*(int *)pte++ = PG_V | PG_KW | unixsize++;
63 	mtpr(TBIA, 1);
64 
65 #ifdef ERNIE
66 	if (coresw)
67 		maxmem = 4096;
68 #endif
69 
70 	/*
71 	 * Initialize maps.
72 	 */
73 	meminit(unixsize, maxmem);
74 	maxmem = freemem;
75 	printf("avail mem = %d\n", ctob(maxmem));
76 	mfree(kernelmap, USRPTSIZE, 1);
77 	ubainit();
78 	timeout(memchk, (caddr_t)0, 60);	/* it will pick its own intvl */
79 }
80 
81 /*
82  * set up a physical address
83  * into users virtual address space.
84  */
85 sysphys()
86 {
87 
88 	if(!suser())
89 		return;
90 	u.u_error = EINVAL;
91 }
92 
93 /*
94  * Initialze the clock, based on the time base which is, e.g.
95  * from a filesystem.  Base provides the time to within six months,
96  * and the time of year clock provides the rest.
97  */
98 clkinit(base)
99 	time_t base;
100 {
101 	register unsigned todr = mfpr(TODR);
102 	long deltat;
103 	int year = YRREF;
104 
105 	/*
106 	 * Have been told that VMS keeps time internally with base TODRZERO.
107 	 * If this is correct, then this routine and VMS should maintain
108 	 * the same date, and switching shouldn't be painful.
109 	 */
110 	if (todr < TODRZERO) {
111 		printf("WARNING: todr too small (battery backup failed?)");
112 		time = base;
113 		/*
114 		 * Believe the time in the file system for lack of
115 		 * anything better, resetting the TODR.
116 		 */
117 		clkset();
118 		goto check;
119 	}
120 	/*
121 	 * Sneak to within 6 month of the time in the filesystem,
122 	 * by starting with the time of the year suggested by the TODR,
123 	 * and advancing through succesive years.  Adding the number of
124 	 * seconds in the current year takes us to the end of the current year
125 	 * and then around into the next year to the same position.
126 	 */
127 	for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) {
128 		if (LEAPYEAR(year))
129 			time += SECDAY;
130 		year++;
131 	}
132 
133 	/*
134 	 * See if we gained/lost two or more days;
135 	 * if so, assume something is amiss.
136 	 */
137 	deltat = time - base;
138 	if (deltat < 0)
139 		deltat = -deltat;
140 	if (deltat < 2*SECDAY)
141 		return;
142 	printf("WARNING: clock %s %d days",
143 	    time < base ? "lost" : "gained", deltat / SECDAY);
144 check:
145 	printf(" -- CHECK AND RESET THE DATE!\n");
146 }
147 
148 /*
149  * Reset the TODR based on the time value; used when the TODR
150  * has a preposterous value and also when the time is reset
151  * by the stime system call.  Also called when the TODR goes past
152  * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
153  * to wrap the TODR around.
154  */
155 clkset()
156 {
157 	int year = YRREF;
158 	unsigned secyr;
159 	unsigned yrtime = time;
160 
161 	/*
162 	 * Whittle the time down to an offset in the current year,
163 	 * by subtracting off whole years as long as possible.
164 	 */
165 	for (;;) {
166 		secyr = SECYR;
167 		if (LEAPYEAR(year))
168 			secyr += SECDAY;
169 		if (yrtime < secyr)
170 			break;
171 		yrtime -= secyr;
172 		year++;
173 	}
174 	mtpr(TODR, TODRZERO + yrtime*100);
175 }
176 
177 #ifdef PGINPROF
178 /*
179  * Return the difference (in microseconds)
180  * between the  current time and a previous
181  * time as represented  by the arguments.
182  * If there is a pending clock interrupt
183  * which has not been serviced due to high
184  * ipl, return error code.
185  */
186 vmtime(otime, olbolt, oicr)
187 	register int otime, olbolt, oicr;
188 {
189 
190 	if (mfpr(ICCS)&ICCS_INT)
191 		return(-1);
192 	else
193 		return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
194 }
195 #endif
196 
197 #ifdef TRACE
198 /*
199  * Put the current time into the trace,
200  * in fractional seconds (i.e. 12345 means the
201  * current time is ``n.12345'' for some n.
202  */
203 ttime()
204 {
205 
206 	trace("%d ", (lbolt*16667 + mfpr(ICR)));
207 }
208 #endif
209 
210 /*
211  * Send an interrupt to process
212  *
213  * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION
214  * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS.
215  */
216 sendsig(p, n)
217 {
218 	register int *usp, *regs;
219 
220 	regs = u.u_ar0;
221 	usp = (int *)regs[SP];
222 #ifdef FASTVAX
223 	usp -= 5;
224 	if ((int)usp <= USRSTACK - ctob(u.u_ssize))
225 		(void) grow((unsigned)usp);
226 	;			/* Avoid asm() label botch */
227 	asm("probew $3,$20,(r11)");
228 	asm("beql bad");
229 	*usp++ = n;
230 	*usp++ = n == SIGILL ? u.u_cfcode : 0;
231 	*usp++ = p;
232 	*usp++ = regs[PC];
233 	*usp++ = regs[PS];
234 	regs[SP] = (int)(usp - 5);
235 #else
236 	(void) grow((unsigned)(usp-5));
237 	if (suword((caddr_t)--usp, regs[PS]))
238 		goto bad;
239 	if (suword((caddr_t)--usp, regs[PC]))
240 		goto bad;
241 	if (suword((caddr_t)--usp, p))
242 		goto bad;
243 	if (suword((caddr_t)--usp, n==SIGILL ? u.u_cfcode : 0))
244 		goto bad;
245 	if (suword((caddr_t)--usp, n))
246 		goto bad;
247 	regs[SP] = (int)usp;
248 #endif
249 	regs[PS] &= ~(PSL_CM|PSL_FPD);
250 	regs[PC] = (int)u.u_pcb.pcb_sigc;
251 	return;
252 
253 #ifdef FASTVAX
254 asm("bad:");
255 #endif
256 bad:
257 	printf("%d: cant send signal\n", u.u_procp->p_pid);
258 	psignal(u.u_procp, SIGKILL);
259 }
260 
261 dorti()
262 {
263 	struct frame {
264 		int	handler;
265 		unsigned int
266 			psw:16,
267 			mask:12,
268 			:1,
269 			s:1,
270 			spa:2;
271 		int	savap;
272 		int	savfp;
273 		int	savpc;
274 	} frame;
275 	register int sp;
276 	register int reg, mask;
277 	extern int ipcreg[];
278 
279 	(void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
280 	sp = u.u_ar0[FP] + sizeof (frame);
281 	u.u_ar0[PC] = frame.savpc;
282 	u.u_ar0[FP] = frame.savfp;
283 	u.u_ar0[AP] = frame.savap;
284 	mask = frame.mask;
285 	for (reg = 0; reg <= 11; reg++) {
286 		if (mask&1) {
287 			u.u_ar0[ipcreg[reg]] = fuword(sp);
288 			sp += 4;
289 		}
290 		mask >>= 1;
291 	}
292 	sp += frame.spa;
293 	u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.psw;
294 	if (frame.s)
295 		sp += 4 + 4 * (fuword(sp) & 0xff);
296 	/* phew, now the rei */
297 	u.u_ar0[PC] = fuword(sp);
298 	sp += 4;
299 	u.u_ar0[PS] = fuword(sp);
300 	sp += 4;
301 	u.u_ar0[PS] |= PSL_CURMOD|PSL_PRVMOD;
302 	u.u_ar0[PS] &= ~PSL_USERCLR;
303 }
304 
305 /*
306  * Check memory controller for memory parity errors
307  */
308 #define	MEMINTVL	(60*60*10)		/* 10 minutes */
309 int	memintvl = MEMINTVL;
310 
311 #define	MHIERR	0x20000000
312 #define	MERLOG	0x10000000
313 
314 memchk()
315 {
316 	register int c = mcr[2];
317 
318 	if (c & MERLOG) {
319 		printf("MEMERR: mcra %X mcrb %X mcrc %X\n", mcr[0],
320 		    mcr[1], c);
321 		mcr[2] = (MERLOG|MHIERR);
322 	}
323 	if (memintvl > 0)
324 		timeout(memchk, (caddr_t)0, memintvl);
325 }
326 
327 /*
328  * Invalidate single all pte's in a cluster
329  */
330 tbiscl(v)
331 	unsigned v;
332 {
333 	register caddr_t addr;		/* must be first reg var */
334 	register int i;
335 
336 	asm(".set TBIS,58");
337 	addr = ptob(v);
338 	for (i = 0; i < CLSIZE; i++) {
339 #ifdef lint
340 		mtpr(TBIS, addr);
341 #else
342 		asm("mtpr r11,$TBIS");
343 #endif
344 		addr += NBPG;
345 	}
346 }
347 
348 int	hangcnt;
349 
350 unhang()
351 {
352 	register struct uba_regs *up = (struct uba_regs *)UBA0;
353 
354 	if (up->uba_sr == 0)
355 		return;
356 	hangcnt++;
357 	if (hangcnt > 5*HZ) {
358 		hangcnt = 0;
359 		printf("HANG ");
360 		ubareset();
361 	}
362 }
363 
364 int	waittime = -1;
365 
366 boot(panic, arghowto)
367 	int panic, arghowto;
368 {
369 	register int howto;		/* r11 == how to boot */
370 	register int devtype;		/* r10 == major of root dev */
371 
372 	howto = arghowto;
373 	if ((howto&RB_NOSYNC)==0 && waittime < 0) {
374 		waittime = 0;
375 		update();
376 		printf("syncing disks... ");
377 		while (++waittime <= 5)
378 			sleep((caddr_t)&lbolt, PZERO);
379 		printf("done\n");
380 	}
381 	splx(0x1f);			/* extreme priority */
382 	devtype = major(rootdev);
383 	if ((howto&RB_HALT)==0) {
384 		while ((mfpr(TXCS)&TXCS_RDY) == 0)
385 			continue;
386 		mtpr(TXDB, panic == RB_PANIC ? TXDB_AUTOR : TXDB_BOOT);
387 	}
388 	for (;;)
389 		asm("halt");
390 }
391