xref: /original-bsd/sys/tahoe/tahoe/machdep.c (revision 6b3572dd)
1 /*
2  * Copyright (c) 1982,1987,1988 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)machdep.c	7.13 (Berkeley) 06/28/90
7  */
8 
9 #include "param.h"
10 #include "systm.h"
11 #include "user.h"
12 #include "kernel.h"
13 #include "map.h"
14 #include "vm.h"
15 #include "proc.h"
16 #include "buf.h"
17 #include "reboot.h"
18 #include "conf.h"
19 #include "file.h"
20 #include "text.h"
21 #include "clist.h"
22 #include "callout.h"
23 #include "cmap.h"
24 #include "malloc.h"
25 #include "mbuf.h"
26 #include "msgbuf.h"
27 #ifdef SYSVSHM
28 #include "shm.h"
29 #endif
30 
31 #include "cpu.h"
32 #include "reg.h"
33 #include "pte.h"
34 #include "psl.h"
35 #include "mem.h"
36 #include "mtpr.h"
37 #include "cp.h"
38 
39 #include "../tahoevba/vbavar.h"
40 
41 /*
42  * Declare these as initialized data so we can patch them.
43  */
44 int	nswbuf = 0;
45 #ifdef	NBUF
46 int	nbuf = NBUF;
47 #else
48 int	nbuf = 0;
49 #endif
50 #ifdef	BUFPAGES
51 int	bufpages = BUFPAGES;
52 #else
53 int	bufpages = 0;
54 #endif
55 #include "yc.h"
56 #if NCY > 0
57 #include "../tahoevba/cyreg.h"
58 #endif
59 int	msgbufmapped;		/* set when safe to use msgbuf */
60 int	physmem = MAXMEM;	/* max supported memory, changes to actual */
61 
62 /*
63  * Machine-dependent startup code
64  */
65 startup(firstaddr)
66 	int firstaddr;
67 {
68 	register int unixsize;
69 	register unsigned i;
70 	register struct pte *pte;
71 	int mapaddr, j;
72 	register caddr_t v;
73 	int maxbufs, base, residual;
74 
75 	/*
76 	 * Initialize error message buffer (at end of core).
77 	 */
78 	maxmem = physmem - btoc(sizeof (struct msgbuf));
79 	pte = msgbufmap;
80 	for (i = 1; i < btoc(sizeof (struct msgbuf)) + 1; i++)
81 		*(int *)pte++ = PG_V | PG_KW | (physmem - i);
82 	mtpr(TBIA, 1);
83 	msgbufmapped = 1;
84 #ifdef KADB
85 	kdb_init();			/* startup kernel debugger */
86 	(void) cnopen(makedev(0, 1), 0);	/* open console XXX */
87 #endif
88 	/*
89 	 * Good {morning,afternoon,evening,night}.
90 	 */
91 	printf(version);
92 	printf("real mem = %d\n", ctob(physmem));
93 
94 	/*
95 	 * Allocate space for system data structures.
96 	 * The first available real memory address is in "firstaddr".
97 	 * The first available kernel virtual address is in "v".
98 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
99 	 * As pages of memory are allocated and cleared,
100 	 * "firstaddr" is incremented.
101 	 * An index into the kernel page table corresponding to the
102 	 * virtual memory address maintained in "v" is kept in "mapaddr".
103 	 */
104 	v = (caddr_t)(0xc0000000 | (firstaddr * NBPG));
105 #define	valloc(name, type, num) \
106 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
107 #define	valloclim(name, type, num, lim) \
108 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
109 #if NCY > 0
110 	/*
111 	 * Allocate raw buffers for tapemaster controllers
112 	 * first, as they need buffers in the first megabyte.
113 	 */
114 	valloc(cybuf, char, NCY * CYMAXIO);
115 #endif
116 	valloclim(file, struct file, nfile, fileNFILE);
117 	valloclim(proc, struct proc, nproc, procNPROC);
118 	valloclim(text, struct text, ntext, textNTEXT);
119 	valloc(cfree, struct cblock, nclist);
120 	valloc(callout, struct callout, ncallout);
121 	valloc(swapmap, struct map, nswapmap = nproc * 2);
122 	valloc(argmap, struct map, ARGMAPSIZE);
123 	valloc(kernelmap, struct map, nproc);
124 	valloc(mbmap, struct map, nmbclusters/4);
125 	valloc(kmemmap, struct map, ekmempt - kmempt);
126 	valloc(kmemusage, struct kmemusage, ekmempt - kmempt);
127 #ifdef SYSVSHM
128 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
129 #endif
130 
131 	/*
132 	 * Determine how many buffers to allocate.
133 	 * Use 10% of memory for the first 2 Meg, 5% of the remaining
134 	 * memory. Insure a minimum of 16 buffers.
135 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
136 	 */
137 	if (bufpages == 0)
138 		if (physmem < (2 * 1024 * 1024))
139 			bufpages = physmem / 10 / CLSIZE;
140 		else
141 			bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE;
142 	if (nbuf == 0) {
143 		nbuf = bufpages / 2;
144 		if (nbuf < 16)
145 			nbuf = 16;
146 	}
147 	if (nswbuf == 0) {
148 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
149 		if (nswbuf > 256)
150 			nswbuf = 256;		/* sanity */
151 	}
152 	valloc(swbuf, struct buf, nswbuf);
153 
154 	/*
155 	 * Now the amount of virtual memory remaining for buffers
156 	 * can be calculated, estimating needs for the cmap.
157 	 */
158 	ncmap = (maxmem*NBPG - ((int)v &~ 0xc0000000)) /
159 		(CLBYTES + sizeof(struct cmap)) + 2;
160 	maxbufs = ((SYSPTSIZE * NBPG) -
161 	    ((int)(v + ncmap * sizeof(struct cmap)) - 0xc0000000)) /
162 		(MAXBSIZE + sizeof(struct buf));
163 	if (maxbufs < 16)
164 		panic("sys pt too small");
165 	if (nbuf > maxbufs) {
166 		printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
167 		nbuf = maxbufs;
168 	}
169 	if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
170 		bufpages = nbuf * (MAXBSIZE / CLBYTES);
171 	valloc(buf, struct buf, nbuf);
172 
173 	/*
174 	 * Allocate space for core map.
175 	 * Allow space for all of phsical memory minus the amount
176 	 * dedicated to the system. The amount of physical memory
177 	 * dedicated to the system is the total virtual memory of
178 	 * the system thus far, plus core map, buffer pages,
179 	 * and buffer headers not yet allocated.
180 	 * Add 2: 1 because the 0th entry is unused, 1 for rounding.
181 	 */
182 	ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0xc0000000)) /
183 		(CLBYTES + sizeof(struct cmap)) + 2;
184 	valloclim(cmap, struct cmap, ncmap, ecmap);
185 
186 	/*
187 	 * Clear space allocated thus far, and make r/w entries
188 	 * for the space in the kernel map.
189 	 */
190 	unixsize = btoc((int)v &~ 0xc0000000);
191 	while (firstaddr < unixsize) {
192 		*(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr;
193 		clearseg((unsigned)firstaddr);
194 		firstaddr++;
195 	}
196 
197 	/*
198 	 * Now allocate buffers proper.  They are different than the above
199 	 * in that they usually occupy more virtual memory than physical.
200 	 */
201 	v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
202 	valloc(buffers, char, MAXBSIZE * nbuf);
203 	base = bufpages / nbuf;
204 	residual = bufpages % nbuf;
205 	mapaddr = firstaddr;
206 	for (i = 0; i < residual; i++) {
207 		for (j = 0; j < (base + 1) * CLSIZE; j++) {
208 			*(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
209 			clearseg((unsigned)firstaddr);
210 			firstaddr++;
211 		}
212 		mapaddr += MAXBSIZE / NBPG;
213 	}
214 	for (i = residual; i < nbuf; i++) {
215 		for (j = 0; j < base * CLSIZE; j++) {
216 			*(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
217 			clearseg((unsigned)firstaddr);
218 			firstaddr++;
219 		}
220 		mapaddr += MAXBSIZE / NBPG;
221 	}
222 
223 	unixsize = btoc((int)v &~ 0xc0000000);
224 	if (firstaddr >= physmem - 8*UPAGES)
225 		panic("no memory");
226 	mtpr(TBIA, 1);			/* After we just cleared it all! */
227 
228 	/*
229 	 * Initialize callouts
230 	 */
231 	callfree = callout;
232 	for (i = 1; i < ncallout; i++)
233 		callout[i-1].c_next = &callout[i];
234 
235 	/*
236 	 * Initialize memory allocator and swap
237 	 * and user page table maps.
238 	 *
239 	 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
240 	 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
241 	 */
242 	meminit(firstaddr, maxmem);
243 	maxmem = freemem;
244 	printf("avail mem = %d\n", ctob(maxmem));
245 	printf("using %d buffers containing %d bytes of memory\n",
246 		nbuf, bufpages * CLBYTES);
247 	rminit(kernelmap, (long)USRPTSIZE, (long)1,
248 	    "usrpt", nproc);
249 	rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE,
250 	    "mbclusters", nmbclusters/4);
251 	kmeminit();		/* now safe to do malloc/free */
252 	intenable = 1;		/* Enable interrupts from now on */
253 
254 	/*
255 	 * Set up CPU-specific registers, cache, etc.
256 	 */
257 	initcpu();
258 
259 	/*
260 	 * Set up buffers, so they can be used to read disk labels.
261 	 */
262 	bhinit();
263 	binit();
264 
265 	/*
266 	 * Configure the system.
267 	 */
268 	configure();
269 }
270 
271 #ifdef PGINPROF
272 /*
273  * Return the difference (in microseconds)
274  * between the  current time and a previous
275  * time as represented  by the arguments.
276  * If there is a pending clock interrupt
277  * which has not been serviced due to high
278  * ipl, return error code.
279  */
280 /*ARGSUSED*/
281 vmtime(otime, olbolt, oicr)
282 	register int otime, olbolt, oicr;
283 {
284 
285 	return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667);
286 }
287 #endif
288 
289 /*
290  * Send an interrupt to process.
291  *
292  * Stack is set up to allow sigcode stored
293  * in u. to call routine, followed by kcall
294  * to sigreturn routine below.  After sigreturn
295  * resets the signal mask, the stack, and the
296  * frame pointer, it returns to the user
297  * specified pc, psl.
298  */
299 sendsig(catcher, sig, mask, code)
300 	sig_t catcher;
301 	int sig, mask;
302 	unsigned code;
303 {
304 	register struct sigcontext *scp;
305 	register struct proc *p = u.u_procp;
306 	register int *regs;
307 	register struct sigframe {
308 		int	sf_signum;
309 		int	sf_code;
310 		struct	sigcontext *sf_scp;
311 		sig_t	sf_handler;
312 		int	sf_regs[6];		/* r0-r5 */
313 		struct	sigcontext *sf_scpcopy;
314 	} *fp;
315 	int oonstack;
316 
317 	regs = u.u_ar0;
318 	oonstack = u.u_onstack;
319 	/*
320 	 * Allocate and validate space for the signal handler
321 	 * context. Note that if the stack is in P0 space, the
322 	 * call to grow() is a nop, and the useracc() check
323 	 * will fail if the process has not already allocated
324 	 * the space with a `brk'.
325 	 */
326 	if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
327 		scp = (struct sigcontext *)u.u_sigsp - 1;
328 		u.u_onstack = 1;
329 	} else
330 		scp = (struct sigcontext *)regs[SP] - 1;
331 	fp = (struct sigframe *)scp - 1;
332 	if ((int)fp <= USRSTACK - ctob(u.u_ssize))
333 		(void) grow((unsigned)fp);
334 	if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) {
335 		/*
336 		 * Process has trashed its stack; give it an illegal
337 		 * instruction to halt it in its tracks.
338 		 */
339 		SIGACTION(p, SIGILL) = SIG_DFL;
340 		sig = sigmask(SIGILL);
341 		p->p_sigignore &= ~sig;
342 		p->p_sigcatch &= ~sig;
343 		p->p_sigmask &= ~sig;
344 		psignal(p, SIGILL);
345 		return;
346 	}
347 	/*
348 	 * Build the argument list for the signal handler.
349 	 */
350 	fp->sf_signum = sig;
351 	fp->sf_code = code;
352 	fp->sf_scp = scp;
353 	fp->sf_handler = catcher;
354 	/*
355 	 * Build the callf argument frame to be used to call sigreturn.
356 	 */
357 	fp->sf_scpcopy = scp;
358 	/*
359 	 * Build the signal context to be used by sigreturn.
360 	 */
361 	scp->sc_onstack = oonstack;
362 	scp->sc_mask = mask;
363 	scp->sc_sp = regs[SP];
364 	scp->sc_fp = regs[FP];
365 	scp->sc_pc = regs[PC];
366 	scp->sc_ps = regs[PS];
367 	regs[SP] = (int)fp;
368 	regs[PC] = (int)u.u_pcb.pcb_sigc;
369 }
370 
371 /*
372  * System call to cleanup state after a signal
373  * has been taken.  Reset signal mask and
374  * stack state from context left by sendsig (above).
375  * Return to previous pc and psl as specified by
376  * context left by sendsig. Check carefully to
377  * make sure that the user has not modified the
378  * psl to gain improper priviledges or to cause
379  * a machine fault.
380  */
381 /* ARGSUSED */
382 sigreturn(p, uap, retval)
383 	struct proc *p;
384 	struct args {
385 		struct sigcontext *sigcntxp;
386 	} *uap;
387 	int *retval;
388 {
389 	register struct sigcontext *scp;
390 	register int *regs = u.u_ar0;
391 
392 	scp = uap->sigcntxp;
393 	if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0)
394 		return (EINVAL);
395 	if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 ||
396 	    (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD))
397 		return (EINVAL);
398 	u.u_onstack = scp->sc_onstack & 01;
399 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
400 	regs[FP] = scp->sc_fp;
401 	regs[SP] = scp->sc_sp;
402 	regs[PC] = scp->sc_pc;
403 	regs[PS] = scp->sc_ps;
404 	return (EJUSTRETURN);
405 }
406 
407 int	waittime = -1;
408 
409 boot(arghowto)
410 	int arghowto;
411 {
412 	register long dummy;		/* r12 is reserved */
413 	register int howto;		/* r11 == how to boot */
414 	register int devtype;		/* r10 == major of root dev */
415 	extern char *panicstr;
416 
417 	howto = arghowto;
418 	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
419 		register struct buf *bp;
420 		int iter, nbusy;
421 
422 		waittime = 0;
423 		(void) splnet();
424 		printf("syncing disks... ");
425 		/*
426 		 * Release vnodes held by texts before update.
427 		 */
428 		if (panicstr == 0)
429 			xumount(NULL);
430 		sync();
431 
432 		for (iter = 0; iter < 20; iter++) {
433 			nbusy = 0;
434 			for (bp = &buf[nbuf]; --bp >= buf; )
435 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
436 					nbusy++;
437 			if (nbusy == 0)
438 				break;
439 			printf("%d ", nbusy);
440 			DELAY(40000 * iter);
441 		}
442 		if (nbusy)
443 			printf("giving up\n");
444 		else
445 			printf("done\n");
446 		DELAY(10000);			/* wait for printf to finish */
447 	}
448 	mtpr(IPL, 0x1f);			/* extreme priority */
449 	devtype = major(rootdev);
450 	*(int *)CPBFLG = howto;
451 	if (howto&RB_HALT) {
452 		printf("halting (in tight loop); hit ~h\n\n");
453 		mtpr(IPL, 0x1f);
454 		for (;;)
455 			;
456 	} else {
457 		if (howto & RB_DUMP) {
458 			doadump();		/* CPBOOT's itsself */
459 			/*NOTREACHED*/
460 		}
461 		tocons(CPBOOT);
462 	}
463 #ifdef lint
464 	dummy = 0; dummy = dummy;
465 	printf("howto %d, devtype %d\n", arghowto, devtype);
466 #endif
467 	for (;;)
468 		asm("halt");
469 	/*NOTREACHED*/
470 }
471 
472 struct	cpdcb_o cpcontrol;
473 
474 /*
475  * Send the given comand ('c') to the console processor.
476  * Assumed to be one of the last things the OS does before
477  *  halting or rebooting.
478  */
479 tocons(c)
480 {
481 	register timeout;
482 
483 	cpcontrol.cp_hdr.cp_unit = CPUNIT;
484 	cpcontrol.cp_hdr.cp_comm =  (char)c;
485 	if (c != CPBOOT)
486 		cpcontrol.cp_hdr.cp_count = 1;	/* Just for sanity */
487 	else {
488 		cpcontrol.cp_hdr.cp_count = 4;
489 		*(int *)cpcontrol.cp_buf = 0;	/* r11 value for reboot */
490 	}
491 	timeout = 100000;				/* Delay loop */
492 	while (timeout-- && (cnlast->cp_unit&CPDONE) == 0)
493 		uncache(&cnlast->cp_unit);
494 	/* give up, force it to listen */
495 	mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&cpcontrol));
496 }
497 
498 #if CLSIZE != 1
499 /*
500  * Invalidate single all pte's in a cluster
501  */
502 tbiscl(v)
503 	unsigned v;
504 {
505 	register caddr_t addr;		/* must be first reg var */
506 	register int i;
507 
508 	addr = ptob(v);
509 	for (i = 0; i < CLSIZE; i++) {
510 		mtpr(TBIS, addr);
511 		addr += NBPG;
512 	}
513 }
514 #endif
515 
516 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
517 int	dumpsize = 0;		/* also for savecore */
518 
519 dumpconf()
520 {
521 	int nblks;
522 
523 	dumpsize = physmem;
524 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
525 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
526 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
527 			dumpsize = btoc(dbtob(nblks - dumplo));
528 		else if (dumplo == 0)
529 			dumplo = nblks - btodb(ctob(physmem));
530 	}
531 	/*
532 	 * Don't dump on the first CLSIZE pages,
533 	 * in case the dump device includes a disk label.
534 	 */
535 	if (dumplo < CLSIZE)
536 		dumplo = CLSIZE;
537 }
538 
539 /*
540  * Doadump comes here after turning off memory management and
541  * getting on the dump stack, either when called above, or by
542  * the auto-restart code.
543  */
544 dumpsys()
545 {
546 
547 	if (dumpdev == NODEV)
548 		return;
549 	/*
550 	 * For dumps during autoconfiguration,
551 	 * if dump device has already configured...
552 	 */
553 	if (dumpsize == 0)
554 		dumpconf();
555 	if (dumplo < 0)
556 		return;
557 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
558 	printf("dump ");
559 	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
560 
561 	case ENXIO:
562 		printf("device bad\n");
563 		break;
564 
565 	case EFAULT:
566 		printf("device not ready\n");
567 		break;
568 
569 	case EINVAL:
570 		printf("area improper\n");
571 		break;
572 
573 	case EIO:
574 		printf("i/o error\n");
575 		break;
576 
577 	default:
578 		printf("succeeded\n");
579 		break;
580 	}
581 	printf("\n\n");
582 	DELAY(1000);
583 	tocons(CPBOOT);
584 }
585 
586 /*
587  * Bus error 'recovery' code.
588  * Print out the buss frame and then give up.
589  * (More information from special registers can be printed here.)
590  */
591 
592 /*
593  * Frame for bus error
594  */
595 struct buserframe {
596 	int	which_bus;		/* primary or secondary */
597 	int	memerreg;		/* memory error register */
598 	int	trp_pc;			/* trapped pc */
599 	int	trp_psl;		/* trapped psl */
600 };
601 
602 char	*mem_errcd[8] = {
603 	"Unknown error code 0",
604 	"Address parity error",		/* APE */
605 	"Data parity error",		/* DPE */
606 	"Data check error",		/* DCE */
607 	"Versabus timeout",		/* VTO */
608 	"Versabus error",		/* VBE */
609 	"Non-existent memory",		/* NEM */
610 	"Unknown error code 7",
611 };
612 
613 buserror(v)
614 	caddr_t v;
615 {
616 	register struct buserframe *busef = (struct buserframe *)v;
617 	register long reg;
618 
619 	printf("bus error, address %x, psl %x\n",
620 	    busef->trp_pc, busef->trp_psl);
621 	reg =  busef->memerreg;
622 	printf("mear %x %s\n",
623 	    ((reg&MEAR)>>16)&0xffff, mem_errcd[reg & ERRCD]);
624 	if (reg&AXE)
625 		printf("adapter external error\n");
626 	printf("error master: %s\n", reg&ERM ? "versabus" : "tahoe");
627 	if (reg&IVV)
628 		printf("illegal interrupt vector from ipl %d\n", (reg>>2)&7);
629 	reg = busef->which_bus;
630 	printf("mcbr %x versabus type %x\n",
631 	    ((reg&MCBR)>>16)&0xffff, reg & 0xffc3);
632 	if ((busef->memerreg&IVV) == 0)
633 		panic("buserror");
634 }
635 
636 microtime(tvp)
637 	register struct timeval *tvp;
638 {
639 	int s = splhigh();
640 
641 	*tvp = time;
642 	tvp->tv_usec += tick;
643 	while (tvp->tv_usec > 1000000) {
644 		tvp->tv_sec++;
645 		tvp->tv_usec -= 1000000;
646 	}
647 	splx(s);
648 }
649 
650 initcpu()
651 {
652 	register struct proc *p;
653 
654 	p = &proc[0];
655 #define	initkey(which, p, index) \
656     which/**/_cache[index] = 1, which/**/_cnt[index] = 1; \
657     p->p_/**/which = index;
658 	initkey(ckey, p, MAXCKEY);
659 	initkey(dkey, p, MAXDKEY);
660 }
661 
662 /*
663  * Clear registers on exec
664  */
665 /* ARGSUSED */
666 setregs(entry, retval)
667 	u_long entry;
668 	int *retval;
669 {
670 
671 #ifdef notdef
672 	/* should pass args to init on the stack */
673 	for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
674 		*rp++ = 0;
675 #endif
676 	u.u_ar0[FP] = 0;	/* bottom of the fp chain */
677 	u.u_ar0[PC] = entry + 2;
678 }
679