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