xref: /openbsd/sys/arch/alpha/alpha/machdep.c (revision f3914c62)
1*f3914c62Sniklas /*	$OpenBSD: machdep.c,v 1.21 1997/07/08 10:55:54 niklas Exp $	*/
23a630e3fSniklas /*	$NetBSD: machdep.c,v 1.61 1996/12/07 01:54:49 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5417eba8cSderaadt  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
6df930be7Sderaadt  * All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Author: Chris G. Demetriou
9df930be7Sderaadt  *
10df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
11df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
12df930be7Sderaadt  * notice and this permission notice appear in all copies of the
13df930be7Sderaadt  * software, derivative works or modified versions, and any portions
14df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
15df930be7Sderaadt  *
16df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19df930be7Sderaadt  *
20df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
21df930be7Sderaadt  *
22df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23df930be7Sderaadt  *  School of Computer Science
24df930be7Sderaadt  *  Carnegie Mellon University
25df930be7Sderaadt  *  Pittsburgh PA 15213-3890
26df930be7Sderaadt  *
27df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
28df930be7Sderaadt  * rights to redistribute these changes.
29df930be7Sderaadt  */
30df930be7Sderaadt 
31df930be7Sderaadt #include <sys/param.h>
32df930be7Sderaadt #include <sys/systm.h>
33df930be7Sderaadt #include <sys/signalvar.h>
34df930be7Sderaadt #include <sys/kernel.h>
35df930be7Sderaadt #include <sys/map.h>
36df930be7Sderaadt #include <sys/proc.h>
37df930be7Sderaadt #include <sys/buf.h>
38df930be7Sderaadt #include <sys/reboot.h>
39417eba8cSderaadt #include <sys/device.h>
40df930be7Sderaadt #include <sys/conf.h>
41df930be7Sderaadt #include <sys/file.h>
42df930be7Sderaadt #ifdef REAL_CLISTS
43df930be7Sderaadt #include <sys/clist.h>
44df930be7Sderaadt #endif
45df930be7Sderaadt #include <sys/callout.h>
46df930be7Sderaadt #include <sys/malloc.h>
47df930be7Sderaadt #include <sys/mbuf.h>
48df930be7Sderaadt #include <sys/msgbuf.h>
49df930be7Sderaadt #include <sys/ioctl.h>
50df930be7Sderaadt #include <sys/tty.h>
51df930be7Sderaadt #include <sys/user.h>
52df930be7Sderaadt #include <sys/exec.h>
53df930be7Sderaadt #include <sys/exec_ecoff.h>
54df930be7Sderaadt #include <sys/sysctl.h>
5550ce9ee0Sniklas #include <sys/core.h>
5650ce9ee0Sniklas #include <sys/kcore.h>
5750ce9ee0Sniklas #include <machine/kcore.h>
58df930be7Sderaadt #ifdef SYSVMSG
59df930be7Sderaadt #include <sys/msg.h>
60df930be7Sderaadt #endif
61df930be7Sderaadt #ifdef SYSVSEM
62df930be7Sderaadt #include <sys/sem.h>
63df930be7Sderaadt #endif
64df930be7Sderaadt #ifdef SYSVSHM
65df930be7Sderaadt #include <sys/shm.h>
66df930be7Sderaadt #endif
67df930be7Sderaadt 
68df930be7Sderaadt #include <sys/mount.h>
69df930be7Sderaadt #include <sys/syscallargs.h>
70df930be7Sderaadt 
7150ce9ee0Sniklas #include <vm/pmap.h>
72df930be7Sderaadt #include <vm/vm_kern.h>
73df930be7Sderaadt 
74df930be7Sderaadt #include <dev/cons.h>
75df930be7Sderaadt 
7650ce9ee0Sniklas #include <machine/autoconf.h>
77df930be7Sderaadt #include <machine/cpu.h>
78df930be7Sderaadt #include <machine/reg.h>
79df930be7Sderaadt #include <machine/rpb.h>
80df930be7Sderaadt #include <machine/prom.h>
813a630e3fSniklas #include <machine/cpuconf.h>
82df930be7Sderaadt 
8312f8bbedSniklas #ifdef DDB
8412f8bbedSniklas #include <machine/db_machdep.h>
8512f8bbedSniklas #include <ddb/db_access.h>
8612f8bbedSniklas #include <ddb/db_sym.h>
8712f8bbedSniklas #include <ddb/db_extern.h>
8812f8bbedSniklas #endif
8912f8bbedSniklas 
90df930be7Sderaadt #include <net/netisr.h>
9150ce9ee0Sniklas #include <net/if.h>
9250ce9ee0Sniklas 
9350ce9ee0Sniklas #ifdef INET
9450ce9ee0Sniklas #include <netinet/in.h>
9550ce9ee0Sniklas #include <netinet/if_ether.h>
9650ce9ee0Sniklas #include <netinet/ip_var.h>
9750ce9ee0Sniklas #endif
9850ce9ee0Sniklas #ifdef NS
9950ce9ee0Sniklas #include <netns/ns_var.h>
10050ce9ee0Sniklas #endif
10150ce9ee0Sniklas #ifdef ISO
10250ce9ee0Sniklas #include <netiso/iso.h>
10350ce9ee0Sniklas #include <netiso/clnp.h>
10450ce9ee0Sniklas #endif
1053a630e3fSniklas #ifdef CCITT
1063a630e3fSniklas #include <netccitt/x25.h>
1073a630e3fSniklas #include <netccitt/pk.h>
1083a630e3fSniklas #include <netccitt/pk_extern.h>
1093a630e3fSniklas #endif
1103a630e3fSniklas #ifdef NATM
1113a630e3fSniklas #include <netnatm/natm.h>
1123a630e3fSniklas #endif
11350ce9ee0Sniklas #include "ppp.h"
11450ce9ee0Sniklas #if NPPP > 0
11550ce9ee0Sniklas #include <net/ppp_defs.h>
11650ce9ee0Sniklas #include <net/if_ppp.h>
11750ce9ee0Sniklas #endif
118df930be7Sderaadt 
119417eba8cSderaadt #include "le_ioasic.h"			/* for le_iomem creation */
120df930be7Sderaadt 
121df930be7Sderaadt vm_map_t buffer_map;
122df930be7Sderaadt 
12350ce9ee0Sniklas int	cpu_dump __P((void));
1243a630e3fSniklas int	cpu_dumpsize __P((void));
12550ce9ee0Sniklas void	do_sir __P((void));
1263a630e3fSniklas void	dumpsys __P((void));
1273a630e3fSniklas void	identifycpu __P((void));
1283a630e3fSniklas void	netintr __P((void));
1293a630e3fSniklas void	regdump __P((struct trapframe *framep));
1303a630e3fSniklas void	printregs __P((struct reg *));
131df930be7Sderaadt 
132df930be7Sderaadt /*
133df930be7Sderaadt  * Declare these as initialized data so we can patch them.
134df930be7Sderaadt  */
135df930be7Sderaadt int	nswbuf = 0;
136df930be7Sderaadt #ifdef	NBUF
137df930be7Sderaadt int	nbuf = NBUF;
138df930be7Sderaadt #else
139df930be7Sderaadt int	nbuf = 0;
140df930be7Sderaadt #endif
141df930be7Sderaadt #ifdef	BUFPAGES
142df930be7Sderaadt int	bufpages = BUFPAGES;
143df930be7Sderaadt #else
144df930be7Sderaadt int	bufpages = 0;
145df930be7Sderaadt #endif
146df930be7Sderaadt int	msgbufmapped = 0;	/* set when safe to use msgbuf */
147df930be7Sderaadt int	maxmem;			/* max memory per process */
148df930be7Sderaadt 
149df930be7Sderaadt int	totalphysmem;		/* total amount of physical memory in system */
15074652a67Sniklas int	physmem;		/* physical mem used by OpenBSD + some rsvd */
151df930be7Sderaadt int	firstusablepage;	/* first usable memory page */
152df930be7Sderaadt int	lastusablepage;		/* last usable memory page */
153df930be7Sderaadt int	resvmem;		/* amount of memory reserved for PROM */
154df930be7Sderaadt int	unusedmem;		/* amount of memory for OS that we don't use */
155df930be7Sderaadt int	unknownmem;		/* amount of memory with an unknown use */
156df930be7Sderaadt 
157df930be7Sderaadt int	cputype;		/* system type, from the RPB */
158df930be7Sderaadt 
159df930be7Sderaadt /*
160df930be7Sderaadt  * XXX We need an address to which we can assign things so that they
161df930be7Sderaadt  * won't be optimized away because we didn't use the value.
162df930be7Sderaadt  */
163df930be7Sderaadt u_int32_t no_optimize;
164df930be7Sderaadt 
165df930be7Sderaadt /* the following is used externally (sysctl_hw) */
166df930be7Sderaadt char	machine[] = "alpha";
167417eba8cSderaadt char	cpu_model[128];
1683a630e3fSniklas const struct cpusw *cpu_fn_switch;		/* function switch */
169df930be7Sderaadt 
170df930be7Sderaadt struct	user *proc0paddr;
171df930be7Sderaadt 
172df930be7Sderaadt /* Number of machine cycles per microsecond */
173df930be7Sderaadt u_int64_t	cycles_per_usec;
174df930be7Sderaadt 
175df930be7Sderaadt /* some memory areas for device DMA.  "ick." */
176df930be7Sderaadt caddr_t		le_iomem;		/* XXX iomem for LANCE DMA */
177df930be7Sderaadt 
178df930be7Sderaadt /* number of cpus in the box.  really! */
179df930be7Sderaadt int		ncpus;
180df930be7Sderaadt 
181417eba8cSderaadt char boot_flags[64];
1823a630e3fSniklas char booted_kernel[64];
183417eba8cSderaadt 
184417eba8cSderaadt /* for cpu_sysctl() */
185417eba8cSderaadt char	root_device[17];
18650ce9ee0Sniklas int	alpha_unaligned_print = 1;	/* warn about unaligned accesses */
18750ce9ee0Sniklas int	alpha_unaligned_fix = 1;	/* fix up unaligned accesses */
18850ce9ee0Sniklas int	alpha_unaligned_sigbus = 0;	/* don't SIGBUS on fixed-up accesses */
18950ce9ee0Sniklas 
1903a630e3fSniklas void
191*f3914c62Sniklas alpha_init(pfn, ptb, symend)
192df930be7Sderaadt 	u_long pfn;		/* first free PFN number */
193df930be7Sderaadt 	u_long ptb;		/* PFN of current level 1 page table */
194*f3914c62Sniklas 	char *symend;		/* end of the symbol table */
195df930be7Sderaadt {
196df930be7Sderaadt 	extern char _end[];
197*f3914c62Sniklas 	extern char *esym;
198df930be7Sderaadt 	caddr_t start, v;
199df930be7Sderaadt 	struct mddt *mddtp;
200df930be7Sderaadt 	int i, mddtweird;
201df930be7Sderaadt 	char *p;
202df930be7Sderaadt 
203*f3914c62Sniklas 	/* Save the symbol table end */
204*f3914c62Sniklas 	esym = symend;
205*f3914c62Sniklas 
206df930be7Sderaadt 	/*
207df930be7Sderaadt 	 * Turn off interrupts and floating point.
208df930be7Sderaadt 	 * Make sure the instruction and data streams are consistent.
209df930be7Sderaadt 	 */
210df930be7Sderaadt 	(void)splhigh();
21150ce9ee0Sniklas 	alpha_pal_wrfen(0);
21250ce9ee0Sniklas 	ALPHA_TBIA();
21350ce9ee0Sniklas 	alpha_pal_imb();
214df930be7Sderaadt 
215df930be7Sderaadt 	/*
216df930be7Sderaadt 	 * get address of the restart block, while we the bootstrap
217df930be7Sderaadt 	 * mapping is still around.
218df930be7Sderaadt 	 */
21950ce9ee0Sniklas 	hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(
22050ce9ee0Sniklas 	    (vm_offset_t)(*(struct rpb **)HWRPB_ADDR));
221df930be7Sderaadt 
222df930be7Sderaadt 	/*
223df930be7Sderaadt 	 * Remember how many cycles there are per microsecond,
224df930be7Sderaadt 	 * so that we can use delay().  Round up, for safety.
225df930be7Sderaadt 	 */
226df930be7Sderaadt 	cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
227df930be7Sderaadt 
228df930be7Sderaadt 	/*
229df930be7Sderaadt 	 * Init the PROM interface, so we can use printf
230df930be7Sderaadt 	 * until PROM mappings go away in consinit.
231df930be7Sderaadt 	 */
232df930be7Sderaadt 	init_prom_interface();
233df930be7Sderaadt 
234df930be7Sderaadt 	/*
235df930be7Sderaadt 	 * Point interrupt/exception vectors to our own.
236df930be7Sderaadt 	 */
23750ce9ee0Sniklas 	alpha_pal_wrent(XentInt, ALPHA_KENTRY_INT);
23850ce9ee0Sniklas 	alpha_pal_wrent(XentArith, ALPHA_KENTRY_ARITH);
23950ce9ee0Sniklas 	alpha_pal_wrent(XentMM, ALPHA_KENTRY_MM);
24050ce9ee0Sniklas 	alpha_pal_wrent(XentIF, ALPHA_KENTRY_IF);
24150ce9ee0Sniklas 	alpha_pal_wrent(XentUna, ALPHA_KENTRY_UNA);
24250ce9ee0Sniklas 	alpha_pal_wrent(XentSys, ALPHA_KENTRY_SYS);
24350ce9ee0Sniklas 
24450ce9ee0Sniklas 	/*
24550ce9ee0Sniklas 	 * Disable System and Processor Correctable Error reporting.
24650ce9ee0Sniklas 	 * Clear pending machine checks and error reports, etc.
24750ce9ee0Sniklas 	 */
24850ce9ee0Sniklas 	alpha_pal_wrmces(alpha_pal_rdmces() | ALPHA_MCES_DSC | ALPHA_MCES_DPC);
249df930be7Sderaadt 
250df930be7Sderaadt 	/*
251df930be7Sderaadt 	 * Find out how much memory is available, by looking at
252df930be7Sderaadt 	 * the memory cluster descriptors.  This also tries to do
253df930be7Sderaadt 	 * its best to detect things things that have never been seen
254df930be7Sderaadt 	 * before...
255df930be7Sderaadt 	 *
256df930be7Sderaadt 	 * XXX Assumes that the first "system" cluster is the
257df930be7Sderaadt 	 * only one we can use. Is the second (etc.) system cluster
258df930be7Sderaadt 	 * (if one happens to exist) guaranteed to be contiguous?  or...?
259df930be7Sderaadt 	 */
260df930be7Sderaadt 	mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
261df930be7Sderaadt 
262df930be7Sderaadt 	/*
263df930be7Sderaadt 	 * BEGIN MDDT WEIRDNESS CHECKING
264df930be7Sderaadt 	 */
265df930be7Sderaadt 	mddtweird = 0;
266df930be7Sderaadt 
267df930be7Sderaadt #define cnt	 mddtp->mddt_cluster_cnt
268df930be7Sderaadt #define	usage(n) mddtp->mddt_clusters[(n)].mddt_usage
269df930be7Sderaadt 	if (cnt != 2 && cnt != 3) {
27050ce9ee0Sniklas 		printf("WARNING: weird number (%ld) of mem clusters\n", cnt);
271df930be7Sderaadt 		mddtweird = 1;
272df930be7Sderaadt 	} else if (usage(0) != MDDT_PALCODE ||
273df930be7Sderaadt 		   usage(1) != MDDT_SYSTEM ||
274df930be7Sderaadt 	           (cnt == 3 && usage(2) != MDDT_PALCODE)) {
275df930be7Sderaadt 		mddtweird = 1;
27650ce9ee0Sniklas 		printf("WARNING: %ld mem clusters, but weird config\n", cnt);
277df930be7Sderaadt 	}
278df930be7Sderaadt 
279df930be7Sderaadt 	for (i = 0; i < cnt; i++) {
280df930be7Sderaadt 		if ((usage(i) & MDDT_mbz) != 0) {
281df930be7Sderaadt 			printf("WARNING: mem cluster %d has weird usage %lx\n",
282df930be7Sderaadt 			    i, usage(i));
283df930be7Sderaadt 			mddtweird = 1;
284df930be7Sderaadt 		}
285df930be7Sderaadt 		if (mddtp->mddt_clusters[i].mddt_pg_cnt == 0) {
286df930be7Sderaadt 			printf("WARNING: mem cluster %d has pg cnt == 0\n", i);
287df930be7Sderaadt 			mddtweird = 1;
288df930be7Sderaadt 		}
289df930be7Sderaadt 		/* XXX other things to check? */
290df930be7Sderaadt 	}
291df930be7Sderaadt #undef cnt
292df930be7Sderaadt #undef usage
293df930be7Sderaadt 
294df930be7Sderaadt 	if (mddtweird) {
295df930be7Sderaadt 		printf("\n");
296df930be7Sderaadt 		printf("complete memory cluster information:\n");
297df930be7Sderaadt 		for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
298df930be7Sderaadt 			printf("mddt %d:\n", i);
299df930be7Sderaadt 			printf("\tpfn %lx\n",
300df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pfn);
301df930be7Sderaadt 			printf("\tcnt %lx\n",
302df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_cnt);
303df930be7Sderaadt 			printf("\ttest %lx\n",
304df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_test);
305df930be7Sderaadt 			printf("\tbva %lx\n",
306df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_v_bitaddr);
307df930be7Sderaadt 			printf("\tbpa %lx\n",
308df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_p_bitaddr);
309df930be7Sderaadt 			printf("\tbcksum %lx\n",
310df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_bit_cksum);
311df930be7Sderaadt 			printf("\tusage %lx\n",
312df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_usage);
313df930be7Sderaadt 		}
314df930be7Sderaadt 		printf("\n");
315df930be7Sderaadt 	}
316df930be7Sderaadt 	/*
317df930be7Sderaadt 	 * END MDDT WEIRDNESS CHECKING
318df930be7Sderaadt 	 */
319df930be7Sderaadt 
320df930be7Sderaadt 	for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
321df930be7Sderaadt 		totalphysmem += mddtp->mddt_clusters[i].mddt_pg_cnt;
322df930be7Sderaadt #define	usage(n) mddtp->mddt_clusters[(n)].mddt_usage
323df930be7Sderaadt #define	pgcnt(n) mddtp->mddt_clusters[(n)].mddt_pg_cnt
324df930be7Sderaadt 		if ((usage(i) & MDDT_mbz) != 0)
325df930be7Sderaadt 			unknownmem += pgcnt(i);
326df930be7Sderaadt 		else if ((usage(i) & ~MDDT_mbz) == MDDT_PALCODE)
327df930be7Sderaadt 			resvmem += pgcnt(i);
328df930be7Sderaadt 		else if ((usage(i) & ~MDDT_mbz) == MDDT_SYSTEM) {
329df930be7Sderaadt 			/*
330df930be7Sderaadt 			 * assumes that the system cluster listed is
331df930be7Sderaadt 			 * one we're in...
332df930be7Sderaadt 			 */
333df930be7Sderaadt 			if (physmem != resvmem) {
334df930be7Sderaadt 				physmem += pgcnt(i);
335df930be7Sderaadt 				firstusablepage =
336df930be7Sderaadt 				    mddtp->mddt_clusters[i].mddt_pfn;
33774652a67Sniklas 				lastusablepage =
33874652a67Sniklas 				    firstusablepage + pgcnt(i) - 1;
339df930be7Sderaadt 			} else
340df930be7Sderaadt 				unusedmem += pgcnt(i);
341df930be7Sderaadt 		}
342df930be7Sderaadt #undef usage
343df930be7Sderaadt #undef pgcnt
344df930be7Sderaadt 	}
345df930be7Sderaadt 	if (totalphysmem == 0)
346df930be7Sderaadt 		panic("can't happen: system seems to have no memory!");
347df930be7Sderaadt 	maxmem = physmem;
348df930be7Sderaadt 
349df930be7Sderaadt #if 0
350df930be7Sderaadt 	printf("totalphysmem = %d\n", totalphysmem);
351df930be7Sderaadt 	printf("physmem = %d\n", physmem);
352df930be7Sderaadt 	printf("firstusablepage = %d\n", firstusablepage);
353df930be7Sderaadt 	printf("lastusablepage = %d\n", lastusablepage);
354df930be7Sderaadt 	printf("resvmem = %d\n", resvmem);
355df930be7Sderaadt 	printf("unusedmem = %d\n", unusedmem);
356df930be7Sderaadt 	printf("unknownmem = %d\n", unknownmem);
357df930be7Sderaadt #endif
358df930be7Sderaadt 
359df930be7Sderaadt 	/*
360df930be7Sderaadt 	 * find out this CPU's page size
361df930be7Sderaadt 	 */
362df930be7Sderaadt 	PAGE_SIZE = hwrpb->rpb_page_size;
36334fbf6deSderaadt 	if (PAGE_SIZE != 8192)
36434fbf6deSderaadt 		panic("page size %d != 8192?!", PAGE_SIZE);
365df930be7Sderaadt 
366*f3914c62Sniklas 	v = (caddr_t)alpha_round_page(symend ? symend : _end);
367df930be7Sderaadt 	/*
368df930be7Sderaadt 	 * Init mapping for u page(s) for proc 0
369df930be7Sderaadt 	 */
370df930be7Sderaadt 	start = v;
371df930be7Sderaadt 	curproc->p_addr = proc0paddr = (struct user *)v;
372df930be7Sderaadt 	v += UPAGES * NBPG;
373df930be7Sderaadt 
374df930be7Sderaadt 	/*
375df930be7Sderaadt 	 * Find out what hardware we're on, and remember its type name.
376df930be7Sderaadt 	 */
377df930be7Sderaadt 	cputype = hwrpb->rpb_type;
3783a630e3fSniklas 	if (cputype < 0 || cputype > ncpusw) {
3793a630e3fSniklas unknown_cputype:
3803a630e3fSniklas 		printf("\n");
3813a630e3fSniklas 		printf("Unknown system type %d.\n", cputype);
3823a630e3fSniklas 		printf("\n");
3833a630e3fSniklas 		panic("unknown system type");
3843a630e3fSniklas 	}
3853a630e3fSniklas 	cpu_fn_switch = &cpusw[cputype];
3863a630e3fSniklas 	if (cpu_fn_switch->family == NULL)
3873a630e3fSniklas 		goto unknown_cputype;
3883a630e3fSniklas 	if (cpu_fn_switch->option == NULL) {
3893a630e3fSniklas 		printf("\n");
3900bc98093Smichaels 		printf("OpenBSD does not currently support system type %d\n",
3913a630e3fSniklas 		    cputype);
3923a630e3fSniklas 		printf("(%s family).\n", cpu_fn_switch->family);
3933a630e3fSniklas 		printf("\n");
3943a630e3fSniklas 		panic("unsupported system type");
3953a630e3fSniklas 	}
3963a630e3fSniklas 	if (!cpu_fn_switch->present) {
3973a630e3fSniklas 		printf("\n");
3983a630e3fSniklas 		printf("Support for system type %d (%s family) is\n", cputype,
3993a630e3fSniklas 		    cpu_fn_switch->family);
40074652a67Sniklas 		printf("not present in this kernel.  Build a kernel with "
40174652a67Sniklas 		    "\"options %s\"\n", cpu_fn_switch->option);
4023a630e3fSniklas 		printf("to include support for this system type.\n");
4033a630e3fSniklas 		printf("\n");
4043a630e3fSniklas 		panic("support for system not present");
405df930be7Sderaadt 	}
406df930be7Sderaadt 
4073a630e3fSniklas 	if ((*cpu_fn_switch->model_name)() != NULL)
4083a630e3fSniklas 		strncpy(cpu_model, (*cpu_fn_switch->model_name)(),
4093a630e3fSniklas 		    sizeof cpu_model - 1);
4103a630e3fSniklas 	else {
41174652a67Sniklas 		strncpy(cpu_model, cpu_fn_switch->family,
41274652a67Sniklas 		    sizeof cpu_model - 1);
4133a630e3fSniklas 		strcat(cpu_model, " family");		/* XXX */
4143a630e3fSniklas 	}
415417eba8cSderaadt 	cpu_model[sizeof cpu_model - 1] = '\0';
416df930be7Sderaadt 
417417eba8cSderaadt #if NLE_IOASIC > 0
418df930be7Sderaadt 	/*
419df930be7Sderaadt 	 * Grab 128K at the top of physical memory for the lance chip
420df930be7Sderaadt 	 * on machines where it does dma through the I/O ASIC.
421df930be7Sderaadt 	 * It must be physically contiguous and aligned on a 128K boundary.
422417eba8cSderaadt 	 *
423417eba8cSderaadt 	 * Note that since this is conditional on the presence of
424417eba8cSderaadt 	 * IOASIC-attached 'le' units in the kernel config, the
425417eba8cSderaadt 	 * message buffer may move on these systems.  This shouldn't
426417eba8cSderaadt 	 * be a problem, because once people have a kernel config that
427417eba8cSderaadt 	 * they use, they're going to stick with it.
428df930be7Sderaadt 	 */
429df930be7Sderaadt 	if (cputype == ST_DEC_3000_500 ||
430df930be7Sderaadt 	    cputype == ST_DEC_3000_300) {	/* XXX possibly others? */
431df930be7Sderaadt 		lastusablepage -= btoc(128 * 1024);
43250ce9ee0Sniklas 		le_iomem =
43350ce9ee0Sniklas 		    (caddr_t)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1));
434df930be7Sderaadt 	}
435417eba8cSderaadt #endif /* NLE_IOASIC */
436df930be7Sderaadt 
437df930be7Sderaadt 	/*
438df930be7Sderaadt 	 * Initialize error message buffer (at end of core).
439df930be7Sderaadt 	 */
440df930be7Sderaadt 	lastusablepage -= btoc(sizeof (struct msgbuf));
44150ce9ee0Sniklas 	msgbufp =
44250ce9ee0Sniklas 	    (struct msgbuf *)ALPHA_PHYS_TO_K0SEG(ctob(lastusablepage + 1));
443df930be7Sderaadt 	msgbufmapped = 1;
444df930be7Sderaadt 
445df930be7Sderaadt 	/*
446df930be7Sderaadt 	 * Allocate space for system data structures.
447df930be7Sderaadt 	 * The first available kernel virtual address is in "v".
448df930be7Sderaadt 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
449df930be7Sderaadt 	 *
450df930be7Sderaadt 	 * These data structures are allocated here instead of cpu_startup()
451df930be7Sderaadt 	 * because physical memory is directly addressable. We don't have
452df930be7Sderaadt 	 * to map these into virtual address space.
453df930be7Sderaadt 	 */
454df930be7Sderaadt #define valloc(name, type, num) \
45534fbf6deSderaadt 	    (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num))
456df930be7Sderaadt #define valloclim(name, type, num, lim) \
45734fbf6deSderaadt 	    (name) = (type *)v; v = (caddr_t)ALIGN((lim) = ((name)+(num)))
458df930be7Sderaadt #ifdef REAL_CLISTS
459df930be7Sderaadt 	valloc(cfree, struct cblock, nclist);
460df930be7Sderaadt #endif
461df930be7Sderaadt 	valloc(callout, struct callout, ncallout);
462df930be7Sderaadt 	valloc(swapmap, struct map, nswapmap = maxproc * 2);
463df930be7Sderaadt #ifdef SYSVSHM
464df930be7Sderaadt 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
465df930be7Sderaadt #endif
466df930be7Sderaadt #ifdef SYSVSEM
467df930be7Sderaadt 	valloc(sema, struct semid_ds, seminfo.semmni);
468df930be7Sderaadt 	valloc(sem, struct sem, seminfo.semmns);
469df930be7Sderaadt 	/* This is pretty disgusting! */
470df930be7Sderaadt 	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
471df930be7Sderaadt #endif
472df930be7Sderaadt #ifdef SYSVMSG
473df930be7Sderaadt 	valloc(msgpool, char, msginfo.msgmax);
474df930be7Sderaadt 	valloc(msgmaps, struct msgmap, msginfo.msgseg);
475df930be7Sderaadt 	valloc(msghdrs, struct msg, msginfo.msgtql);
476df930be7Sderaadt 	valloc(msqids, struct msqid_ds, msginfo.msgmni);
477df930be7Sderaadt #endif
478df930be7Sderaadt 
479df930be7Sderaadt 	/*
480df930be7Sderaadt 	 * Determine how many buffers to allocate.
481417eba8cSderaadt 	 * We allocate 10% of memory for buffer space.  Insure a
482df930be7Sderaadt 	 * minimum of 16 buffers.  We allocate 1/2 as many swap buffer
483df930be7Sderaadt 	 * headers as file i/o buffers.
484df930be7Sderaadt 	 */
485df930be7Sderaadt 	if (bufpages == 0)
486417eba8cSderaadt 		bufpages = (physmem * 10) / (CLSIZE * 100);
487df930be7Sderaadt 	if (nbuf == 0) {
488df930be7Sderaadt 		nbuf = bufpages;
489df930be7Sderaadt 		if (nbuf < 16)
490df930be7Sderaadt 			nbuf = 16;
491df930be7Sderaadt 	}
492df930be7Sderaadt 	if (nswbuf == 0) {
493df930be7Sderaadt 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
494df930be7Sderaadt 		if (nswbuf > 256)
495df930be7Sderaadt 			nswbuf = 256;		/* sanity */
496df930be7Sderaadt 	}
497df930be7Sderaadt 	valloc(swbuf, struct buf, nswbuf);
498df930be7Sderaadt 	valloc(buf, struct buf, nbuf);
499df930be7Sderaadt 
500df930be7Sderaadt 	/*
501df930be7Sderaadt 	 * Clear allocated memory.
502df930be7Sderaadt 	 */
503df930be7Sderaadt 	bzero(start, v - start);
504df930be7Sderaadt 
505df930be7Sderaadt 	/*
506df930be7Sderaadt 	 * Initialize the virtual memory system, and set the
507df930be7Sderaadt 	 * page table base register in proc 0's PCB.
508df930be7Sderaadt 	 */
50950ce9ee0Sniklas #ifndef NEW_PMAP
51050ce9ee0Sniklas 	pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT));
51150ce9ee0Sniklas #else
51250ce9ee0Sniklas 	pmap_bootstrap((vm_offset_t)v, ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT),
51350ce9ee0Sniklas 	    hwrpb->rpb_max_asn);
51450ce9ee0Sniklas #endif
515df930be7Sderaadt 
516df930be7Sderaadt 	/*
517df930be7Sderaadt 	 * Initialize the rest of proc 0's PCB, and cache its physical
518df930be7Sderaadt 	 * address.
519df930be7Sderaadt 	 */
520df930be7Sderaadt 	proc0.p_md.md_pcbpaddr =
52150ce9ee0Sniklas 	    (struct pcb *)ALPHA_K0SEG_TO_PHYS((vm_offset_t)&proc0paddr->u_pcb);
522df930be7Sderaadt 
523df930be7Sderaadt 	/*
524df930be7Sderaadt 	 * Set the kernel sp, reserving space for an (empty) trapframe,
525df930be7Sderaadt 	 * and make proc0's trapframe pointer point to it for sanity.
526df930be7Sderaadt 	 */
52750ce9ee0Sniklas 	proc0paddr->u_pcb.pcb_hw.apcb_ksp =
528df930be7Sderaadt 	    (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
52974652a67Sniklas 	proc0.p_md.md_tf =
53074652a67Sniklas 	    (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
53150ce9ee0Sniklas 
53250ce9ee0Sniklas #ifdef NEW_PMAP
53350ce9ee0Sniklas 	pmap_activate(kernel_pmap, &proc0paddr->u_pcb.pcb_hw, 0);
53450ce9ee0Sniklas #endif
535df930be7Sderaadt 
536df930be7Sderaadt 	/*
537df930be7Sderaadt 	 * Look at arguments passed to us and compute boothowto.
5383a630e3fSniklas 	 * Also, get kernel name so it can be used in user-land.
539df930be7Sderaadt 	 */
540417eba8cSderaadt 	prom_getenv(PROM_E_BOOTED_OSFLAGS, boot_flags, sizeof(boot_flags));
541417eba8cSderaadt #if 0
542417eba8cSderaadt 	printf("boot flags = \"%s\"\n", boot_flags);
543df930be7Sderaadt #endif
5443a630e3fSniklas 	prom_getenv(PROM_E_BOOTED_FILE, booted_kernel,
5453a630e3fSniklas 	    sizeof(booted_kernel));
5463a630e3fSniklas #if 0
5473a630e3fSniklas 	printf("booted kernel = \"%s\"\n", booted_kernel);
5483a630e3fSniklas #endif
549417eba8cSderaadt 
550417eba8cSderaadt 	boothowto = RB_SINGLE;
551df930be7Sderaadt #ifdef KADB
552df930be7Sderaadt 	boothowto |= RB_KDB;
553df930be7Sderaadt #endif
554df930be7Sderaadt 	for (p = boot_flags; p && *p != '\0'; p++) {
555417eba8cSderaadt 		/*
556417eba8cSderaadt 		 * Note that we'd really like to differentiate case here,
557417eba8cSderaadt 		 * but the Alpha AXP Architecture Reference Manual
558417eba8cSderaadt 		 * says that we shouldn't.
559417eba8cSderaadt 		 */
560df930be7Sderaadt 		switch (*p) {
561df930be7Sderaadt 		case 'a': /* autoboot */
562417eba8cSderaadt 		case 'A':
563df930be7Sderaadt 			boothowto &= ~RB_SINGLE;
564df930be7Sderaadt 			break;
565df930be7Sderaadt 
56612f8bbedSniklas 		case 'b': /* Enter DDB as soon as the console is initialised */
56712f8bbedSniklas 		case 'B':
56812f8bbedSniklas 			boothowto |= RB_KDB;
56912f8bbedSniklas 			break;
57012f8bbedSniklas 
57150ce9ee0Sniklas 		case 'c': /* enter user kernel configuration */
57250ce9ee0Sniklas 		case 'C':
57350ce9ee0Sniklas 			boothowto |= RB_CONFIG;
57450ce9ee0Sniklas 			break;
57550ce9ee0Sniklas 
57650ce9ee0Sniklas #ifdef DEBUG
57750ce9ee0Sniklas 		case 'd': /* crash dump immediately after autoconfig */
57850ce9ee0Sniklas 		case 'D':
57950ce9ee0Sniklas 			boothowto |= RB_DUMP;
58050ce9ee0Sniklas 			break;
58150ce9ee0Sniklas #endif
58250ce9ee0Sniklas 
58350ce9ee0Sniklas 		case 'h': /* always halt, never reboot */
58450ce9ee0Sniklas 		case 'H':
58550ce9ee0Sniklas 			boothowto |= RB_HALT;
586df930be7Sderaadt 			break;
587df930be7Sderaadt 
588417eba8cSderaadt #if 0
589417eba8cSderaadt 		case 'm': /* mini root present in memory */
590417eba8cSderaadt 		case 'M':
591417eba8cSderaadt 			boothowto |= RB_MINIROOT;
592417eba8cSderaadt 			break;
593417eba8cSderaadt #endif
59450ce9ee0Sniklas 
59550ce9ee0Sniklas 		case 'n': /* askname */
59650ce9ee0Sniklas 		case 'N':
59750ce9ee0Sniklas 			boothowto |= RB_ASKNAME;
59850ce9ee0Sniklas 			break;
599df930be7Sderaadt 		}
600df930be7Sderaadt 	}
601df930be7Sderaadt 
602df930be7Sderaadt 	/*
603df930be7Sderaadt 	 * Figure out the number of cpus in the box, from RPB fields.
604df930be7Sderaadt 	 * Really.  We mean it.
605df930be7Sderaadt 	 */
606df930be7Sderaadt 	for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
607df930be7Sderaadt 		struct pcs *pcsp;
608df930be7Sderaadt 
609df930be7Sderaadt 		pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off +
610df930be7Sderaadt 		    (i * hwrpb->rpb_pcs_size));
611df930be7Sderaadt 		if ((pcsp->pcs_flags & PCS_PP) != 0)
612df930be7Sderaadt 			ncpus++;
613df930be7Sderaadt 	}
614df930be7Sderaadt }
615df930be7Sderaadt 
616417eba8cSderaadt void
617df930be7Sderaadt consinit()
618df930be7Sderaadt {
6193a630e3fSniklas 	(*cpu_fn_switch->cons_init)();
620df930be7Sderaadt 	pmap_unmap_prom();
62112f8bbedSniklas #ifdef DDB
62212f8bbedSniklas 	ddb_init();
62312f8bbedSniklas 	if (boothowto & RB_KDB)
62412f8bbedSniklas 		Debugger();
62512f8bbedSniklas #endif
626df930be7Sderaadt }
627df930be7Sderaadt 
628417eba8cSderaadt void
629df930be7Sderaadt cpu_startup()
630df930be7Sderaadt {
631df930be7Sderaadt 	register unsigned i;
632df930be7Sderaadt 	int base, residual;
633df930be7Sderaadt 	vm_offset_t minaddr, maxaddr;
634df930be7Sderaadt 	vm_size_t size;
63550ce9ee0Sniklas #if defined(DEBUG)
636df930be7Sderaadt 	extern int pmapdebug;
637df930be7Sderaadt 	int opmapdebug = pmapdebug;
638df930be7Sderaadt 
639df930be7Sderaadt 	pmapdebug = 0;
640df930be7Sderaadt #endif
641df930be7Sderaadt 
642df930be7Sderaadt 	/*
643df930be7Sderaadt 	 * Good {morning,afternoon,evening,night}.
644df930be7Sderaadt 	 */
645df930be7Sderaadt 	printf(version);
646df930be7Sderaadt 	identifycpu();
64750ce9ee0Sniklas 	printf("real mem = %d (%d reserved for PROM, %d used by OpenBSD)\n",
648df930be7Sderaadt 	    ctob(totalphysmem), ctob(resvmem), ctob(physmem));
649df930be7Sderaadt 	if (unusedmem)
650df930be7Sderaadt 		printf("WARNING: unused memory = %d bytes\n", ctob(unusedmem));
651df930be7Sderaadt 	if (unknownmem)
652df930be7Sderaadt 		printf("WARNING: %d bytes of memory with unknown purpose\n",
653df930be7Sderaadt 		    ctob(unknownmem));
654df930be7Sderaadt 
655df930be7Sderaadt 	/*
656df930be7Sderaadt 	 * Allocate virtual address space for file I/O buffers.
657df930be7Sderaadt 	 * Note they are different than the array of headers, 'buf',
658df930be7Sderaadt 	 * and usually occupy more virtual memory than physical.
659df930be7Sderaadt 	 */
660df930be7Sderaadt 	size = MAXBSIZE * nbuf;
661df930be7Sderaadt 	buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
662df930be7Sderaadt 	    &maxaddr, size, TRUE);
663df930be7Sderaadt 	minaddr = (vm_offset_t)buffers;
664df930be7Sderaadt 	if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
665df930be7Sderaadt 			&minaddr, size, FALSE) != KERN_SUCCESS)
666df930be7Sderaadt 		panic("startup: cannot allocate buffers");
667df930be7Sderaadt 	base = bufpages / nbuf;
668df930be7Sderaadt 	residual = bufpages % nbuf;
669df930be7Sderaadt 	for (i = 0; i < nbuf; i++) {
670df930be7Sderaadt 		vm_size_t curbufsize;
671df930be7Sderaadt 		vm_offset_t curbuf;
672df930be7Sderaadt 
673df930be7Sderaadt 		/*
674df930be7Sderaadt 		 * First <residual> buffers get (base+1) physical pages
675df930be7Sderaadt 		 * allocated for them.  The rest get (base) physical pages.
676df930be7Sderaadt 		 *
677df930be7Sderaadt 		 * The rest of each buffer occupies virtual space,
678df930be7Sderaadt 		 * but has no physical memory allocated for it.
679df930be7Sderaadt 		 */
680df930be7Sderaadt 		curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
681df930be7Sderaadt 		curbufsize = CLBYTES * (i < residual ? base+1 : base);
682df930be7Sderaadt 		vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
683df930be7Sderaadt 		vm_map_simplify(buffer_map, curbuf);
684df930be7Sderaadt 	}
685df930be7Sderaadt 	/*
686df930be7Sderaadt 	 * Allocate a submap for exec arguments.  This map effectively
687df930be7Sderaadt 	 * limits the number of processes exec'ing at any time.
688df930be7Sderaadt 	 */
689df930be7Sderaadt 	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
690df930be7Sderaadt 				 16 * NCARGS, TRUE);
691df930be7Sderaadt 
692df930be7Sderaadt 	/*
693df930be7Sderaadt 	 * Allocate a submap for physio
694df930be7Sderaadt 	 */
695df930be7Sderaadt 	phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
696df930be7Sderaadt 				 VM_PHYS_SIZE, TRUE);
697df930be7Sderaadt 
698df930be7Sderaadt 	/*
699df930be7Sderaadt 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
700df930be7Sderaadt 	 * we use the more space efficient malloc in place of kmem_alloc.
701df930be7Sderaadt 	 */
702df930be7Sderaadt 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
703df930be7Sderaadt 	    M_MBUF, M_NOWAIT);
704df930be7Sderaadt 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
705df930be7Sderaadt 	mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
706df930be7Sderaadt 	    VM_MBUF_SIZE, FALSE);
707df930be7Sderaadt 	/*
708df930be7Sderaadt 	 * Initialize callouts
709df930be7Sderaadt 	 */
710df930be7Sderaadt 	callfree = callout;
711df930be7Sderaadt 	for (i = 1; i < ncallout; i++)
712df930be7Sderaadt 		callout[i-1].c_next = &callout[i];
713df930be7Sderaadt 	callout[i-1].c_next = NULL;
714df930be7Sderaadt 
71550ce9ee0Sniklas #if defined(DEBUG)
716df930be7Sderaadt 	pmapdebug = opmapdebug;
717df930be7Sderaadt #endif
718df930be7Sderaadt 	printf("avail mem = %ld\n", (long)ptoa(cnt.v_free_count));
719df930be7Sderaadt 	printf("using %ld buffers containing %ld bytes of memory\n",
720df930be7Sderaadt 		(long)nbuf, (long)(bufpages * CLBYTES));
721df930be7Sderaadt 
722df930be7Sderaadt 	/*
723df930be7Sderaadt 	 * Set up buffers, so they can be used to read disk labels.
724df930be7Sderaadt 	 */
725df930be7Sderaadt 	bufinit();
726df930be7Sderaadt 
727df930be7Sderaadt 	/*
728df930be7Sderaadt 	 * Configure the system.
729df930be7Sderaadt 	 */
73041033391Sderaadt 	if (boothowto & RB_CONFIG) {
73141033391Sderaadt #ifdef BOOT_CONFIG
73241033391Sderaadt 		user_config();
73341033391Sderaadt #else
73441033391Sderaadt 		printf("kernel does not support -c; continuing..\n");
73541033391Sderaadt #endif
73641033391Sderaadt 	}
737df930be7Sderaadt 	configure();
73850ce9ee0Sniklas 
73950ce9ee0Sniklas 	/*
74050ce9ee0Sniklas 	 * Note that bootstrapping is finished, and set the HWRPB up
74150ce9ee0Sniklas 	 * to do restarts.
74250ce9ee0Sniklas 	 */
7433a630e3fSniklas 	hwrpb_restart_setup();
744df930be7Sderaadt }
745df930be7Sderaadt 
74650ce9ee0Sniklas void
747df930be7Sderaadt identifycpu()
748df930be7Sderaadt {
749df930be7Sderaadt 
750df930be7Sderaadt 	/*
751df930be7Sderaadt 	 * print out CPU identification information.
752df930be7Sderaadt 	 */
75350ce9ee0Sniklas 	printf("%s, %ldMHz\n", cpu_model,
754df930be7Sderaadt 	    hwrpb->rpb_cc_freq / 1000000);	/* XXX true for 21164? */
75550ce9ee0Sniklas 	printf("%ld byte page size, %d processor%s.\n",
756df930be7Sderaadt 	    hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s");
757df930be7Sderaadt #if 0
758df930be7Sderaadt 	/* this isn't defined for any systems that we run on? */
759df930be7Sderaadt 	printf("serial number 0x%lx 0x%lx\n",
760df930be7Sderaadt 	    ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]);
761df930be7Sderaadt 
762df930be7Sderaadt 	/* and these aren't particularly useful! */
763df930be7Sderaadt 	printf("variation: 0x%lx, revision 0x%lx\n",
764df930be7Sderaadt 	    hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
765df930be7Sderaadt #endif
766df930be7Sderaadt }
767df930be7Sderaadt 
768df930be7Sderaadt int	waittime = -1;
769df930be7Sderaadt struct pcb dumppcb;
770df930be7Sderaadt 
771417eba8cSderaadt void
77250ce9ee0Sniklas boot(howto /* , bootstr */)
773df930be7Sderaadt 	int howto;
77450ce9ee0Sniklas 	/* char *bootstr; */
775df930be7Sderaadt {
776df930be7Sderaadt 	extern int cold;
777df930be7Sderaadt 
778df930be7Sderaadt 	/* If system is cold, just halt. */
779df930be7Sderaadt 	if (cold) {
780df930be7Sderaadt 		howto |= RB_HALT;
781df930be7Sderaadt 		goto haltsys;
782df930be7Sderaadt 	}
783df930be7Sderaadt 
78450ce9ee0Sniklas 	/* If "always halt" was specified as a boot flag, obey. */
78550ce9ee0Sniklas 	if ((boothowto & RB_HALT) != 0)
78650ce9ee0Sniklas 		howto |= RB_HALT;
78750ce9ee0Sniklas 
788df930be7Sderaadt 	boothowto = howto;
789df930be7Sderaadt 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
79050ce9ee0Sniklas 		extern struct proc proc0;
79150ce9ee0Sniklas 
79250ce9ee0Sniklas 		/* protect against curproc->p_stats.foo refs in sync   XXX */
79350ce9ee0Sniklas 		if (curproc == NULL)
79450ce9ee0Sniklas 			curproc = &proc0;
79550ce9ee0Sniklas 
796df930be7Sderaadt 		waittime = 0;
797df930be7Sderaadt 		vfs_shutdown();
798df930be7Sderaadt 		/*
799df930be7Sderaadt 		 * If we've been adjusting the clock, the todr
80067365115Skstailey 		 * will be out of synch; adjust it now unless
80167365115Skstailey 		 * the system was sitting in ddb.
802df930be7Sderaadt 		 */
80367365115Skstailey 		if ((howto & RB_TIMEBAD) == 0) {
804df930be7Sderaadt 			resettodr();
80567365115Skstailey 		} else {
80667365115Skstailey 			printf("WARNING: not updating battery clock\n");
80767365115Skstailey 		}
808df930be7Sderaadt 	}
809df930be7Sderaadt 
810df930be7Sderaadt 	/* Disable interrupts. */
811df930be7Sderaadt 	splhigh();
812df930be7Sderaadt 
813df930be7Sderaadt 	/* If rebooting and a dump is requested do it. */
81450ce9ee0Sniklas #if 0
81550ce9ee0Sniklas 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
81650ce9ee0Sniklas #else
81750ce9ee0Sniklas 	if (howto & RB_DUMP)
81850ce9ee0Sniklas #endif
819df930be7Sderaadt 		dumpsys();
820df930be7Sderaadt 
82134fbf6deSderaadt haltsys:
82234fbf6deSderaadt 
823df930be7Sderaadt 	/* run any shutdown hooks */
824df930be7Sderaadt 	doshutdownhooks();
825df930be7Sderaadt 
826df930be7Sderaadt #ifdef BOOTKEY
827df930be7Sderaadt 	printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
828df930be7Sderaadt 	cngetc();
829df930be7Sderaadt 	printf("\n");
830df930be7Sderaadt #endif
831df930be7Sderaadt 
832df930be7Sderaadt 	/* Finally, halt/reboot the system. */
833df930be7Sderaadt 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
834df930be7Sderaadt 	prom_halt(howto & RB_HALT);
835df930be7Sderaadt 	/*NOTREACHED*/
836df930be7Sderaadt }
837df930be7Sderaadt 
838df930be7Sderaadt /*
839df930be7Sderaadt  * These variables are needed by /sbin/savecore
840df930be7Sderaadt  */
841df930be7Sderaadt u_long	dumpmag = 0x8fca0101;	/* magic number */
842df930be7Sderaadt int 	dumpsize = 0;		/* pages */
843df930be7Sderaadt long	dumplo = 0; 		/* blocks */
844df930be7Sderaadt 
845df930be7Sderaadt /*
84650ce9ee0Sniklas  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
84750ce9ee0Sniklas  */
84850ce9ee0Sniklas int
84950ce9ee0Sniklas cpu_dumpsize()
85050ce9ee0Sniklas {
85150ce9ee0Sniklas 	int size;
85250ce9ee0Sniklas 
85350ce9ee0Sniklas 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
85450ce9ee0Sniklas 	if (roundup(size, dbtob(1)) != dbtob(1))
85550ce9ee0Sniklas 		return -1;
85650ce9ee0Sniklas 
85750ce9ee0Sniklas 	return (1);
85850ce9ee0Sniklas }
85950ce9ee0Sniklas 
86050ce9ee0Sniklas /*
86150ce9ee0Sniklas  * cpu_dump: dump machine-dependent kernel core dump headers.
86250ce9ee0Sniklas  */
86350ce9ee0Sniklas int
86450ce9ee0Sniklas cpu_dump()
86550ce9ee0Sniklas {
86650ce9ee0Sniklas 	int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
86750ce9ee0Sniklas 	long buf[dbtob(1) / sizeof (long)];
86850ce9ee0Sniklas 	kcore_seg_t	*segp;
86950ce9ee0Sniklas 	cpu_kcore_hdr_t	*cpuhdrp;
87050ce9ee0Sniklas 
87150ce9ee0Sniklas         dump = bdevsw[major(dumpdev)].d_dump;
87250ce9ee0Sniklas 
87350ce9ee0Sniklas 	segp = (kcore_seg_t *)buf;
87450ce9ee0Sniklas 	cpuhdrp =
87550ce9ee0Sniklas 	    (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)];
87650ce9ee0Sniklas 
87750ce9ee0Sniklas 	/*
87850ce9ee0Sniklas 	 * Generate a segment header.
87950ce9ee0Sniklas 	 */
88050ce9ee0Sniklas 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
88150ce9ee0Sniklas 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
88250ce9ee0Sniklas 
88350ce9ee0Sniklas 	/*
88450ce9ee0Sniklas 	 * Add the machine-dependent header info
88550ce9ee0Sniklas 	 */
88650ce9ee0Sniklas 	cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map);
88750ce9ee0Sniklas 	cpuhdrp->page_size = PAGE_SIZE;
88850ce9ee0Sniklas 	cpuhdrp->core_seg.start = ctob(firstusablepage);
88950ce9ee0Sniklas 	cpuhdrp->core_seg.size = ctob(physmem);
89050ce9ee0Sniklas 
89150ce9ee0Sniklas 	return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
89250ce9ee0Sniklas }
89350ce9ee0Sniklas 
89450ce9ee0Sniklas /*
895df930be7Sderaadt  * This is called by configure to set dumplo and dumpsize.
896df930be7Sderaadt  * Dumps always skip the first CLBYTES of disk space
897df930be7Sderaadt  * in case there might be a disk label stored there.
898df930be7Sderaadt  * If there is extra space, put dump at the end to
899df930be7Sderaadt  * reduce the chance that swapping trashes it.
900df930be7Sderaadt  */
901df930be7Sderaadt void
902df930be7Sderaadt dumpconf()
903df930be7Sderaadt {
90450ce9ee0Sniklas 	int nblks, dumpblks;	/* size of dump area */
905df930be7Sderaadt 	int maj;
906df930be7Sderaadt 
907df930be7Sderaadt 	if (dumpdev == NODEV)
90850ce9ee0Sniklas 		goto bad;
909df930be7Sderaadt 	maj = major(dumpdev);
910df930be7Sderaadt 	if (maj < 0 || maj >= nblkdev)
911df930be7Sderaadt 		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
912df930be7Sderaadt 	if (bdevsw[maj].d_psize == NULL)
91350ce9ee0Sniklas 		goto bad;
914df930be7Sderaadt 	nblks = (*bdevsw[maj].d_psize)(dumpdev);
915df930be7Sderaadt 	if (nblks <= ctod(1))
91650ce9ee0Sniklas 		goto bad;
91750ce9ee0Sniklas 
91850ce9ee0Sniklas 	dumpblks = cpu_dumpsize();
91950ce9ee0Sniklas 	if (dumpblks < 0)
92050ce9ee0Sniklas 		goto bad;
92150ce9ee0Sniklas 	dumpblks += ctod(physmem);
92250ce9ee0Sniklas 
92350ce9ee0Sniklas 	/* If dump won't fit (incl. room for possible label), punt. */
92450ce9ee0Sniklas 	if (dumpblks > (nblks - ctod(1)))
92550ce9ee0Sniklas 		goto bad;
92650ce9ee0Sniklas 
92750ce9ee0Sniklas 	/* Put dump at end of partition */
92850ce9ee0Sniklas 	dumplo = nblks - dumpblks;
92950ce9ee0Sniklas 
93050ce9ee0Sniklas 	/* dumpsize is in page units, and doesn't include headers. */
93150ce9ee0Sniklas 	dumpsize = physmem;
932df930be7Sderaadt 	return;
933df930be7Sderaadt 
93450ce9ee0Sniklas bad:
93550ce9ee0Sniklas 	dumpsize = 0;
93650ce9ee0Sniklas 	return;
937df930be7Sderaadt }
938df930be7Sderaadt 
939df930be7Sderaadt /*
94050ce9ee0Sniklas  * Dump the kernel's image to the swap partition.
941df930be7Sderaadt  */
94250ce9ee0Sniklas #define	BYTES_PER_DUMP	NBPG
94350ce9ee0Sniklas 
944df930be7Sderaadt void
945df930be7Sderaadt dumpsys()
946df930be7Sderaadt {
94750ce9ee0Sniklas 	unsigned bytes, i, n;
94850ce9ee0Sniklas 	int maddr, psize;
94950ce9ee0Sniklas 	daddr_t blkno;
95050ce9ee0Sniklas 	int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
95150ce9ee0Sniklas 	int error;
952df930be7Sderaadt 
95350ce9ee0Sniklas 	/* Save registers. */
95450ce9ee0Sniklas 	savectx(&dumppcb);
95550ce9ee0Sniklas 
95650ce9ee0Sniklas 	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
957df930be7Sderaadt 	if (dumpdev == NODEV)
958df930be7Sderaadt 		return;
95950ce9ee0Sniklas 
96050ce9ee0Sniklas 	/*
96150ce9ee0Sniklas 	 * For dumps during autoconfiguration,
96250ce9ee0Sniklas 	 * if dump device has already configured...
96350ce9ee0Sniklas 	 */
964df930be7Sderaadt 	if (dumpsize == 0)
96550ce9ee0Sniklas 		dumpconf();
96650ce9ee0Sniklas 	if (dumplo <= 0) {
96750ce9ee0Sniklas 		printf("\ndump to dev %x not possible\n", dumpdev);
968df930be7Sderaadt 		return;
969df930be7Sderaadt 	}
97050ce9ee0Sniklas 	printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo);
971df930be7Sderaadt 
97250ce9ee0Sniklas 	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
973df930be7Sderaadt 	printf("dump ");
97450ce9ee0Sniklas 	if (psize == -1) {
97550ce9ee0Sniklas 		printf("area unavailable\n");
97650ce9ee0Sniklas 		return;
97750ce9ee0Sniklas 	}
97850ce9ee0Sniklas 
97950ce9ee0Sniklas 	/* XXX should purge all outstanding keystrokes. */
98050ce9ee0Sniklas 
98150ce9ee0Sniklas 	if ((error = cpu_dump()) != 0)
98250ce9ee0Sniklas 		goto err;
98350ce9ee0Sniklas 
98450ce9ee0Sniklas 	bytes = ctob(physmem);
98550ce9ee0Sniklas 	maddr = ctob(firstusablepage);
98650ce9ee0Sniklas 	blkno = dumplo + cpu_dumpsize();
98750ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
98850ce9ee0Sniklas 	error = 0;
98950ce9ee0Sniklas 	for (i = 0; i < bytes; i += n) {
99050ce9ee0Sniklas 
99150ce9ee0Sniklas 		/* Print out how many MBs we to go. */
99250ce9ee0Sniklas 		n = bytes - i;
99350ce9ee0Sniklas 		if (n && (n % (1024*1024)) == 0)
99450ce9ee0Sniklas 			printf("%d ", n / (1024 * 1024));
99550ce9ee0Sniklas 
99650ce9ee0Sniklas 		/* Limit size for next transfer. */
99750ce9ee0Sniklas 		if (n > BYTES_PER_DUMP)
99850ce9ee0Sniklas 			n =  BYTES_PER_DUMP;
99950ce9ee0Sniklas 
100050ce9ee0Sniklas 		error = (*dump)(dumpdev, blkno,
100150ce9ee0Sniklas 		    (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n);
100250ce9ee0Sniklas 		if (error)
100350ce9ee0Sniklas 			break;
100450ce9ee0Sniklas 		maddr += n;
100550ce9ee0Sniklas 		blkno += btodb(n);			/* XXX? */
100650ce9ee0Sniklas 
100750ce9ee0Sniklas 		/* XXX should look for keystrokes, to cancel. */
100850ce9ee0Sniklas 	}
100950ce9ee0Sniklas 
101050ce9ee0Sniklas err:
101150ce9ee0Sniklas 	switch (error) {
1012df930be7Sderaadt 
1013df930be7Sderaadt 	case ENXIO:
1014df930be7Sderaadt 		printf("device bad\n");
1015df930be7Sderaadt 		break;
1016df930be7Sderaadt 
1017df930be7Sderaadt 	case EFAULT:
1018df930be7Sderaadt 		printf("device not ready\n");
1019df930be7Sderaadt 		break;
1020df930be7Sderaadt 
1021df930be7Sderaadt 	case EINVAL:
1022df930be7Sderaadt 		printf("area improper\n");
1023df930be7Sderaadt 		break;
1024df930be7Sderaadt 
1025df930be7Sderaadt 	case EIO:
1026df930be7Sderaadt 		printf("i/o error\n");
1027df930be7Sderaadt 		break;
1028df930be7Sderaadt 
1029df930be7Sderaadt 	case EINTR:
1030df930be7Sderaadt 		printf("aborted from console\n");
1031df930be7Sderaadt 		break;
1032df930be7Sderaadt 
103350ce9ee0Sniklas 	case 0:
1034df930be7Sderaadt 		printf("succeeded\n");
1035df930be7Sderaadt 		break;
103650ce9ee0Sniklas 
103750ce9ee0Sniklas 	default:
103850ce9ee0Sniklas 		printf("error %d\n", error);
103950ce9ee0Sniklas 		break;
1040df930be7Sderaadt 	}
1041df930be7Sderaadt 	printf("\n\n");
1042df930be7Sderaadt 	delay(1000);
1043df930be7Sderaadt }
1044df930be7Sderaadt 
1045df930be7Sderaadt void
1046df930be7Sderaadt frametoreg(framep, regp)
1047df930be7Sderaadt 	struct trapframe *framep;
1048df930be7Sderaadt 	struct reg *regp;
1049df930be7Sderaadt {
1050df930be7Sderaadt 
1051df930be7Sderaadt 	regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
1052df930be7Sderaadt 	regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
1053df930be7Sderaadt 	regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
1054df930be7Sderaadt 	regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
1055df930be7Sderaadt 	regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
1056df930be7Sderaadt 	regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
1057df930be7Sderaadt 	regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
1058df930be7Sderaadt 	regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
1059df930be7Sderaadt 	regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
1060df930be7Sderaadt 	regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
1061df930be7Sderaadt 	regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
1062df930be7Sderaadt 	regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
1063df930be7Sderaadt 	regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
1064df930be7Sderaadt 	regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
1065df930be7Sderaadt 	regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
1066df930be7Sderaadt 	regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
106750ce9ee0Sniklas 	regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0];
106850ce9ee0Sniklas 	regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1];
106950ce9ee0Sniklas 	regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2];
1070df930be7Sderaadt 	regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
1071df930be7Sderaadt 	regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
1072df930be7Sderaadt 	regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
1073df930be7Sderaadt 	regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
1074df930be7Sderaadt 	regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
1075df930be7Sderaadt 	regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
1076df930be7Sderaadt 	regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
1077df930be7Sderaadt 	regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
1078df930be7Sderaadt 	regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
1079df930be7Sderaadt 	regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
108050ce9ee0Sniklas 	regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP];
108150ce9ee0Sniklas 	/* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */
1082df930be7Sderaadt 	regp->r_regs[R_ZERO] = 0;
1083df930be7Sderaadt }
1084df930be7Sderaadt 
1085df930be7Sderaadt void
1086df930be7Sderaadt regtoframe(regp, framep)
1087df930be7Sderaadt 	struct reg *regp;
1088df930be7Sderaadt 	struct trapframe *framep;
1089df930be7Sderaadt {
1090df930be7Sderaadt 
1091df930be7Sderaadt 	framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
1092df930be7Sderaadt 	framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
1093df930be7Sderaadt 	framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
1094df930be7Sderaadt 	framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
1095df930be7Sderaadt 	framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
1096df930be7Sderaadt 	framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
1097df930be7Sderaadt 	framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
1098df930be7Sderaadt 	framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
1099df930be7Sderaadt 	framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
1100df930be7Sderaadt 	framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
1101df930be7Sderaadt 	framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
1102df930be7Sderaadt 	framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
1103df930be7Sderaadt 	framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
1104df930be7Sderaadt 	framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
1105df930be7Sderaadt 	framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
1106df930be7Sderaadt 	framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
110750ce9ee0Sniklas 	framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0];
110850ce9ee0Sniklas 	framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1];
110950ce9ee0Sniklas 	framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2];
1110df930be7Sderaadt 	framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
1111df930be7Sderaadt 	framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
1112df930be7Sderaadt 	framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
1113df930be7Sderaadt 	framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
1114df930be7Sderaadt 	framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
1115df930be7Sderaadt 	framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
1116df930be7Sderaadt 	framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
1117df930be7Sderaadt 	framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
1118df930be7Sderaadt 	framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
1119df930be7Sderaadt 	framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
112050ce9ee0Sniklas 	framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP];
112150ce9ee0Sniklas 	/* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */
1122df930be7Sderaadt 	/* ??? = regp->r_regs[R_ZERO]; */
1123df930be7Sderaadt }
1124df930be7Sderaadt 
1125df930be7Sderaadt void
1126df930be7Sderaadt printregs(regp)
1127df930be7Sderaadt 	struct reg *regp;
1128df930be7Sderaadt {
1129df930be7Sderaadt 	int i;
1130df930be7Sderaadt 
1131df930be7Sderaadt 	for (i = 0; i < 32; i++)
1132df930be7Sderaadt 		printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
1133df930be7Sderaadt 		   i & 1 ? "\n" : "\t");
1134df930be7Sderaadt }
1135df930be7Sderaadt 
1136df930be7Sderaadt void
1137df930be7Sderaadt regdump(framep)
1138df930be7Sderaadt 	struct trapframe *framep;
1139df930be7Sderaadt {
1140df930be7Sderaadt 	struct reg reg;
1141df930be7Sderaadt 
1142df930be7Sderaadt 	frametoreg(framep, &reg);
114350ce9ee0Sniklas 	reg.r_regs[R_SP] = alpha_pal_rdusp();
114450ce9ee0Sniklas 
1145df930be7Sderaadt 	printf("REGISTERS:\n");
1146df930be7Sderaadt 	printregs(&reg);
1147df930be7Sderaadt }
1148df930be7Sderaadt 
1149df930be7Sderaadt #ifdef DEBUG
1150df930be7Sderaadt int sigdebug = 0;
1151df930be7Sderaadt int sigpid = 0;
1152df930be7Sderaadt #define	SDB_FOLLOW	0x01
1153df930be7Sderaadt #define	SDB_KSTACK	0x02
1154df930be7Sderaadt #endif
1155df930be7Sderaadt 
1156df930be7Sderaadt /*
1157df930be7Sderaadt  * Send an interrupt to process.
1158df930be7Sderaadt  */
1159df930be7Sderaadt void
11605e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val)
1161df930be7Sderaadt 	sig_t catcher;
1162df930be7Sderaadt 	int sig, mask;
1163df930be7Sderaadt 	u_long code;
11645e1760a6Sderaadt 	int type;
11655e1760a6Sderaadt 	union sigval val;
1166df930be7Sderaadt {
1167df930be7Sderaadt 	struct proc *p = curproc;
1168df930be7Sderaadt 	struct sigcontext *scp, ksc;
1169df930be7Sderaadt 	struct trapframe *frame;
1170df930be7Sderaadt 	struct sigacts *psp = p->p_sigacts;
11712bf9c155Sderaadt 	int oonstack, fsize, rndfsize, kscsize;
1172df930be7Sderaadt 	extern char sigcode[], esigcode[];
1173df930be7Sderaadt 	extern struct proc *fpcurproc;
11742bf9c155Sderaadt 	siginfo_t *sip, ksi;
1175df930be7Sderaadt 
1176df930be7Sderaadt 	frame = p->p_md.md_tf;
1177df930be7Sderaadt 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
1178df930be7Sderaadt 	fsize = sizeof ksc;
1179df930be7Sderaadt 	rndfsize = ((fsize + 15) / 16) * 16;
11802bf9c155Sderaadt 	kscsize = rndfsize;
11812bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
11822bf9c155Sderaadt 		fsize += sizeof ksi;
11832bf9c155Sderaadt 		rndfsize = ((fsize + 15) / 16) * 16;
11842bf9c155Sderaadt 	}
118574652a67Sniklas 
1186df930be7Sderaadt 	/*
1187df930be7Sderaadt 	 * Allocate and validate space for the signal handler
1188df930be7Sderaadt 	 * context. Note that if the stack is in P0 space, the
1189df930be7Sderaadt 	 * call to grow() is a nop, and the useracc() check
1190df930be7Sderaadt 	 * will fail if the process has not already allocated
1191df930be7Sderaadt 	 * the space with a `brk'.
1192df930be7Sderaadt 	 */
1193df930be7Sderaadt 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1194df930be7Sderaadt 	    (psp->ps_sigonstack & sigmask(sig))) {
11958bc2093aSderaadt 		scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp +
1196df930be7Sderaadt 		    psp->ps_sigstk.ss_size - rndfsize);
1197df930be7Sderaadt 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
1198df930be7Sderaadt 	} else
119950ce9ee0Sniklas 		scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize);
1200df930be7Sderaadt 	if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
1201df930be7Sderaadt 		(void)grow(p, (u_long)scp);
1202df930be7Sderaadt #ifdef DEBUG
1203df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
120450ce9ee0Sniklas 		printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
1205df930be7Sderaadt 		    sig, &oonstack, scp);
1206df930be7Sderaadt #endif
1207df930be7Sderaadt 	if (useracc((caddr_t)scp, fsize, B_WRITE) == 0) {
1208df930be7Sderaadt #ifdef DEBUG
1209df930be7Sderaadt 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1210df930be7Sderaadt 			printf("sendsig(%d): useracc failed on sig %d\n",
1211df930be7Sderaadt 			    p->p_pid, sig);
1212df930be7Sderaadt #endif
1213df930be7Sderaadt 		/*
1214df930be7Sderaadt 		 * Process has trashed its stack; give it an illegal
1215df930be7Sderaadt 		 * instruction to halt it in its tracks.
1216df930be7Sderaadt 		 */
1217df930be7Sderaadt 		SIGACTION(p, SIGILL) = SIG_DFL;
1218df930be7Sderaadt 		sig = sigmask(SIGILL);
1219df930be7Sderaadt 		p->p_sigignore &= ~sig;
1220df930be7Sderaadt 		p->p_sigcatch &= ~sig;
1221df930be7Sderaadt 		p->p_sigmask &= ~sig;
1222df930be7Sderaadt 		psignal(p, SIGILL);
1223df930be7Sderaadt 		return;
1224df930be7Sderaadt 	}
1225df930be7Sderaadt 
1226df930be7Sderaadt 	/*
1227df930be7Sderaadt 	 * Build the signal context to be used by sigreturn.
1228df930be7Sderaadt 	 */
1229df930be7Sderaadt 	ksc.sc_onstack = oonstack;
1230df930be7Sderaadt 	ksc.sc_mask = mask;
123150ce9ee0Sniklas 	ksc.sc_pc = frame->tf_regs[FRAME_PC];
123250ce9ee0Sniklas 	ksc.sc_ps = frame->tf_regs[FRAME_PS];
1233df930be7Sderaadt 
1234df930be7Sderaadt 	/* copy the registers. */
1235df930be7Sderaadt 	frametoreg(frame, (struct reg *)ksc.sc_regs);
1236df930be7Sderaadt 	ksc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
123750ce9ee0Sniklas 	ksc.sc_regs[R_SP] = alpha_pal_rdusp();
1238df930be7Sderaadt 
1239df930be7Sderaadt 	/* save the floating-point state, if necessary, then copy it. */
1240df930be7Sderaadt 	if (p == fpcurproc) {
124150ce9ee0Sniklas 		alpha_pal_wrfen(1);
1242df930be7Sderaadt 		savefpstate(&p->p_addr->u_pcb.pcb_fp);
124350ce9ee0Sniklas 		alpha_pal_wrfen(0);
1244df930be7Sderaadt 		fpcurproc = NULL;
1245df930be7Sderaadt 	}
1246df930be7Sderaadt 	ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
1247df930be7Sderaadt 	bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
1248df930be7Sderaadt 	    sizeof(struct fpreg));
1249df930be7Sderaadt 	ksc.sc_fp_control = 0;					/* XXX ? */
1250df930be7Sderaadt 	bzero(ksc.sc_reserved, sizeof ksc.sc_reserved);		/* XXX */
1251df930be7Sderaadt 	bzero(ksc.sc_xxx, sizeof ksc.sc_xxx);			/* XXX */
1252df930be7Sderaadt 
1253df930be7Sderaadt 
1254df930be7Sderaadt #ifdef COMPAT_OSF1
1255df930be7Sderaadt 	/*
1256df930be7Sderaadt 	 * XXX Create an OSF/1-style sigcontext and associated goo.
1257df930be7Sderaadt 	 */
1258df930be7Sderaadt #endif
1259df930be7Sderaadt 
12602bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
12612bf9c155Sderaadt 		initsiginfo(&ksi, sig, code, type, val);
12622bf9c155Sderaadt 		sip = (void *)scp + kscsize;
12632bf9c155Sderaadt 		(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize);
12642bf9c155Sderaadt 	}
12652bf9c155Sderaadt 
1266df930be7Sderaadt 	/*
1267df930be7Sderaadt 	 * copy the frame out to userland.
1268df930be7Sderaadt 	 */
12692bf9c155Sderaadt 	(void) copyout((caddr_t)&ksc, (caddr_t)scp, kscsize);
1270df930be7Sderaadt #ifdef DEBUG
1271df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
127250ce9ee0Sniklas 		printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig,
1273df930be7Sderaadt 		    scp, code);
1274df930be7Sderaadt #endif
1275df930be7Sderaadt 
1276df930be7Sderaadt 	/*
1277df930be7Sderaadt 	 * Set up the registers to return to sigcode.
1278df930be7Sderaadt 	 */
127950ce9ee0Sniklas 	frame->tf_regs[FRAME_PC] =
128050ce9ee0Sniklas 	    (u_int64_t)PS_STRINGS - (esigcode - sigcode);
128150ce9ee0Sniklas 	frame->tf_regs[FRAME_A0] = sig;
12822bf9c155Sderaadt 	frame->tf_regs[FRAME_A1] = (psp->ps_siginfo & sigmask(sig)) ?
12832bf9c155Sderaadt 	    (u_int64_t)sip : NULL;
128450ce9ee0Sniklas 	frame->tf_regs[FRAME_A2] = (u_int64_t)scp;
1285df930be7Sderaadt 	frame->tf_regs[FRAME_T12] = (u_int64_t)catcher;		/* t12 is pv */
128650ce9ee0Sniklas 	alpha_pal_wrusp((unsigned long)scp);
1287df930be7Sderaadt 
1288df930be7Sderaadt #ifdef DEBUG
1289df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1290df930be7Sderaadt 		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
129150ce9ee0Sniklas 		    frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]);
1292df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1293df930be7Sderaadt 		printf("sendsig(%d): sig %d returns\n",
1294df930be7Sderaadt 		    p->p_pid, sig);
1295df930be7Sderaadt #endif
1296df930be7Sderaadt }
1297df930be7Sderaadt 
1298df930be7Sderaadt /*
1299df930be7Sderaadt  * System call to cleanup state after a signal
1300df930be7Sderaadt  * has been taken.  Reset signal mask and
1301df930be7Sderaadt  * stack state from context left by sendsig (above).
1302df930be7Sderaadt  * Return to previous pc and psl as specified by
1303df930be7Sderaadt  * context left by sendsig. Check carefully to
1304df930be7Sderaadt  * make sure that the user has not modified the
1305df930be7Sderaadt  * psl to gain improper priviledges or to cause
1306df930be7Sderaadt  * a machine fault.
1307df930be7Sderaadt  */
1308df930be7Sderaadt /* ARGSUSED */
1309df930be7Sderaadt int
1310df930be7Sderaadt sys_sigreturn(p, v, retval)
1311df930be7Sderaadt 	struct proc *p;
1312df930be7Sderaadt 	void *v;
1313df930be7Sderaadt 	register_t *retval;
1314df930be7Sderaadt {
1315df930be7Sderaadt 	struct sys_sigreturn_args /* {
1316df930be7Sderaadt 		syscallarg(struct sigcontext *) sigcntxp;
1317df930be7Sderaadt 	} */ *uap = v;
1318df930be7Sderaadt 	struct sigcontext *scp, ksc;
1319df930be7Sderaadt 	extern struct proc *fpcurproc;
1320df930be7Sderaadt 
1321df930be7Sderaadt 	scp = SCARG(uap, sigcntxp);
1322df930be7Sderaadt #ifdef DEBUG
1323df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
132450ce9ee0Sniklas 	    printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
1325df930be7Sderaadt #endif
1326df930be7Sderaadt 
1327df930be7Sderaadt 	if (ALIGN(scp) != (u_int64_t)scp)
1328df930be7Sderaadt 		return (EINVAL);
1329df930be7Sderaadt 
1330df930be7Sderaadt 	/*
1331df930be7Sderaadt 	 * Test and fetch the context structure.
1332df930be7Sderaadt 	 * We grab it all at once for speed.
1333df930be7Sderaadt 	 */
1334df930be7Sderaadt 	if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
1335df930be7Sderaadt 	    copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
1336df930be7Sderaadt 		return (EINVAL);
1337df930be7Sderaadt 
1338df930be7Sderaadt 	if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)		/* magic number */
1339df930be7Sderaadt 		return (EINVAL);
1340df930be7Sderaadt 	/*
1341df930be7Sderaadt 	 * Restore the user-supplied information
1342df930be7Sderaadt 	 */
1343df930be7Sderaadt 	if (ksc.sc_onstack)
1344df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
1345df930be7Sderaadt 	else
1346df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1347df930be7Sderaadt 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1348df930be7Sderaadt 
134950ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
135050ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PS] =
135150ce9ee0Sniklas 	    (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
1352df930be7Sderaadt 
1353df930be7Sderaadt 	regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
135450ce9ee0Sniklas 	alpha_pal_wrusp(ksc.sc_regs[R_SP]);
1355df930be7Sderaadt 
1356df930be7Sderaadt 	/* XXX ksc.sc_ownedfp ? */
1357df930be7Sderaadt 	if (p == fpcurproc)
1358df930be7Sderaadt 		fpcurproc = NULL;
1359df930be7Sderaadt 	bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
1360df930be7Sderaadt 	    sizeof(struct fpreg));
1361df930be7Sderaadt 	/* XXX ksc.sc_fp_control ? */
1362df930be7Sderaadt 
1363df930be7Sderaadt #ifdef DEBUG
1364df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1365df930be7Sderaadt 		printf("sigreturn(%d): returns\n", p->p_pid);
1366df930be7Sderaadt #endif
1367df930be7Sderaadt 	return (EJUSTRETURN);
1368df930be7Sderaadt }
1369df930be7Sderaadt 
1370df930be7Sderaadt /*
1371df930be7Sderaadt  * machine dependent system variables.
1372df930be7Sderaadt  */
137350ce9ee0Sniklas int
1374df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1375df930be7Sderaadt 	int *name;
1376df930be7Sderaadt 	u_int namelen;
1377df930be7Sderaadt 	void *oldp;
1378df930be7Sderaadt 	size_t *oldlenp;
1379df930be7Sderaadt 	void *newp;
1380df930be7Sderaadt 	size_t newlen;
1381df930be7Sderaadt 	struct proc *p;
1382df930be7Sderaadt {
1383df930be7Sderaadt 	dev_t consdev;
1384df930be7Sderaadt 
1385df930be7Sderaadt 	/* all sysctl names at this level are terminal */
1386df930be7Sderaadt 	if (namelen != 1)
1387df930be7Sderaadt 		return (ENOTDIR);		/* overloaded */
1388df930be7Sderaadt 
1389df930be7Sderaadt 	switch (name[0]) {
1390df930be7Sderaadt 	case CPU_CONSDEV:
1391df930be7Sderaadt 		if (cn_tab != NULL)
1392df930be7Sderaadt 			consdev = cn_tab->cn_dev;
1393df930be7Sderaadt 		else
1394df930be7Sderaadt 			consdev = NODEV;
1395df930be7Sderaadt 		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1396df930be7Sderaadt 			sizeof consdev));
1397417eba8cSderaadt 
1398417eba8cSderaadt 	case CPU_ROOT_DEVICE:
1399417eba8cSderaadt 		return (sysctl_rdstring(oldp, oldlenp, newp, root_device));
1400417eba8cSderaadt 
140150ce9ee0Sniklas 	case CPU_UNALIGNED_PRINT:
140250ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
140350ce9ee0Sniklas 		    &alpha_unaligned_print));
140450ce9ee0Sniklas 
140550ce9ee0Sniklas 	case CPU_UNALIGNED_FIX:
140650ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
140750ce9ee0Sniklas 		    &alpha_unaligned_fix));
140850ce9ee0Sniklas 
140950ce9ee0Sniklas 	case CPU_UNALIGNED_SIGBUS:
141050ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
141150ce9ee0Sniklas 		    &alpha_unaligned_sigbus));
141250ce9ee0Sniklas 
14133a630e3fSniklas 	case CPU_BOOTED_KERNEL:
14143a630e3fSniklas 		return (sysctl_rdstring(oldp, oldlenp, newp, booted_kernel));
14153a630e3fSniklas 
1416df930be7Sderaadt 	default:
1417df930be7Sderaadt 		return (EOPNOTSUPP);
1418df930be7Sderaadt 	}
1419df930be7Sderaadt 	/* NOTREACHED */
1420df930be7Sderaadt }
1421df930be7Sderaadt 
1422df930be7Sderaadt /*
1423df930be7Sderaadt  * Set registers on exec.
1424df930be7Sderaadt  */
1425df930be7Sderaadt void
1426df930be7Sderaadt setregs(p, pack, stack, retval)
1427df930be7Sderaadt 	register struct proc *p;
1428df930be7Sderaadt 	struct exec_package *pack;
1429df930be7Sderaadt 	u_long stack;
1430df930be7Sderaadt 	register_t *retval;
1431df930be7Sderaadt {
1432df930be7Sderaadt 	struct trapframe *tfp = p->p_md.md_tf;
1433df930be7Sderaadt 	extern struct proc *fpcurproc;
14343a630e3fSniklas #ifdef DEBUG
14353a630e3fSniklas 	int i;
14363a630e3fSniklas #endif
1437df930be7Sderaadt 
1438df930be7Sderaadt #ifdef DEBUG
143950ce9ee0Sniklas 	/*
144050ce9ee0Sniklas 	 * Crash and dump, if the user requested it.
144150ce9ee0Sniklas 	 */
144250ce9ee0Sniklas 	if (boothowto & RB_DUMP)
144350ce9ee0Sniklas 		panic("crash requested by boot flags");
144450ce9ee0Sniklas #endif
144550ce9ee0Sniklas 
144650ce9ee0Sniklas #ifdef DEBUG
144750ce9ee0Sniklas 	for (i = 0; i < FRAME_SIZE; i++)
1448df930be7Sderaadt 		tfp->tf_regs[i] = 0xbabefacedeadbeef;
1449df930be7Sderaadt #else
145050ce9ee0Sniklas 	bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
1451df930be7Sderaadt #endif
1452df930be7Sderaadt 	bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
1453df930be7Sderaadt #define FP_RN 2 /* XXX */
1454df930be7Sderaadt 	p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58;
145550ce9ee0Sniklas 	alpha_pal_wrusp(stack);
145650ce9ee0Sniklas 	tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
145750ce9ee0Sniklas 	tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
1458df930be7Sderaadt 
145950ce9ee0Sniklas 	tfp->tf_regs[FRAME_A0] = stack;
146050ce9ee0Sniklas 	/* a1 and a2 already zeroed */
146150ce9ee0Sniklas 	tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC];	/* a.k.a. PV */
146250ce9ee0Sniklas 
146350ce9ee0Sniklas 	p->p_md.md_flags &= ~MDP_FPUSED;
1464df930be7Sderaadt 	if (fpcurproc == p)
1465df930be7Sderaadt 		fpcurproc = NULL;
1466df930be7Sderaadt 
1467df930be7Sderaadt 	retval[0] = retval[1] = 0;
1468df930be7Sderaadt }
1469df930be7Sderaadt 
1470df930be7Sderaadt void
1471df930be7Sderaadt netintr()
1472df930be7Sderaadt {
147350ce9ee0Sniklas 	int n, s;
147450ce9ee0Sniklas 
147550ce9ee0Sniklas 	s = splhigh();
147650ce9ee0Sniklas 	n = netisr;
147750ce9ee0Sniklas 	netisr = 0;
147850ce9ee0Sniklas 	splx(s);
147950ce9ee0Sniklas 
148050ce9ee0Sniklas #define	DONETISR(bit, fn)						\
148150ce9ee0Sniklas 	do {								\
148250ce9ee0Sniklas 		if (n & (1 << (bit)))					\
148350ce9ee0Sniklas 			fn;						\
148450ce9ee0Sniklas 	} while (0)
148550ce9ee0Sniklas 
1486df930be7Sderaadt #ifdef INET
148750ce9ee0Sniklas 	DONETISR(NETISR_ARP, arpintr());
148850ce9ee0Sniklas 	DONETISR(NETISR_IP, ipintr());
1489df930be7Sderaadt #endif
1490df930be7Sderaadt #ifdef NS
149150ce9ee0Sniklas 	DONETISR(NETISR_NS, nsintr());
1492df930be7Sderaadt #endif
1493df930be7Sderaadt #ifdef ISO
149450ce9ee0Sniklas 	DONETISR(NETISR_ISO, clnlintr());
1495df930be7Sderaadt #endif
1496df930be7Sderaadt #ifdef CCITT
149750ce9ee0Sniklas 	DONETISR(NETISR_CCITT, ccittintr());
1498df930be7Sderaadt #endif
149950ce9ee0Sniklas #ifdef NATM
150050ce9ee0Sniklas 	DONETISR(NETISR_NATM, natmintr());
1501df930be7Sderaadt #endif
150250ce9ee0Sniklas #if NPPP > 1
150350ce9ee0Sniklas 	DONETISR(NETISR_PPP, pppintr());
150450ce9ee0Sniklas #endif
150550ce9ee0Sniklas 
150650ce9ee0Sniklas #undef DONETISR
1507df930be7Sderaadt }
1508df930be7Sderaadt 
1509df930be7Sderaadt void
1510df930be7Sderaadt do_sir()
1511df930be7Sderaadt {
15123a630e3fSniklas 	u_int64_t n;
1513df930be7Sderaadt 
15143a630e3fSniklas 	do {
15153a630e3fSniklas 		(void)splhigh();
15163a630e3fSniklas 		n = ssir;
15173a630e3fSniklas 		ssir = 0;
15183a630e3fSniklas 		splsoft();		/* don't recurse through spl0() */
15193a630e3fSniklas 
15203a630e3fSniklas #define	DO_SIR(bit, fn)							\
15213a630e3fSniklas 		do {							\
15223a630e3fSniklas 			if (n & (bit)) {				\
15233a630e3fSniklas 				cnt.v_soft++;				\
15243a630e3fSniklas 				fn;					\
15253a630e3fSniklas 			}						\
15263a630e3fSniklas 		} while (0)
15273a630e3fSniklas 
15283a630e3fSniklas 		DO_SIR(SIR_NET, netintr());
15293a630e3fSniklas 		DO_SIR(SIR_CLOCK, softclock());
15303a630e3fSniklas 
15313a630e3fSniklas #undef DO_SIR
15323a630e3fSniklas 	} while (ssir != 0);
1533df930be7Sderaadt }
1534df930be7Sderaadt 
1535df930be7Sderaadt int
1536df930be7Sderaadt spl0()
1537df930be7Sderaadt {
1538df930be7Sderaadt 
15393a630e3fSniklas 	if (ssir)
15403a630e3fSniklas 		do_sir();		/* it lowers the IPL itself */
1541df930be7Sderaadt 
154250ce9ee0Sniklas 	return (alpha_pal_swpipl(ALPHA_PSL_IPL_0));
1543df930be7Sderaadt }
1544df930be7Sderaadt 
1545df930be7Sderaadt /*
1546df930be7Sderaadt  * The following primitives manipulate the run queues.  _whichqs tells which
1547df930be7Sderaadt  * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
1548e464495eSniklas  * into queues, Remrunqueue removes them from queues.  The running process is
1549e464495eSniklas  * on no queue, other processes are on a queue related to p->p_priority,
1550e464495eSniklas  * divided by 4 actually to shrink the 0-127 range of priorities into the 32
1551e464495eSniklas  * available queues.
1552df930be7Sderaadt  */
1553df930be7Sderaadt /*
1554df930be7Sderaadt  * setrunqueue(p)
1555df930be7Sderaadt  *	proc *p;
1556df930be7Sderaadt  *
1557df930be7Sderaadt  * Call should be made at splclock(), and p->p_stat should be SRUN.
1558df930be7Sderaadt  */
1559df930be7Sderaadt 
1560df930be7Sderaadt void
1561df930be7Sderaadt setrunqueue(p)
1562df930be7Sderaadt 	struct proc *p;
1563df930be7Sderaadt {
1564df930be7Sderaadt 	int bit;
1565df930be7Sderaadt 
1566df930be7Sderaadt 	/* firewall: p->p_back must be NULL */
1567df930be7Sderaadt 	if (p->p_back != NULL)
1568df930be7Sderaadt 		panic("setrunqueue");
1569df930be7Sderaadt 
1570df930be7Sderaadt 	bit = p->p_priority >> 2;
1571df930be7Sderaadt 	whichqs |= (1 << bit);
1572df930be7Sderaadt 	p->p_forw = (struct proc *)&qs[bit];
1573df930be7Sderaadt 	p->p_back = qs[bit].ph_rlink;
1574df930be7Sderaadt 	p->p_back->p_forw = p;
1575df930be7Sderaadt 	qs[bit].ph_rlink = p;
1576df930be7Sderaadt }
1577df930be7Sderaadt 
1578df930be7Sderaadt /*
1579e464495eSniklas  * remrunqueue(p)
1580df930be7Sderaadt  *
1581df930be7Sderaadt  * Call should be made at splclock().
1582df930be7Sderaadt  */
1583df930be7Sderaadt void
1584d3cbbad5Skstailey remrunqueue(p)
1585df930be7Sderaadt 	struct proc *p;
1586df930be7Sderaadt {
1587df930be7Sderaadt 	int bit;
1588df930be7Sderaadt 
1589df930be7Sderaadt 	bit = p->p_priority >> 2;
1590df930be7Sderaadt 	if ((whichqs & (1 << bit)) == 0)
1591d3cbbad5Skstailey 		panic("remrunqueue");
1592df930be7Sderaadt 
1593df930be7Sderaadt 	p->p_back->p_forw = p->p_forw;
1594df930be7Sderaadt 	p->p_forw->p_back = p->p_back;
1595df930be7Sderaadt 	p->p_back = NULL;	/* for firewall checking. */
1596df930be7Sderaadt 
1597df930be7Sderaadt 	if ((struct proc *)&qs[bit] == qs[bit].ph_link)
1598df930be7Sderaadt 		whichqs &= ~(1 << bit);
1599df930be7Sderaadt }
1600df930be7Sderaadt 
1601df930be7Sderaadt /*
1602df930be7Sderaadt  * Return the best possible estimate of the time in the timeval
1603df930be7Sderaadt  * to which tvp points.  Unfortunately, we can't read the hardware registers.
1604df930be7Sderaadt  * We guarantee that the time will be greater than the value obtained by a
1605df930be7Sderaadt  * previous call.
1606df930be7Sderaadt  */
1607df930be7Sderaadt void
1608df930be7Sderaadt microtime(tvp)
1609df930be7Sderaadt 	register struct timeval *tvp;
1610df930be7Sderaadt {
1611df930be7Sderaadt 	int s = splclock();
1612df930be7Sderaadt 	static struct timeval lasttime;
1613df930be7Sderaadt 
1614df930be7Sderaadt 	*tvp = time;
1615df930be7Sderaadt #ifdef notdef
1616df930be7Sderaadt 	tvp->tv_usec += clkread();
1617df930be7Sderaadt 	while (tvp->tv_usec > 1000000) {
1618df930be7Sderaadt 		tvp->tv_sec++;
1619df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1620df930be7Sderaadt 	}
1621df930be7Sderaadt #endif
1622df930be7Sderaadt 	if (tvp->tv_sec == lasttime.tv_sec &&
1623df930be7Sderaadt 	    tvp->tv_usec <= lasttime.tv_usec &&
1624df930be7Sderaadt 	    (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
1625df930be7Sderaadt 		tvp->tv_sec++;
1626df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1627df930be7Sderaadt 	}
1628df930be7Sderaadt 	lasttime = *tvp;
1629df930be7Sderaadt 	splx(s);
1630df930be7Sderaadt }
1631df930be7Sderaadt 
1632417eba8cSderaadt /*
1633417eba8cSderaadt  * Wait "n" microseconds.
1634417eba8cSderaadt  */
163550ce9ee0Sniklas void
1636417eba8cSderaadt delay(n)
163750ce9ee0Sniklas 	unsigned long n;
1638417eba8cSderaadt {
1639417eba8cSderaadt 	long N = cycles_per_usec * (n);
1640417eba8cSderaadt 
1641417eba8cSderaadt 	while (N > 0)				/* XXX */
1642417eba8cSderaadt 		N -= 3;				/* XXX */
1643417eba8cSderaadt }
1644417eba8cSderaadt 
1645df930be7Sderaadt #if defined(COMPAT_OSF1) || 1		/* XXX */
16463a630e3fSniklas void	cpu_exec_ecoff_setregs __P((struct proc *, struct exec_package *,
16473a630e3fSniklas 	    u_long, register_t *));
16483a630e3fSniklas 
1649df930be7Sderaadt void
1650417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval)
1651df930be7Sderaadt 	struct proc *p;
1652417eba8cSderaadt 	struct exec_package *epp;
1653df930be7Sderaadt 	u_long stack;
1654df930be7Sderaadt 	register_t *retval;
1655df930be7Sderaadt {
1656417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
1657df930be7Sderaadt 
1658417eba8cSderaadt 	setregs(p, epp, stack, retval);
165950ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value;
1660df930be7Sderaadt }
1661df930be7Sderaadt 
1662df930be7Sderaadt /*
1663df930be7Sderaadt  * cpu_exec_ecoff_hook():
1664df930be7Sderaadt  *	cpu-dependent ECOFF format hook for execve().
1665df930be7Sderaadt  *
1666df930be7Sderaadt  * Do any machine-dependent diddling of the exec package when doing ECOFF.
1667df930be7Sderaadt  *
1668df930be7Sderaadt  */
1669df930be7Sderaadt int
1670417eba8cSderaadt cpu_exec_ecoff_hook(p, epp)
1671df930be7Sderaadt 	struct proc *p;
1672df930be7Sderaadt 	struct exec_package *epp;
1673df930be7Sderaadt {
1674417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
1675a2f8ce8dSderaadt 	extern struct emul emul_native;
1676df930be7Sderaadt #ifdef COMPAT_OSF1
1677df930be7Sderaadt 	extern struct emul emul_osf1;
1678df930be7Sderaadt #endif
1679df930be7Sderaadt 
1680417eba8cSderaadt 	switch (execp->f.f_magic) {
1681df930be7Sderaadt #ifdef COMPAT_OSF1
1682df930be7Sderaadt 	case ECOFF_MAGIC_ALPHA:
1683df930be7Sderaadt 		epp->ep_emul = &emul_osf1;
1684df930be7Sderaadt 		break;
1685df930be7Sderaadt #endif
1686df930be7Sderaadt 
168750ce9ee0Sniklas 	case ECOFF_MAGIC_NATIVE_ALPHA:
1688a2f8ce8dSderaadt 		epp->ep_emul = &emul_native;
1689df930be7Sderaadt 		break;
1690df930be7Sderaadt 
1691df930be7Sderaadt 	default:
169234fbf6deSderaadt 		return ENOEXEC;
1693df930be7Sderaadt 	}
1694df930be7Sderaadt 	return 0;
1695df930be7Sderaadt }
1696df930be7Sderaadt #endif
1697e464495eSniklas 
1698e464495eSniklas /* XXX XXX BEGIN XXX XXX */
1699e464495eSniklas vm_offset_t alpha_XXX_dmamap_or;				/* XXX */
1700e464495eSniklas 								/* XXX */
1701e464495eSniklas vm_offset_t							/* XXX */
1702e464495eSniklas alpha_XXX_dmamap(v)						/* XXX */
1703e464495eSniklas 	vm_offset_t v;						/* XXX */
1704e464495eSniklas {								/* XXX */
1705e464495eSniklas 								/* XXX */
1706e464495eSniklas 	return (vtophys(v) | alpha_XXX_dmamap_or);		/* XXX */
1707e464495eSniklas }								/* XXX */
1708e464495eSniklas /* XXX XXX END XXX XXX */
1709