xref: /openbsd/sys/arch/alpha/alpha/machdep.c (revision 41033391)
1417eba8cSderaadt /*	$NetBSD: machdep.c,v 1.19.4.5 1996/06/15 03:56:33 cgd Exp $	*/
2df930be7Sderaadt 
3df930be7Sderaadt /*
4417eba8cSderaadt  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
5df930be7Sderaadt  * All rights reserved.
6df930be7Sderaadt  *
7df930be7Sderaadt  * Author: Chris G. Demetriou
8df930be7Sderaadt  *
9df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
10df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
11df930be7Sderaadt  * notice and this permission notice appear in all copies of the
12df930be7Sderaadt  * software, derivative works or modified versions, and any portions
13df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
14df930be7Sderaadt  *
15df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18df930be7Sderaadt  *
19df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
20df930be7Sderaadt  *
21df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22df930be7Sderaadt  *  School of Computer Science
23df930be7Sderaadt  *  Carnegie Mellon University
24df930be7Sderaadt  *  Pittsburgh PA 15213-3890
25df930be7Sderaadt  *
26df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
27df930be7Sderaadt  * rights to redistribute these changes.
28df930be7Sderaadt  */
29df930be7Sderaadt 
30df930be7Sderaadt #include <sys/param.h>
31df930be7Sderaadt #include <sys/systm.h>
32df930be7Sderaadt #include <sys/signalvar.h>
33df930be7Sderaadt #include <sys/kernel.h>
34df930be7Sderaadt #include <sys/map.h>
35df930be7Sderaadt #include <sys/proc.h>
36df930be7Sderaadt #include <sys/buf.h>
37df930be7Sderaadt #include <sys/reboot.h>
38417eba8cSderaadt #include <sys/device.h>
39df930be7Sderaadt #include <sys/conf.h>
40df930be7Sderaadt #include <sys/file.h>
41df930be7Sderaadt #ifdef REAL_CLISTS
42df930be7Sderaadt #include <sys/clist.h>
43df930be7Sderaadt #endif
44df930be7Sderaadt #include <sys/callout.h>
45df930be7Sderaadt #include <sys/malloc.h>
46df930be7Sderaadt #include <sys/mbuf.h>
47df930be7Sderaadt #include <sys/msgbuf.h>
48df930be7Sderaadt #include <sys/ioctl.h>
49df930be7Sderaadt #include <sys/tty.h>
50df930be7Sderaadt #include <sys/user.h>
51df930be7Sderaadt #include <sys/exec.h>
52df930be7Sderaadt #include <sys/exec_ecoff.h>
53df930be7Sderaadt #include <sys/sysctl.h>
54df930be7Sderaadt #ifdef SYSVMSG
55df930be7Sderaadt #include <sys/msg.h>
56df930be7Sderaadt #endif
57df930be7Sderaadt #ifdef SYSVSEM
58df930be7Sderaadt #include <sys/sem.h>
59df930be7Sderaadt #endif
60df930be7Sderaadt #ifdef SYSVSHM
61df930be7Sderaadt #include <sys/shm.h>
62df930be7Sderaadt #endif
63df930be7Sderaadt 
64df930be7Sderaadt #include <sys/mount.h>
65df930be7Sderaadt #include <sys/syscallargs.h>
66df930be7Sderaadt 
67df930be7Sderaadt #include <vm/vm_kern.h>
68df930be7Sderaadt 
69df930be7Sderaadt #include <dev/cons.h>
70df930be7Sderaadt 
71df930be7Sderaadt #include <machine/cpu.h>
72df930be7Sderaadt #include <machine/reg.h>
73df930be7Sderaadt #include <machine/rpb.h>
74df930be7Sderaadt #include <machine/prom.h>
75df930be7Sderaadt 
76df930be7Sderaadt #ifdef DEC_3000_500
77df930be7Sderaadt #include <alpha/alpha/dec_3000_500.h>
78df930be7Sderaadt #endif
79df930be7Sderaadt #ifdef DEC_3000_300
80df930be7Sderaadt #include <alpha/alpha/dec_3000_300.h>
81df930be7Sderaadt #endif
82df930be7Sderaadt #ifdef DEC_2100_A50
83df930be7Sderaadt #include <alpha/alpha/dec_2100_a50.h>
84df930be7Sderaadt #endif
8534fbf6deSderaadt #ifdef DEC_KN20AA
8634fbf6deSderaadt #include <alpha/alpha/dec_kn20aa.h>
8734fbf6deSderaadt #endif
8834fbf6deSderaadt #ifdef DEC_AXPPCI_33
8934fbf6deSderaadt #include <alpha/alpha/dec_axppci_33.h>
9034fbf6deSderaadt #endif
9134fbf6deSderaadt #ifdef DEC_21000
9234fbf6deSderaadt #include <alpha/alpha/dec_21000.h>
9334fbf6deSderaadt #endif
94df930be7Sderaadt 
95df930be7Sderaadt #include <net/netisr.h>
96df930be7Sderaadt #include "ether.h"
97df930be7Sderaadt 
98417eba8cSderaadt #include "le_ioasic.h"			/* for le_iomem creation */
99df930be7Sderaadt 
100df930be7Sderaadt vm_map_t buffer_map;
101df930be7Sderaadt 
102df930be7Sderaadt void dumpsys __P((void));
103df930be7Sderaadt 
104df930be7Sderaadt /*
105df930be7Sderaadt  * Declare these as initialized data so we can patch them.
106df930be7Sderaadt  */
107df930be7Sderaadt int	nswbuf = 0;
108df930be7Sderaadt #ifdef	NBUF
109df930be7Sderaadt int	nbuf = NBUF;
110df930be7Sderaadt #else
111df930be7Sderaadt int	nbuf = 0;
112df930be7Sderaadt #endif
113df930be7Sderaadt #ifdef	BUFPAGES
114df930be7Sderaadt int	bufpages = BUFPAGES;
115df930be7Sderaadt #else
116df930be7Sderaadt int	bufpages = 0;
117df930be7Sderaadt #endif
118df930be7Sderaadt int	msgbufmapped = 0;	/* set when safe to use msgbuf */
119df930be7Sderaadt int	maxmem;			/* max memory per process */
120df930be7Sderaadt 
121df930be7Sderaadt int	totalphysmem;		/* total amount of physical memory in system */
122df930be7Sderaadt int	physmem;		/* physical memory used by NetBSD + some rsvd */
123df930be7Sderaadt int	firstusablepage;	/* first usable memory page */
124df930be7Sderaadt int	lastusablepage;		/* last usable memory page */
125df930be7Sderaadt int	resvmem;		/* amount of memory reserved for PROM */
126df930be7Sderaadt int	unusedmem;		/* amount of memory for OS that we don't use */
127df930be7Sderaadt int	unknownmem;		/* amount of memory with an unknown use */
128df930be7Sderaadt 
129df930be7Sderaadt int	cputype;		/* system type, from the RPB */
130df930be7Sderaadt 
131df930be7Sderaadt /*
132df930be7Sderaadt  * XXX We need an address to which we can assign things so that they
133df930be7Sderaadt  * won't be optimized away because we didn't use the value.
134df930be7Sderaadt  */
135df930be7Sderaadt u_int32_t no_optimize;
136df930be7Sderaadt 
137df930be7Sderaadt /* the following is used externally (sysctl_hw) */
138df930be7Sderaadt char	machine[] = "alpha";
139417eba8cSderaadt char	cpu_model[128];
140df930be7Sderaadt char	*model_names[] = {
141df930be7Sderaadt 	"UNKNOWN (0)",
142df930be7Sderaadt 	"Alpha Demonstration Unit",
143df930be7Sderaadt 	"DEC 4000 (\"Cobra\")",
144df930be7Sderaadt 	"DEC 7000 (\"Ruby\")",
145df930be7Sderaadt 	"DEC 3000/500 (\"Flamingo\") family",
146df930be7Sderaadt 	"UNKNOWN (5)",
147df930be7Sderaadt 	"DEC 2000/300 (\"Jensen\")",
148df930be7Sderaadt 	"DEC 3000/300 (\"Pelican\")",
149df930be7Sderaadt 	"UNKNOWN (8)",
150df930be7Sderaadt 	"DEC 2100/A500 (\"Sable\")",
151df930be7Sderaadt 	"AXPvme 64",
152df930be7Sderaadt 	"AXPpci 33 (\"NoName\")",
15334fbf6deSderaadt 	"DEC 21000 (\"TurboLaser\")",
154df930be7Sderaadt 	"DEC 2100/A50 (\"Avanti\") family",
155df930be7Sderaadt 	"Mustang",
15634fbf6deSderaadt 	"DEC KN20AA",
15734fbf6deSderaadt 	"UNKNOWN (16)",
158df930be7Sderaadt 	"DEC 1000 (\"Mikasa\")",
159df930be7Sderaadt };
160df930be7Sderaadt int	nmodel_names = sizeof model_names/sizeof model_names[0];
161df930be7Sderaadt 
162df930be7Sderaadt struct	user *proc0paddr;
163df930be7Sderaadt 
164df930be7Sderaadt /* Number of machine cycles per microsecond */
165df930be7Sderaadt u_int64_t	cycles_per_usec;
166df930be7Sderaadt 
167df930be7Sderaadt /* some memory areas for device DMA.  "ick." */
168df930be7Sderaadt caddr_t		le_iomem;		/* XXX iomem for LANCE DMA */
169df930be7Sderaadt 
170df930be7Sderaadt /* Interrupt vectors (in locore) */
171df930be7Sderaadt extern int XentInt(), XentArith(), XentMM(), XentIF(), XentUna(), XentSys();
172df930be7Sderaadt 
173df930be7Sderaadt /* number of cpus in the box.  really! */
174df930be7Sderaadt int		ncpus;
175df930be7Sderaadt 
176df930be7Sderaadt /* various CPU-specific functions. */
177df930be7Sderaadt char		*(*cpu_modelname) __P((void));
178417eba8cSderaadt void		(*cpu_consinit) __P((void));
179417eba8cSderaadt void		(*cpu_device_register) __P((struct device *dev, void *aux));
180df930be7Sderaadt char		*cpu_iobus;
181df930be7Sderaadt 
182417eba8cSderaadt char boot_flags[64];
183417eba8cSderaadt 
184417eba8cSderaadt /* for cpu_sysctl() */
185417eba8cSderaadt char		root_device[17];
186df930be7Sderaadt 
187df930be7Sderaadt int
188417eba8cSderaadt alpha_init(pfn, ptb)
189df930be7Sderaadt 	u_long pfn;		/* first free PFN number */
190df930be7Sderaadt 	u_long ptb;		/* PFN of current level 1 page table */
191df930be7Sderaadt {
192df930be7Sderaadt 	extern char _end[];
193df930be7Sderaadt 	caddr_t start, v;
194df930be7Sderaadt 	struct mddt *mddtp;
195df930be7Sderaadt 	int i, mddtweird;
196df930be7Sderaadt 	char *p;
197df930be7Sderaadt 
198df930be7Sderaadt 	/*
199df930be7Sderaadt 	 * Turn off interrupts and floating point.
200df930be7Sderaadt 	 * Make sure the instruction and data streams are consistent.
201df930be7Sderaadt 	 */
202df930be7Sderaadt 	(void)splhigh();
203df930be7Sderaadt 	pal_wrfen(0);
204df930be7Sderaadt 	TBIA();
205df930be7Sderaadt 	IMB();
206df930be7Sderaadt 
207df930be7Sderaadt 	/*
208df930be7Sderaadt 	 * get address of the restart block, while we the bootstrap
209df930be7Sderaadt 	 * mapping is still around.
210df930be7Sderaadt 	 */
211df930be7Sderaadt 	hwrpb = (struct rpb *) phystok0seg(*(struct rpb **)HWRPB_ADDR);
212df930be7Sderaadt 
213df930be7Sderaadt 	/*
214df930be7Sderaadt 	 * Remember how many cycles there are per microsecond,
215df930be7Sderaadt 	 * so that we can use delay().  Round up, for safety.
216df930be7Sderaadt 	 */
217df930be7Sderaadt 	cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
218df930be7Sderaadt 
219df930be7Sderaadt 	/*
220df930be7Sderaadt 	 * Init the PROM interface, so we can use printf
221df930be7Sderaadt 	 * until PROM mappings go away in consinit.
222df930be7Sderaadt 	 */
223df930be7Sderaadt 	init_prom_interface();
224df930be7Sderaadt 
225df930be7Sderaadt 	/*
226df930be7Sderaadt 	 * Point interrupt/exception vectors to our own.
227df930be7Sderaadt 	 */
228df930be7Sderaadt 	pal_wrent(XentInt, 0);
229df930be7Sderaadt 	pal_wrent(XentArith, 1);
230df930be7Sderaadt 	pal_wrent(XentMM, 2);
231df930be7Sderaadt 	pal_wrent(XentIF, 3);
232df930be7Sderaadt 	pal_wrent(XentUna, 4);
233df930be7Sderaadt 	pal_wrent(XentSys, 5);
234df930be7Sderaadt 
235df930be7Sderaadt 	/*
236df930be7Sderaadt 	 * Find out how much memory is available, by looking at
237df930be7Sderaadt 	 * the memory cluster descriptors.  This also tries to do
238df930be7Sderaadt 	 * its best to detect things things that have never been seen
239df930be7Sderaadt 	 * before...
240df930be7Sderaadt 	 *
241df930be7Sderaadt 	 * XXX Assumes that the first "system" cluster is the
242df930be7Sderaadt 	 * only one we can use. Is the second (etc.) system cluster
243df930be7Sderaadt 	 * (if one happens to exist) guaranteed to be contiguous?  or...?
244df930be7Sderaadt 	 */
245df930be7Sderaadt 	mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
246df930be7Sderaadt 
247df930be7Sderaadt 	/*
248df930be7Sderaadt 	 * BEGIN MDDT WEIRDNESS CHECKING
249df930be7Sderaadt 	 */
250df930be7Sderaadt 	mddtweird = 0;
251df930be7Sderaadt 
252df930be7Sderaadt #define cnt	 mddtp->mddt_cluster_cnt
253df930be7Sderaadt #define	usage(n) mddtp->mddt_clusters[(n)].mddt_usage
254df930be7Sderaadt 	if (cnt != 2 && cnt != 3) {
255df930be7Sderaadt 		printf("WARNING: weird number (%d) of mem clusters\n", cnt);
256df930be7Sderaadt 		mddtweird = 1;
257df930be7Sderaadt 	} else if (usage(0) != MDDT_PALCODE ||
258df930be7Sderaadt 		   usage(1) != MDDT_SYSTEM ||
259df930be7Sderaadt 	           (cnt == 3 && usage(2) != MDDT_PALCODE)) {
260df930be7Sderaadt 		mddtweird = 1;
261df930be7Sderaadt 		printf("WARNING: %d mem clusters, but weird config\n", cnt);
262df930be7Sderaadt 	}
263df930be7Sderaadt 
264df930be7Sderaadt 	for (i = 0; i < cnt; i++) {
265df930be7Sderaadt 		if ((usage(i) & MDDT_mbz) != 0) {
266df930be7Sderaadt 			printf("WARNING: mem cluster %d has weird usage %lx\n",
267df930be7Sderaadt 			    i, usage(i));
268df930be7Sderaadt 			mddtweird = 1;
269df930be7Sderaadt 		}
270df930be7Sderaadt 		if (mddtp->mddt_clusters[i].mddt_pg_cnt == 0) {
271df930be7Sderaadt 			printf("WARNING: mem cluster %d has pg cnt == 0\n", i);
272df930be7Sderaadt 			mddtweird = 1;
273df930be7Sderaadt 		}
274df930be7Sderaadt 		/* XXX other things to check? */
275df930be7Sderaadt 	}
276df930be7Sderaadt #undef cnt
277df930be7Sderaadt #undef usage
278df930be7Sderaadt 
279df930be7Sderaadt 	if (mddtweird) {
280df930be7Sderaadt 		printf("\n");
281df930be7Sderaadt 		printf("complete memory cluster information:\n");
282df930be7Sderaadt 		for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
283df930be7Sderaadt 			printf("mddt %d:\n", i);
284df930be7Sderaadt 			printf("\tpfn %lx\n",
285df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pfn);
286df930be7Sderaadt 			printf("\tcnt %lx\n",
287df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_cnt);
288df930be7Sderaadt 			printf("\ttest %lx\n",
289df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_test);
290df930be7Sderaadt 			printf("\tbva %lx\n",
291df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_v_bitaddr);
292df930be7Sderaadt 			printf("\tbpa %lx\n",
293df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_p_bitaddr);
294df930be7Sderaadt 			printf("\tbcksum %lx\n",
295df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_bit_cksum);
296df930be7Sderaadt 			printf("\tusage %lx\n",
297df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_usage);
298df930be7Sderaadt 		}
299df930be7Sderaadt 		printf("\n");
300df930be7Sderaadt 	}
301df930be7Sderaadt 	/*
302df930be7Sderaadt 	 * END MDDT WEIRDNESS CHECKING
303df930be7Sderaadt 	 */
304df930be7Sderaadt 
305df930be7Sderaadt 	for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
306df930be7Sderaadt 		totalphysmem += mddtp->mddt_clusters[i].mddt_pg_cnt;
307df930be7Sderaadt #define	usage(n) mddtp->mddt_clusters[(n)].mddt_usage
308df930be7Sderaadt #define	pgcnt(n) mddtp->mddt_clusters[(n)].mddt_pg_cnt
309df930be7Sderaadt 		if ((usage(i) & MDDT_mbz) != 0)
310df930be7Sderaadt 			unknownmem += pgcnt(i);
311df930be7Sderaadt 		else if ((usage(i) & ~MDDT_mbz) == MDDT_PALCODE)
312df930be7Sderaadt 			resvmem += pgcnt(i);
313df930be7Sderaadt 		else if ((usage(i) & ~MDDT_mbz) == MDDT_SYSTEM) {
314df930be7Sderaadt 			/*
315df930be7Sderaadt 			 * assumes that the system cluster listed is
316df930be7Sderaadt 			 * one we're in...
317df930be7Sderaadt 			 */
318df930be7Sderaadt 			if (physmem != resvmem) {
319df930be7Sderaadt 				physmem += pgcnt(i);
320df930be7Sderaadt 				firstusablepage =
321df930be7Sderaadt 				    mddtp->mddt_clusters[i].mddt_pfn;
322df930be7Sderaadt 				lastusablepage = firstusablepage + pgcnt(i) - 1;
323df930be7Sderaadt 			} else
324df930be7Sderaadt 				unusedmem += pgcnt(i);
325df930be7Sderaadt 		}
326df930be7Sderaadt #undef usage
327df930be7Sderaadt #undef pgcnt
328df930be7Sderaadt 	}
329df930be7Sderaadt 	if (totalphysmem == 0)
330df930be7Sderaadt 		panic("can't happen: system seems to have no memory!");
331df930be7Sderaadt 	maxmem = physmem;
332df930be7Sderaadt 
333df930be7Sderaadt #if 0
334df930be7Sderaadt 	printf("totalphysmem = %d\n", totalphysmem);
335df930be7Sderaadt 	printf("physmem = %d\n", physmem);
336df930be7Sderaadt 	printf("firstusablepage = %d\n", firstusablepage);
337df930be7Sderaadt 	printf("lastusablepage = %d\n", lastusablepage);
338df930be7Sderaadt 	printf("resvmem = %d\n", resvmem);
339df930be7Sderaadt 	printf("unusedmem = %d\n", unusedmem);
340df930be7Sderaadt 	printf("unknownmem = %d\n", unknownmem);
341df930be7Sderaadt #endif
342df930be7Sderaadt 
343df930be7Sderaadt 	/*
344df930be7Sderaadt 	 * find out this CPU's page size
345df930be7Sderaadt 	 */
346df930be7Sderaadt 	PAGE_SIZE = hwrpb->rpb_page_size;
34734fbf6deSderaadt 	if (PAGE_SIZE != 8192)
34834fbf6deSderaadt 		panic("page size %d != 8192?!", PAGE_SIZE);
349df930be7Sderaadt 
350df930be7Sderaadt 	v = (caddr_t)alpha_round_page(_end);
351df930be7Sderaadt 	/*
352df930be7Sderaadt 	 * Init mapping for u page(s) for proc 0
353df930be7Sderaadt 	 */
354df930be7Sderaadt 	start = v;
355df930be7Sderaadt 	curproc->p_addr = proc0paddr = (struct user *)v;
356df930be7Sderaadt 	v += UPAGES * NBPG;
357df930be7Sderaadt 
358df930be7Sderaadt 	/*
359df930be7Sderaadt 	 * Find out what hardware we're on, and remember its type name.
360df930be7Sderaadt 	 */
361df930be7Sderaadt 	cputype = hwrpb->rpb_type;
362df930be7Sderaadt 	switch (cputype) {
363df930be7Sderaadt #ifdef DEC_3000_500				/* and 400, [6-9]00 */
364df930be7Sderaadt 	case ST_DEC_3000_500:
365df930be7Sderaadt 		cpu_modelname = dec_3000_500_modelname;
366df930be7Sderaadt 		cpu_consinit = dec_3000_500_consinit;
367417eba8cSderaadt 		cpu_device_register = dec_3000_500_device_register;
368200d7a17Sderaadt 		cpu_iobus = "tcasic";
369df930be7Sderaadt 		break;
370df930be7Sderaadt #endif
371df930be7Sderaadt 
372df930be7Sderaadt #ifdef DEC_3000_300
373df930be7Sderaadt 	case ST_DEC_3000_300:
374df930be7Sderaadt 		cpu_modelname = dec_3000_300_modelname;
375df930be7Sderaadt 		cpu_consinit = dec_3000_300_consinit;
376417eba8cSderaadt 		cpu_device_register = dec_3000_300_device_register;
377200d7a17Sderaadt 		cpu_iobus = "tcasic";
378df930be7Sderaadt 		break;
379df930be7Sderaadt #endif
380df930be7Sderaadt 
381df930be7Sderaadt #ifdef DEC_2100_A50
382df930be7Sderaadt 	case ST_DEC_2100_A50:
383df930be7Sderaadt 		cpu_modelname = dec_2100_a50_modelname;
384df930be7Sderaadt 		cpu_consinit = dec_2100_a50_consinit;
385417eba8cSderaadt 		cpu_device_register = dec_2100_a50_device_register;
386df930be7Sderaadt 		cpu_iobus = "apecs";
387df930be7Sderaadt 		break;
388df930be7Sderaadt #endif
389df930be7Sderaadt 
39034fbf6deSderaadt #ifdef DEC_KN20AA
39134fbf6deSderaadt 	case ST_DEC_KN20AA:
39234fbf6deSderaadt 		cpu_modelname = dec_kn20aa_modelname;
39334fbf6deSderaadt 		cpu_consinit = dec_kn20aa_consinit;
394417eba8cSderaadt 		cpu_device_register = dec_kn20aa_device_register;
39534fbf6deSderaadt 		cpu_iobus = "cia";
39634fbf6deSderaadt 		break;
39734fbf6deSderaadt #endif
39834fbf6deSderaadt 
39934fbf6deSderaadt #ifdef DEC_AXPPCI_33
40034fbf6deSderaadt 	case ST_DEC_AXPPCI_33:
40134fbf6deSderaadt 		cpu_modelname = dec_axppci_33_modelname;
40234fbf6deSderaadt 		cpu_consinit = dec_axppci_33_consinit;
403417eba8cSderaadt 		cpu_device_register = dec_axppci_33_device_register;
40434fbf6deSderaadt 		cpu_iobus = "lca";
40534fbf6deSderaadt 		break;
40634fbf6deSderaadt #endif
40734fbf6deSderaadt 
408df930be7Sderaadt #ifdef DEC_2000_300
409df930be7Sderaadt 	case ST_DEC_2000_300:
410df930be7Sderaadt 		cpu_modelname = dec_2000_300_modelname;
411df930be7Sderaadt 		cpu_consinit = dec_2000_300_consinit;
412417eba8cSderaadt 		cpu_device_register = dec_2000_300_device_register;
413df930be7Sderaadt 		cpu_iobus = "ibus";
414df930be7Sderaadt 	XXX DEC 2000/300 NOT SUPPORTED
41534fbf6deSderaadt 		break;
416df930be7Sderaadt #endif
417df930be7Sderaadt 
41834fbf6deSderaadt #ifdef DEC_21000
41934fbf6deSderaadt 	case ST_DEC_21000:
42034fbf6deSderaadt 		cpu_modelname = dec_21000_modelname;
42134fbf6deSderaadt 		cpu_consinit = dec_21000_consinit;
422417eba8cSderaadt 		cpu_device_register = dec_21000_device_register;
42334fbf6deSderaadt 		cpu_iobus = "tlsb";
424417eba8cSderaadt 	XXX DEC 21000 NOT SUPPORTED
42534fbf6deSderaadt 		break;
426df930be7Sderaadt #endif
427df930be7Sderaadt 
428df930be7Sderaadt 	default:
429df930be7Sderaadt 		if (cputype > nmodel_names)
430df930be7Sderaadt 			panic("Unknown system type %d", cputype);
431df930be7Sderaadt 		else
432df930be7Sderaadt 			panic("Support for %s system type not in kernel.",
433df930be7Sderaadt 			    model_names[cputype]);
434df930be7Sderaadt 	}
435df930be7Sderaadt 
436417eba8cSderaadt 	if ((*cpu_modelname)() != NULL)
437417eba8cSderaadt 		strncpy(cpu_model, (*cpu_modelname)(), sizeof cpu_model - 1);
438417eba8cSderaadt 	else
439417eba8cSderaadt 		strncpy(cpu_model, model_names[cputype], sizeof cpu_model - 1);
440417eba8cSderaadt 	cpu_model[sizeof cpu_model - 1] = '\0';
441df930be7Sderaadt 
442417eba8cSderaadt #if NLE_IOASIC > 0
443df930be7Sderaadt 	/*
444df930be7Sderaadt 	 * Grab 128K at the top of physical memory for the lance chip
445df930be7Sderaadt 	 * on machines where it does dma through the I/O ASIC.
446df930be7Sderaadt 	 * It must be physically contiguous and aligned on a 128K boundary.
447417eba8cSderaadt 	 *
448417eba8cSderaadt 	 * Note that since this is conditional on the presence of
449417eba8cSderaadt 	 * IOASIC-attached 'le' units in the kernel config, the
450417eba8cSderaadt 	 * message buffer may move on these systems.  This shouldn't
451417eba8cSderaadt 	 * be a problem, because once people have a kernel config that
452417eba8cSderaadt 	 * they use, they're going to stick with it.
453df930be7Sderaadt 	 */
454df930be7Sderaadt 	if (cputype == ST_DEC_3000_500 ||
455df930be7Sderaadt 	    cputype == ST_DEC_3000_300) {	/* XXX possibly others? */
456df930be7Sderaadt 		lastusablepage -= btoc(128 * 1024);
457df930be7Sderaadt 		le_iomem = (caddr_t)phystok0seg(ctob(lastusablepage + 1));
458df930be7Sderaadt 	}
459417eba8cSderaadt #endif /* NLE_IOASIC */
460df930be7Sderaadt 
461df930be7Sderaadt 	/*
462df930be7Sderaadt 	 * Initialize error message buffer (at end of core).
463df930be7Sderaadt 	 */
464df930be7Sderaadt 	lastusablepage -= btoc(sizeof (struct msgbuf));
465df930be7Sderaadt 	msgbufp = (struct msgbuf *)phystok0seg(ctob(lastusablepage + 1));
466df930be7Sderaadt 	msgbufmapped = 1;
467df930be7Sderaadt 
468df930be7Sderaadt 	/*
469df930be7Sderaadt 	 * Allocate space for system data structures.
470df930be7Sderaadt 	 * The first available kernel virtual address is in "v".
471df930be7Sderaadt 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
472df930be7Sderaadt 	 *
473df930be7Sderaadt 	 * These data structures are allocated here instead of cpu_startup()
474df930be7Sderaadt 	 * because physical memory is directly addressable. We don't have
475df930be7Sderaadt 	 * to map these into virtual address space.
476df930be7Sderaadt 	 */
477df930be7Sderaadt #define valloc(name, type, num) \
47834fbf6deSderaadt 	    (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num))
479df930be7Sderaadt #define valloclim(name, type, num, lim) \
48034fbf6deSderaadt 	    (name) = (type *)v; v = (caddr_t)ALIGN((lim) = ((name)+(num)))
481df930be7Sderaadt #ifdef REAL_CLISTS
482df930be7Sderaadt 	valloc(cfree, struct cblock, nclist);
483df930be7Sderaadt #endif
484df930be7Sderaadt 	valloc(callout, struct callout, ncallout);
485df930be7Sderaadt 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
486df930be7Sderaadt #ifdef SYSVSHM
487df930be7Sderaadt 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
488df930be7Sderaadt #endif
489df930be7Sderaadt #ifdef SYSVSEM
490df930be7Sderaadt 	valloc(sema, struct semid_ds, seminfo.semmni);
491df930be7Sderaadt 	valloc(sem, struct sem, seminfo.semmns);
492df930be7Sderaadt 	/* This is pretty disgusting! */
493df930be7Sderaadt 	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
494df930be7Sderaadt #endif
495df930be7Sderaadt #ifdef SYSVMSG
496df930be7Sderaadt 	valloc(msgpool, char, msginfo.msgmax);
497df930be7Sderaadt 	valloc(msgmaps, struct msgmap, msginfo.msgseg);
498df930be7Sderaadt 	valloc(msghdrs, struct msg, msginfo.msgtql);
499df930be7Sderaadt 	valloc(msqids, struct msqid_ds, msginfo.msgmni);
500df930be7Sderaadt #endif
501df930be7Sderaadt 
502df930be7Sderaadt 	/*
503df930be7Sderaadt 	 * Determine how many buffers to allocate.
504417eba8cSderaadt 	 * We allocate 10% of memory for buffer space.  Insure a
505df930be7Sderaadt 	 * minimum of 16 buffers.  We allocate 1/2 as many swap buffer
506df930be7Sderaadt 	 * headers as file i/o buffers.
507df930be7Sderaadt 	 */
508df930be7Sderaadt 	if (bufpages == 0)
509417eba8cSderaadt 		bufpages = (physmem * 10) / (CLSIZE * 100);
510df930be7Sderaadt 	if (nbuf == 0) {
511df930be7Sderaadt 		nbuf = bufpages;
512df930be7Sderaadt 		if (nbuf < 16)
513df930be7Sderaadt 			nbuf = 16;
514df930be7Sderaadt 	}
515df930be7Sderaadt 	if (nswbuf == 0) {
516df930be7Sderaadt 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
517df930be7Sderaadt 		if (nswbuf > 256)
518df930be7Sderaadt 			nswbuf = 256;		/* sanity */
519df930be7Sderaadt 	}
520df930be7Sderaadt 	valloc(swbuf, struct buf, nswbuf);
521df930be7Sderaadt 	valloc(buf, struct buf, nbuf);
522df930be7Sderaadt 
523df930be7Sderaadt 	/*
524df930be7Sderaadt 	 * Clear allocated memory.
525df930be7Sderaadt 	 */
526df930be7Sderaadt 	bzero(start, v - start);
527df930be7Sderaadt 
528df930be7Sderaadt 	/*
529df930be7Sderaadt 	 * Initialize the virtual memory system, and set the
530df930be7Sderaadt 	 * page table base register in proc 0's PCB.
531df930be7Sderaadt 	 */
532df930be7Sderaadt 	pmap_bootstrap((vm_offset_t)v, phystok0seg(ptb << PGSHIFT));
533df930be7Sderaadt 
534df930be7Sderaadt 	/*
535df930be7Sderaadt 	 * Initialize the rest of proc 0's PCB, and cache its physical
536df930be7Sderaadt 	 * address.
537df930be7Sderaadt 	 */
538df930be7Sderaadt 	proc0.p_md.md_pcbpaddr =
539df930be7Sderaadt 	    (struct pcb *)k0segtophys(&proc0paddr->u_pcb);
540df930be7Sderaadt 
541df930be7Sderaadt 	/*
542df930be7Sderaadt 	 * Set the kernel sp, reserving space for an (empty) trapframe,
543df930be7Sderaadt 	 * and make proc0's trapframe pointer point to it for sanity.
544df930be7Sderaadt 	 */
545df930be7Sderaadt 	proc0paddr->u_pcb.pcb_ksp =
546df930be7Sderaadt 	    (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
547df930be7Sderaadt 	proc0.p_md.md_tf = (struct trapframe *)proc0paddr->u_pcb.pcb_ksp;
548df930be7Sderaadt 
549df930be7Sderaadt 	/*
550df930be7Sderaadt 	 * Look at arguments passed to us and compute boothowto.
551df930be7Sderaadt 	 */
552417eba8cSderaadt 	prom_getenv(PROM_E_BOOTED_OSFLAGS, boot_flags, sizeof(boot_flags));
553417eba8cSderaadt #if 0
554417eba8cSderaadt 	printf("boot flags = \"%s\"\n", boot_flags);
555df930be7Sderaadt #endif
556417eba8cSderaadt 
557417eba8cSderaadt 	boothowto = RB_SINGLE;
558df930be7Sderaadt #ifdef KADB
559df930be7Sderaadt 	boothowto |= RB_KDB;
560df930be7Sderaadt #endif
561df930be7Sderaadt 	for (p = boot_flags; p && *p != '\0'; p++) {
562417eba8cSderaadt 		/*
563417eba8cSderaadt 		 * Note that we'd really like to differentiate case here,
564417eba8cSderaadt 		 * but the Alpha AXP Architecture Reference Manual
565417eba8cSderaadt 		 * says that we shouldn't.
566417eba8cSderaadt 		 */
567df930be7Sderaadt 		switch (*p) {
568df930be7Sderaadt 		case 'a': /* autoboot */
569417eba8cSderaadt 		case 'A':
570df930be7Sderaadt 			boothowto &= ~RB_SINGLE;
571df930be7Sderaadt 			break;
572df930be7Sderaadt 
573417eba8cSderaadt 		case 'n': /* askname */
574417eba8cSderaadt 		case 'N':
575df930be7Sderaadt 			boothowto |= RB_ASKNAME;
576df930be7Sderaadt 			break;
577df930be7Sderaadt 
578417eba8cSderaadt #if 0
579417eba8cSderaadt 		case 'm': /* mini root present in memory */
580417eba8cSderaadt 		case 'M':
581417eba8cSderaadt 			boothowto |= RB_MINIROOT;
582417eba8cSderaadt 			break;
583417eba8cSderaadt #endif
584df930be7Sderaadt 		}
585df930be7Sderaadt 	}
586df930be7Sderaadt 
587df930be7Sderaadt 	/*
588df930be7Sderaadt 	 * Figure out the number of cpus in the box, from RPB fields.
589df930be7Sderaadt 	 * Really.  We mean it.
590df930be7Sderaadt 	 */
591df930be7Sderaadt 	for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
592df930be7Sderaadt 		struct pcs *pcsp;
593df930be7Sderaadt 
594df930be7Sderaadt 		pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off +
595df930be7Sderaadt 		    (i * hwrpb->rpb_pcs_size));
596df930be7Sderaadt 		if ((pcsp->pcs_flags & PCS_PP) != 0)
597df930be7Sderaadt 			ncpus++;
598df930be7Sderaadt 	}
599df930be7Sderaadt 
600df930be7Sderaadt 	return (0);
601df930be7Sderaadt }
602df930be7Sderaadt 
603417eba8cSderaadt void
604df930be7Sderaadt consinit()
605df930be7Sderaadt {
606df930be7Sderaadt 
607417eba8cSderaadt 	(*cpu_consinit)();
608df930be7Sderaadt 	pmap_unmap_prom();
609df930be7Sderaadt }
610df930be7Sderaadt 
611417eba8cSderaadt void
612df930be7Sderaadt cpu_startup()
613df930be7Sderaadt {
614df930be7Sderaadt 	register unsigned i;
615df930be7Sderaadt 	register caddr_t v;
616df930be7Sderaadt 	int base, residual;
617df930be7Sderaadt 	vm_offset_t minaddr, maxaddr;
618df930be7Sderaadt 	vm_size_t size;
619df930be7Sderaadt #ifdef DEBUG
620df930be7Sderaadt 	extern int pmapdebug;
621df930be7Sderaadt 	int opmapdebug = pmapdebug;
622df930be7Sderaadt 
623df930be7Sderaadt 	pmapdebug = 0;
624df930be7Sderaadt #endif
625df930be7Sderaadt 
626df930be7Sderaadt 	/*
627df930be7Sderaadt 	 * Good {morning,afternoon,evening,night}.
628df930be7Sderaadt 	 */
629df930be7Sderaadt 	printf(version);
630df930be7Sderaadt 	identifycpu();
631df930be7Sderaadt 	printf("real mem = %d (%d reserved for PROM, %d used by NetBSD)\n",
632df930be7Sderaadt 	    ctob(totalphysmem), ctob(resvmem), ctob(physmem));
633df930be7Sderaadt 	if (unusedmem)
634df930be7Sderaadt 		printf("WARNING: unused memory = %d bytes\n", ctob(unusedmem));
635df930be7Sderaadt 	if (unknownmem)
636df930be7Sderaadt 		printf("WARNING: %d bytes of memory with unknown purpose\n",
637df930be7Sderaadt 		    ctob(unknownmem));
638df930be7Sderaadt 
639df930be7Sderaadt 	/*
640df930be7Sderaadt 	 * Allocate virtual address space for file I/O buffers.
641df930be7Sderaadt 	 * Note they are different than the array of headers, 'buf',
642df930be7Sderaadt 	 * and usually occupy more virtual memory than physical.
643df930be7Sderaadt 	 */
644df930be7Sderaadt 	size = MAXBSIZE * nbuf;
645df930be7Sderaadt 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
646df930be7Sderaadt 	    &maxaddr, size, TRUE);
647df930be7Sderaadt 	minaddr = (vm_offset_t)buffers;
648df930be7Sderaadt 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
649df930be7Sderaadt 			&minaddr, size, FALSE) != KERN_SUCCESS)
650df930be7Sderaadt 		panic("startup: cannot allocate buffers");
651df930be7Sderaadt 	base = bufpages / nbuf;
652df930be7Sderaadt 	residual = bufpages % nbuf;
653df930be7Sderaadt 	for (i = 0; i < nbuf; i++) {
654df930be7Sderaadt 		vm_size_t curbufsize;
655df930be7Sderaadt 		vm_offset_t curbuf;
656df930be7Sderaadt 
657df930be7Sderaadt 		/*
658df930be7Sderaadt 		 * First <residual> buffers get (base+1) physical pages
659df930be7Sderaadt 		 * allocated for them.  The rest get (base) physical pages.
660df930be7Sderaadt 		 *
661df930be7Sderaadt 		 * The rest of each buffer occupies virtual space,
662df930be7Sderaadt 		 * but has no physical memory allocated for it.
663df930be7Sderaadt 		 */
664df930be7Sderaadt 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
665df930be7Sderaadt 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
666df930be7Sderaadt 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
667df930be7Sderaadt 		vm_map_simplify(buffer_map, curbuf);
668df930be7Sderaadt 	}
669df930be7Sderaadt 	/*
670df930be7Sderaadt 	 * Allocate a submap for exec arguments.  This map effectively
671df930be7Sderaadt 	 * limits the number of processes exec'ing at any time.
672df930be7Sderaadt 	 */
673df930be7Sderaadt 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
674df930be7Sderaadt 				 16 * NCARGS, TRUE);
675df930be7Sderaadt 
676df930be7Sderaadt 	/*
677df930be7Sderaadt 	 * Allocate a submap for physio
678df930be7Sderaadt 	 */
679df930be7Sderaadt 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
680df930be7Sderaadt 				 VM_PHYS_SIZE, TRUE);
681df930be7Sderaadt 
682df930be7Sderaadt 	/*
683df930be7Sderaadt 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
684df930be7Sderaadt 	 * we use the more space efficient malloc in place of kmem_alloc.
685df930be7Sderaadt 	 */
686df930be7Sderaadt 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
687df930be7Sderaadt 	    M_MBUF, M_NOWAIT);
688df930be7Sderaadt 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
689df930be7Sderaadt 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
690df930be7Sderaadt 	    VM_MBUF_SIZE, FALSE);
691df930be7Sderaadt 	/*
692df930be7Sderaadt 	 * Initialize callouts
693df930be7Sderaadt 	 */
694df930be7Sderaadt 	callfree = callout;
695df930be7Sderaadt 	for (i = 1; i < ncallout; i++)
696df930be7Sderaadt 		callout[i-1].c_next = &callout[i];
697df930be7Sderaadt 	callout[i-1].c_next = NULL;
698df930be7Sderaadt 
699df930be7Sderaadt #ifdef DEBUG
700df930be7Sderaadt 	pmapdebug = opmapdebug;
701df930be7Sderaadt #endif
702df930be7Sderaadt 	printf("avail mem = %ld\n", (long)ptoa(cnt.v_free_count));
703df930be7Sderaadt 	printf("using %ld buffers containing %ld bytes of memory\n",
704df930be7Sderaadt 		(long)nbuf, (long)(bufpages * CLBYTES));
705df930be7Sderaadt 
706df930be7Sderaadt 	/*
707df930be7Sderaadt 	 * Set up buffers, so they can be used to read disk labels.
708df930be7Sderaadt 	 */
709df930be7Sderaadt 	bufinit();
710df930be7Sderaadt 
711df930be7Sderaadt 	/*
712df930be7Sderaadt 	 * Configure the system.
713df930be7Sderaadt 	 */
714*41033391Sderaadt 	if (boothowto & RB_CONFIG) {
715*41033391Sderaadt #ifdef BOOT_CONFIG
716*41033391Sderaadt 		user_config();
717*41033391Sderaadt #else
718*41033391Sderaadt 		printf("kernel does not support -c; continuing..\n");
719*41033391Sderaadt #endif
720*41033391Sderaadt 	}
721df930be7Sderaadt 	configure();
722df930be7Sderaadt }
723df930be7Sderaadt 
724df930be7Sderaadt identifycpu()
725df930be7Sderaadt {
726df930be7Sderaadt 
727df930be7Sderaadt 	/*
728df930be7Sderaadt 	 * print out CPU identification information.
729df930be7Sderaadt 	 */
730df930be7Sderaadt 	printf("%s, %dMHz\n", cpu_model,
731df930be7Sderaadt 	    hwrpb->rpb_cc_freq / 1000000);	/* XXX true for 21164? */
732df930be7Sderaadt 	printf("%d byte page size, %d processor%s.\n",
733df930be7Sderaadt 	    hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s");
734df930be7Sderaadt #if 0
735df930be7Sderaadt 	/* this isn't defined for any systems that we run on? */
736df930be7Sderaadt 	printf("serial number 0x%lx 0x%lx\n",
737df930be7Sderaadt 	    ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]);
738df930be7Sderaadt 
739df930be7Sderaadt 	/* and these aren't particularly useful! */
740df930be7Sderaadt 	printf("variation: 0x%lx, revision 0x%lx\n",
741df930be7Sderaadt 	    hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
742df930be7Sderaadt #endif
743df930be7Sderaadt }
744df930be7Sderaadt 
745df930be7Sderaadt int	waittime = -1;
746df930be7Sderaadt struct pcb dumppcb;
747df930be7Sderaadt 
748417eba8cSderaadt void
749df930be7Sderaadt boot(howto)
750df930be7Sderaadt 	int howto;
751df930be7Sderaadt {
752df930be7Sderaadt 	extern int cold;
753df930be7Sderaadt 
754df930be7Sderaadt 	/* If system is cold, just halt. */
755df930be7Sderaadt 	if (cold) {
756df930be7Sderaadt 		howto |= RB_HALT;
757df930be7Sderaadt 		goto haltsys;
758df930be7Sderaadt 	}
759df930be7Sderaadt 
760df930be7Sderaadt 	boothowto = howto;
761df930be7Sderaadt 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
762df930be7Sderaadt 		waittime = 0;
763df930be7Sderaadt 		vfs_shutdown();
764df930be7Sderaadt 		/*
765df930be7Sderaadt 		 * If we've been adjusting the clock, the todr
766df930be7Sderaadt 		 * will be out of synch; adjust it now.
767df930be7Sderaadt 		 */
768df930be7Sderaadt 		resettodr();
769df930be7Sderaadt 	}
770df930be7Sderaadt 
771df930be7Sderaadt 	/* Disable interrupts. */
772df930be7Sderaadt 	splhigh();
773df930be7Sderaadt 
774df930be7Sderaadt 	/* If rebooting and a dump is requested do it. */
775df930be7Sderaadt 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) {
776df930be7Sderaadt 		savectx(&dumppcb, 0);
777df930be7Sderaadt 		dumpsys();
778df930be7Sderaadt 	}
779df930be7Sderaadt 
78034fbf6deSderaadt haltsys:
78134fbf6deSderaadt 
782df930be7Sderaadt 	/* run any shutdown hooks */
783df930be7Sderaadt 	doshutdownhooks();
784df930be7Sderaadt 
785df930be7Sderaadt #ifdef BOOTKEY
786df930be7Sderaadt 	printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
787df930be7Sderaadt 	cngetc();
788df930be7Sderaadt 	printf("\n");
789df930be7Sderaadt #endif
790df930be7Sderaadt 
791df930be7Sderaadt 	/* Finally, halt/reboot the system. */
792df930be7Sderaadt 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
793df930be7Sderaadt 	prom_halt(howto & RB_HALT);
794df930be7Sderaadt 	/*NOTREACHED*/
795df930be7Sderaadt }
796df930be7Sderaadt 
797df930be7Sderaadt /*
798df930be7Sderaadt  * These variables are needed by /sbin/savecore
799df930be7Sderaadt  */
800df930be7Sderaadt u_long	dumpmag = 0x8fca0101;	/* magic number */
801df930be7Sderaadt int 	dumpsize = 0;		/* pages */
802df930be7Sderaadt long	dumplo = 0; 		/* blocks */
803df930be7Sderaadt 
804df930be7Sderaadt /*
805df930be7Sderaadt  * This is called by configure to set dumplo and dumpsize.
806df930be7Sderaadt  * Dumps always skip the first CLBYTES of disk space
807df930be7Sderaadt  * in case there might be a disk label stored there.
808df930be7Sderaadt  * If there is extra space, put dump at the end to
809df930be7Sderaadt  * reduce the chance that swapping trashes it.
810df930be7Sderaadt  */
811df930be7Sderaadt void
812df930be7Sderaadt dumpconf()
813df930be7Sderaadt {
814df930be7Sderaadt 	int nblks;	/* size of dump area */
815df930be7Sderaadt 	int maj;
816df930be7Sderaadt 
817df930be7Sderaadt 	if (dumpdev == NODEV)
818df930be7Sderaadt 		return;
819df930be7Sderaadt 	maj = major(dumpdev);
820df930be7Sderaadt 	if (maj < 0 || maj >= nblkdev)
821df930be7Sderaadt 		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
822df930be7Sderaadt 	if (bdevsw[maj].d_psize == NULL)
823df930be7Sderaadt 		return;
824df930be7Sderaadt 	nblks = (*bdevsw[maj].d_psize)(dumpdev);
825df930be7Sderaadt 	if (nblks <= ctod(1))
826df930be7Sderaadt 		return;
827df930be7Sderaadt 
828df930be7Sderaadt 	/* XXX XXX XXX STARTING MEMORY LOCATION */
829df930be7Sderaadt 	dumpsize = physmem;
830df930be7Sderaadt 
831df930be7Sderaadt 	/* Always skip the first CLBYTES, in case there is a label there. */
832df930be7Sderaadt 	if (dumplo < ctod(1))
833df930be7Sderaadt 		dumplo = ctod(1);
834df930be7Sderaadt 
835df930be7Sderaadt 	/* Put dump at end of partition, and make it fit. */
836df930be7Sderaadt 	if (dumpsize > dtoc(nblks - dumplo))
837df930be7Sderaadt 		dumpsize = dtoc(nblks - dumplo);
838df930be7Sderaadt 	if (dumplo < nblks - ctod(dumpsize))
839df930be7Sderaadt 		dumplo = nblks - ctod(dumpsize);
840df930be7Sderaadt }
841df930be7Sderaadt 
842df930be7Sderaadt /*
843df930be7Sderaadt  * Doadump comes here after turning off memory management and
844df930be7Sderaadt  * getting on the dump stack, either when called above, or by
845df930be7Sderaadt  * the auto-restart code.
846df930be7Sderaadt  */
847df930be7Sderaadt void
848df930be7Sderaadt dumpsys()
849df930be7Sderaadt {
850df930be7Sderaadt 
851df930be7Sderaadt 	msgbufmapped = 0;
852df930be7Sderaadt 	if (dumpdev == NODEV)
853df930be7Sderaadt 		return;
854df930be7Sderaadt 	if (dumpsize == 0) {
855df930be7Sderaadt 		dumpconf();
856df930be7Sderaadt 		if (dumpsize == 0)
857df930be7Sderaadt 			return;
858df930be7Sderaadt 	}
859df930be7Sderaadt 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
860df930be7Sderaadt 
861df930be7Sderaadt 	printf("dump ");
862df930be7Sderaadt 	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
863df930be7Sderaadt 
864df930be7Sderaadt 	case ENXIO:
865df930be7Sderaadt 		printf("device bad\n");
866df930be7Sderaadt 		break;
867df930be7Sderaadt 
868df930be7Sderaadt 	case EFAULT:
869df930be7Sderaadt 		printf("device not ready\n");
870df930be7Sderaadt 		break;
871df930be7Sderaadt 
872df930be7Sderaadt 	case EINVAL:
873df930be7Sderaadt 		printf("area improper\n");
874df930be7Sderaadt 		break;
875df930be7Sderaadt 
876df930be7Sderaadt 	case EIO:
877df930be7Sderaadt 		printf("i/o error\n");
878df930be7Sderaadt 		break;
879df930be7Sderaadt 
880df930be7Sderaadt 	case EINTR:
881df930be7Sderaadt 		printf("aborted from console\n");
882df930be7Sderaadt 		break;
883df930be7Sderaadt 
884df930be7Sderaadt 	default:
885df930be7Sderaadt 		printf("succeeded\n");
886df930be7Sderaadt 		break;
887df930be7Sderaadt 	}
888df930be7Sderaadt 	printf("\n\n");
889df930be7Sderaadt 	delay(1000);
890df930be7Sderaadt }
891df930be7Sderaadt 
892df930be7Sderaadt void
893df930be7Sderaadt frametoreg(framep, regp)
894df930be7Sderaadt 	struct trapframe *framep;
895df930be7Sderaadt 	struct reg *regp;
896df930be7Sderaadt {
897df930be7Sderaadt 
898df930be7Sderaadt 	regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
899df930be7Sderaadt 	regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
900df930be7Sderaadt 	regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
901df930be7Sderaadt 	regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
902df930be7Sderaadt 	regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
903df930be7Sderaadt 	regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
904df930be7Sderaadt 	regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
905df930be7Sderaadt 	regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
906df930be7Sderaadt 	regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
907df930be7Sderaadt 	regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
908df930be7Sderaadt 	regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
909df930be7Sderaadt 	regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
910df930be7Sderaadt 	regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
911df930be7Sderaadt 	regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
912df930be7Sderaadt 	regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
913df930be7Sderaadt 	regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
914df930be7Sderaadt 	regp->r_regs[R_A0] = framep->tf_a0;
915df930be7Sderaadt 	regp->r_regs[R_A1] = framep->tf_a1;
916df930be7Sderaadt 	regp->r_regs[R_A2] = framep->tf_a2;
917df930be7Sderaadt 	regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
918df930be7Sderaadt 	regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
919df930be7Sderaadt 	regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
920df930be7Sderaadt 	regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
921df930be7Sderaadt 	regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
922df930be7Sderaadt 	regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
923df930be7Sderaadt 	regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
924df930be7Sderaadt 	regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
925df930be7Sderaadt 	regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
926df930be7Sderaadt 	regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
927df930be7Sderaadt 	regp->r_regs[R_GP] = framep->tf_gp;
928df930be7Sderaadt 	regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP];
929df930be7Sderaadt 	regp->r_regs[R_ZERO] = 0;
930df930be7Sderaadt }
931df930be7Sderaadt 
932df930be7Sderaadt void
933df930be7Sderaadt regtoframe(regp, framep)
934df930be7Sderaadt 	struct reg *regp;
935df930be7Sderaadt 	struct trapframe *framep;
936df930be7Sderaadt {
937df930be7Sderaadt 
938df930be7Sderaadt 	framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
939df930be7Sderaadt 	framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
940df930be7Sderaadt 	framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
941df930be7Sderaadt 	framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
942df930be7Sderaadt 	framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
943df930be7Sderaadt 	framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
944df930be7Sderaadt 	framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
945df930be7Sderaadt 	framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
946df930be7Sderaadt 	framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
947df930be7Sderaadt 	framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
948df930be7Sderaadt 	framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
949df930be7Sderaadt 	framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
950df930be7Sderaadt 	framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
951df930be7Sderaadt 	framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
952df930be7Sderaadt 	framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
953df930be7Sderaadt 	framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
954df930be7Sderaadt 	framep->tf_a0 = regp->r_regs[R_A0];
955df930be7Sderaadt 	framep->tf_a1 = regp->r_regs[R_A1];
956df930be7Sderaadt 	framep->tf_a2 = regp->r_regs[R_A2];
957df930be7Sderaadt 	framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
958df930be7Sderaadt 	framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
959df930be7Sderaadt 	framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
960df930be7Sderaadt 	framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
961df930be7Sderaadt 	framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
962df930be7Sderaadt 	framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
963df930be7Sderaadt 	framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
964df930be7Sderaadt 	framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
965df930be7Sderaadt 	framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
966df930be7Sderaadt 	framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
967df930be7Sderaadt 	framep->tf_gp = regp->r_regs[R_GP];
968df930be7Sderaadt 	framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP];
969df930be7Sderaadt 	/* ??? = regp->r_regs[R_ZERO]; */
970df930be7Sderaadt }
971df930be7Sderaadt 
972df930be7Sderaadt void
973df930be7Sderaadt printregs(regp)
974df930be7Sderaadt 	struct reg *regp;
975df930be7Sderaadt {
976df930be7Sderaadt 	int i;
977df930be7Sderaadt 
978df930be7Sderaadt 	for (i = 0; i < 32; i++)
979df930be7Sderaadt 		printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
980df930be7Sderaadt 		   i & 1 ? "\n" : "\t");
981df930be7Sderaadt }
982df930be7Sderaadt 
983df930be7Sderaadt void
984df930be7Sderaadt regdump(framep)
985df930be7Sderaadt 	struct trapframe *framep;
986df930be7Sderaadt {
987df930be7Sderaadt 	struct reg reg;
988df930be7Sderaadt 
989df930be7Sderaadt 	frametoreg(framep, &reg);
990df930be7Sderaadt 	printf("REGISTERS:\n");
991df930be7Sderaadt 	printregs(&reg);
992df930be7Sderaadt }
993df930be7Sderaadt 
994df930be7Sderaadt #ifdef DEBUG
995df930be7Sderaadt int sigdebug = 0;
996df930be7Sderaadt int sigpid = 0;
997df930be7Sderaadt #define	SDB_FOLLOW	0x01
998df930be7Sderaadt #define	SDB_KSTACK	0x02
999df930be7Sderaadt #endif
1000df930be7Sderaadt 
1001df930be7Sderaadt /*
1002df930be7Sderaadt  * Send an interrupt to process.
1003df930be7Sderaadt  */
1004df930be7Sderaadt void
1005df930be7Sderaadt sendsig(catcher, sig, mask, code)
1006df930be7Sderaadt 	sig_t catcher;
1007df930be7Sderaadt 	int sig, mask;
1008df930be7Sderaadt 	u_long code;
1009df930be7Sderaadt {
1010df930be7Sderaadt 	struct proc *p = curproc;
1011df930be7Sderaadt 	struct sigcontext *scp, ksc;
1012df930be7Sderaadt 	struct trapframe *frame;
1013df930be7Sderaadt 	struct sigacts *psp = p->p_sigacts;
1014df930be7Sderaadt 	int oonstack, fsize, rndfsize;
1015df930be7Sderaadt 	extern char sigcode[], esigcode[];
1016df930be7Sderaadt 	extern struct proc *fpcurproc;
1017df930be7Sderaadt 
1018df930be7Sderaadt 	frame = p->p_md.md_tf;
1019df930be7Sderaadt 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
1020df930be7Sderaadt 	fsize = sizeof ksc;
1021df930be7Sderaadt 	rndfsize = ((fsize + 15) / 16) * 16;
1022df930be7Sderaadt 	/*
1023df930be7Sderaadt 	 * Allocate and validate space for the signal handler
1024df930be7Sderaadt 	 * context. Note that if the stack is in P0 space, the
1025df930be7Sderaadt 	 * call to grow() is a nop, and the useracc() check
1026df930be7Sderaadt 	 * will fail if the process has not already allocated
1027df930be7Sderaadt 	 * the space with a `brk'.
1028df930be7Sderaadt 	 */
1029df930be7Sderaadt 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1030df930be7Sderaadt 	    (psp->ps_sigonstack & sigmask(sig))) {
10318bc2093aSderaadt 		scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp +
1032df930be7Sderaadt 		    psp->ps_sigstk.ss_size - rndfsize);
1033df930be7Sderaadt 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
1034df930be7Sderaadt 	} else
1035df930be7Sderaadt 		scp = (struct sigcontext *)(frame->tf_regs[FRAME_SP] -
1036df930be7Sderaadt 		    rndfsize);
1037df930be7Sderaadt 	if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
1038df930be7Sderaadt 		(void)grow(p, (u_long)scp);
1039df930be7Sderaadt #ifdef DEBUG
1040df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1041df930be7Sderaadt 		printf("sendsig(%d): sig %d ssp %lx usp %lx\n", p->p_pid,
1042df930be7Sderaadt 		    sig, &oonstack, scp);
1043df930be7Sderaadt #endif
1044df930be7Sderaadt 	if (useracc((caddr_t)scp, fsize, B_WRITE) == 0) {
1045df930be7Sderaadt #ifdef DEBUG
1046df930be7Sderaadt 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1047df930be7Sderaadt 			printf("sendsig(%d): useracc failed on sig %d\n",
1048df930be7Sderaadt 			    p->p_pid, sig);
1049df930be7Sderaadt #endif
1050df930be7Sderaadt 		/*
1051df930be7Sderaadt 		 * Process has trashed its stack; give it an illegal
1052df930be7Sderaadt 		 * instruction to halt it in its tracks.
1053df930be7Sderaadt 		 */
1054df930be7Sderaadt 		SIGACTION(p, SIGILL) = SIG_DFL;
1055df930be7Sderaadt 		sig = sigmask(SIGILL);
1056df930be7Sderaadt 		p->p_sigignore &= ~sig;
1057df930be7Sderaadt 		p->p_sigcatch &= ~sig;
1058df930be7Sderaadt 		p->p_sigmask &= ~sig;
1059df930be7Sderaadt 		psignal(p, SIGILL);
1060df930be7Sderaadt 		return;
1061df930be7Sderaadt 	}
1062df930be7Sderaadt 
1063df930be7Sderaadt 	/*
1064df930be7Sderaadt 	 * Build the signal context to be used by sigreturn.
1065df930be7Sderaadt 	 */
1066df930be7Sderaadt 	ksc.sc_onstack = oonstack;
1067df930be7Sderaadt 	ksc.sc_mask = mask;
1068df930be7Sderaadt 	ksc.sc_pc = frame->tf_pc;
1069df930be7Sderaadt 	ksc.sc_ps = frame->tf_ps;
1070df930be7Sderaadt 
1071df930be7Sderaadt 	/* copy the registers. */
1072df930be7Sderaadt 	frametoreg(frame, (struct reg *)ksc.sc_regs);
1073df930be7Sderaadt 	ksc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
1074df930be7Sderaadt 
1075df930be7Sderaadt 	/* save the floating-point state, if necessary, then copy it. */
1076df930be7Sderaadt 	if (p == fpcurproc) {
1077df930be7Sderaadt 		pal_wrfen(1);
1078df930be7Sderaadt 		savefpstate(&p->p_addr->u_pcb.pcb_fp);
1079df930be7Sderaadt 		pal_wrfen(0);
1080df930be7Sderaadt 		fpcurproc = NULL;
1081df930be7Sderaadt 	}
1082df930be7Sderaadt 	ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
1083df930be7Sderaadt 	bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
1084df930be7Sderaadt 	    sizeof(struct fpreg));
1085df930be7Sderaadt 	ksc.sc_fp_control = 0;					/* XXX ? */
1086df930be7Sderaadt 	bzero(ksc.sc_reserved, sizeof ksc.sc_reserved);		/* XXX */
1087df930be7Sderaadt 	bzero(ksc.sc_xxx, sizeof ksc.sc_xxx);			/* XXX */
1088df930be7Sderaadt 
1089df930be7Sderaadt 
1090df930be7Sderaadt #ifdef COMPAT_OSF1
1091df930be7Sderaadt 	/*
1092df930be7Sderaadt 	 * XXX Create an OSF/1-style sigcontext and associated goo.
1093df930be7Sderaadt 	 */
1094df930be7Sderaadt #endif
1095df930be7Sderaadt 
1096df930be7Sderaadt 	/*
1097df930be7Sderaadt 	 * copy the frame out to userland.
1098df930be7Sderaadt 	 */
1099df930be7Sderaadt 	(void) copyout((caddr_t)&ksc, (caddr_t)scp, fsize);
1100df930be7Sderaadt #ifdef DEBUG
1101df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1102df930be7Sderaadt 		printf("sendsig(%d): sig %d scp %lx code %lx\n", p->p_pid, sig,
1103df930be7Sderaadt 		    scp, code);
1104df930be7Sderaadt #endif
1105df930be7Sderaadt 
1106df930be7Sderaadt 	/*
1107df930be7Sderaadt 	 * Set up the registers to return to sigcode.
1108df930be7Sderaadt 	 */
1109df930be7Sderaadt 	frame->tf_pc = (u_int64_t)PS_STRINGS - (esigcode - sigcode);
1110df930be7Sderaadt 	frame->tf_regs[FRAME_SP] = (u_int64_t)scp;
1111df930be7Sderaadt 	frame->tf_a0 = sig;
1112df930be7Sderaadt 	frame->tf_a1 = code;
1113df930be7Sderaadt 	frame->tf_a2 = (u_int64_t)scp;
1114df930be7Sderaadt 	frame->tf_regs[FRAME_T12] = (u_int64_t)catcher;		/* t12 is pv */
1115df930be7Sderaadt 
1116df930be7Sderaadt #ifdef DEBUG
1117df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1118df930be7Sderaadt 		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
1119df930be7Sderaadt 		    frame->tf_pc, frame->tf_regs[FRAME_A3]);
1120df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1121df930be7Sderaadt 		printf("sendsig(%d): sig %d returns\n",
1122df930be7Sderaadt 		    p->p_pid, sig);
1123df930be7Sderaadt #endif
1124df930be7Sderaadt }
1125df930be7Sderaadt 
1126df930be7Sderaadt /*
1127df930be7Sderaadt  * System call to cleanup state after a signal
1128df930be7Sderaadt  * has been taken.  Reset signal mask and
1129df930be7Sderaadt  * stack state from context left by sendsig (above).
1130df930be7Sderaadt  * Return to previous pc and psl as specified by
1131df930be7Sderaadt  * context left by sendsig. Check carefully to
1132df930be7Sderaadt  * make sure that the user has not modified the
1133df930be7Sderaadt  * psl to gain improper priviledges or to cause
1134df930be7Sderaadt  * a machine fault.
1135df930be7Sderaadt  */
1136df930be7Sderaadt /* ARGSUSED */
1137df930be7Sderaadt int
1138df930be7Sderaadt sys_sigreturn(p, v, retval)
1139df930be7Sderaadt 	struct proc *p;
1140df930be7Sderaadt 	void *v;
1141df930be7Sderaadt 	register_t *retval;
1142df930be7Sderaadt {
1143df930be7Sderaadt 	struct sys_sigreturn_args /* {
1144df930be7Sderaadt 		syscallarg(struct sigcontext *) sigcntxp;
1145df930be7Sderaadt 	} */ *uap = v;
1146df930be7Sderaadt 	struct sigcontext *scp, ksc;
1147df930be7Sderaadt 	extern struct proc *fpcurproc;
1148df930be7Sderaadt 
1149df930be7Sderaadt 	scp = SCARG(uap, sigcntxp);
1150df930be7Sderaadt #ifdef DEBUG
1151df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1152df930be7Sderaadt 	    printf("sigreturn: pid %d, scp %lx\n", p->p_pid, scp);
1153df930be7Sderaadt #endif
1154df930be7Sderaadt 
1155df930be7Sderaadt 	if (ALIGN(scp) != (u_int64_t)scp)
1156df930be7Sderaadt 		return (EINVAL);
1157df930be7Sderaadt 
1158df930be7Sderaadt 	/*
1159df930be7Sderaadt 	 * Test and fetch the context structure.
1160df930be7Sderaadt 	 * We grab it all at once for speed.
1161df930be7Sderaadt 	 */
1162df930be7Sderaadt 	if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
1163df930be7Sderaadt 	    copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
1164df930be7Sderaadt 		return (EINVAL);
1165df930be7Sderaadt 
1166df930be7Sderaadt 	if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)		/* magic number */
1167df930be7Sderaadt 		return (EINVAL);
1168df930be7Sderaadt 	/*
1169df930be7Sderaadt 	 * Restore the user-supplied information
1170df930be7Sderaadt 	 */
1171df930be7Sderaadt 	if (ksc.sc_onstack)
1172df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
1173df930be7Sderaadt 	else
1174df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1175df930be7Sderaadt 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1176df930be7Sderaadt 
1177df930be7Sderaadt 	p->p_md.md_tf->tf_pc = ksc.sc_pc;
1178df930be7Sderaadt 	p->p_md.md_tf->tf_ps = (ksc.sc_ps | PSL_USERSET) & ~PSL_USERCLR;
1179df930be7Sderaadt 
1180df930be7Sderaadt 	regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
1181df930be7Sderaadt 
1182df930be7Sderaadt 	/* XXX ksc.sc_ownedfp ? */
1183df930be7Sderaadt 	if (p == fpcurproc)
1184df930be7Sderaadt 		fpcurproc = NULL;
1185df930be7Sderaadt 	bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
1186df930be7Sderaadt 	    sizeof(struct fpreg));
1187df930be7Sderaadt 	/* XXX ksc.sc_fp_control ? */
1188df930be7Sderaadt 
1189df930be7Sderaadt #ifdef DEBUG
1190df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1191df930be7Sderaadt 		printf("sigreturn(%d): returns\n", p->p_pid);
1192df930be7Sderaadt #endif
1193df930be7Sderaadt 	return (EJUSTRETURN);
1194df930be7Sderaadt }
1195df930be7Sderaadt 
1196df930be7Sderaadt /*
1197df930be7Sderaadt  * machine dependent system variables.
1198df930be7Sderaadt  */
1199df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1200df930be7Sderaadt 	int *name;
1201df930be7Sderaadt 	u_int namelen;
1202df930be7Sderaadt 	void *oldp;
1203df930be7Sderaadt 	size_t *oldlenp;
1204df930be7Sderaadt 	void *newp;
1205df930be7Sderaadt 	size_t newlen;
1206df930be7Sderaadt 	struct proc *p;
1207df930be7Sderaadt {
1208df930be7Sderaadt 	dev_t consdev;
1209df930be7Sderaadt 
1210df930be7Sderaadt 	/* all sysctl names at this level are terminal */
1211df930be7Sderaadt 	if (namelen != 1)
1212df930be7Sderaadt 		return (ENOTDIR);		/* overloaded */
1213df930be7Sderaadt 
1214df930be7Sderaadt 	switch (name[0]) {
1215df930be7Sderaadt 	case CPU_CONSDEV:
1216df930be7Sderaadt 		if (cn_tab != NULL)
1217df930be7Sderaadt 			consdev = cn_tab->cn_dev;
1218df930be7Sderaadt 		else
1219df930be7Sderaadt 			consdev = NODEV;
1220df930be7Sderaadt 		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1221df930be7Sderaadt 			sizeof consdev));
1222417eba8cSderaadt 
1223417eba8cSderaadt 	case CPU_ROOT_DEVICE:
1224417eba8cSderaadt 		return (sysctl_rdstring(oldp, oldlenp, newp, root_device));
1225417eba8cSderaadt 
1226df930be7Sderaadt 	default:
1227df930be7Sderaadt 		return (EOPNOTSUPP);
1228df930be7Sderaadt 	}
1229df930be7Sderaadt 	/* NOTREACHED */
1230df930be7Sderaadt }
1231df930be7Sderaadt 
1232df930be7Sderaadt /*
1233df930be7Sderaadt  * Set registers on exec.
1234df930be7Sderaadt  */
1235df930be7Sderaadt void
1236df930be7Sderaadt setregs(p, pack, stack, retval)
1237df930be7Sderaadt 	register struct proc *p;
1238df930be7Sderaadt 	struct exec_package *pack;
1239df930be7Sderaadt 	u_long stack;
1240df930be7Sderaadt 	register_t *retval;
1241df930be7Sderaadt {
1242df930be7Sderaadt 	struct trapframe *tfp = p->p_md.md_tf;
1243df930be7Sderaadt 	int i;
1244df930be7Sderaadt 	extern struct proc *fpcurproc;
1245df930be7Sderaadt 
1246df930be7Sderaadt #ifdef DEBUG
1247df930be7Sderaadt 	for (i = 0; i < FRAME_NSAVEREGS; i++)
1248df930be7Sderaadt 		tfp->tf_regs[i] = 0xbabefacedeadbeef;
1249df930be7Sderaadt 	tfp->tf_gp = 0xbabefacedeadbeef;
1250df930be7Sderaadt 	tfp->tf_a0 = 0xbabefacedeadbeef;
1251df930be7Sderaadt 	tfp->tf_a1 = 0xbabefacedeadbeef;
1252df930be7Sderaadt 	tfp->tf_a2 = 0xbabefacedeadbeef;
1253df930be7Sderaadt #else
1254df930be7Sderaadt 	bzero(tfp->tf_regs, FRAME_NSAVEREGS * sizeof tfp->tf_regs[0]);
1255df930be7Sderaadt 	tfp->tf_gp = 0;
1256df930be7Sderaadt 	tfp->tf_a0 = 0;
1257df930be7Sderaadt 	tfp->tf_a1 = 0;
1258df930be7Sderaadt 	tfp->tf_a2 = 0;
1259df930be7Sderaadt #endif
1260df930be7Sderaadt 	bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
1261df930be7Sderaadt #define FP_RN 2 /* XXX */
1262df930be7Sderaadt 	p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58;
1263df930be7Sderaadt 	tfp->tf_regs[FRAME_SP] = stack;	/* restored to usp in trap return */
1264df930be7Sderaadt 	tfp->tf_ps = PSL_USERSET;
1265df930be7Sderaadt 	tfp->tf_pc = pack->ep_entry & ~3;
1266df930be7Sderaadt 
1267df930be7Sderaadt 	p->p_md.md_flags & ~MDP_FPUSED;
1268df930be7Sderaadt 	if (fpcurproc == p)
1269df930be7Sderaadt 		fpcurproc = NULL;
1270df930be7Sderaadt 
1271df930be7Sderaadt 	retval[0] = retval[1] = 0;
1272df930be7Sderaadt }
1273df930be7Sderaadt 
1274df930be7Sderaadt void
1275df930be7Sderaadt netintr()
1276df930be7Sderaadt {
1277df930be7Sderaadt #ifdef INET
1278df930be7Sderaadt #if NETHER > 0
1279df930be7Sderaadt 	if (netisr & (1 << NETISR_ARP)) {
1280df930be7Sderaadt 		netisr &= ~(1 << NETISR_ARP);
1281df930be7Sderaadt 		arpintr();
1282df930be7Sderaadt 	}
1283df930be7Sderaadt #endif
1284df930be7Sderaadt 	if (netisr & (1 << NETISR_IP)) {
1285df930be7Sderaadt 		netisr &= ~(1 << NETISR_IP);
1286df930be7Sderaadt 		ipintr();
1287df930be7Sderaadt 	}
1288df930be7Sderaadt #endif
1289df930be7Sderaadt #ifdef NS
1290df930be7Sderaadt 	if (netisr & (1 << NETISR_NS)) {
1291df930be7Sderaadt 		netisr &= ~(1 << NETISR_NS);
1292df930be7Sderaadt 		nsintr();
1293df930be7Sderaadt 	}
1294df930be7Sderaadt #endif
1295df930be7Sderaadt #ifdef ISO
1296df930be7Sderaadt 	if (netisr & (1 << NETISR_ISO)) {
1297df930be7Sderaadt 		netisr &= ~(1 << NETISR_ISO);
1298df930be7Sderaadt 		clnlintr();
1299df930be7Sderaadt 	}
1300df930be7Sderaadt #endif
1301df930be7Sderaadt #ifdef CCITT
1302df930be7Sderaadt 	if (netisr & (1 << NETISR_CCITT)) {
1303df930be7Sderaadt 		netisr &= ~(1 << NETISR_CCITT);
1304df930be7Sderaadt 		ccittintr();
1305df930be7Sderaadt 	}
1306df930be7Sderaadt #endif
1307df930be7Sderaadt #ifdef PPP
1308df930be7Sderaadt 	if (netisr & (1 << NETISR_PPP)) {
1309417eba8cSderaadt 		netisr &= ~(1 << NETISR_PPP);
1310df930be7Sderaadt 		pppintr();
1311df930be7Sderaadt 	}
1312df930be7Sderaadt #endif
1313df930be7Sderaadt }
1314df930be7Sderaadt 
1315df930be7Sderaadt void
1316df930be7Sderaadt do_sir()
1317df930be7Sderaadt {
1318df930be7Sderaadt 
1319df930be7Sderaadt 	if (ssir & SIR_NET) {
1320df930be7Sderaadt 		siroff(SIR_NET);
1321df930be7Sderaadt 		cnt.v_soft++;
1322df930be7Sderaadt 		netintr();
1323df930be7Sderaadt 	}
1324df930be7Sderaadt 	if (ssir & SIR_CLOCK) {
1325df930be7Sderaadt 		siroff(SIR_CLOCK);
1326df930be7Sderaadt 		cnt.v_soft++;
1327df930be7Sderaadt 		softclock();
1328df930be7Sderaadt 	}
1329df930be7Sderaadt }
1330df930be7Sderaadt 
1331df930be7Sderaadt int
1332df930be7Sderaadt spl0()
1333df930be7Sderaadt {
1334df930be7Sderaadt 
1335df930be7Sderaadt 	if (ssir) {
1336df930be7Sderaadt 		splsoft();
1337df930be7Sderaadt 		do_sir();
1338df930be7Sderaadt 	}
1339df930be7Sderaadt 
1340df930be7Sderaadt 	return (pal_swpipl(PSL_IPL_0));
1341df930be7Sderaadt }
1342df930be7Sderaadt 
1343df930be7Sderaadt /*
1344df930be7Sderaadt  * The following primitives manipulate the run queues.  _whichqs tells which
1345df930be7Sderaadt  * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
1346df930be7Sderaadt  * into queues, Remrq removes them from queues.  The running process is on
1347df930be7Sderaadt  * no queue, other processes are on a queue related to p->p_priority, divided
1348df930be7Sderaadt  * by 4 actually to shrink the 0-127 range of priorities into the 32 available
1349df930be7Sderaadt  * queues.
1350df930be7Sderaadt  */
1351df930be7Sderaadt /*
1352df930be7Sderaadt  * setrunqueue(p)
1353df930be7Sderaadt  *	proc *p;
1354df930be7Sderaadt  *
1355df930be7Sderaadt  * Call should be made at splclock(), and p->p_stat should be SRUN.
1356df930be7Sderaadt  */
1357df930be7Sderaadt 
1358df930be7Sderaadt void
1359df930be7Sderaadt setrunqueue(p)
1360df930be7Sderaadt 	struct proc *p;
1361df930be7Sderaadt {
1362df930be7Sderaadt 	int bit;
1363df930be7Sderaadt 
1364df930be7Sderaadt 	/* firewall: p->p_back must be NULL */
1365df930be7Sderaadt 	if (p->p_back != NULL)
1366df930be7Sderaadt 		panic("setrunqueue");
1367df930be7Sderaadt 
1368df930be7Sderaadt 	bit = p->p_priority >> 2;
1369df930be7Sderaadt 	whichqs |= (1 << bit);
1370df930be7Sderaadt 	p->p_forw = (struct proc *)&qs[bit];
1371df930be7Sderaadt 	p->p_back = qs[bit].ph_rlink;
1372df930be7Sderaadt 	p->p_back->p_forw = p;
1373df930be7Sderaadt 	qs[bit].ph_rlink = p;
1374df930be7Sderaadt }
1375df930be7Sderaadt 
1376df930be7Sderaadt /*
1377df930be7Sderaadt  * Remrq(p)
1378df930be7Sderaadt  *
1379df930be7Sderaadt  * Call should be made at splclock().
1380df930be7Sderaadt  */
1381df930be7Sderaadt void
1382df930be7Sderaadt remrq(p)
1383df930be7Sderaadt 	struct proc *p;
1384df930be7Sderaadt {
1385df930be7Sderaadt 	int bit;
1386df930be7Sderaadt 
1387df930be7Sderaadt 	bit = p->p_priority >> 2;
1388df930be7Sderaadt 	if ((whichqs & (1 << bit)) == 0)
1389df930be7Sderaadt 		panic("remrq");
1390df930be7Sderaadt 
1391df930be7Sderaadt 	p->p_back->p_forw = p->p_forw;
1392df930be7Sderaadt 	p->p_forw->p_back = p->p_back;
1393df930be7Sderaadt 	p->p_back = NULL;	/* for firewall checking. */
1394df930be7Sderaadt 
1395df930be7Sderaadt 	if ((struct proc *)&qs[bit] == qs[bit].ph_link)
1396df930be7Sderaadt 		whichqs &= ~(1 << bit);
1397df930be7Sderaadt }
1398df930be7Sderaadt 
1399df930be7Sderaadt /*
1400df930be7Sderaadt  * Return the best possible estimate of the time in the timeval
1401df930be7Sderaadt  * to which tvp points.  Unfortunately, we can't read the hardware registers.
1402df930be7Sderaadt  * We guarantee that the time will be greater than the value obtained by a
1403df930be7Sderaadt  * previous call.
1404df930be7Sderaadt  */
1405df930be7Sderaadt void
1406df930be7Sderaadt microtime(tvp)
1407df930be7Sderaadt 	register struct timeval *tvp;
1408df930be7Sderaadt {
1409df930be7Sderaadt 	int s = splclock();
1410df930be7Sderaadt 	static struct timeval lasttime;
1411df930be7Sderaadt 
1412df930be7Sderaadt 	*tvp = time;
1413df930be7Sderaadt #ifdef notdef
1414df930be7Sderaadt 	tvp->tv_usec += clkread();
1415df930be7Sderaadt 	while (tvp->tv_usec > 1000000) {
1416df930be7Sderaadt 		tvp->tv_sec++;
1417df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1418df930be7Sderaadt 	}
1419df930be7Sderaadt #endif
1420df930be7Sderaadt 	if (tvp->tv_sec == lasttime.tv_sec &&
1421df930be7Sderaadt 	    tvp->tv_usec <= lasttime.tv_usec &&
1422df930be7Sderaadt 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
1423df930be7Sderaadt 		tvp->tv_sec++;
1424df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1425df930be7Sderaadt 	}
1426df930be7Sderaadt 	lasttime = *tvp;
1427df930be7Sderaadt 	splx(s);
1428df930be7Sderaadt }
1429df930be7Sderaadt 
1430417eba8cSderaadt /*
1431417eba8cSderaadt  * Wait "n" microseconds.
1432417eba8cSderaadt  */
1433417eba8cSderaadt int
1434417eba8cSderaadt delay(n)
1435417eba8cSderaadt 	int n;
1436417eba8cSderaadt {
1437417eba8cSderaadt 	long N = cycles_per_usec * (n);
1438417eba8cSderaadt 
1439417eba8cSderaadt 	while (N > 0)				/* XXX */
1440417eba8cSderaadt 		N -= 3;				/* XXX */
1441417eba8cSderaadt }
1442417eba8cSderaadt 
1443df930be7Sderaadt #if defined(COMPAT_OSF1) || 1		/* XXX */
1444df930be7Sderaadt void
1445417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval)
1446df930be7Sderaadt 	struct proc *p;
1447417eba8cSderaadt 	struct exec_package *epp;
1448df930be7Sderaadt 	u_long stack;
1449df930be7Sderaadt 	register_t *retval;
1450df930be7Sderaadt {
1451417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
1452df930be7Sderaadt 
1453417eba8cSderaadt 	setregs(p, epp, stack, retval);
1454417eba8cSderaadt 	p->p_md.md_tf->tf_gp = execp->a.gp_value;
1455df930be7Sderaadt }
1456df930be7Sderaadt 
1457df930be7Sderaadt /*
1458df930be7Sderaadt  * cpu_exec_ecoff_hook():
1459df930be7Sderaadt  *	cpu-dependent ECOFF format hook for execve().
1460df930be7Sderaadt  *
1461df930be7Sderaadt  * Do any machine-dependent diddling of the exec package when doing ECOFF.
1462df930be7Sderaadt  *
1463df930be7Sderaadt  */
1464df930be7Sderaadt int
1465417eba8cSderaadt cpu_exec_ecoff_hook(p, epp)
1466df930be7Sderaadt 	struct proc *p;
1467df930be7Sderaadt 	struct exec_package *epp;
1468df930be7Sderaadt {
1469417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
1470a2f8ce8dSderaadt 	extern struct emul emul_native;
1471df930be7Sderaadt #ifdef COMPAT_OSF1
1472df930be7Sderaadt 	extern struct emul emul_osf1;
1473df930be7Sderaadt #endif
1474df930be7Sderaadt 
1475417eba8cSderaadt 	switch (execp->f.f_magic) {
1476df930be7Sderaadt #ifdef COMPAT_OSF1
1477df930be7Sderaadt 	case ECOFF_MAGIC_ALPHA:
1478df930be7Sderaadt 		epp->ep_emul = &emul_osf1;
1479df930be7Sderaadt 		break;
1480df930be7Sderaadt #endif
1481df930be7Sderaadt 
1482417eba8cSderaadt 	case ECOFF_MAGIC_NETBSD_ALPHA:
1483a2f8ce8dSderaadt 		epp->ep_emul = &emul_native;
1484df930be7Sderaadt 		break;
1485df930be7Sderaadt 
1486df930be7Sderaadt 	default:
148734fbf6deSderaadt 		return ENOEXEC;
1488df930be7Sderaadt 	}
1489df930be7Sderaadt 	return 0;
1490df930be7Sderaadt }
1491df930be7Sderaadt #endif
1492df930be7Sderaadt 
1493df930be7Sderaadt vm_offset_t
1494df930be7Sderaadt vtophys(vaddr)
1495df930be7Sderaadt 	vm_offset_t vaddr;
1496df930be7Sderaadt {
1497df930be7Sderaadt 	vm_offset_t paddr;
1498df930be7Sderaadt 
1499df930be7Sderaadt 	if (vaddr < K0SEG_BEGIN) {
1500df930be7Sderaadt 		printf("vtophys: invalid vaddr 0x%lx", vaddr);
1501df930be7Sderaadt 		paddr = vaddr;
1502df930be7Sderaadt 	} else if (vaddr < K0SEG_END)
1503df930be7Sderaadt 		paddr = k0segtophys(vaddr);
1504df930be7Sderaadt 	else
1505df930be7Sderaadt 		paddr = vatopa(vaddr);
1506df930be7Sderaadt 
1507df930be7Sderaadt #if 0
1508df930be7Sderaadt 	printf("vtophys(0x%lx) -> %lx\n", vaddr, paddr);
1509df930be7Sderaadt #endif
1510df930be7Sderaadt 
1511df930be7Sderaadt 	return (paddr);
1512df930be7Sderaadt }
1513