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