xref: /original-bsd/sys/sparc/sparc/machdep.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)machdep.c	8.1 (Berkeley) 06/11/93
17  *
18  * from: $Header: machdep.c,v 1.41 93/05/27 04:39:05 torek Exp $
19  */
20 
21 #include <sys/param.h>
22 #include <sys/proc.h>
23 #include <sys/user.h>
24 #include <sys/map.h>
25 #include <sys/buf.h>
26 #include <sys/device.h>
27 #include <sys/reboot.h>
28 #include <sys/systm.h>
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/clist.h>
32 #include <sys/callout.h>
33 #include <sys/malloc.h>
34 #include <sys/mbuf.h>
35 #include <sys/mount.h>
36 #include <sys/msgbuf.h>
37 #ifdef SYSVSHM
38 #include <sys/shm.h>
39 #endif
40 #include <sys/exec.h>
41 #include <sys/sysctl.h>
42 
43 #include <machine/autoconf.h>
44 #include <machine/frame.h>
45 #include <machine/cpu.h>
46 
47 #include <vm/vm_kern.h>
48 #include <vm/vm_page.h>
49 
50 #include <sparc/sparc/asm.h>
51 #include <sparc/sparc/cache.h>
52 #include <sparc/sparc/vaddrs.h>
53 
54 vm_map_t buffer_map;
55 extern vm_offset_t avail_end;
56 
57 /*
58  * Declare these as initialized data so we can patch them.
59  */
60 int	nswbuf = 0;
61 #ifdef	NBUF
62 int	nbuf = NBUF;
63 #else
64 int	nbuf = 0;
65 #endif
66 #ifdef	BUFPAGES
67 int	bufpages = BUFPAGES;
68 #else
69 int	bufpages = 0;
70 #endif
71 
72 int	physmem;
73 
74 extern struct msgbuf msgbuf;
75 struct	msgbuf *msgbufp = &msgbuf;
76 int	msgbufmapped = 1;	/* message buffer is always mapped */
77 
78 /*
79  * safepri is a safe priority for sleep to set for a spin-wait
80  * during autoconfiguration or after a panic.
81  */
82 int   safepri = 0;
83 
84 caddr_t allocsys();
85 
86 /*
87  * Machine-dependent startup code
88  */
89 cpu_startup()
90 {
91 	register unsigned i;
92 	register caddr_t v;
93 	register int sz;
94 	int base, residual;
95 #ifdef DEBUG
96 	extern int pmapdebug;
97 	int opmapdebug = pmapdebug;
98 #endif
99 	vm_offset_t minaddr, maxaddr;
100 	vm_size_t size;
101 
102 #ifdef DEBUG
103 	pmapdebug = 0;
104 #endif
105 
106 	/*
107 	 * Good {morning,afternoon,evening,night}.
108 	 */
109 	printf(version);
110 	/*identifycpu();*/
111 	physmem = btoc(avail_end);
112 	printf("real mem = %d\n", avail_end);
113 
114 	/*
115 	 * Find out how much space we need, allocate it,
116 	 * and then give everything true virtual addresses.
117 	 */
118 	sz = (int)allocsys((caddr_t)0);
119 	if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
120 		panic("startup: no room for tables");
121 	if (allocsys(v) - v != sz)
122 		panic("startup: table size inconsistency");
123 
124 	/*
125 	 * Now allocate buffers proper.  They are different than the above
126 	 * in that they usually occupy more virtual memory than physical.
127 	 */
128 	size = MAXBSIZE * nbuf;
129 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
130 	    &maxaddr, size, FALSE);
131 	minaddr = (vm_offset_t)buffers;
132 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
133 			&minaddr, size, FALSE) != KERN_SUCCESS)
134 		panic("startup: cannot allocate buffers");
135 	base = bufpages / nbuf;
136 	residual = bufpages % nbuf;
137 	for (i = 0; i < nbuf; i++) {
138 		vm_size_t curbufsize;
139 		vm_offset_t curbuf;
140 
141 		/*
142 		 * First <residual> buffers get (base+1) physical pages
143 		 * allocated for them.  The rest get (base) physical pages.
144 		 *
145 		 * The rest of each buffer occupies virtual space,
146 		 * but has no physical memory allocated for it.
147 		 */
148 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
149 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
150 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
151 		vm_map_simplify(buffer_map, curbuf);
152 	}
153 	/*
154 	 * Allocate a submap for exec arguments.  This map effectively
155 	 * limits the number of processes exec'ing at any time.
156 	 */
157 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
158 	    16*NCARGS, TRUE);
159 	/*
160 	 * Allocate a map for physio.  Others use a submap of the kernel
161 	 * map, but we want one completely separate, even though it uses
162 	 * the same pmap.
163 	 */
164 	phys_map = vm_map_create(kernel_pmap, DVMA_BASE, DVMA_END, 1);
165 	if (phys_map == NULL)
166 		panic("unable to create DVMA map");
167 
168 	/*
169 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
170 	 * we use the more space efficient malloc in place of kmem_alloc.
171 	 */
172 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
173 				   M_MBUF, M_NOWAIT);
174 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
175 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
176 			       VM_MBUF_SIZE, FALSE);
177 	/*
178 	 * Initialize callouts
179 	 */
180 	callfree = callout;
181 	for (i = 1; i < ncallout; i++)
182 		callout[i-1].c_next = &callout[i];
183 	callout[i-1].c_next = NULL;
184 
185 #ifdef DEBUG
186 	pmapdebug = opmapdebug;
187 #endif
188 	printf("avail mem = %d\n", ptoa(cnt.v_free_count));
189 	printf("using %d buffers containing %d bytes of memory\n",
190 		nbuf, bufpages * CLBYTES);
191 
192 	/*
193 	 * Set up buffers, so they can be used to read disk labels.
194 	 */
195 	bufinit();
196 
197 	/*
198 	 * Configure the system.
199 	 */
200 	configure();
201 
202 	/*
203 	 * Turn on the cache (do after configuration due to a bug in
204 	 * some versions of the SPARC chips -- this info from Gilmore).
205 	 */
206 	cache_enable();
207 }
208 
209 /*
210  * Allocate space for system data structures.  We are given
211  * a starting virtual address and we return a final virtual
212  * address; along the way we set each data structure pointer.
213  *
214  * You call allocsys() with 0 to find out how much space we want,
215  * allocate that much and fill it with zeroes, and then call
216  * allocsys() again with the correct base virtual address.
217  */
218 caddr_t
219 allocsys(v)
220 	register caddr_t v;
221 {
222 
223 #define	valloc(name, type, num) \
224 	    v = (caddr_t)(((name) = (type *)v) + (num))
225 	valloc(cfree, struct cblock, nclist);
226 	valloc(callout, struct callout, ncallout);
227 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
228 #ifdef SYSVSHM
229 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
230 #endif
231 
232 	/*
233 	 * Determine how many buffers to allocate (enough to
234 	 * hold 5% of total physical memory, but at least 16).
235 	 * Allocate 1/2 as many swap buffer headers as file i/o buffers.
236 	 */
237 	if (bufpages == 0)
238 		bufpages = (physmem / 20) / CLSIZE;
239 	if (nbuf == 0) {
240 		nbuf = bufpages;
241 		if (nbuf < 16)
242 			nbuf = 16;
243 	}
244 	if (nswbuf == 0) {
245 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
246 		if (nswbuf > 256)
247 			nswbuf = 256;		/* sanity */
248 	}
249 	valloc(swbuf, struct buf, nswbuf);
250 	valloc(buf, struct buf, nbuf);
251 	return (v);
252 }
253 
254 /*
255  * Set up registers on exec.
256  *
257  * XXX this entire mess must be fixed
258  */
259 /* ARGSUSED */
260 setregs(p, entry, retval)
261 	register struct proc *p;
262 	u_long entry;
263 	int retval[2];
264 {
265 	register struct trapframe *tf = p->p_md.md_tf;
266 	register struct fpstate *fs;
267 	register int psr, sp;
268 
269 	/*
270 	 * The syscall will ``return'' to npc or %g7 or %g2; set them all.
271 	 * Set the rest of the registers to 0 except for %o6 (stack pointer,
272 	 * built in exec()) and psr (retain CWP and PSR_S bits).
273 	 */
274 	psr = tf->tf_psr & (PSR_S | PSR_CWP);
275 	sp = tf->tf_out[6];
276 	if ((fs = p->p_md.md_fpstate) != NULL) {
277 		/*
278 		 * We hold an FPU state.  If we own *the* FPU chip state
279 		 * we must get rid of it, and the only way to do that is
280 		 * to save it.  In any case, get rid of our FPU state.
281 		 */
282 		if (p == fpproc) {
283 			savefpstate(fs);
284 			fpproc = NULL;
285 		}
286 		free((void *)fs, M_SUBPROC);
287 		p->p_md.md_fpstate = NULL;
288 	}
289 	bzero((caddr_t)tf, sizeof *tf);
290 	tf->tf_psr = psr;
291 	tf->tf_global[2] = tf->tf_global[7] = tf->tf_npc = entry & ~3;
292 	tf->tf_out[6] = sp;
293 	retval[1] = 0;
294 }
295 
296 #ifdef DEBUG
297 int sigdebug = 0;
298 int sigpid = 0;
299 #define SDB_FOLLOW	0x01
300 #define SDB_KSTACK	0x02
301 #define SDB_FPSTATE	0x04
302 #endif
303 
304 struct sigframe {
305 	int	sf_signo;		/* signal number */
306 	int	sf_code;		/* code */
307 #ifdef COMPAT_SUNOS
308 	struct	sigcontext *sf_scp;	/* points to user addr of sigcontext */
309 #else
310 	int	sf_xxx;			/* placeholder */
311 #endif
312 	int	sf_addr;		/* SunOS compat, always 0 for now */
313 	struct	sigcontext sf_sc;	/* actual sigcontext */
314 };
315 
316 /*
317  * machine dependent system variables.
318  */
319 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
320 	int *name;
321 	u_int namelen;
322 	void *oldp;
323 	size_t *oldlenp;
324 	void *newp;
325 	size_t newlen;
326 	struct proc *p;
327 {
328 
329 	/* all sysctl names are this level are terminal */
330 	if (namelen != 1)
331 		return (ENOTDIR);	/* overloaded */
332 
333 	switch (name[0]) {
334 	default:
335 		return (EOPNOTSUPP);
336 	}
337 	/* NOTREACHED */
338 }
339 
340 /*
341  * Send an interrupt to process.
342  */
343 void
344 sendsig(catcher, sig, mask, code)
345 	sig_t catcher;
346 	int sig, mask;
347 	unsigned code;
348 {
349 	register struct proc *p = curproc;
350 	register struct sigacts *psp = p->p_sigacts;
351 	register struct sigframe *fp;
352 	register struct trapframe *tf;
353 	register int addr, oonstack, oldsp, newsp;
354 	struct sigframe sf;
355 	extern char sigcode[], esigcode[];
356 #define	szsigcode	(esigcode - sigcode)
357 
358 	tf = p->p_md.md_tf;
359 	oldsp = tf->tf_out[6];
360 	oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
361 	/*
362 	 * Compute new user stack addresses, subtract off
363 	 * one signal frame, and align.
364 	 */
365 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
366 	    (psp->ps_sigonstack & sigmask(sig))) {
367 		fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
368 					 psp->ps_sigstk.ss_size);
369 		psp->ps_sigstk.ss_flags |= SA_ONSTACK;
370 	} else
371 		fp = (struct sigframe *)oldsp;
372 	fp = (struct sigframe *)((int)(fp - 1) & ~7);
373 
374 #ifdef DEBUG
375 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
376 		printf("sendsig: %s[%d] sig %d newusp %x scp %x\n",
377 		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc);
378 #endif
379 	/*
380 	 * Now set up the signal frame.  We build it in kernel space
381 	 * and then copy it out.  We probably ought to just build it
382 	 * directly in user space....
383 	 */
384 	sf.sf_signo = sig;
385 	sf.sf_code = code;
386 #ifdef COMPAT_SUNOS
387 	sf.sf_scp = &fp->sf_sc;
388 #endif
389 	sf.sf_addr = 0;			/* XXX */
390 
391 	/*
392 	 * Build the signal context to be used by sigreturn.
393 	 */
394 	sf.sf_sc.sc_onstack = oonstack;
395 	sf.sf_sc.sc_mask = mask;
396 	sf.sf_sc.sc_sp = oldsp;
397 	sf.sf_sc.sc_pc = tf->tf_pc;
398 	sf.sf_sc.sc_npc = tf->tf_npc;
399 	sf.sf_sc.sc_psr = tf->tf_psr;
400 	sf.sf_sc.sc_g1 = tf->tf_global[1];
401 	sf.sf_sc.sc_o0 = tf->tf_out[0];
402 
403 	/*
404 	 * Put the stack in a consistent state before we whack away
405 	 * at it.  Note that write_user_windows may just dump the
406 	 * registers into the pcb; we need them in the process's memory.
407 	 * We also need to make sure that when we start the signal handler,
408 	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
409 	 * joins seamlessly with the frame it was in when the signal occurred,
410 	 * so that the debugger and _longjmp code can back up through it.
411 	 */
412 	newsp = (int)fp - sizeof(struct rwindow);
413 	write_user_windows();
414 	if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
415 	    suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)) {
416 		/*
417 		 * Process has trashed its stack; give it an illegal
418 		 * instruction to halt it in its tracks.
419 		 */
420 #ifdef DEBUG
421 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
422 			printf("sendsig: window save or copyout error\n");
423 #endif
424 		sigexit(p, SIGILL);
425 		/* NOTREACHED */
426 	}
427 #ifdef DEBUG
428 	if (sigdebug & SDB_FOLLOW)
429 		printf("sendsig: %s[%d] sig %d scp %x\n",
430 		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
431 #endif
432 	/*
433 	 * Arrange to continue execution at the code copied out in exec().
434 	 * It needs the function to call in %g1, and a new stack pointer.
435 	 */
436 #ifdef COMPAT_SUNOS
437 	if (psp->ps_usertramp & sigmask(sig)) {
438 		addr = (int)catcher;	/* user does his own trampolining */
439 	} else
440 #endif
441 	{
442 		addr = USRSTACK - sizeof(struct ps_strings) - szsigcode;
443 		tf->tf_global[1] = (int)catcher;
444 	}
445 	tf->tf_pc = addr;
446 	tf->tf_npc = addr + 4;
447 	tf->tf_out[6] = newsp;
448 #ifdef DEBUG
449 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
450 		printf("sendsig: about to return to catcher\n");
451 #endif
452 }
453 
454 /*
455  * System call to cleanup state after a signal
456  * has been taken.  Reset signal mask and
457  * stack state from context left by sendsig (above),
458  * and return to the given trap frame (if there is one).
459  * Check carefully to make sure that the user has not
460  * modified the state to gain improper privileges or to cause
461  * a machine fault.
462  */
463 /* ARGSUSED */
464 struct sigreturn_args {
465 	struct sigcontext *scp;
466 };
467 sigreturn(p, uap, retval)
468 	register struct proc *p;
469 	struct sigreturn_args *uap;
470 	int *retval;
471 {
472 	register struct sigcontext *scp;
473 	register struct trapframe *tf;
474 
475 	/* First ensure consistent stack state (see sendsig). */
476 	write_user_windows();
477 	if (rwindow_save(p))
478 		sigexit(p, SIGILL);
479 #ifdef DEBUG
480 	if (sigdebug & SDB_FOLLOW)
481 		printf("sigreturn: %s[%d], scp %x\n",
482 		    p->p_comm, p->p_pid, uap->scp);
483 #endif
484 	scp = uap->scp;
485 	if ((int)scp & 3 || useracc((caddr_t)scp, sizeof *scp, B_WRITE) == 0)
486 		return (EINVAL);
487 	tf = p->p_md.md_tf;
488 	/*
489 	 * Only the icc bits in the psr are used, so it need not be
490 	 * verified.  pc and npc must be multiples of 4.  This is all
491 	 * that is required; if it holds, just do it.
492 	 */
493 	if (((scp->sc_pc | scp->sc_npc) & 3) != 0)
494 		return (EINVAL);
495 	/* take only psr ICC field */
496 	tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (scp->sc_psr & PSR_ICC);
497 	tf->tf_pc = scp->sc_pc;
498 	tf->tf_npc = scp->sc_npc;
499 	tf->tf_global[1] = scp->sc_g1;
500 	tf->tf_out[0] = scp->sc_o0;
501 	tf->tf_out[6] = scp->sc_sp;
502 	if (scp->sc_onstack & 1)
503 		p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
504 	else
505 		p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
506 	p->p_sigmask = scp->sc_mask & ~sigcantmask;
507 	return (EJUSTRETURN);
508 }
509 
510 int	waittime = -1;
511 
512 boot(howto)
513 	register int howto;
514 {
515 	int i;
516 	static char str[4];	/* room for "-sd\0" */
517 	extern volatile void romhalt(void);
518 	extern volatile void romboot(char *);
519 
520 	fb_unblank();
521 	boothowto = howto;
522 	if ((howto & RB_NOSYNC) == 0 && waittime < 0 && rootfs) {
523 		register struct buf *bp;
524 		int iter, nbusy;
525 #if 1
526 		extern struct proc proc0;
527 
528 		/* protect against curproc->p_stats.foo refs in sync()   XXX */
529 		if (curproc == NULL)
530 			curproc = &proc0;
531 #endif
532 		waittime = 0;
533 		(void) spl0();
534 		printf("syncing disks... ");
535 		/*
536 		 * Release vnodes held by texts before sync.
537 		 */
538 		if (panicstr == 0)
539 			vnode_pager_umount((struct mount *)NULL);
540 		sync(&proc0, (void *)NULL, (int *)NULL);
541 
542 		for (iter = 0; iter < 20; iter++) {
543 			nbusy = 0;
544 			for (bp = &buf[nbuf]; --bp >= buf; )
545 				if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
546 					nbusy++;
547 			if (nbusy == 0)
548 				break;
549 			printf("%d ", nbusy);
550 			DELAY(40000 * iter);
551 		}
552 		if (nbusy)
553 			printf("giving up\n");
554 		else
555 			printf("done\n");
556 		/*
557 		 * If we've been adjusting the clock, the todr
558 		 * will be out of synch; adjust it now.
559 		 */
560 		resettodr();
561 	}
562 	(void) splhigh();		/* ??? */
563 	if (howto & RB_HALT) {
564 		printf("halted\n\n");
565 		romhalt();
566 	}
567 	if (howto & RB_DUMP)
568 		dumpsys();
569 	printf("rebooting\n\n");
570 	i = 1;
571 	if (howto & RB_SINGLE)
572 		str[i++] = 's';
573 	if (howto & RB_KDB)
574 		str[i++] = 'd';
575 	if (i > 1) {
576 		str[0] = '-';
577 		str[i] = 0;
578 	} else
579 		str[0] = 0;
580 	romboot(str);
581 	/*NOTREACHED*/
582 }
583 
584 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
585 int	dumpsize = 0;		/* also for savecore */
586 long	dumplo = 0;
587 
588 dumpconf()
589 {
590 	int nblks;
591 
592 	dumpsize = physmem;
593 #define DUMPMMU
594 #ifdef DUMPMMU
595 #define NPMEG 128
596 	/*
597 	 * savecore views the image in units of pages (i.e., dumpsize is in
598 	 * pages) so we round the two mmu entities into page-sized chunks.
599 	 * The PMEGs (32kB) and the segment table (512 bytes plus padding)
600 	 * are appending to the end of the crash dump.
601 	 */
602 	dumpsize += btoc(sizeof(((struct kpmap *)0)->pm_rsegmap)) +
603 		btoc(NPMEG * NPTESG * sizeof(int));
604 #endif
605 	if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
606 		nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
607 		/*
608 		 * Don't dump on the first CLBYTES (why CLBYTES?)
609 		 * in case the dump device includes a disk label.
610 		 */
611 		if (dumplo < btodb(CLBYTES))
612 			dumplo = btodb(CLBYTES);
613 
614 		/*
615 		 * If dumpsize is too big for the partition, truncate it.
616 		 * Otherwise, put the dump at the end of the partition
617 		 * by making dumplo as large as possible.
618 		 */
619 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
620 			dumpsize = btoc(dbtob(nblks - dumplo));
621 		else if (dumplo + ctod(dumpsize) > nblks)
622 			dumplo = nblks - ctod(dumpsize);
623 	}
624 }
625 
626 #ifdef DUMPMMU
627 /* XXX */
628 #include <machine/ctlreg.h>
629 #define	getpte(va)		lda(va, ASI_PTE)
630 #define	setsegmap(va, pmeg)	stba(va, ASI_SEGMAP, pmeg)
631 
632 /*
633  * Write the mmu contents to the dump device.
634  * This gets appended to the end of a crash dump since
635  * there is no in-core copy of kernel memory mappings.
636  */
637 int
638 dumpmmu(blkno)
639 	register daddr_t blkno;
640 {
641 	register int (*dump)(/*dev_t, daddr_t, caddr_t, int*/);
642 	register int pmeg;
643 	register int addr;	/* unused kernel virtual address */
644 	register int i;
645 	register int *pte, *ptend;
646 	register int error;
647 	register struct kpmap *kpmap = &kernel_pmap_store;
648 	int buffer[dbtob(1) / sizeof(int)];
649 	extern int seginval;	/* from pmap.c */
650 
651 
652 	dump = bdevsw[major(dumpdev)].d_dump;
653 
654 	/*
655 	 * dump page table entries
656 	 *
657 	 * We dump each pmeg in order (by segment number).  Since the MMU
658 	 * automatically maps the given virtual segment to a pmeg we must
659 	 * iterate over the segments by incrementing an unused segment slot
660 	 * in the MMU.  This fixed segment number is used in the virtual
661 	 * address argument to getpte().
662 	 */
663 
664 	/* First find an unused virtual segment. */
665 	i = NKSEG;
666 	while (kpmap->pm_rsegmap[--i] != seginval)
667 		if (i <= 0)
668 			return (-1);
669 	/*
670 	 * Compute the base address corresponding to the unused segment.
671 	 * Note that the kernel segments start after all the user segments
672 	 * so we must account for this offset.
673 	 */
674 	addr = VSTOVA(i + NUSEG);
675 	/*
676 	 * Go through the pmegs and dump each one.
677 	 */
678 	pte = buffer;
679 	ptend = &buffer[sizeof(buffer) / sizeof(buffer[0])];
680 	for (pmeg = 0; pmeg < NPMEG; ++pmeg) {
681 		register int va = addr;
682 
683 		setsegmap(addr, pmeg);
684 		i = NPTESG;
685 		do {
686 			*pte++ = getpte(va);
687 			if (pte >= ptend) {
688 				/*
689 				 * Note that we'll dump the last block
690 				 * the last time through the loops because
691 				 * all the PMEGs occupy 32KB which is
692 				 * a multiple of the block size.
693 				 */
694 				error = (*dump)(dumpdev, blkno,
695 						(caddr_t)buffer,
696 						dbtob(1));
697 				if (error != 0)
698 					return (error);
699 				++blkno;
700 				pte = buffer;
701 			}
702 			va += NBPG;
703 		} while (--i > 0);
704 	}
705 	setsegmap(addr, seginval);
706 
707 	/*
708 	 * dump (512 byte) segment map
709 	 * XXX assume it's a multiple of the block size
710 	 */
711 	error = (*dump)(dumpdev, blkno, (caddr_t)kpmap->pm_rsegmap,
712 			sizeof(kpmap->pm_rsegmap));
713 	return (error);
714 }
715 #endif
716 
717 #define	BYTES_PER_DUMP	(32 * 1024)	/* must be a multiple of pagesize */
718 static vm_offset_t dumpspace;
719 
720 caddr_t
721 reserve_dumppages(p)
722 	caddr_t p;
723 {
724 
725 	dumpspace = (vm_offset_t)p;
726 	return (p + BYTES_PER_DUMP);
727 }
728 
729 /*
730  * Write a crash dump.
731  */
732 dumpsys()
733 {
734 	register unsigned bytes, i, n;
735 	register int maddr, psize;
736 	register daddr_t blkno;
737 	register int (*dump)(/*dev_t, daddr_t, caddr_t, int, int*/);
738 	int error = 0;
739 
740 	if (dumpdev == NODEV)
741 		return;
742 	/* copy registers to memory */
743 	snapshot(cpcb);
744 	/*
745 	 * For dumps during autoconfiguration,
746 	 * if dump device has already configured...
747 	 */
748 	if (dumpsize == 0)
749 		dumpconf();
750 	if (dumplo < 0)
751 		return;
752 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
753 
754 	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
755 	printf("dump ");
756 	if (psize == -1) {
757 		printf("area unavailable\n");
758 		return;
759 	}
760 	bytes = physmem << PGSHIFT;
761 	maddr = 0;
762 	blkno = dumplo;
763 	dump = bdevsw[major(dumpdev)].d_dump;
764 	for (i = 0; i < bytes; i += n) {
765 		n = bytes - i;
766 		if (n > BYTES_PER_DUMP)
767 			 n = BYTES_PER_DUMP;
768 #ifdef DEBUG
769 		/* print out how many MBs we have dumped */
770 		if (i && (i % (1024*1024)) == 0)
771 			printf("%d ", i / (1024*1024));
772 #endif
773 		(void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);
774 		error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, (int)n);
775 		if (error)
776 			break;
777 		maddr += n;
778 		blkno += btodb(n);
779 	}
780 #ifdef DUMPMMU
781 	if (!error)
782 		error = dumpmmu(blkno);
783 #endif
784 	switch (error) {
785 
786 	case ENXIO:
787 		printf("device bad\n");
788 		break;
789 
790 	case EFAULT:
791 		printf("device not ready\n");
792 		break;
793 
794 	case EINVAL:
795 		printf("area improper\n");
796 		break;
797 
798 	case EIO:
799 		printf("i/o error\n");
800 		break;
801 
802 	case 0:
803 		printf("succeeded\n");
804 		break;
805 
806 	default:
807 		printf("error %d\n", error);
808 		break;
809 	}
810 }
811 
812 /*
813  * Map an I/O device given physical address and size in bytes, e.g.,
814  *
815  *	mydev = (struct mydev *)mapdev(myioaddr, 0, sizeof(struct mydev));
816  *
817  * See also machine/autoconf.h.
818  */
819 void *
820 mapdev(phys, virt, size)
821 	register void *phys;
822 	register int virt, size;
823 {
824 	register vm_offset_t v;
825 	register void *ret;
826 	static vm_offset_t iobase = IODEV_BASE;
827 
828 	size = round_page(size);
829 	if (virt)
830 		v = trunc_page(virt);
831 	else {
832 		v = iobase;
833 		iobase += size;
834 		if (iobase > IODEV_END)	/* unlikely */
835 			panic("mapiodev");
836 	}
837 	ret = (void *)v;
838 	phys = (void *)trunc_page(phys);
839 	do {
840 		pmap_enter(kernel_pmap, v,
841 		    (vm_offset_t)phys | PMAP_OBIO | PMAP_NC,
842 		    VM_PROT_READ | VM_PROT_WRITE, 1);
843 		v += PAGE_SIZE;
844 		phys += PAGE_SIZE;
845 	} while ((size -= PAGE_SIZE) > 0);
846 	return (ret);
847 }
848