xref: /original-bsd/sys/pmax/pmax/machdep.c (revision e59fb703)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department and Ralph Campbell.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: machdep.c 1.63 91/04/24$
13  *
14  *	@(#)machdep.c	7.1 (Berkeley) 01/07/92
15  */
16 
17 #include "param.h"
18 #include "systm.h"
19 #include "signalvar.h"
20 #include "kernel.h"
21 #include "map.h"
22 #include "proc.h"
23 #include "buf.h"
24 #include "reboot.h"
25 #include "conf.h"
26 #include "file.h"
27 #include "clist.h"
28 #include "callout.h"
29 #include "malloc.h"
30 #include "mbuf.h"
31 #include "msgbuf.h"
32 #include "user.h"
33 #ifdef SYSVSHM
34 #include "shm.h"
35 #endif
36 
37 #include "vm/vm.h"
38 #include "vm/vm_kern.h"
39 #include "vm/vm_page.h"
40 
41 #include "../include/cpu.h"
42 #include "../include/reg.h"
43 #include "../include/psl.h"
44 #include "../include/machMon.h"
45 #include "clockreg.h"
46 #include "pte.h"
47 
48 #define	MAXMEM	24*1024*CLSIZE	/* XXX - from cmap.h */
49 
50 vm_map_t buffer_map;
51 
52 /*
53  * Declare these as initialized data so we can patch them.
54  */
55 int	nswbuf = 0;
56 #ifdef	NBUF
57 int	nbuf = NBUF;
58 #else
59 int	nbuf = 0;
60 #endif
61 #ifdef	BUFPAGES
62 int	bufpages = BUFPAGES;
63 #else
64 int	bufpages = 0;
65 #endif
66 int	msgbufmapped;		/* set when safe to use msgbuf */
67 int	maxmem;			/* max memory per process */
68 int	physmem = MAXMEM;	/* max supported memory, changes to actual */
69 /*
70  * safepri is a safe priority for sleep to set for a spin-wait
71  * during autoconfiguration or after a panic.
72  */
73 int	safepri = PSL_LOWIPL;
74 
75 struct	user *proc0paddr;
76 struct	proc nullproc;		/* for use by swtch_exit() */
77 
78 /*
79  * Do all the stuff that locore normally does before calling main().
80  * Process arguments passed to us by the prom monitor.
81  * Return the first page address following the system.
82  */
83 mach_init(argc, argv)
84 	int argc;
85 	char *argv[];
86 {
87 	register char *cp;
88 	register int i;
89 	register unsigned firstaddr;
90 	register caddr_t v;
91 	extern char edata[], end[];
92 	extern char MachUTLBMiss[], MachUTLBMissEnd[];
93 	extern char MachException[], MachExceptionEnd[];
94 #ifdef ATTR
95 	extern char *pmap_attributes;
96 #endif
97 
98 	/* clear BSS segment, pages for u, and proc[0] page table */
99 	v = (caddr_t)pmax_round_page(end) + 2 * UPAGES * NBPG;
100 	bzero(edata, v - edata);
101 
102 	/* look at argv[0] and compute bootdev */
103 	makebootdev(argv[0]);
104 
105 	/*
106 	 * Look at arguments passed to us and compute boothowto.
107 	 */
108 #ifdef GENERIC
109 	boothowto = RB_SINGLE | RB_ASKNAME;
110 #else
111 	boothowto = RB_SINGLE | RB_DFLTROOT;
112 #endif
113 	if (argc > 1) {
114 		for (i = 1; i < argc; i++) {
115 			for (cp = argv[i]; *cp; cp++) {
116 				switch (*cp) {
117 				case '-':
118 					continue;
119 
120 				case '0': /* XXX */
121 				case '1': /* XXX */
122 				case '2': /* XXX */
123 				case '3': /* XXX */
124 				case '4': /* XXX */
125 				case '5': /* XXX */
126 				case '6': /* XXX */
127 				    {
128 					extern int sii_debug;
129 
130 					sii_debug = *cp - '0';
131 					break;
132 				    }
133 
134 				case 'a': /* autoboot */
135 					boothowto &= ~RB_SINGLE;
136 					break;
137 
138 				case 'n': /* ask for names */
139 					boothowto |= RB_ASKNAME;
140 					boothowto &= ~RB_DFLTROOT;
141 					break;
142 
143 				case 'N': /* don't ask for names */
144 					boothowto &= ~RB_ASKNAME;
145 					boothowto |= RB_DFLTROOT;
146 				}
147 			}
148 		}
149 	}
150 
151 	/*
152 	 * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
153 	 */
154 	firstaddr = pmax_round_page(end);
155 	curproc->p_addr = proc0paddr = (struct user *)firstaddr;
156 	curproc->p_regs = proc0paddr->u_pcb.pcb_regs;
157 	for (i = 0; i < UPAGES; i++) {
158 		MachTLBWriteIndexed(i,
159 			(UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT),
160 			curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M);
161 		firstaddr += NBPG;
162 	}
163 	MachSetPID(1);
164 
165 	/*
166 	 * init nullproc for swtch_exit().
167 	 * init mapping for u page(s), pm_tlbpid 0
168 	 * This could be used for an idle process.
169 	 */
170 	nullproc.p_regs = ((struct user *)firstaddr)->u_pcb.pcb_regs;
171 	for (i = 0; i < UPAGES; i++) {
172 		nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M;
173 		firstaddr += NBPG;
174 	}
175 
176 	/*
177 	 * Copy down exception vector code.
178 	 */
179 	if (MachUTLBMissEnd - MachUTLBMiss > 0x80)
180 		panic("startup: UTLB code too large");
181 	bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC,
182 		MachUTLBMissEnd - MachUTLBMiss);
183 	bcopy(MachException, (char *)MACH_GEN_EXC_VEC,
184 		MachExceptionEnd - MachException);
185 
186 	/*
187 	 * Clear out the I and D caches.
188 	 */
189 	MachConfigCache();
190 	MachFlushCache();
191 
192 	/*
193 	 * Find out how much memory is available.
194 	 */
195 	physmem = btoc(v - KERNBASE);
196 	cp = (char *)(MACH_UNCACHED_MEMORY_ADDR + (physmem << PGSHIFT));
197 	while (cp < (char *)MACH_UNCACHED_FRAME_BUFFER_ADDR) {
198 		if (badaddr(cp, 4))
199 			break;
200 		cp += NBPG;
201 		physmem++;
202 	}
203 	maxmem = physmem + btoc(KERNBASE);
204 
205 	/*
206 	 * Initialize error message buffer (at end of core).
207 	 */
208 	maxmem -= btoc(sizeof (struct msgbuf));
209 	msgbufp = (struct msgbuf *)(maxmem << PGSHIFT);
210 	msgbufmapped = 1;
211 
212 	/*
213 	 * Allocate space for system data structures.
214 	 * The first available real memory address is in "firstaddr".
215 	 * The first available kernel virtual address is in "v".
216 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
217 	 * As pages of memory are allocated and cleared,
218 	 * "firstaddr" is incremented.
219 	 */
220 	/*
221 	 * These data structures are allocated here instead of cpu_startup()
222 	 * because physical memory is directly addressable. We don't have
223 	 * to map these into virtual address space.
224 	 */
225 	firstaddr = (unsigned)v;
226 
227 #define	valloc(name, type, num) \
228 	    (name) = (type *)v; v = (caddr_t)((name)+(num))
229 #define	valloclim(name, type, num, lim) \
230 	    (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
231 	valloc(cfree, struct cblock, nclist);
232 	valloc(callout, struct callout, ncallout);
233 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
234 #ifdef SYSVSHM
235 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
236 #endif
237 #ifdef ATTR
238 	/* this is allocated here just to save a few bytes */
239 	valloc(pmap_attributes, char, physmem);
240 #endif
241 
242 	/*
243 	 * Determine how many buffers to allocate.
244 	 * We allocate more buffer space than the BSD standard of
245 	 * using 10% of memory for the first 2 Meg, 5% of remaining.
246 	 * We just allocate a flat 10%.  Insure a minimum of 16 buffers.
247 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
248 	 */
249 	if (bufpages == 0)
250 		bufpages = physmem / 10 / CLSIZE;
251 	if (nbuf == 0) {
252 		nbuf = bufpages;
253 		if (nbuf < 16)
254 			nbuf = 16;
255 	}
256 	if (nswbuf == 0) {
257 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
258 		if (nswbuf > 256)
259 			nswbuf = 256;		/* sanity */
260 	}
261 	valloc(swbuf, struct buf, nswbuf);
262 	valloc(buf, struct buf, nbuf);
263 
264 	/*
265 	 * Clear allocated memory.
266 	 */
267 	v = (caddr_t)pmax_round_page(v);
268 	bzero((caddr_t)firstaddr, (unsigned)v - firstaddr);
269 
270 	/*
271 	 * Initialize the virtual memory system.
272 	 */
273 	pmap_bootstrap((vm_offset_t)v);
274 }
275 
276 /*
277  * Console initialization: called early on from main,
278  * before vm init or startup.  Do enough configuration
279  * to choose and initialize a console.
280  */
281 consinit()
282 {
283 
284 #include "pm.h"
285 #if NPM > 0
286 	/*
287 	 * Initialize the console before we print anything out.
288 	 */
289 	pminit();
290 #endif
291 }
292 
293 /*
294  * cpu_startup: allocate memory for variable-sized tables,
295  * initialize cpu, and do autoconfiguration.
296  */
297 cpu_startup()
298 {
299 	register unsigned i;
300 	register caddr_t v, firstaddr;
301 	int base, residual;
302 	extern long Usrptsize;
303 	extern struct map *useriomap;
304 #ifdef DEBUG
305 	extern int pmapdebug;
306 	int opmapdebug = pmapdebug;
307 #endif
308 	vm_offset_t minaddr, maxaddr;
309 	vm_size_t size;
310 
311 #ifdef DEBUG
312 	pmapdebug = 0;
313 #endif
314 
315 	/*
316 	 * Good {morning,afternoon,evening,night}.
317 	 */
318 	printf(version);
319 	printf("real mem = %d\n", ctob(physmem));
320 
321 	/*
322 	 * Allocate virtual address space for file I/O buffers.
323 	 * Note they are different than the array of headers, 'buf',
324 	 * and usually occupy more virtual memory than physical.
325 	 */
326 	size = MAXBSIZE * nbuf;
327 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers,
328 				   &maxaddr, size, FALSE);
329 	minaddr = (vm_offset_t)buffers;
330 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
331 			&minaddr, size, FALSE) != KERN_SUCCESS)
332 		panic("startup: cannot allocate buffers");
333 	base = bufpages / nbuf;
334 	residual = bufpages % nbuf;
335 	for (i = 0; i < nbuf; i++) {
336 		vm_size_t curbufsize;
337 		vm_offset_t curbuf;
338 
339 		/*
340 		 * First <residual> buffers get (base+1) physical pages
341 		 * allocated for them.  The rest get (base) physical pages.
342 		 *
343 		 * The rest of each buffer occupies virtual space,
344 		 * but has no physical memory allocated for it.
345 		 */
346 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
347 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
348 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
349 		vm_map_simplify(buffer_map, curbuf);
350 	}
351 	/*
352 	 * Allocate a submap for exec arguments.  This map effectively
353 	 * limits the number of processes exec'ing at any time.
354 	 */
355 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
356 				 16*NCARGS, TRUE);
357 	/*
358 	 * Allocate a submap for physio
359 	 */
360 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
361 				 VM_PHYS_SIZE, TRUE);
362 
363 	/*
364 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
365 	 * we use the more space efficient malloc in place of kmem_alloc.
366 	 */
367 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
368 				   M_MBUF, M_NOWAIT);
369 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
370 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr,
371 			       VM_MBUF_SIZE, FALSE);
372 	/*
373 	 * Initialize callouts
374 	 */
375 	callfree = callout;
376 	for (i = 1; i < ncallout; i++)
377 		callout[i-1].c_next = &callout[i];
378 
379 #ifdef DEBUG
380 	pmapdebug = opmapdebug;
381 #endif
382 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
383 	printf("using %d buffers containing %d bytes of memory\n",
384 		nbuf, bufpages * CLBYTES);
385 	/*
386 	 * Set up CPU-specific registers, cache, etc.
387 	 */
388 	initcpu();
389 
390 	/*
391 	 * Set up buffers, so they can be used to read disk labels.
392 	 */
393 	bufinit();
394 
395 	/*
396 	 * Configure the system.
397 	 */
398 	configure();
399 }
400 
401 /*
402  * Set registers on exec.
403  * Clear all registers except sp, pc.
404  */
405 setregs(p, entry, retval)
406 	register struct proc *p;
407 	u_long entry;
408 	int retval[2];
409 {
410 	int sp = p->p_regs[SP];
411 
412 	bzero((caddr_t)p->p_regs, (FSR + 1) * sizeof(int));
413 	p->p_regs[SP] = sp;
414 	p->p_regs[PC] = entry;
415 	p->p_regs[PS] = PSL_USERSET;
416 	p->p_md.md_flags & ~MDP_FPUSED;
417 }
418 
419 /*
420  * WARNING: code in locore.s assumes the layout shown for sf_signum
421  * thru sf_handler so... don't screw with them!
422  */
423 struct sigframe {
424 	int	sf_signum;		/* signo for handler */
425 	int	sf_code;		/* additional info for handler */
426 	struct	sigcontext *sf_scp;	/* context ptr for handler */
427 	sig_t	sf_handler;		/* handler addr for u_sigc */
428 };
429 
430 #ifdef DEBUG
431 int sigdebug = 0;
432 int sigpid = 0;
433 #define SDB_FOLLOW	0x01
434 #define SDB_KSTACK	0x02
435 #define SDB_FPSTATE	0x04
436 #endif
437 
438 /*
439  * Send an interrupt to process.
440  */
441 void
442 sendsig(catcher, sig, mask, code)
443 	sig_t catcher;
444 	int sig, mask;
445 	unsigned code;
446 {
447 	register struct proc *p = curproc;
448 	register struct sigframe *fp;
449 	register struct sigacts *ps = p->p_sigacts;
450 	register struct sigcontext *scp;
451 	register int *regs;
452 	int oonstack, fsize;
453 	struct sigcontext ksc;
454 
455 	regs = p->p_regs;
456 	oonstack = ps->ps_onstack;
457 	/*
458 	 * Allocate and validate space for the signal handler
459 	 * context. Note that if the stack is in data space, the
460 	 * call to grow() is a nop, and the copyout()
461 	 * will fail if the process has not already allocated
462 	 * the space with a `brk'.
463 	 */
464 	if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) {
465 		scp = (struct sigcontext *)ps->ps_sigsp - 1;
466 		ps->ps_onstack = 1;
467 	} else
468 		scp = (struct sigcontext *)regs[SP] - 1;
469 	fp = (struct sigframe *)scp - 1;
470 	if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
471 		(void)grow(p, (unsigned)fp);
472 	/*
473 	 * Build the signal context to be used by sigreturn.
474 	 */
475 	ksc.sc_onstack = oonstack;
476 	ksc.sc_mask = mask;
477 	ksc.sc_pc = regs[PC];
478 	ksc.sc_regs[ZERO] = 0xACEDBADE;		/* magic number */
479 	bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
480 		sizeof(ksc.sc_regs) - sizeof(int));
481 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
482 	if (ksc.sc_fpused) {
483 		extern struct proc *machFPCurProcPtr;
484 
485 		/* if FPU has current state, save it first */
486 		if (p == machFPCurProcPtr) {
487 			MachSaveCurFPState(p);
488 			machFPCurProcPtr = (struct proc *)0;
489 		}
490 		bcopy((caddr_t)&p->p_regs[F0], (caddr_t)ksc.sc_fpregs,
491 			sizeof(ksc.sc_fpregs));
492 	}
493 	if (copyout((caddr_t)&ksc, (caddr_t)scp, sizeof(ksc))) {
494 		/*
495 		 * Process has trashed its stack; give it an illegal
496 		 * instruction to halt it in its tracks.
497 		 */
498 		SIGACTION(p, SIGILL) = SIG_DFL;
499 		sig = sigmask(SIGILL);
500 		p->p_sigignore &= ~sig;
501 		p->p_sigcatch &= ~sig;
502 		p->p_sigmask &= ~sig;
503 		psignal(p, SIGILL);
504 		return;
505 	}
506 	/*
507 	 * Build the argument list for the signal handler.
508 	 */
509 	regs[A0] = sig;
510 	regs[A1] = code;
511 	regs[A2] = (int)scp;
512 	regs[A3] = (int)catcher;
513 
514 	regs[PC] = (int)catcher;
515 	regs[SP] = (int)fp;
516 	regs[RA] = KERNBASE;	/* this causes a trap which we interpret as
517 				 * meaning "do a sigreturn". */
518 #ifdef DEBUG
519 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
520 		printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
521 		       p->p_pid, sig, &oonstack, fp, fp->sf_scp);
522 #endif
523 }
524 
525 /*
526  * System call to cleanup state after a signal
527  * has been taken.  Reset signal mask and
528  * stack state from context left by sendsig (above).
529  * Return to previous pc and psl as specified by
530  * context left by sendsig. Check carefully to
531  * make sure that the user has not modified the
532  * psl to gain improper priviledges or to cause
533  * a machine fault.
534  */
535 /* ARGSUSED */
536 sigreturn(p, uap, retval)
537 	struct proc *p;
538 	struct args {
539 		struct sigcontext *sigcntxp;
540 	} *uap;
541 	int *retval;
542 {
543 	register struct sigcontext *scp;
544 	register int *regs;
545 	struct sigcontext ksc;
546 	int error;
547 
548 	register struct frame *frame;
549 	register int rf;
550 	struct sigcontext tsigc;
551 	int flags;
552 
553 	scp = uap->sigcntxp;
554 #ifdef DEBUG
555 	if (sigdebug & SDB_FOLLOW)
556 		printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
557 #endif
558 	regs = p->p_regs;
559 	/*
560 	 * Test and fetch the context structure.
561 	 * We grab it all at once for speed.
562 	 */
563 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
564 	if (error != 0 || ksc.sc_regs[ZERO] != 0xACEDBADE ||
565 	    (unsigned)ksc.sc_regs[SP] < (unsigned)regs[SP]) {
566 #ifdef DEBUG
567 		if (!(sigdebug & SDB_FOLLOW))
568 			printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
569 		printf("  old sp %x ra %x pc %x\n",
570 			regs[SP], regs[RA], regs[PC]);
571 		printf("  new sp %x ra %x pc %x err %d z %x\n",
572 			ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
573 			error, ksc.sc_regs[ZERO]);
574 #endif
575 		if (regs[PC] == KERNBASE) {
576 			int sig;
577 
578 			/*
579 			 * Process has trashed its stack; give it an illegal
580 			 * instruction to halt it in its tracks.
581 			 */
582 			SIGACTION(p, SIGILL) = SIG_DFL;
583 			sig = sigmask(SIGILL);
584 			p->p_sigignore &= ~sig;
585 			p->p_sigcatch &= ~sig;
586 			p->p_sigmask &= ~sig;
587 			psignal(p, SIGILL);
588 		}
589 		return (EINVAL);
590 	}
591 	/*
592 	 * Restore the user supplied information
593 	 */
594 	p->p_sigacts->ps_onstack = scp->sc_onstack & 01;
595 	p->p_sigmask = scp->sc_mask &~ sigcantmask;
596 	regs[PC] = ksc.sc_pc;
597 	bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)&regs[1],
598 		sizeof(ksc.sc_regs) - sizeof(int));
599 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
600 	if (ksc.sc_fpused)
601 		bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_regs[F0],
602 			sizeof(ksc.sc_fpregs));
603 	return (EJUSTRETURN);
604 }
605 
606 int	waittime = -1;
607 
608 boot(howto)
609 	register int howto;
610 {
611 
612 	trapDump("boot"); /* XXX */
613 	/* take a snap shot before clobbering any registers */
614 	if (curproc)
615 		savectx(curproc->p_addr, 0);
616 
617 	howto |= RB_HALT; /* XXX */
618 	boothowto = howto;
619 	if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
620 		register struct buf *bp;
621 		int iter, nbusy;
622 
623 		waittime = 0;
624 		(void) spl0();
625 		printf("syncing disks... ");
626 		/*
627 		 * Release vnodes held by texts before sync.
628 		 */
629 		if (panicstr == 0)
630 			vnode_pager_umount(NULL);
631 #ifdef notdef
632 #include "fd.h"
633 #if NFD > 0
634 		fdshutdown();
635 #endif
636 #endif
637 		sync(&proc0, (void *)NULL, (int *)NULL);
638 
639 		for (iter = 0; iter < 20; iter++) {
640 			nbusy = 0;
641 			for (bp = &buf[nbuf]; --bp >= buf; )
642 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
643 					nbusy++;
644 			if (nbusy == 0)
645 				break;
646 			printf("%d ", nbusy);
647 			DELAY(40000 * iter);
648 		}
649 		if (nbusy)
650 			printf("giving up\n");
651 		else
652 			printf("done\n");
653 		/*
654 		 * If we've been adjusting the clock, the todr
655 		 * will be out of synch; adjust it now.
656 		 */
657 		resettodr();
658 	}
659 	(void) splhigh();		/* extreme priority */
660 	if (howto & RB_HALT) {
661 #ifdef DEBUG
662 		void (*f)() = (void (*)())MACH_MON_RESTART;
663 #else
664 		void (*f)() = (void (*)())MACH_MON_REINIT;
665 #endif
666 
667 		(*f)();	/* jump back to prom monitor */
668 	} else {
669 		void (*f)() = (void (*)())MACH_MON_AUTOBOOT;
670 
671 		if (howto & RB_DUMP)
672 			dumpsys();
673 		(*f)();	/* jump back to prom monitor and do 'auto' cmd */
674 		/*NOTREACHED*/
675 	}
676 	/*NOTREACHED*/
677 }
678 
679 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
680 int	dumpsize = 0;		/* also for savecore */
681 long	dumplo = 0;
682 
683 dumpconf()
684 {
685 	int nblks;
686 
687 	dumpsize = physmem;
688 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
689 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
690 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
691 			dumpsize = btoc(dbtob(nblks - dumplo));
692 		else if (dumplo == 0)
693 			dumplo = nblks - btodb(ctob(physmem));
694 	}
695 	/*
696 	 * Don't dump on the first CLBYTES (why CLBYTES?)
697 	 * in case the dump device includes a disk label.
698 	 */
699 	if (dumplo < btodb(CLBYTES))
700 		dumplo = btodb(CLBYTES);
701 }
702 
703 /*
704  * Doadump comes here after turning off memory management and
705  * getting on the dump stack, either when called above, or by
706  * the auto-restart code.
707  */
708 dumpsys()
709 {
710 	int error;
711 
712 	msgbufmapped = 0;
713 	if (dumpdev == NODEV)
714 		return;
715 	/*
716 	 * For dumps during autoconfiguration,
717 	 * if dump device has already configured...
718 	 */
719 	if (dumpsize == 0)
720 		dumpconf();
721 	if (dumplo < 0)
722 		return;
723 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
724 	printf("dump ");
725 	switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
726 
727 	case ENXIO:
728 		printf("device bad\n");
729 		break;
730 
731 	case EFAULT:
732 		printf("device not ready\n");
733 		break;
734 
735 	case EINVAL:
736 		printf("area improper\n");
737 		break;
738 
739 	case EIO:
740 		printf("i/o error\n");
741 		break;
742 
743 	default:
744 		printf("error %d\n", error);
745 		break;
746 
747 	case 0:
748 		printf("succeeded\n");
749 	}
750 }
751 
752 /*
753  * Return the best possible estimate of the time in the timeval
754  * to which tvp points.  Unfortunately, we can't read the hardware registers.
755  * We guarantee that the time will be greater than the value obtained by a
756  * previous call.
757  */
758 microtime(tvp)
759 	register struct timeval *tvp;
760 {
761 	int s = splclock();
762 	static struct timeval lasttime;
763 
764 	*tvp = time;
765 #ifdef notdef
766 	tvp->tv_usec += clkread();
767 	while (tvp->tv_usec > 1000000) {
768 		tvp->tv_sec++;
769 		tvp->tv_usec -= 1000000;
770 	}
771 #endif
772 	if (tvp->tv_sec == lasttime.tv_sec &&
773 	    tvp->tv_usec <= lasttime.tv_usec &&
774 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
775 		tvp->tv_sec++;
776 		tvp->tv_usec -= 1000000;
777 	}
778 	lasttime = *tvp;
779 	splx(s);
780 }
781 
782 initcpu()
783 {
784 	register volatile struct chiptime *c;
785 	int i;
786 
787 	/* disable clock interrupts (until startrtclock()) */
788 	c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
789 	c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
790 	i = c->regc;
791 	spl0();		/* safe to turn interrupts on now */
792 	return (i);
793 }
794