xref: /openbsd/sys/arch/alpha/alpha/machdep.c (revision aed035ab)
1*aed035abSart /* $NetBSD: machdep.c,v 1.206 2000/05/23 05:12:54 thorpej Exp $ */
2*aed035abSart 
3*aed035abSart /*-
4*aed035abSart  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5*aed035abSart  * All rights reserved.
6*aed035abSart  *
7*aed035abSart  * This code is derived from software contributed to The NetBSD Foundation
8*aed035abSart  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9*aed035abSart  * NASA Ames Research Center and by Chris G. Demetriou.
10*aed035abSart  *
11*aed035abSart  * Redistribution and use in source and binary forms, with or without
12*aed035abSart  * modification, are permitted provided that the following conditions
13*aed035abSart  * are met:
14*aed035abSart  * 1. Redistributions of source code must retain the above copyright
15*aed035abSart  *    notice, this list of conditions and the following disclaimer.
16*aed035abSart  * 2. Redistributions in binary form must reproduce the above copyright
17*aed035abSart  *    notice, this list of conditions and the following disclaimer in the
18*aed035abSart  *    documentation and/or other materials provided with the distribution.
19*aed035abSart  * 3. All advertising materials mentioning features or use of this software
20*aed035abSart  *    must display the following acknowledgement:
21*aed035abSart  *	This product includes software developed by the NetBSD
22*aed035abSart  *	Foundation, Inc. and its contributors.
23*aed035abSart  * 4. Neither the name of The NetBSD Foundation nor the names of its
24*aed035abSart  *    contributors may be used to endorse or promote products derived
25*aed035abSart  *    from this software without specific prior written permission.
26*aed035abSart  *
27*aed035abSart  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28*aed035abSart  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29*aed035abSart  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30*aed035abSart  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31*aed035abSart  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*aed035abSart  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*aed035abSart  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*aed035abSart  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*aed035abSart  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*aed035abSart  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*aed035abSart  * POSSIBILITY OF SUCH DAMAGE.
38*aed035abSart  */
39df930be7Sderaadt 
40df930be7Sderaadt /*
41417eba8cSderaadt  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
42df930be7Sderaadt  * All rights reserved.
43df930be7Sderaadt  *
44df930be7Sderaadt  * Author: Chris G. Demetriou
45df930be7Sderaadt  *
46df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
47df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
48df930be7Sderaadt  * notice and this permission notice appear in all copies of the
49df930be7Sderaadt  * software, derivative works or modified versions, and any portions
50df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
51df930be7Sderaadt  *
52df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
53df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
54df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
55df930be7Sderaadt  *
56df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
57df930be7Sderaadt  *
58df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
59df930be7Sderaadt  *  School of Computer Science
60df930be7Sderaadt  *  Carnegie Mellon University
61df930be7Sderaadt  *  Pittsburgh PA 15213-3890
62df930be7Sderaadt  *
63df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
64df930be7Sderaadt  * rights to redistribute these changes.
65df930be7Sderaadt  */
66df930be7Sderaadt 
67df930be7Sderaadt #include <sys/param.h>
68df930be7Sderaadt #include <sys/systm.h>
69df930be7Sderaadt #include <sys/signalvar.h>
70df930be7Sderaadt #include <sys/kernel.h>
71df930be7Sderaadt #include <sys/map.h>
72df930be7Sderaadt #include <sys/proc.h>
73df930be7Sderaadt #include <sys/buf.h>
74df930be7Sderaadt #include <sys/reboot.h>
75417eba8cSderaadt #include <sys/device.h>
76df930be7Sderaadt #include <sys/conf.h>
77df930be7Sderaadt #include <sys/file.h>
78df930be7Sderaadt #ifdef REAL_CLISTS
79df930be7Sderaadt #include <sys/clist.h>
80df930be7Sderaadt #endif
81d66eba84Sart #include <sys/timeout.h>
82df930be7Sderaadt #include <sys/malloc.h>
83df930be7Sderaadt #include <sys/mbuf.h>
84df930be7Sderaadt #include <sys/msgbuf.h>
85df930be7Sderaadt #include <sys/ioctl.h>
86df930be7Sderaadt #include <sys/tty.h>
87df930be7Sderaadt #include <sys/user.h>
88df930be7Sderaadt #include <sys/exec.h>
89df930be7Sderaadt #include <sys/exec_ecoff.h>
90*aed035abSart #include <vm/vm.h>
91df930be7Sderaadt #include <sys/sysctl.h>
9250ce9ee0Sniklas #include <sys/core.h>
9350ce9ee0Sniklas #include <sys/kcore.h>
9450ce9ee0Sniklas #include <machine/kcore.h>
95df930be7Sderaadt #ifdef SYSVMSG
96df930be7Sderaadt #include <sys/msg.h>
97df930be7Sderaadt #endif
98df930be7Sderaadt #ifdef SYSVSEM
99df930be7Sderaadt #include <sys/sem.h>
100df930be7Sderaadt #endif
101df930be7Sderaadt #ifdef SYSVSHM
102df930be7Sderaadt #include <sys/shm.h>
103df930be7Sderaadt #endif
104df930be7Sderaadt 
105df930be7Sderaadt #include <sys/mount.h>
106df930be7Sderaadt #include <sys/syscallargs.h>
107df930be7Sderaadt 
108df930be7Sderaadt #include <vm/vm_kern.h>
109*aed035abSart #include <uvm/uvm_extern.h>
110df930be7Sderaadt 
111df930be7Sderaadt #include <dev/cons.h>
112df930be7Sderaadt 
11350ce9ee0Sniklas #include <machine/autoconf.h>
114df930be7Sderaadt #include <machine/cpu.h>
115df930be7Sderaadt #include <machine/reg.h>
116df930be7Sderaadt #include <machine/rpb.h>
117df930be7Sderaadt #include <machine/prom.h>
1183a630e3fSniklas #include <machine/cpuconf.h>
119df930be7Sderaadt 
12012f8bbedSniklas #ifdef DDB
12112f8bbedSniklas #include <machine/db_machdep.h>
12212f8bbedSniklas #include <ddb/db_access.h>
12312f8bbedSniklas #include <ddb/db_sym.h>
12412f8bbedSniklas #include <ddb/db_extern.h>
12512f8bbedSniklas #endif
12612f8bbedSniklas 
127df930be7Sderaadt #include <net/netisr.h>
12850ce9ee0Sniklas #include <net/if.h>
12950ce9ee0Sniklas 
13050ce9ee0Sniklas #ifdef INET
13150ce9ee0Sniklas #include <netinet/in.h>
13250ce9ee0Sniklas #include <netinet/if_ether.h>
13350ce9ee0Sniklas #include <netinet/ip_var.h>
13450ce9ee0Sniklas #endif
135287546eaSitojun 
136287546eaSitojun #ifdef INET6
137287546eaSitojun # ifndef INET
138287546eaSitojun #  include <netinet/in.h>
139287546eaSitojun # endif
1408038b434Sitojun #include <netinet/ip6.h>
141287546eaSitojun #include <netinet6/ip6_var.h>
142287546eaSitojun #endif
143287546eaSitojun 
14450ce9ee0Sniklas #include "ppp.h"
145661c8891Sjason #include "bridge.h"
146df930be7Sderaadt 
147417eba8cSderaadt #include "le_ioasic.h"			/* for le_iomem creation */
148df930be7Sderaadt 
14950ce9ee0Sniklas int	cpu_dump __P((void));
1503a630e3fSniklas int	cpu_dumpsize __P((void));
151*aed035abSart u_long	cpu_dump_mempagecnt __P((void));
15250ce9ee0Sniklas void	do_sir __P((void));
1533a630e3fSniklas void	dumpsys __P((void));
154*aed035abSart caddr_t allocsys __P((caddr_t));
1553a630e3fSniklas void	identifycpu __P((void));
1563a630e3fSniklas void	netintr __P((void));
1573a630e3fSniklas void	regdump __P((struct trapframe *framep));
1583a630e3fSniklas void	printregs __P((struct reg *));
159df930be7Sderaadt 
160df930be7Sderaadt /*
161df930be7Sderaadt  * Declare these as initialized data so we can patch them.
162df930be7Sderaadt  */
163df930be7Sderaadt #ifdef	NBUF
164df930be7Sderaadt int	nbuf = NBUF;
165df930be7Sderaadt #else
166df930be7Sderaadt int	nbuf = 0;
167df930be7Sderaadt #endif
168df930be7Sderaadt #ifdef	BUFPAGES
169df930be7Sderaadt int	bufpages = BUFPAGES;
170df930be7Sderaadt #else
171df930be7Sderaadt int	bufpages = 0;
172df930be7Sderaadt #endif
173*aed035abSart 
174*aed035abSart vm_map_t exec_map = NULL;
175*aed035abSart vm_map_t mb_map = NULL;
176*aed035abSart vm_map_t phys_map = NULL;
177*aed035abSart 
178df930be7Sderaadt int	maxmem;			/* max memory per process */
179df930be7Sderaadt 
180df930be7Sderaadt int	totalphysmem;		/* total amount of physical memory in system */
18174652a67Sniklas int	physmem;		/* physical mem used by OpenBSD + some rsvd */
182df930be7Sderaadt int	resvmem;		/* amount of memory reserved for PROM */
183df930be7Sderaadt int	unusedmem;		/* amount of memory for OS that we don't use */
184df930be7Sderaadt int	unknownmem;		/* amount of memory with an unknown use */
185df930be7Sderaadt 
186df930be7Sderaadt int	cputype;		/* system type, from the RPB */
187df930be7Sderaadt 
188df930be7Sderaadt /*
189df930be7Sderaadt  * XXX We need an address to which we can assign things so that they
190df930be7Sderaadt  * won't be optimized away because we didn't use the value.
191df930be7Sderaadt  */
192df930be7Sderaadt u_int32_t no_optimize;
193df930be7Sderaadt 
194df930be7Sderaadt /* the following is used externally (sysctl_hw) */
195*aed035abSart char	machine[] = MACHINE;		/* from <machine/param.h> */
196417eba8cSderaadt char	cpu_model[128];
197*aed035abSart char	root_device[17];
198df930be7Sderaadt 
199df930be7Sderaadt struct	user *proc0paddr;
200df930be7Sderaadt 
201df930be7Sderaadt /* Number of machine cycles per microsecond */
202df930be7Sderaadt u_int64_t	cycles_per_usec;
203df930be7Sderaadt 
204df930be7Sderaadt /* number of cpus in the box.  really! */
205df930be7Sderaadt int		ncpus;
206df930be7Sderaadt 
207*aed035abSart #if !defined(MULTIPROCESSOR)
208*aed035abSart /* A single machine check info structure for single CPU configurations. */
209*aed035abSart struct mchkinfo mchkinfo_store;
210*aed035abSart #endif
211*aed035abSart 
212*aed035abSart struct bootinfo_kernel bootinfo;
213*aed035abSart 
214*aed035abSart /* For built-in TCDS */
215*aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
216*aed035abSart u_int8_t	dec_3000_scsiid[2], dec_3000_scsifast[2];
217*aed035abSart #endif
218*aed035abSart 
219*aed035abSart struct platform platform;
220417eba8cSderaadt 
221417eba8cSderaadt /* for cpu_sysctl() */
22250ce9ee0Sniklas int	alpha_unaligned_print = 1;	/* warn about unaligned accesses */
22350ce9ee0Sniklas int	alpha_unaligned_fix = 1;	/* fix up unaligned accesses */
22450ce9ee0Sniklas int	alpha_unaligned_sigbus = 0;	/* don't SIGBUS on fixed-up accesses */
22550ce9ee0Sniklas 
226*aed035abSart /*
227*aed035abSart  * XXX This should be dynamically sized, but we have the chicken-egg problem!
228*aed035abSart  * XXX it should also be larger than it is, because not all of the mddt
229*aed035abSart  * XXX clusters end up being used for VM.
230*aed035abSart  */
231*aed035abSart phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];	/* low size bits overloaded */
232*aed035abSart int	mem_cluster_cnt;
233*aed035abSart 
2343a630e3fSniklas void
235*aed035abSart alpha_init(pfn, ptb, bim, bip, biv)
236df930be7Sderaadt 	u_long pfn;		/* first free PFN number */
237df930be7Sderaadt 	u_long ptb;		/* PFN of current level 1 page table */
238*aed035abSart 	u_long bim;		/* bootinfo magic */
239*aed035abSart 	u_long bip;		/* bootinfo pointer */
240*aed035abSart 	u_long biv;		/* bootinfo version */
241df930be7Sderaadt {
242*aed035abSart 	extern char kernel_text[], _end[];
243df930be7Sderaadt 	struct mddt *mddtp;
244*aed035abSart 	struct mddt_cluster *memc;
245df930be7Sderaadt 	int i, mddtweird;
246*aed035abSart 	struct vm_physseg *vps;
247*aed035abSart 	vaddr_t kernstart, kernend;
248*aed035abSart 	paddr_t kernstartpfn, kernendpfn, pfn0, pfn1;
249*aed035abSart 	vsize_t size;
250df930be7Sderaadt 	char *p;
251*aed035abSart 	caddr_t v;
252*aed035abSart 	char *bootinfo_msg;
253*aed035abSart 	const struct cpuinit *c;
254*aed035abSart 	extern caddr_t esym;
255*aed035abSart 	struct cpu_info *ci;
256*aed035abSart 	cpuid_t cpu_id;
257df930be7Sderaadt 
258*aed035abSart 	/* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */
259f3914c62Sniklas 
260df930be7Sderaadt 	/*
261*aed035abSart 	 * Turn off interrupts (not mchecks) and floating point.
262df930be7Sderaadt 	 * Make sure the instruction and data streams are consistent.
263df930be7Sderaadt 	 */
264*aed035abSart 	(void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
26550ce9ee0Sniklas 	alpha_pal_wrfen(0);
26650ce9ee0Sniklas 	ALPHA_TBIA();
26750ce9ee0Sniklas 	alpha_pal_imb();
268df930be7Sderaadt 
269*aed035abSart 	cpu_id = cpu_number();
270*aed035abSart 
271*aed035abSart #if defined(MULTIPROCESSOR)
272df930be7Sderaadt 	/*
273*aed035abSart 	 * Set our SysValue to the address of our cpu_info structure.
274*aed035abSart 	 * Secondary processors do this in their spinup trampoline.
275df930be7Sderaadt 	 */
276*aed035abSart 	alpha_pal_wrval((u_long)&cpu_info[cpu_id]);
277*aed035abSart #endif
278*aed035abSart 
279*aed035abSart 	ci = curcpu();
280*aed035abSart 	ci->ci_cpuid = cpu_id;
281*aed035abSart 
282*aed035abSart 	/*
283*aed035abSart 	 * Get critical system information (if possible, from the
284*aed035abSart 	 * information provided by the boot program).
285*aed035abSart 	 */
286*aed035abSart 	bootinfo_msg = NULL;
287*aed035abSart 	if (bim == BOOTINFO_MAGIC) {
288*aed035abSart 		if (biv == 0) {		/* backward compat */
289*aed035abSart 			biv = *(u_long *)bip;
290*aed035abSart 			bip += 8;
291*aed035abSart 		}
292*aed035abSart 		switch (biv) {
293*aed035abSart 		case 1: {
294*aed035abSart 			struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip;
295*aed035abSart 
296*aed035abSart 			bootinfo.ssym = v1p->ssym;
297*aed035abSart 			bootinfo.esym = v1p->esym;
298*aed035abSart 			/* hwrpb may not be provided by boot block in v1 */
299*aed035abSart 			if (v1p->hwrpb != NULL) {
300*aed035abSart 				bootinfo.hwrpb_phys =
301*aed035abSart 				    ((struct rpb *)v1p->hwrpb)->rpb_phys;
302*aed035abSart 				bootinfo.hwrpb_size = v1p->hwrpbsize;
303*aed035abSart 			} else {
304*aed035abSart 				bootinfo.hwrpb_phys =
305*aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_phys;
306*aed035abSart 				bootinfo.hwrpb_size =
307*aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_size;
308*aed035abSart 			}
309*aed035abSart 			bcopy(v1p->boot_flags, bootinfo.boot_flags,
310*aed035abSart 			    min(sizeof v1p->boot_flags,
311*aed035abSart 			      sizeof bootinfo.boot_flags));
312*aed035abSart 			bcopy(v1p->booted_kernel, bootinfo.booted_kernel,
313*aed035abSart 			    min(sizeof v1p->booted_kernel,
314*aed035abSart 			      sizeof bootinfo.booted_kernel));
315*aed035abSart 			/* booted dev not provided in bootinfo */
316*aed035abSart 			init_prom_interface((struct rpb *)
317*aed035abSart 			    ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys));
318*aed035abSart                 	prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
319*aed035abSart 			    sizeof bootinfo.booted_dev);
320*aed035abSart 			break;
321*aed035abSart 		}
322*aed035abSart 		default:
323*aed035abSart 			bootinfo_msg = "unknown bootinfo version";
324*aed035abSart 			goto nobootinfo;
325*aed035abSart 		}
326*aed035abSart 	} else {
327*aed035abSart 		bootinfo_msg = "boot program did not pass bootinfo";
328*aed035abSart nobootinfo:
329*aed035abSart 		bootinfo.ssym = (u_long)_end;
330*aed035abSart 		bootinfo.esym = (u_long)_end;
331*aed035abSart 		bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys;
332*aed035abSart 		bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size;
333*aed035abSart 		init_prom_interface((struct rpb *)HWRPB_ADDR);
334*aed035abSart 		prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
335*aed035abSart 		    sizeof bootinfo.boot_flags);
336*aed035abSart 		prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
337*aed035abSart 		    sizeof bootinfo.booted_kernel);
338*aed035abSart 		prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
339*aed035abSart 		    sizeof bootinfo.booted_dev);
340*aed035abSart 	}
341*aed035abSart 
342*aed035abSart 	esym = (caddr_t)bootinfo.esym;
343*aed035abSart 	/*
344*aed035abSart 	 * Initialize the kernel's mapping of the RPB.  It's needed for
345*aed035abSart 	 * lots of things.
346*aed035abSart 	 */
347*aed035abSart 	hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys);
348*aed035abSart 
349*aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
350*aed035abSart 	if (hwrpb->rpb_type == ST_DEC_3000_300 ||
351*aed035abSart 	    hwrpb->rpb_type == ST_DEC_3000_500) {
352*aed035abSart 		prom_getenv(PROM_E_SCSIID, dec_3000_scsiid,
353*aed035abSart 		    sizeof(dec_3000_scsiid));
354*aed035abSart 		prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast,
355*aed035abSart 		    sizeof(dec_3000_scsifast));
356*aed035abSart 	}
357*aed035abSart #endif
358df930be7Sderaadt 
359df930be7Sderaadt 	/*
360df930be7Sderaadt 	 * Remember how many cycles there are per microsecond,
361df930be7Sderaadt 	 * so that we can use delay().  Round up, for safety.
362df930be7Sderaadt 	 */
363df930be7Sderaadt 	cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
364df930be7Sderaadt 
365df930be7Sderaadt 	/*
366*aed035abSart 	 * Initalize the (temporary) bootstrap console interface, so
367*aed035abSart 	 * we can use printf until the VM system starts being setup.
368*aed035abSart 	 * The real console is initialized before then.
369df930be7Sderaadt 	 */
370*aed035abSart 	init_bootstrap_console();
371*aed035abSart 
372*aed035abSart 	/* OUTPUT NOW ALLOWED */
373*aed035abSart 
374*aed035abSart 	/* delayed from above */
375*aed035abSart 	if (bootinfo_msg)
376*aed035abSart 		printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n",
377*aed035abSart 		    bootinfo_msg, bim, bip, biv);
378*aed035abSart 
379*aed035abSart 	/* Initialize the trap vectors on the primary processor. */
380*aed035abSart 	trap_init();
381df930be7Sderaadt 
382df930be7Sderaadt 	/*
383*aed035abSart 	 * Find out what hardware we're on, and do basic initialization.
384df930be7Sderaadt 	 */
385*aed035abSart 	cputype = hwrpb->rpb_type;
386*aed035abSart 	if (cputype < 0) {
387*aed035abSart 		/*
388*aed035abSart 		 * At least some white-box systems have SRM which
389*aed035abSart 		 * reports a systype that's the negative of their
390*aed035abSart 		 * blue-box counterpart.
391*aed035abSart 		 */
392*aed035abSart 		cputype = -cputype;
393*aed035abSart 	}
394*aed035abSart 	c = platform_lookup(cputype);
395*aed035abSart 	if (c == NULL) {
396*aed035abSart 		platform_not_supported();
397*aed035abSart 		/* NOTREACHED */
398*aed035abSart 	}
399*aed035abSart 	(*c->init)();
400*aed035abSart 	strcpy(cpu_model, platform.model);
40150ce9ee0Sniklas 
40250ce9ee0Sniklas 	/*
403*aed035abSart 	 * Initalize the real console, so that the bootstrap console is
404*aed035abSart 	 * no longer necessary.
40550ce9ee0Sniklas 	 */
406*aed035abSart 	(*platform.cons_init)();
407*aed035abSart 
408*aed035abSart #ifdef DIAGNOSTIC
409*aed035abSart 	/* Paranoid sanity checking */
410*aed035abSart 
411*aed035abSart 	/* We should always be running on the primary. */
412*aed035abSart 	assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami());
413*aed035abSart 
414*aed035abSart 	/*
415*aed035abSart 	 * On single-CPU systypes, the primary should always be CPU 0,
416*aed035abSart 	 * except on Alpha 8200 systems where the CPU id is related
417*aed035abSart 	 * to the VID, which is related to the Turbo Laser node id.
418*aed035abSart 	 */
419*aed035abSart 	if (cputype != ST_DEC_21000)
420*aed035abSart 		assert(hwrpb->rpb_primary_cpu_id == 0);
421*aed035abSart #endif
422*aed035abSart 
423*aed035abSart 	/* NO MORE FIRMWARE ACCESS ALLOWED */
424*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
425*aed035abSart 	/*
426*aed035abSart 	 * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and
427*aed035abSart 	 * XXX pmap_uses_prom_console() evaluates to non-zero.)
428*aed035abSart 	 */
429*aed035abSart #endif
430*aed035abSart 
431*aed035abSart 	/*
432*aed035abSart 	 * find out this system's page size
433*aed035abSart 	 */
434*aed035abSart 	PAGE_SIZE = hwrpb->rpb_page_size;
435*aed035abSart 	if (PAGE_SIZE != 8192)
436*aed035abSart 		panic("page size %d != 8192?!", PAGE_SIZE);
437*aed035abSart 
438*aed035abSart 	/*
439*aed035abSart 	 * Initialize PAGE_SIZE-dependent variables.
440*aed035abSart 	 */
441*aed035abSart 	uvm_setpagesize();
442*aed035abSart 
443*aed035abSart 	/*
444*aed035abSart 	 * Find the beginning and end of the kernel (and leave a
445*aed035abSart 	 * bit of space before the beginning for the bootstrap
446*aed035abSart 	 * stack).
447*aed035abSart 	 */
448*aed035abSart 	kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE;
449*aed035abSart #ifdef DDB
450*aed035abSart 	kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym);
451*aed035abSart #else
452*aed035abSart 	kernend = (vaddr_t)round_page((vaddr_t)_end);
453*aed035abSart #endif
454*aed035abSart 
455*aed035abSart 	kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart));
456*aed035abSart 	kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend));
457df930be7Sderaadt 
458df930be7Sderaadt 	/*
459df930be7Sderaadt 	 * Find out how much memory is available, by looking at
460df930be7Sderaadt 	 * the memory cluster descriptors.  This also tries to do
461df930be7Sderaadt 	 * its best to detect things things that have never been seen
462df930be7Sderaadt 	 * before...
463df930be7Sderaadt 	 */
464df930be7Sderaadt 	mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
465df930be7Sderaadt 
466*aed035abSart 	/* MDDT SANITY CHECKING */
467df930be7Sderaadt 	mddtweird = 0;
468*aed035abSart 	if (mddtp->mddt_cluster_cnt < 2) {
469df930be7Sderaadt 		mddtweird = 1;
470*aed035abSart 		printf("WARNING: weird number of mem clusters: %lu\n",
471*aed035abSart 		    mddtp->mddt_cluster_cnt);
472df930be7Sderaadt 	}
473df930be7Sderaadt 
474*aed035abSart #if 0
475*aed035abSart 	printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt);
476*aed035abSart #endif
477df930be7Sderaadt 
478*aed035abSart 	for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
479*aed035abSart 		memc = &mddtp->mddt_clusters[i];
480*aed035abSart #if 0
481*aed035abSart 		printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i,
482*aed035abSart 		    memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage);
483*aed035abSart #endif
484*aed035abSart 		totalphysmem += memc->mddt_pg_cnt;
485*aed035abSart 		if (mem_cluster_cnt < VM_PHYSSEG_MAX) {	/* XXX */
486*aed035abSart 			mem_clusters[mem_cluster_cnt].start =
487*aed035abSart 			    ptoa(memc->mddt_pfn);
488*aed035abSart 			mem_clusters[mem_cluster_cnt].size =
489*aed035abSart 			    ptoa(memc->mddt_pg_cnt);
490*aed035abSart 			if (memc->mddt_usage & MDDT_mbz ||
491*aed035abSart 			    memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */
492*aed035abSart 			    memc->mddt_usage & MDDT_PALCODE)
493*aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
494*aed035abSart 				    VM_PROT_READ;
495*aed035abSart 			else
496*aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
497*aed035abSart 				    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
498*aed035abSart 			mem_cluster_cnt++;
499*aed035abSart 		}
500*aed035abSart 
501*aed035abSart 		if (memc->mddt_usage & MDDT_mbz) {
502*aed035abSart 			mddtweird = 1;
503*aed035abSart 			printf("WARNING: mem cluster %d has weird "
504*aed035abSart 			    "usage 0x%lx\n", i, memc->mddt_usage);
505*aed035abSart 			unknownmem += memc->mddt_pg_cnt;
506*aed035abSart 			continue;
507*aed035abSart 		}
508*aed035abSart 		if (memc->mddt_usage & MDDT_NONVOLATILE) {
509*aed035abSart 			/* XXX should handle these... */
510*aed035abSart 			printf("WARNING: skipping non-volatile mem "
511*aed035abSart 			    "cluster %d\n", i);
512*aed035abSart 			unusedmem += memc->mddt_pg_cnt;
513*aed035abSart 			continue;
514*aed035abSart 		}
515*aed035abSart 		if (memc->mddt_usage & MDDT_PALCODE) {
516*aed035abSart 			resvmem += memc->mddt_pg_cnt;
517*aed035abSart 			continue;
518*aed035abSart 		}
519*aed035abSart 
520*aed035abSart 		/*
521*aed035abSart 		 * We have a memory cluster available for system
522*aed035abSart 		 * software use.  We must determine if this cluster
523*aed035abSart 		 * holds the kernel.
524*aed035abSart 		 */
525*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
526*aed035abSart 		/*
527*aed035abSart 		 * XXX If the kernel uses the PROM console, we only use the
528*aed035abSart 		 * XXX memory after the kernel in the first system segment,
529*aed035abSart 		 * XXX to avoid clobbering prom mapping, data, etc.
530*aed035abSart 		 */
531*aed035abSart 	    if (!pmap_uses_prom_console() || physmem == 0) {
532*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
533*aed035abSart 		physmem += memc->mddt_pg_cnt;
534*aed035abSart 		pfn0 = memc->mddt_pfn;
535*aed035abSart 		pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt;
536*aed035abSart 		if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) {
537*aed035abSart 			/*
538*aed035abSart 			 * Must compute the location of the kernel
539*aed035abSart 			 * within the segment.
540*aed035abSart 			 */
541*aed035abSart #if 0
542*aed035abSart 			printf("Cluster %d contains kernel\n", i);
543*aed035abSart #endif
544*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
545*aed035abSart 		    if (!pmap_uses_prom_console()) {
546*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
547*aed035abSart 			if (pfn0 < kernstartpfn) {
548*aed035abSart 				/*
549*aed035abSart 				 * There is a chunk before the kernel.
550*aed035abSart 				 */
551*aed035abSart #if 0
552*aed035abSart 				printf("Loading chunk before kernel: "
553*aed035abSart 				    "0x%lx / 0x%lx\n", pfn0, kernstartpfn);
554*aed035abSart #endif
555*aed035abSart 				uvm_page_physload(pfn0, kernstartpfn,
556*aed035abSart 				    pfn0, kernstartpfn, VM_FREELIST_DEFAULT);
557*aed035abSart 			}
558*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
559*aed035abSart 		    }
560*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
561*aed035abSart 			if (kernendpfn < pfn1) {
562*aed035abSart 				/*
563*aed035abSart 				 * There is a chunk after the kernel.
564*aed035abSart 				 */
565*aed035abSart #if 0
566*aed035abSart 				printf("Loading chunk after kernel: "
567*aed035abSart 				    "0x%lx / 0x%lx\n", kernendpfn, pfn1);
568*aed035abSart #endif
569*aed035abSart 				uvm_page_physload(kernendpfn, pfn1,
570*aed035abSart 				    kernendpfn, pfn1, VM_FREELIST_DEFAULT);
571*aed035abSart 			}
572*aed035abSart 		} else {
573*aed035abSart 			/*
574*aed035abSart 			 * Just load this cluster as one chunk.
575*aed035abSart 			 */
576*aed035abSart #if 0
577*aed035abSart 			printf("Loading cluster %d: 0x%lx / 0x%lx\n", i,
578*aed035abSart 			    pfn0, pfn1);
579*aed035abSart #endif
580*aed035abSart 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1,
581*aed035abSart 			    VM_FREELIST_DEFAULT);
582*aed035abSart 		}
583*aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
584*aed035abSart 	    }
585*aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
586*aed035abSart 	}
587*aed035abSart 
588*aed035abSart 	/*
589*aed035abSart 	 * Dump out the MDDT if it looks odd...
590*aed035abSart 	 */
591df930be7Sderaadt 	if (mddtweird) {
592df930be7Sderaadt 		printf("\n");
593df930be7Sderaadt 		printf("complete memory cluster information:\n");
594df930be7Sderaadt 		for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
595df930be7Sderaadt 			printf("mddt %d:\n", i);
596df930be7Sderaadt 			printf("\tpfn %lx\n",
597df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pfn);
598df930be7Sderaadt 			printf("\tcnt %lx\n",
599df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_cnt);
600df930be7Sderaadt 			printf("\ttest %lx\n",
601df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_test);
602df930be7Sderaadt 			printf("\tbva %lx\n",
603df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_v_bitaddr);
604df930be7Sderaadt 			printf("\tbpa %lx\n",
605df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_p_bitaddr);
606df930be7Sderaadt 			printf("\tbcksum %lx\n",
607df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_bit_cksum);
608df930be7Sderaadt 			printf("\tusage %lx\n",
609df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_usage);
610df930be7Sderaadt 		}
611df930be7Sderaadt 		printf("\n");
612df930be7Sderaadt 	}
613df930be7Sderaadt 
614df930be7Sderaadt 	if (totalphysmem == 0)
615df930be7Sderaadt 		panic("can't happen: system seems to have no memory!");
616df930be7Sderaadt 	maxmem = physmem;
617df930be7Sderaadt #if 0
618df930be7Sderaadt 	printf("totalphysmem = %d\n", totalphysmem);
619df930be7Sderaadt 	printf("physmem = %d\n", physmem);
620df930be7Sderaadt 	printf("resvmem = %d\n", resvmem);
621df930be7Sderaadt 	printf("unusedmem = %d\n", unusedmem);
622df930be7Sderaadt 	printf("unknownmem = %d\n", unknownmem);
623df930be7Sderaadt #endif
624df930be7Sderaadt 
625df930be7Sderaadt 	/*
626*aed035abSart 	 * Initialize error message buffer (at end of core).
627df930be7Sderaadt 	 */
628*aed035abSart 	{
629*aed035abSart 		vsize_t sz = (vsize_t)round_page(MSGBUFSIZE);
630*aed035abSart 		vsize_t reqsz = sz;
631df930be7Sderaadt 
632*aed035abSart 		vps = &vm_physmem[vm_nphysseg - 1];
633e1da84e1Salex 
634*aed035abSart 		/* shrink so that it'll fit in the last segment */
635*aed035abSart 		if ((vps->avail_end - vps->avail_start) < atop(sz))
636*aed035abSart 			sz = ptoa(vps->avail_end - vps->avail_start);
637*aed035abSart 
638*aed035abSart 		vps->end -= atop(sz);
639*aed035abSart 		vps->avail_end -= atop(sz);
640*aed035abSart 		initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz);
641*aed035abSart 
642*aed035abSart 		/* Remove the last segment if it now has no pages. */
643*aed035abSart 		if (vps->start == vps->end)
644*aed035abSart 			vm_nphysseg--;
645*aed035abSart 
646*aed035abSart 		/* warn if the message buffer had to be shrunk */
647*aed035abSart 		if (sz != reqsz)
648*aed035abSart 			printf("WARNING: %ld bytes not available for msgbuf "
649*aed035abSart 			    "in last cluster (%ld used)\n", reqsz, sz);
650*aed035abSart 
651*aed035abSart 	}
652*aed035abSart 
653df930be7Sderaadt 	/*
654df930be7Sderaadt 	 * Init mapping for u page(s) for proc 0
655df930be7Sderaadt 	 */
656*aed035abSart 	proc0.p_addr = proc0paddr =
657*aed035abSart 	    (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL);
658df930be7Sderaadt 
659df930be7Sderaadt 	/*
660*aed035abSart 	 * Allocate space for system data structures.  These data structures
661*aed035abSart 	 * are allocated here instead of cpu_startup() because physical
662*aed035abSart 	 * memory is directly addressable.  We don't have to map these into
663*aed035abSart 	 * virtual address space.
664df930be7Sderaadt 	 */
665*aed035abSart 	size = (vsize_t)allocsys(NULL);
666*aed035abSart 	v = (caddr_t)pmap_steal_memory(size, NULL, NULL);
667*aed035abSart 	if ((allocsys(v) - v) != size)
668*aed035abSart 		panic("alpha_init: table size inconsistency");
669df930be7Sderaadt 
670df930be7Sderaadt 	/*
671df930be7Sderaadt 	 * Clear allocated memory.
672df930be7Sderaadt 	 */
673*aed035abSart 	bzero(v, size);
674df930be7Sderaadt 
675df930be7Sderaadt 	/*
676df930be7Sderaadt 	 * Initialize the virtual memory system, and set the
677df930be7Sderaadt 	 * page table base register in proc 0's PCB.
678df930be7Sderaadt 	 */
679*aed035abSart 	pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT),
680*aed035abSart 	    hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt);
681df930be7Sderaadt 
682df930be7Sderaadt 	/*
683df930be7Sderaadt 	 * Initialize the rest of proc 0's PCB, and cache its physical
684df930be7Sderaadt 	 * address.
685df930be7Sderaadt 	 */
686df930be7Sderaadt 	proc0.p_md.md_pcbpaddr =
687*aed035abSart 	    (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb);
688df930be7Sderaadt 
689df930be7Sderaadt 	/*
690df930be7Sderaadt 	 * Set the kernel sp, reserving space for an (empty) trapframe,
691df930be7Sderaadt 	 * and make proc0's trapframe pointer point to it for sanity.
692df930be7Sderaadt 	 */
69350ce9ee0Sniklas 	proc0paddr->u_pcb.pcb_hw.apcb_ksp =
694df930be7Sderaadt 	    (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
69574652a67Sniklas 	proc0.p_md.md_tf =
69674652a67Sniklas 	    (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
69750ce9ee0Sniklas 
698*aed035abSart 	/*
699*aed035abSart 	 * Initialize the primary CPU's idle PCB to proc0's.  In a
700*aed035abSart 	 * MULTIPROCESSOR configuration, each CPU will later get
701*aed035abSart 	 * its own idle PCB when autoconfiguration runs.
702*aed035abSart 	 */
703*aed035abSart 	ci->ci_idle_pcb = &proc0paddr->u_pcb;
704*aed035abSart 	ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr;
705df930be7Sderaadt 
706df930be7Sderaadt 	/*
707df930be7Sderaadt 	 * Look at arguments passed to us and compute boothowto.
708df930be7Sderaadt 	 */
709417eba8cSderaadt 
710417eba8cSderaadt 	boothowto = RB_SINGLE;
711df930be7Sderaadt #ifdef KADB
712df930be7Sderaadt 	boothowto |= RB_KDB;
713df930be7Sderaadt #endif
714*aed035abSart 	for (p = bootinfo.boot_flags; p && *p != '\0'; p++) {
715417eba8cSderaadt 		/*
716417eba8cSderaadt 		 * Note that we'd really like to differentiate case here,
717417eba8cSderaadt 		 * but the Alpha AXP Architecture Reference Manual
718417eba8cSderaadt 		 * says that we shouldn't.
719417eba8cSderaadt 		 */
720df930be7Sderaadt 		switch (*p) {
721df930be7Sderaadt 		case 'a': /* autoboot */
722417eba8cSderaadt 		case 'A':
723df930be7Sderaadt 			boothowto &= ~RB_SINGLE;
724df930be7Sderaadt 			break;
725df930be7Sderaadt 
72612f8bbedSniklas 		case 'b': /* Enter DDB as soon as the console is initialised */
72712f8bbedSniklas 		case 'B':
72812f8bbedSniklas 			boothowto |= RB_KDB;
72912f8bbedSniklas 			break;
73012f8bbedSniklas 
73150ce9ee0Sniklas 		case 'c': /* enter user kernel configuration */
73250ce9ee0Sniklas 		case 'C':
73350ce9ee0Sniklas 			boothowto |= RB_CONFIG;
73450ce9ee0Sniklas 			break;
73550ce9ee0Sniklas 
73650ce9ee0Sniklas #ifdef DEBUG
73750ce9ee0Sniklas 		case 'd': /* crash dump immediately after autoconfig */
73850ce9ee0Sniklas 		case 'D':
73950ce9ee0Sniklas 			boothowto |= RB_DUMP;
74050ce9ee0Sniklas 			break;
74150ce9ee0Sniklas #endif
74250ce9ee0Sniklas 
74350ce9ee0Sniklas 		case 'h': /* always halt, never reboot */
74450ce9ee0Sniklas 		case 'H':
74550ce9ee0Sniklas 			boothowto |= RB_HALT;
746df930be7Sderaadt 			break;
747df930be7Sderaadt 
748417eba8cSderaadt #if 0
749417eba8cSderaadt 		case 'm': /* mini root present in memory */
750417eba8cSderaadt 		case 'M':
751417eba8cSderaadt 			boothowto |= RB_MINIROOT;
752417eba8cSderaadt 			break;
753417eba8cSderaadt #endif
75450ce9ee0Sniklas 
75550ce9ee0Sniklas 		case 'n': /* askname */
75650ce9ee0Sniklas 		case 'N':
75750ce9ee0Sniklas 			boothowto |= RB_ASKNAME;
75850ce9ee0Sniklas 			break;
759*aed035abSart 
760*aed035abSart 		case 's': /* single-user (default, supported for sanity) */
761*aed035abSart 		case 'S':
762*aed035abSart 			boothowto |= RB_SINGLE;
763*aed035abSart 			break;
764*aed035abSart 
765*aed035abSart 		case '-':
766*aed035abSart 			/*
767*aed035abSart 			 * Just ignore this.  It's not required, but it's
768*aed035abSart 			 * common for it to be passed regardless.
769*aed035abSart 			 */
770*aed035abSart 			break;
771*aed035abSart 
772*aed035abSart 		default:
773*aed035abSart 			printf("Unrecognized boot flag '%c'.\n", *p);
774*aed035abSart 			break;
775df930be7Sderaadt 		}
776df930be7Sderaadt 	}
777df930be7Sderaadt 
778*aed035abSart 
779df930be7Sderaadt 	/*
780df930be7Sderaadt 	 * Figure out the number of cpus in the box, from RPB fields.
781df930be7Sderaadt 	 * Really.  We mean it.
782df930be7Sderaadt 	 */
783df930be7Sderaadt 	for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
784df930be7Sderaadt 		struct pcs *pcsp;
785df930be7Sderaadt 
786*aed035abSart 		pcsp = LOCATE_PCS(hwrpb, i);
787df930be7Sderaadt 		if ((pcsp->pcs_flags & PCS_PP) != 0)
788df930be7Sderaadt 			ncpus++;
789df930be7Sderaadt 	}
790*aed035abSart 
791*aed035abSart 	/*
792*aed035abSart 	 * Initialize debuggers, and break into them if appropriate.
793*aed035abSart 	 */
794*aed035abSart #ifdef DDB
795*aed035abSart 	ddb_init();
796*aed035abSart 
797*aed035abSart 	if (boothowto & RB_KDB)
798*aed035abSart 		Debugger();
799*aed035abSart #endif
800*aed035abSart #ifdef KGDB
801*aed035abSart 	if (boothowto & RB_KDB)
802*aed035abSart 		kgdb_connect(0);
803*aed035abSart #endif
804*aed035abSart 	/*
805*aed035abSart 	 * Figure out our clock frequency, from RPB fields.
806*aed035abSart 	 */
807*aed035abSart 	hz = hwrpb->rpb_intr_freq >> 12;
808*aed035abSart 	if (!(60 <= hz && hz <= 10240)) {
809*aed035abSart 		hz = 1024;
810*aed035abSart #ifdef DIAGNOSTIC
811*aed035abSart 		printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n",
812*aed035abSart 			hwrpb->rpb_intr_freq, hz);
813*aed035abSart #endif
814*aed035abSart 	}
815*aed035abSart }
816*aed035abSart 
817*aed035abSart caddr_t
818*aed035abSart allocsys(v)
819*aed035abSart 	caddr_t v;
820*aed035abSart {
821*aed035abSart 	/*
822*aed035abSart 	 * Allocate space for system data structures.
823*aed035abSart 	 * The first available kernel virtual address is in "v".
824*aed035abSart 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
825*aed035abSart 	 *
826*aed035abSart 	 * These data structures are allocated here instead of cpu_startup()
827*aed035abSart 	 * because physical memory is directly addressable. We don't have
828*aed035abSart 	 * to map these into virtual address space.
829*aed035abSart 	 */
830*aed035abSart #define valloc(name, type, num) \
831*aed035abSart 	    (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num))
832*aed035abSart 
833*aed035abSart #ifdef REAL_CLISTS
834*aed035abSart 	valloc(cfree, struct cblock, nclist);
835*aed035abSart #endif
836*aed035abSart 	valloc(timeouts, struct timeout, ntimeout);
837*aed035abSart #ifdef SYSVSHM
838*aed035abSart 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
839*aed035abSart #endif
840*aed035abSart #ifdef SYSVSEM
841*aed035abSart 	valloc(sema, struct semid_ds, seminfo.semmni);
842*aed035abSart 	valloc(sem, struct sem, seminfo.semmns);
843*aed035abSart 	/* This is pretty disgusting! */
844*aed035abSart 	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
845*aed035abSart #endif
846*aed035abSart #ifdef SYSVMSG
847*aed035abSart 	valloc(msgpool, char, msginfo.msgmax);
848*aed035abSart 	valloc(msgmaps, struct msgmap, msginfo.msgseg);
849*aed035abSart 	valloc(msghdrs, struct msg, msginfo.msgtql);
850*aed035abSart 	valloc(msqids, struct msqid_ds, msginfo.msgmni);
851*aed035abSart #endif
852*aed035abSart 
853*aed035abSart #ifndef BUFCACHEPERCENT
854*aed035abSart #define BUFCACHEPERCENT 10
855*aed035abSart #endif
856*aed035abSart 	/*
857*aed035abSart 	 * Determine how many buffers to allocate.
858*aed035abSart 	 * We allocate 10% of memory for buffer space.  Insure a
859*aed035abSart 	 * minimum of 16 buffers.
860*aed035abSart 	 */
861*aed035abSart 	if (bufpages == 0)
862*aed035abSart 		bufpages = (physmem / ((100/BUFCACHEPERCENT) / CLSIZE));
863*aed035abSart 	if (nbuf == 0) {
864*aed035abSart 		nbuf = bufpages;
865*aed035abSart 		if (nbuf < 16)
866*aed035abSart 			nbuf = 16;
867*aed035abSart 	}
868*aed035abSart 	valloc(buf, struct buf, nbuf);
869*aed035abSart 
870*aed035abSart #undef valloc
871*aed035abSart 
872*aed035abSart 	return v;
873df930be7Sderaadt }
874df930be7Sderaadt 
875417eba8cSderaadt void
876df930be7Sderaadt consinit()
877df930be7Sderaadt {
878*aed035abSart 
879*aed035abSart 	/*
880*aed035abSart 	 * Everything related to console initialization is done
881*aed035abSart 	 * in alpha_init().
882*aed035abSart 	 */
883*aed035abSart #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE)
884*aed035abSart 	printf("consinit: %susing prom console\n",
885*aed035abSart 	    pmap_uses_prom_console() ? "" : "not ");
88612f8bbedSniklas #endif
887df930be7Sderaadt }
888df930be7Sderaadt 
889417eba8cSderaadt void
890df930be7Sderaadt cpu_startup()
891df930be7Sderaadt {
892df930be7Sderaadt 	register unsigned i;
893df930be7Sderaadt 	int base, residual;
894*aed035abSart 	vaddr_t minaddr, maxaddr;
895*aed035abSart 	vsize_t size;
89650ce9ee0Sniklas #if defined(DEBUG)
897df930be7Sderaadt 	extern int pmapdebug;
898df930be7Sderaadt 	int opmapdebug = pmapdebug;
899df930be7Sderaadt 
900df930be7Sderaadt 	pmapdebug = 0;
901df930be7Sderaadt #endif
902df930be7Sderaadt 
903df930be7Sderaadt 	/*
904df930be7Sderaadt 	 * Good {morning,afternoon,evening,night}.
905df930be7Sderaadt 	 */
906df930be7Sderaadt 	printf(version);
907df930be7Sderaadt 	identifycpu();
908*aed035abSart 	printf("total memory = %d\n", ptoa(totalphysmem));
909*aed035abSart 	printf("(%d reserved for PROM, ", ptoa(resvmem));
910*aed035abSart 	printf("%d used by OpenBSD)\n", ptoa(physmem));
911*aed035abSart 	if (unusedmem) {
912*aed035abSart 		printf("WARNING: unused memory = %d\n", ptoa(unusedmem));
913*aed035abSart 	}
914*aed035abSart 	if (unknownmem) {
915*aed035abSart 		printf("WARNING: %d of memory with unknown purpose\n", ptoa(unknownmem));
916*aed035abSart 	}
917df930be7Sderaadt 
918df930be7Sderaadt 	/*
919df930be7Sderaadt 	 * Allocate virtual address space for file I/O buffers.
920df930be7Sderaadt 	 * Note they are different than the array of headers, 'buf',
921df930be7Sderaadt 	 * and usually occupy more virtual memory than physical.
922df930be7Sderaadt 	 */
923df930be7Sderaadt 	size = MAXBSIZE * nbuf;
924*aed035abSart 	if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
925*aed035abSart 		    NULL, UVM_UNKNOWN_OFFSET,
926*aed035abSart 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
927*aed035abSart 				UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
928*aed035abSart 		panic("startup: cannot allocate VM for buffers");
929df930be7Sderaadt 	base = bufpages / nbuf;
930df930be7Sderaadt 	residual = bufpages % nbuf;
931df930be7Sderaadt 	for (i = 0; i < nbuf; i++) {
932*aed035abSart 		vsize_t curbufsize;
933*aed035abSart 		vaddr_t curbuf;
934*aed035abSart 		struct vm_page *pg;
935df930be7Sderaadt 
936df930be7Sderaadt 		/*
937*aed035abSart 		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
938*aed035abSart 		 * that MAXBSIZE space, we allocate and map (base+1) pages
939*aed035abSart 		 * for the first "residual" buffers, and then we allocate
940*aed035abSart 		 * "base" pages for the rest.
941df930be7Sderaadt 		 */
942*aed035abSart 		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
943*aed035abSart 		curbufsize = NBPG * ((i < residual) ? (base+1) : base);
944*aed035abSart 
945*aed035abSart 		while (curbufsize) {
946*aed035abSart 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
947*aed035abSart 			if (pg == NULL)
948*aed035abSart 				panic("cpu_startup: not enough memory for "
949*aed035abSart 				    "buffer cache");
950*aed035abSart 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
951*aed035abSart 					VM_PROT_READ|VM_PROT_WRITE);
952*aed035abSart 			curbuf += PAGE_SIZE;
953*aed035abSart 			curbufsize -= PAGE_SIZE;
954*aed035abSart 		}
955df930be7Sderaadt 	}
956df930be7Sderaadt 	/*
957df930be7Sderaadt 	 * Allocate a submap for exec arguments.  This map effectively
958df930be7Sderaadt 	 * limits the number of processes exec'ing at any time.
959df930be7Sderaadt 	 */
960*aed035abSart 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
961*aed035abSart 				   16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
962df930be7Sderaadt 
963df930be7Sderaadt 	/*
964df930be7Sderaadt 	 * Allocate a submap for physio
965df930be7Sderaadt 	 */
966*aed035abSart 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
967*aed035abSart 				   VM_PHYS_SIZE, 0, FALSE, NULL);
968df930be7Sderaadt 
969df930be7Sderaadt 	/*
970df930be7Sderaadt 	 * Finally, allocate mbuf pool.  Since mclrefcnt is an off-size
971df930be7Sderaadt 	 * we use the more space efficient malloc in place of kmem_alloc.
972df930be7Sderaadt 	 */
973df930be7Sderaadt 	mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
974df930be7Sderaadt 			M_MBUF, M_NOWAIT);
975df930be7Sderaadt 	bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
976*aed035abSart 	mb_map = uvm_km_suballoc(kernel_map, (vaddr_t *)&mbutl, &maxaddr,
977*aed035abSart 			VM_MBUF_SIZE, VM_MAP_INTRSAFE, FALSE, NULL);
978*aed035abSart 
979df930be7Sderaadt 	/*
980d66eba84Sart 	 * Initialize timeouts
981df930be7Sderaadt 	 */
982d66eba84Sart 	timeout_init();
983df930be7Sderaadt 
98450ce9ee0Sniklas #if defined(DEBUG)
985df930be7Sderaadt 	pmapdebug = opmapdebug;
986df930be7Sderaadt #endif
987*aed035abSart 	printf("avail memory = %d\n", ptoa(uvmexp.free));
988*aed035abSart #if 0
989*aed035abSart 	{
990*aed035abSart 		extern u_long pmap_pages_stolen;
991*aed035abSart 
992*aed035abSart 		printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE);
993*aed035abSart 	}
994*aed035abSart #endif
995*aed035abSart 	printf("using %ld buffers containing %d of memory\n", (long)nbuf, bufpages * NBPG);
996df930be7Sderaadt 
997df930be7Sderaadt 	/*
998df930be7Sderaadt 	 * Set up buffers, so they can be used to read disk labels.
999df930be7Sderaadt 	 */
1000df930be7Sderaadt 	bufinit();
1001df930be7Sderaadt 
1002df930be7Sderaadt 	/*
1003df930be7Sderaadt 	 * Configure the system.
1004df930be7Sderaadt 	 */
100541033391Sderaadt 	if (boothowto & RB_CONFIG) {
100641033391Sderaadt #ifdef BOOT_CONFIG
100741033391Sderaadt 		user_config();
100841033391Sderaadt #else
100941033391Sderaadt 		printf("kernel does not support -c; continuing..\n");
101041033391Sderaadt #endif
101141033391Sderaadt 	}
1012df930be7Sderaadt 	configure();
101350ce9ee0Sniklas 
101450ce9ee0Sniklas 	/*
1015*aed035abSart 	 * Set up the HWPCB so that it's safe to configure secondary
1016*aed035abSart 	 * CPUs.
101750ce9ee0Sniklas 	 */
1018*aed035abSart 	hwrpb_primary_init();
1019*aed035abSart }
1020*aed035abSart 
1021*aed035abSart /*
1022*aed035abSart  * Retrieve the platform name from the DSR.
1023*aed035abSart  */
1024*aed035abSart const char *
1025*aed035abSart alpha_dsr_sysname()
1026*aed035abSart {
1027*aed035abSart 	struct dsrdb *dsr;
1028*aed035abSart 	const char *sysname;
1029*aed035abSart 
1030*aed035abSart 	/*
1031*aed035abSart 	 * DSR does not exist on early HWRPB versions.
1032*aed035abSart 	 */
1033*aed035abSart 	if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS)
1034*aed035abSart 		return (NULL);
1035*aed035abSart 
1036*aed035abSart 	dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off);
1037*aed035abSart 	sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off +
1038*aed035abSart 	    sizeof(u_int64_t)));
1039*aed035abSart 	return (sysname);
1040*aed035abSart }
1041*aed035abSart 
1042*aed035abSart /*
1043*aed035abSart  * Lookup the system specified system variation in the provided table,
1044*aed035abSart  * returning the model string on match.
1045*aed035abSart  */
1046*aed035abSart const char *
1047*aed035abSart alpha_variation_name(variation, avtp)
1048*aed035abSart 	u_int64_t variation;
1049*aed035abSart 	const struct alpha_variation_table *avtp;
1050*aed035abSart {
1051*aed035abSart 	int i;
1052*aed035abSart 
1053*aed035abSart 	for (i = 0; avtp[i].avt_model != NULL; i++)
1054*aed035abSart 		if (avtp[i].avt_variation == variation)
1055*aed035abSart 			return (avtp[i].avt_model);
1056*aed035abSart 	return (NULL);
1057*aed035abSart }
1058*aed035abSart 
1059*aed035abSart /*
1060*aed035abSart  * Generate a default platform name based for unknown system variations.
1061*aed035abSart  */
1062*aed035abSart const char *
1063*aed035abSart alpha_unknown_sysname()
1064*aed035abSart {
1065*aed035abSart 	static char s[128];		/* safe size */
1066*aed035abSart 
1067*aed035abSart 	sprintf(s, "%s family, unknown model variation 0x%lx",
1068*aed035abSart 	    platform.family, hwrpb->rpb_variation & SV_ST_MASK);
1069*aed035abSart 	return ((const char *)s);
1070df930be7Sderaadt }
1071df930be7Sderaadt 
107250ce9ee0Sniklas void
1073df930be7Sderaadt identifycpu()
1074df930be7Sderaadt {
1075*aed035abSart 	char *s;
1076df930be7Sderaadt 
1077df930be7Sderaadt 	/*
1078df930be7Sderaadt 	 * print out CPU identification information.
1079df930be7Sderaadt 	 */
1080*aed035abSart 	printf("%s", cpu_model);
1081*aed035abSart 	for(s = cpu_model; *s; ++s)
1082*aed035abSart 		if(strncasecmp(s, "MHz", 3) == 0)
1083*aed035abSart 			goto skipMHz;
1084*aed035abSart 	printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000);
1085*aed035abSart skipMHz:
1086*aed035abSart 	printf("\n");
108750ce9ee0Sniklas 	printf("%ld byte page size, %d processor%s.\n",
1088df930be7Sderaadt 	    hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s");
1089df930be7Sderaadt #if 0
1090df930be7Sderaadt 	/* this isn't defined for any systems that we run on? */
1091df930be7Sderaadt 	printf("serial number 0x%lx 0x%lx\n",
1092df930be7Sderaadt 	    ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]);
1093df930be7Sderaadt 
1094df930be7Sderaadt 	/* and these aren't particularly useful! */
1095df930be7Sderaadt 	printf("variation: 0x%lx, revision 0x%lx\n",
1096df930be7Sderaadt 	    hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
1097df930be7Sderaadt #endif
1098df930be7Sderaadt }
1099df930be7Sderaadt 
1100df930be7Sderaadt int	waittime = -1;
1101df930be7Sderaadt struct pcb dumppcb;
1102df930be7Sderaadt 
1103417eba8cSderaadt void
1104*aed035abSart boot(howto)
1105df930be7Sderaadt 	int howto;
1106df930be7Sderaadt {
1107df930be7Sderaadt 	extern int cold;
1108df930be7Sderaadt 
1109*aed035abSart #if defined(MULTIPROCESSOR)
1110*aed035abSart #if 0 /* XXX See below. */
1111*aed035abSart 	u_long cpu_id;
1112*aed035abSart #endif
1113*aed035abSart #endif
1114*aed035abSart 
1115*aed035abSart #if defined(MULTIPROCESSOR)
1116*aed035abSart 	/* We must be running on the primary CPU. */
1117*aed035abSart 	if (alpha_pal_whami() != hwrpb->rpb_primary_cpu_id)
1118*aed035abSart 		panic("cpu_reboot: not on primary CPU!");
1119*aed035abSart #endif
1120*aed035abSart 
1121df930be7Sderaadt 	/* If system is cold, just halt. */
1122df930be7Sderaadt 	if (cold) {
1123df930be7Sderaadt 		howto |= RB_HALT;
1124df930be7Sderaadt 		goto haltsys;
1125df930be7Sderaadt 	}
1126df930be7Sderaadt 
112750ce9ee0Sniklas 	/* If "always halt" was specified as a boot flag, obey. */
112850ce9ee0Sniklas 	if ((boothowto & RB_HALT) != 0)
112950ce9ee0Sniklas 		howto |= RB_HALT;
113050ce9ee0Sniklas 
1131df930be7Sderaadt 	boothowto = howto;
1132df930be7Sderaadt 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1133df930be7Sderaadt 		waittime = 0;
1134df930be7Sderaadt 		vfs_shutdown();
1135df930be7Sderaadt 		/*
1136df930be7Sderaadt 		 * If we've been adjusting the clock, the todr
1137*aed035abSart 		 * will be out of synch; adjust it now.
1138df930be7Sderaadt 		 */
1139df930be7Sderaadt 		resettodr();
1140df930be7Sderaadt 	}
1141df930be7Sderaadt 
1142df930be7Sderaadt 	/* Disable interrupts. */
1143df930be7Sderaadt 	splhigh();
1144df930be7Sderaadt 
1145df930be7Sderaadt 	/* If rebooting and a dump is requested do it. */
114650ce9ee0Sniklas #if 0
114750ce9ee0Sniklas 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
114850ce9ee0Sniklas #else
114950ce9ee0Sniklas 	if (howto & RB_DUMP)
115050ce9ee0Sniklas #endif
1151df930be7Sderaadt 		dumpsys();
1152df930be7Sderaadt 
115334fbf6deSderaadt haltsys:
115434fbf6deSderaadt 
1155df930be7Sderaadt 	/* run any shutdown hooks */
1156df930be7Sderaadt 	doshutdownhooks();
1157df930be7Sderaadt 
1158*aed035abSart #if defined(MULTIPROCESSOR)
1159*aed035abSart #if 0 /* XXX doesn't work when called from here?! */
1160*aed035abSart 	/* Kill off any secondary CPUs. */
1161*aed035abSart 	for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) {
1162*aed035abSart 		if (cpu_id == hwrpb->rpb_primary_cpu_id ||
1163*aed035abSart 		    cpu_info[cpu_id].ci_softc == NULL)
1164*aed035abSart 			continue;
1165*aed035abSart 		cpu_halt_secondary(cpu_id);
1166*aed035abSart 	}
1167*aed035abSart #endif
1168*aed035abSart #endif
1169*aed035abSart 
1170df930be7Sderaadt #ifdef BOOTKEY
1171df930be7Sderaadt 	printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
1172*aed035abSart 	cnpollc(1);	/* for proper keyboard command handling */
1173df930be7Sderaadt 	cngetc();
1174*aed035abSart 	cnpollc(0);
1175df930be7Sderaadt 	printf("\n");
1176df930be7Sderaadt #endif
1177df930be7Sderaadt 
1178*aed035abSart 	/* Finally, powerdown/halt/reboot the system. */
1179*aed035abSart 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN &&
1180*aed035abSart 	    platform.powerdown != NULL) {
1181*aed035abSart 		(*platform.powerdown)();
1182*aed035abSart 		printf("WARNING: powerdown failed!\n");
1183*aed035abSart 	}
1184df930be7Sderaadt 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
1185df930be7Sderaadt 	prom_halt(howto & RB_HALT);
1186df930be7Sderaadt 	/*NOTREACHED*/
1187df930be7Sderaadt }
1188df930be7Sderaadt 
1189df930be7Sderaadt /*
1190df930be7Sderaadt  * These variables are needed by /sbin/savecore
1191df930be7Sderaadt  */
1192df930be7Sderaadt u_long	dumpmag = 0x8fca0101;	/* magic number */
1193df930be7Sderaadt int 	dumpsize = 0;		/* pages */
1194df930be7Sderaadt long	dumplo = 0; 		/* blocks */
1195df930be7Sderaadt 
1196df930be7Sderaadt /*
119750ce9ee0Sniklas  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
119850ce9ee0Sniklas  */
119950ce9ee0Sniklas int
120050ce9ee0Sniklas cpu_dumpsize()
120150ce9ee0Sniklas {
120250ce9ee0Sniklas 	int size;
120350ce9ee0Sniklas 
1204*aed035abSart 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
1205*aed035abSart 	    ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
120650ce9ee0Sniklas 	if (roundup(size, dbtob(1)) != dbtob(1))
120750ce9ee0Sniklas 		return -1;
120850ce9ee0Sniklas 
120950ce9ee0Sniklas 	return (1);
121050ce9ee0Sniklas }
121150ce9ee0Sniklas 
121250ce9ee0Sniklas /*
1213*aed035abSart  * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped.
1214*aed035abSart  */
1215*aed035abSart u_long
1216*aed035abSart cpu_dump_mempagecnt()
1217*aed035abSart {
1218*aed035abSart 	u_long i, n;
1219*aed035abSart 
1220*aed035abSart 	n = 0;
1221*aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++)
1222*aed035abSart 		n += atop(mem_clusters[i].size);
1223*aed035abSart 	return (n);
1224*aed035abSart }
1225*aed035abSart 
1226*aed035abSart /*
122750ce9ee0Sniklas  * cpu_dump: dump machine-dependent kernel core dump headers.
122850ce9ee0Sniklas  */
122950ce9ee0Sniklas int
123050ce9ee0Sniklas cpu_dump()
123150ce9ee0Sniklas {
123250ce9ee0Sniklas 	int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1233*aed035abSart 	char buf[dbtob(1)];
123450ce9ee0Sniklas 	kcore_seg_t *segp;
123550ce9ee0Sniklas 	cpu_kcore_hdr_t *cpuhdrp;
1236*aed035abSart 	phys_ram_seg_t *memsegp;
1237*aed035abSart 	int i;
123850ce9ee0Sniklas 
123950ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
124050ce9ee0Sniklas 
1241*aed035abSart 	bzero(buf, sizeof buf);
124250ce9ee0Sniklas 	segp = (kcore_seg_t *)buf;
1243*aed035abSart 	cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
1244*aed035abSart 	memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) +
1245*aed035abSart 	    ALIGN(sizeof(*cpuhdrp))];
124650ce9ee0Sniklas 
124750ce9ee0Sniklas 	/*
124850ce9ee0Sniklas 	 * Generate a segment header.
124950ce9ee0Sniklas 	 */
125050ce9ee0Sniklas 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
125150ce9ee0Sniklas 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
125250ce9ee0Sniklas 
125350ce9ee0Sniklas 	/*
1254*aed035abSart 	 * Add the machine-dependent header info.
125550ce9ee0Sniklas 	 */
1256*aed035abSart 	cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map);
125750ce9ee0Sniklas 	cpuhdrp->page_size = PAGE_SIZE;
1258*aed035abSart 	cpuhdrp->nmemsegs = mem_cluster_cnt;
1259*aed035abSart 
1260*aed035abSart 	/*
1261*aed035abSart 	 * Fill in the memory segment descriptors.
1262*aed035abSart 	 */
1263*aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
1264*aed035abSart 		memsegp[i].start = mem_clusters[i].start;
1265*aed035abSart 		memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK;
1266*aed035abSart 	}
126750ce9ee0Sniklas 
126850ce9ee0Sniklas 	return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
126950ce9ee0Sniklas }
127050ce9ee0Sniklas 
127150ce9ee0Sniklas /*
1272*aed035abSart  * This is called by main to set dumplo and dumpsize.
1273*aed035abSart  * Dumps always skip the first NBPG of disk space
1274df930be7Sderaadt  * in case there might be a disk label stored there.
1275df930be7Sderaadt  * If there is extra space, put dump at the end to
1276df930be7Sderaadt  * reduce the chance that swapping trashes it.
1277df930be7Sderaadt  */
1278df930be7Sderaadt void
1279df930be7Sderaadt dumpconf()
1280df930be7Sderaadt {
128150ce9ee0Sniklas 	int nblks, dumpblks;	/* size of dump area */
1282df930be7Sderaadt 	int maj;
1283df930be7Sderaadt 
1284df930be7Sderaadt 	if (dumpdev == NODEV)
128550ce9ee0Sniklas 		goto bad;
1286df930be7Sderaadt 	maj = major(dumpdev);
1287df930be7Sderaadt 	if (maj < 0 || maj >= nblkdev)
1288df930be7Sderaadt 		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1289df930be7Sderaadt 	if (bdevsw[maj].d_psize == NULL)
129050ce9ee0Sniklas 		goto bad;
1291df930be7Sderaadt 	nblks = (*bdevsw[maj].d_psize)(dumpdev);
1292df930be7Sderaadt 	if (nblks <= ctod(1))
129350ce9ee0Sniklas 		goto bad;
129450ce9ee0Sniklas 
129550ce9ee0Sniklas 	dumpblks = cpu_dumpsize();
129650ce9ee0Sniklas 	if (dumpblks < 0)
129750ce9ee0Sniklas 		goto bad;
1298*aed035abSart 	dumpblks += ctod(cpu_dump_mempagecnt());
129950ce9ee0Sniklas 
130050ce9ee0Sniklas 	/* If dump won't fit (incl. room for possible label), punt. */
130150ce9ee0Sniklas 	if (dumpblks > (nblks - ctod(1)))
130250ce9ee0Sniklas 		goto bad;
130350ce9ee0Sniklas 
130450ce9ee0Sniklas 	/* Put dump at end of partition */
130550ce9ee0Sniklas 	dumplo = nblks - dumpblks;
130650ce9ee0Sniklas 
130750ce9ee0Sniklas 	/* dumpsize is in page units, and doesn't include headers. */
1308*aed035abSart 	dumpsize = cpu_dump_mempagecnt();
1309df930be7Sderaadt 	return;
1310df930be7Sderaadt 
131150ce9ee0Sniklas bad:
131250ce9ee0Sniklas 	dumpsize = 0;
131350ce9ee0Sniklas 	return;
1314df930be7Sderaadt }
1315df930be7Sderaadt 
1316df930be7Sderaadt /*
131750ce9ee0Sniklas  * Dump the kernel's image to the swap partition.
1318df930be7Sderaadt  */
131950ce9ee0Sniklas #define	BYTES_PER_DUMP	NBPG
132050ce9ee0Sniklas 
1321df930be7Sderaadt void
1322df930be7Sderaadt dumpsys()
1323df930be7Sderaadt {
1324*aed035abSart 	u_long totalbytesleft, bytes, i, n, memcl;
1325*aed035abSart 	u_long maddr;
1326*aed035abSart 	int psize;
132750ce9ee0Sniklas 	daddr_t blkno;
132850ce9ee0Sniklas 	int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
132950ce9ee0Sniklas 	int error;
1330067cbd75Sderaadt 	extern int msgbufmapped;
1331df930be7Sderaadt 
133250ce9ee0Sniklas 	/* Save registers. */
133350ce9ee0Sniklas 	savectx(&dumppcb);
133450ce9ee0Sniklas 
133550ce9ee0Sniklas 	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
1336df930be7Sderaadt 	if (dumpdev == NODEV)
1337df930be7Sderaadt 		return;
133850ce9ee0Sniklas 
133950ce9ee0Sniklas 	/*
134050ce9ee0Sniklas 	 * For dumps during autoconfiguration,
134150ce9ee0Sniklas 	 * if dump device has already configured...
134250ce9ee0Sniklas 	 */
1343df930be7Sderaadt 	if (dumpsize == 0)
134450ce9ee0Sniklas 		dumpconf();
134550ce9ee0Sniklas 	if (dumplo <= 0) {
1346*aed035abSart 		printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
1347*aed035abSart 		    minor(dumpdev));
1348df930be7Sderaadt 		return;
1349df930be7Sderaadt 	}
1350*aed035abSart 	printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
1351*aed035abSart 	    minor(dumpdev), dumplo);
1352df930be7Sderaadt 
135350ce9ee0Sniklas 	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1354df930be7Sderaadt 	printf("dump ");
135550ce9ee0Sniklas 	if (psize == -1) {
135650ce9ee0Sniklas 		printf("area unavailable\n");
135750ce9ee0Sniklas 		return;
135850ce9ee0Sniklas 	}
135950ce9ee0Sniklas 
136050ce9ee0Sniklas 	/* XXX should purge all outstanding keystrokes. */
136150ce9ee0Sniklas 
136250ce9ee0Sniklas 	if ((error = cpu_dump()) != 0)
136350ce9ee0Sniklas 		goto err;
136450ce9ee0Sniklas 
1365*aed035abSart 	totalbytesleft = ptoa(cpu_dump_mempagecnt());
136650ce9ee0Sniklas 	blkno = dumplo + cpu_dumpsize();
136750ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
136850ce9ee0Sniklas 	error = 0;
1369*aed035abSart 
1370*aed035abSart 	for (memcl = 0; memcl < mem_cluster_cnt; memcl++) {
1371*aed035abSart 		maddr = mem_clusters[memcl].start;
1372*aed035abSart 		bytes = mem_clusters[memcl].size & ~PAGE_MASK;
1373*aed035abSart 
1374*aed035abSart 		for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
137550ce9ee0Sniklas 
137650ce9ee0Sniklas 			/* Print out how many MBs we to go. */
1377*aed035abSart 			if ((totalbytesleft % (1024*1024)) == 0)
1378*aed035abSart 				printf("%ld ", totalbytesleft / (1024 * 1024));
137950ce9ee0Sniklas 
138050ce9ee0Sniklas 			/* Limit size for next transfer. */
1381*aed035abSart 			n = bytes - i;
138250ce9ee0Sniklas 			if (n > BYTES_PER_DUMP)
138350ce9ee0Sniklas 				n =  BYTES_PER_DUMP;
138450ce9ee0Sniklas 
138550ce9ee0Sniklas 			error = (*dump)(dumpdev, blkno,
138650ce9ee0Sniklas 			    (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n);
138750ce9ee0Sniklas 			if (error)
1388*aed035abSart 				goto err;
138950ce9ee0Sniklas 			maddr += n;
139050ce9ee0Sniklas 			blkno += btodb(n);			/* XXX? */
139150ce9ee0Sniklas 
139250ce9ee0Sniklas 			/* XXX should look for keystrokes, to cancel. */
139350ce9ee0Sniklas 		}
1394*aed035abSart 	}
139550ce9ee0Sniklas 
139650ce9ee0Sniklas err:
139750ce9ee0Sniklas 	switch (error) {
1398df930be7Sderaadt 
1399df930be7Sderaadt 	case ENXIO:
1400df930be7Sderaadt 		printf("device bad\n");
1401df930be7Sderaadt 		break;
1402df930be7Sderaadt 
1403df930be7Sderaadt 	case EFAULT:
1404df930be7Sderaadt 		printf("device not ready\n");
1405df930be7Sderaadt 		break;
1406df930be7Sderaadt 
1407df930be7Sderaadt 	case EINVAL:
1408df930be7Sderaadt 		printf("area improper\n");
1409df930be7Sderaadt 		break;
1410df930be7Sderaadt 
1411df930be7Sderaadt 	case EIO:
1412df930be7Sderaadt 		printf("i/o error\n");
1413df930be7Sderaadt 		break;
1414df930be7Sderaadt 
1415df930be7Sderaadt 	case EINTR:
1416df930be7Sderaadt 		printf("aborted from console\n");
1417df930be7Sderaadt 		break;
1418df930be7Sderaadt 
141950ce9ee0Sniklas 	case 0:
1420df930be7Sderaadt 		printf("succeeded\n");
1421df930be7Sderaadt 		break;
142250ce9ee0Sniklas 
142350ce9ee0Sniklas 	default:
142450ce9ee0Sniklas 		printf("error %d\n", error);
142550ce9ee0Sniklas 		break;
1426df930be7Sderaadt 	}
1427df930be7Sderaadt 	printf("\n\n");
1428df930be7Sderaadt 	delay(1000);
1429df930be7Sderaadt }
1430df930be7Sderaadt 
1431df930be7Sderaadt void
1432df930be7Sderaadt frametoreg(framep, regp)
1433df930be7Sderaadt 	struct trapframe *framep;
1434df930be7Sderaadt 	struct reg *regp;
1435df930be7Sderaadt {
1436df930be7Sderaadt 
1437df930be7Sderaadt 	regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
1438df930be7Sderaadt 	regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
1439df930be7Sderaadt 	regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
1440df930be7Sderaadt 	regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
1441df930be7Sderaadt 	regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
1442df930be7Sderaadt 	regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
1443df930be7Sderaadt 	regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
1444df930be7Sderaadt 	regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
1445df930be7Sderaadt 	regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
1446df930be7Sderaadt 	regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
1447df930be7Sderaadt 	regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
1448df930be7Sderaadt 	regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
1449df930be7Sderaadt 	regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
1450df930be7Sderaadt 	regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
1451df930be7Sderaadt 	regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
1452df930be7Sderaadt 	regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
145350ce9ee0Sniklas 	regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0];
145450ce9ee0Sniklas 	regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1];
145550ce9ee0Sniklas 	regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2];
1456df930be7Sderaadt 	regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
1457df930be7Sderaadt 	regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
1458df930be7Sderaadt 	regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
1459df930be7Sderaadt 	regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
1460df930be7Sderaadt 	regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
1461df930be7Sderaadt 	regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
1462df930be7Sderaadt 	regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
1463df930be7Sderaadt 	regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
1464df930be7Sderaadt 	regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
1465df930be7Sderaadt 	regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
146650ce9ee0Sniklas 	regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP];
146750ce9ee0Sniklas 	/* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */
1468df930be7Sderaadt 	regp->r_regs[R_ZERO] = 0;
1469df930be7Sderaadt }
1470df930be7Sderaadt 
1471df930be7Sderaadt void
1472df930be7Sderaadt regtoframe(regp, framep)
1473df930be7Sderaadt 	struct reg *regp;
1474df930be7Sderaadt 	struct trapframe *framep;
1475df930be7Sderaadt {
1476df930be7Sderaadt 
1477df930be7Sderaadt 	framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
1478df930be7Sderaadt 	framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
1479df930be7Sderaadt 	framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
1480df930be7Sderaadt 	framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
1481df930be7Sderaadt 	framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
1482df930be7Sderaadt 	framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
1483df930be7Sderaadt 	framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
1484df930be7Sderaadt 	framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
1485df930be7Sderaadt 	framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
1486df930be7Sderaadt 	framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
1487df930be7Sderaadt 	framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
1488df930be7Sderaadt 	framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
1489df930be7Sderaadt 	framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
1490df930be7Sderaadt 	framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
1491df930be7Sderaadt 	framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
1492df930be7Sderaadt 	framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
149350ce9ee0Sniklas 	framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0];
149450ce9ee0Sniklas 	framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1];
149550ce9ee0Sniklas 	framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2];
1496df930be7Sderaadt 	framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
1497df930be7Sderaadt 	framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
1498df930be7Sderaadt 	framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
1499df930be7Sderaadt 	framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
1500df930be7Sderaadt 	framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
1501df930be7Sderaadt 	framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
1502df930be7Sderaadt 	framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
1503df930be7Sderaadt 	framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
1504df930be7Sderaadt 	framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
1505df930be7Sderaadt 	framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
150650ce9ee0Sniklas 	framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP];
150750ce9ee0Sniklas 	/* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */
1508df930be7Sderaadt 	/* ??? = regp->r_regs[R_ZERO]; */
1509df930be7Sderaadt }
1510df930be7Sderaadt 
1511df930be7Sderaadt void
1512df930be7Sderaadt printregs(regp)
1513df930be7Sderaadt 	struct reg *regp;
1514df930be7Sderaadt {
1515df930be7Sderaadt 	int i;
1516df930be7Sderaadt 
1517df930be7Sderaadt 	for (i = 0; i < 32; i++)
1518df930be7Sderaadt 		printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
1519df930be7Sderaadt 		   i & 1 ? "\n" : "\t");
1520df930be7Sderaadt }
1521df930be7Sderaadt 
1522df930be7Sderaadt void
1523df930be7Sderaadt regdump(framep)
1524df930be7Sderaadt 	struct trapframe *framep;
1525df930be7Sderaadt {
1526df930be7Sderaadt 	struct reg reg;
1527df930be7Sderaadt 
1528df930be7Sderaadt 	frametoreg(framep, &reg);
152950ce9ee0Sniklas 	reg.r_regs[R_SP] = alpha_pal_rdusp();
153050ce9ee0Sniklas 
1531df930be7Sderaadt 	printf("REGISTERS:\n");
1532df930be7Sderaadt 	printregs(&reg);
1533df930be7Sderaadt }
1534df930be7Sderaadt 
1535df930be7Sderaadt #ifdef DEBUG
1536df930be7Sderaadt int sigdebug = 0;
1537df930be7Sderaadt int sigpid = 0;
1538df930be7Sderaadt #define	SDB_FOLLOW	0x01
1539df930be7Sderaadt #define	SDB_KSTACK	0x02
1540df930be7Sderaadt #endif
1541df930be7Sderaadt 
1542df930be7Sderaadt /*
1543df930be7Sderaadt  * Send an interrupt to process.
1544df930be7Sderaadt  */
1545df930be7Sderaadt void
15465e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val)
1547df930be7Sderaadt 	sig_t catcher;
1548df930be7Sderaadt 	int sig, mask;
1549df930be7Sderaadt 	u_long code;
15505e1760a6Sderaadt 	int type;
15515e1760a6Sderaadt 	union sigval val;
1552df930be7Sderaadt {
1553df930be7Sderaadt 	struct proc *p = curproc;
1554df930be7Sderaadt 	struct sigcontext *scp, ksc;
1555df930be7Sderaadt 	struct trapframe *frame;
1556df930be7Sderaadt 	struct sigacts *psp = p->p_sigacts;
15572bf9c155Sderaadt 	int oonstack, fsize, rndfsize, kscsize;
1558df930be7Sderaadt 	extern char sigcode[], esigcode[];
15592bf9c155Sderaadt 	siginfo_t *sip, ksi;
1560df930be7Sderaadt 
1561df930be7Sderaadt 	frame = p->p_md.md_tf;
1562df930be7Sderaadt 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
1563df930be7Sderaadt 	fsize = sizeof ksc;
1564df930be7Sderaadt 	rndfsize = ((fsize + 15) / 16) * 16;
15652bf9c155Sderaadt 	kscsize = rndfsize;
15662bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
15672bf9c155Sderaadt 		fsize += sizeof ksi;
15682bf9c155Sderaadt 		rndfsize = ((fsize + 15) / 16) * 16;
15692bf9c155Sderaadt 	}
157074652a67Sniklas 
1571df930be7Sderaadt 	/*
1572df930be7Sderaadt 	 * Allocate and validate space for the signal handler
1573df930be7Sderaadt 	 * context. Note that if the stack is in P0 space, the
1574*aed035abSart 	 * call to uvm_grow() is a nop, and the useracc() check
1575df930be7Sderaadt 	 * will fail if the process has not already allocated
1576df930be7Sderaadt 	 * the space with a `brk'.
1577df930be7Sderaadt 	 */
1578df930be7Sderaadt 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1579df930be7Sderaadt 	    (psp->ps_sigonstack & sigmask(sig))) {
15808bc2093aSderaadt 		scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp +
1581df930be7Sderaadt 		    psp->ps_sigstk.ss_size - rndfsize);
1582df930be7Sderaadt 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
1583df930be7Sderaadt 	} else
158450ce9ee0Sniklas 		scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize);
1585df930be7Sderaadt 	if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
1586*aed035abSart 		(void)uvm_grow(p, (u_long)scp);
1587df930be7Sderaadt #ifdef DEBUG
1588df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
158950ce9ee0Sniklas 		printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
1590df930be7Sderaadt 		    sig, &oonstack, scp);
1591df930be7Sderaadt #endif
1592*aed035abSart 	if (uvm_useracc((caddr_t)scp, fsize, B_WRITE) == 0) {
1593df930be7Sderaadt #ifdef DEBUG
1594df930be7Sderaadt 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1595*aed035abSart 			printf("sendsig(%d): uvm_useracc failed on sig %d\n",
1596df930be7Sderaadt 			    p->p_pid, sig);
1597df930be7Sderaadt #endif
1598df930be7Sderaadt 		/*
1599df930be7Sderaadt 		 * Process has trashed its stack; give it an illegal
1600df930be7Sderaadt 		 * instruction to halt it in its tracks.
1601df930be7Sderaadt 		 */
1602df930be7Sderaadt 		SIGACTION(p, SIGILL) = SIG_DFL;
1603df930be7Sderaadt 		sig = sigmask(SIGILL);
1604df930be7Sderaadt 		p->p_sigignore &= ~sig;
1605df930be7Sderaadt 		p->p_sigcatch &= ~sig;
1606df930be7Sderaadt 		p->p_sigmask &= ~sig;
1607df930be7Sderaadt 		psignal(p, SIGILL);
1608df930be7Sderaadt 		return;
1609df930be7Sderaadt 	}
1610df930be7Sderaadt 
1611df930be7Sderaadt 	/*
1612df930be7Sderaadt 	 * Build the signal context to be used by sigreturn.
1613df930be7Sderaadt 	 */
1614df930be7Sderaadt 	ksc.sc_onstack = oonstack;
1615df930be7Sderaadt 	ksc.sc_mask = mask;
161650ce9ee0Sniklas 	ksc.sc_pc = frame->tf_regs[FRAME_PC];
161750ce9ee0Sniklas 	ksc.sc_ps = frame->tf_regs[FRAME_PS];
1618df930be7Sderaadt 
1619df930be7Sderaadt 	/* copy the registers. */
1620df930be7Sderaadt 	frametoreg(frame, (struct reg *)ksc.sc_regs);
1621df930be7Sderaadt 	ksc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
162250ce9ee0Sniklas 	ksc.sc_regs[R_SP] = alpha_pal_rdusp();
1623df930be7Sderaadt 
1624df930be7Sderaadt 	/* save the floating-point state, if necessary, then copy it. */
1625df930be7Sderaadt 	if (p == fpcurproc) {
162650ce9ee0Sniklas 		alpha_pal_wrfen(1);
1627df930be7Sderaadt 		savefpstate(&p->p_addr->u_pcb.pcb_fp);
162850ce9ee0Sniklas 		alpha_pal_wrfen(0);
1629df930be7Sderaadt 		fpcurproc = NULL;
1630df930be7Sderaadt 	}
1631df930be7Sderaadt 	ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
1632df930be7Sderaadt 	bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
1633df930be7Sderaadt 	    sizeof(struct fpreg));
1634df930be7Sderaadt 	ksc.sc_fp_control = 0;					/* XXX ? */
1635df930be7Sderaadt 	bzero(ksc.sc_reserved, sizeof ksc.sc_reserved);		/* XXX */
1636df930be7Sderaadt 	bzero(ksc.sc_xxx, sizeof ksc.sc_xxx);			/* XXX */
1637df930be7Sderaadt 
1638df930be7Sderaadt 
1639df930be7Sderaadt #ifdef COMPAT_OSF1
1640df930be7Sderaadt 	/*
1641df930be7Sderaadt 	 * XXX Create an OSF/1-style sigcontext and associated goo.
1642df930be7Sderaadt 	 */
1643df930be7Sderaadt #endif
1644df930be7Sderaadt 
16452bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
16462bf9c155Sderaadt 		initsiginfo(&ksi, sig, code, type, val);
16472bf9c155Sderaadt 		sip = (void *)scp + kscsize;
16482bf9c155Sderaadt 		(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize);
16492bf9c155Sderaadt 	}
16502bf9c155Sderaadt 
1651df930be7Sderaadt 	/*
1652df930be7Sderaadt 	 * copy the frame out to userland.
1653df930be7Sderaadt 	 */
16542bf9c155Sderaadt 	(void) copyout((caddr_t)&ksc, (caddr_t)scp, kscsize);
1655df930be7Sderaadt #ifdef DEBUG
1656df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
165750ce9ee0Sniklas 		printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig,
1658df930be7Sderaadt 		    scp, code);
1659df930be7Sderaadt #endif
1660df930be7Sderaadt 
1661df930be7Sderaadt 	/*
1662df930be7Sderaadt 	 * Set up the registers to return to sigcode.
1663df930be7Sderaadt 	 */
166450ce9ee0Sniklas 	frame->tf_regs[FRAME_PC] =
166550ce9ee0Sniklas 	    (u_int64_t)PS_STRINGS - (esigcode - sigcode);
166650ce9ee0Sniklas 	frame->tf_regs[FRAME_A0] = sig;
16672bf9c155Sderaadt 	frame->tf_regs[FRAME_A1] = (psp->ps_siginfo & sigmask(sig)) ?
16682bf9c155Sderaadt 	    (u_int64_t)sip : NULL;
166950ce9ee0Sniklas 	frame->tf_regs[FRAME_A2] = (u_int64_t)scp;
1670df930be7Sderaadt 	frame->tf_regs[FRAME_T12] = (u_int64_t)catcher;		/* t12 is pv */
167150ce9ee0Sniklas 	alpha_pal_wrusp((unsigned long)scp);
1672df930be7Sderaadt 
1673df930be7Sderaadt #ifdef DEBUG
1674df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1675df930be7Sderaadt 		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
167650ce9ee0Sniklas 		    frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]);
1677df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1678df930be7Sderaadt 		printf("sendsig(%d): sig %d returns\n",
1679df930be7Sderaadt 		    p->p_pid, sig);
1680df930be7Sderaadt #endif
1681df930be7Sderaadt }
1682df930be7Sderaadt 
1683df930be7Sderaadt /*
1684df930be7Sderaadt  * System call to cleanup state after a signal
1685df930be7Sderaadt  * has been taken.  Reset signal mask and
1686df930be7Sderaadt  * stack state from context left by sendsig (above).
1687df930be7Sderaadt  * Return to previous pc and psl as specified by
1688df930be7Sderaadt  * context left by sendsig. Check carefully to
1689df930be7Sderaadt  * make sure that the user has not modified the
1690df930be7Sderaadt  * psl to gain improper priviledges or to cause
1691df930be7Sderaadt  * a machine fault.
1692df930be7Sderaadt  */
1693df930be7Sderaadt /* ARGSUSED */
1694df930be7Sderaadt int
1695df930be7Sderaadt sys_sigreturn(p, v, retval)
1696df930be7Sderaadt 	struct proc *p;
1697df930be7Sderaadt 	void *v;
1698df930be7Sderaadt 	register_t *retval;
1699df930be7Sderaadt {
1700df930be7Sderaadt 	struct sys_sigreturn_args /* {
1701df930be7Sderaadt 		syscallarg(struct sigcontext *) sigcntxp;
1702df930be7Sderaadt 	} */ *uap = v;
1703df930be7Sderaadt 	struct sigcontext *scp, ksc;
1704df930be7Sderaadt 
1705df930be7Sderaadt 	scp = SCARG(uap, sigcntxp);
1706df930be7Sderaadt #ifdef DEBUG
1707df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
170850ce9ee0Sniklas 	    printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
1709df930be7Sderaadt #endif
1710df930be7Sderaadt 
1711df930be7Sderaadt 	if (ALIGN(scp) != (u_int64_t)scp)
1712df930be7Sderaadt 		return (EINVAL);
1713df930be7Sderaadt 
1714df930be7Sderaadt 	/*
1715df930be7Sderaadt 	 * Test and fetch the context structure.
1716df930be7Sderaadt 	 * We grab it all at once for speed.
1717df930be7Sderaadt 	 */
1718*aed035abSart 	if (uvm_useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
1719df930be7Sderaadt 	    copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
1720df930be7Sderaadt 		return (EINVAL);
1721df930be7Sderaadt 
1722df930be7Sderaadt 	if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)		/* magic number */
1723df930be7Sderaadt 		return (EINVAL);
1724df930be7Sderaadt 	/*
1725df930be7Sderaadt 	 * Restore the user-supplied information
1726df930be7Sderaadt 	 */
1727df930be7Sderaadt 	if (ksc.sc_onstack)
1728df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
1729df930be7Sderaadt 	else
1730df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1731df930be7Sderaadt 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1732df930be7Sderaadt 
173350ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
173450ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PS] =
173550ce9ee0Sniklas 	    (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
1736df930be7Sderaadt 
1737df930be7Sderaadt 	regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
173850ce9ee0Sniklas 	alpha_pal_wrusp(ksc.sc_regs[R_SP]);
1739df930be7Sderaadt 
1740df930be7Sderaadt 	/* XXX ksc.sc_ownedfp ? */
1741df930be7Sderaadt 	if (p == fpcurproc)
1742df930be7Sderaadt 		fpcurproc = NULL;
1743df930be7Sderaadt 	bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
1744df930be7Sderaadt 	    sizeof(struct fpreg));
1745df930be7Sderaadt 	/* XXX ksc.sc_fp_control ? */
1746df930be7Sderaadt 
1747df930be7Sderaadt #ifdef DEBUG
1748df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1749df930be7Sderaadt 		printf("sigreturn(%d): returns\n", p->p_pid);
1750df930be7Sderaadt #endif
1751df930be7Sderaadt 	return (EJUSTRETURN);
1752df930be7Sderaadt }
1753df930be7Sderaadt 
1754df930be7Sderaadt /*
1755df930be7Sderaadt  * machine dependent system variables.
1756df930be7Sderaadt  */
175750ce9ee0Sniklas int
1758df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1759df930be7Sderaadt 	int *name;
1760df930be7Sderaadt 	u_int namelen;
1761df930be7Sderaadt 	void *oldp;
1762df930be7Sderaadt 	size_t *oldlenp;
1763df930be7Sderaadt 	void *newp;
1764df930be7Sderaadt 	size_t newlen;
1765df930be7Sderaadt 	struct proc *p;
1766df930be7Sderaadt {
1767df930be7Sderaadt 	dev_t consdev;
1768df930be7Sderaadt 
1769df930be7Sderaadt 	/* all sysctl names at this level are terminal */
1770df930be7Sderaadt 	if (namelen != 1)
1771df930be7Sderaadt 		return (ENOTDIR);		/* overloaded */
1772df930be7Sderaadt 
1773df930be7Sderaadt 	switch (name[0]) {
1774df930be7Sderaadt 	case CPU_CONSDEV:
1775df930be7Sderaadt 		if (cn_tab != NULL)
1776df930be7Sderaadt 			consdev = cn_tab->cn_dev;
1777df930be7Sderaadt 		else
1778df930be7Sderaadt 			consdev = NODEV;
1779df930be7Sderaadt 		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1780df930be7Sderaadt 			sizeof consdev));
1781417eba8cSderaadt 
1782417eba8cSderaadt 	case CPU_ROOT_DEVICE:
1783*aed035abSart 		return (sysctl_rdstring(oldp, oldlenp, newp,
1784*aed035abSart 		    root_device));
1785417eba8cSderaadt 
178650ce9ee0Sniklas 	case CPU_UNALIGNED_PRINT:
178750ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
178850ce9ee0Sniklas 		    &alpha_unaligned_print));
178950ce9ee0Sniklas 
179050ce9ee0Sniklas 	case CPU_UNALIGNED_FIX:
179150ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
179250ce9ee0Sniklas 		    &alpha_unaligned_fix));
179350ce9ee0Sniklas 
179450ce9ee0Sniklas 	case CPU_UNALIGNED_SIGBUS:
179550ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
179650ce9ee0Sniklas 		    &alpha_unaligned_sigbus));
179750ce9ee0Sniklas 
17983a630e3fSniklas 	case CPU_BOOTED_KERNEL:
1799*aed035abSart 		return (sysctl_rdstring(oldp, oldlenp, newp,
1800*aed035abSart 		    bootinfo.booted_kernel));
18013a630e3fSniklas 
1802df930be7Sderaadt 	default:
1803df930be7Sderaadt 		return (EOPNOTSUPP);
1804df930be7Sderaadt 	}
1805df930be7Sderaadt 	/* NOTREACHED */
1806df930be7Sderaadt }
1807df930be7Sderaadt 
1808df930be7Sderaadt /*
1809df930be7Sderaadt  * Set registers on exec.
1810df930be7Sderaadt  */
1811df930be7Sderaadt void
1812df930be7Sderaadt setregs(p, pack, stack, retval)
1813df930be7Sderaadt 	register struct proc *p;
1814df930be7Sderaadt 	struct exec_package *pack;
1815df930be7Sderaadt 	u_long stack;
1816df930be7Sderaadt 	register_t *retval;
1817df930be7Sderaadt {
1818df930be7Sderaadt 	struct trapframe *tfp = p->p_md.md_tf;
18193a630e3fSniklas #ifdef DEBUG
18203a630e3fSniklas 	int i;
18213a630e3fSniklas #endif
1822df930be7Sderaadt 
1823df930be7Sderaadt #ifdef DEBUG
182450ce9ee0Sniklas 	/*
182550ce9ee0Sniklas 	 * Crash and dump, if the user requested it.
182650ce9ee0Sniklas 	 */
182750ce9ee0Sniklas 	if (boothowto & RB_DUMP)
182850ce9ee0Sniklas 		panic("crash requested by boot flags");
182950ce9ee0Sniklas #endif
183050ce9ee0Sniklas 
183150ce9ee0Sniklas #ifdef DEBUG
183250ce9ee0Sniklas 	for (i = 0; i < FRAME_SIZE; i++)
1833df930be7Sderaadt 		tfp->tf_regs[i] = 0xbabefacedeadbeef;
1834df930be7Sderaadt #else
183550ce9ee0Sniklas 	bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
1836df930be7Sderaadt #endif
1837df930be7Sderaadt 	bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
1838df930be7Sderaadt #define FP_RN 2 /* XXX */
1839df930be7Sderaadt 	p->p_addr->u_pcb.pcb_fp.fpr_cr = (long)FP_RN << 58;
184050ce9ee0Sniklas 	alpha_pal_wrusp(stack);
184150ce9ee0Sniklas 	tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
184250ce9ee0Sniklas 	tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
1843df930be7Sderaadt 
184450ce9ee0Sniklas 	tfp->tf_regs[FRAME_A0] = stack;
184550ce9ee0Sniklas 	/* a1 and a2 already zeroed */
184650ce9ee0Sniklas 	tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC];	/* a.k.a. PV */
184750ce9ee0Sniklas 
184850ce9ee0Sniklas 	p->p_md.md_flags &= ~MDP_FPUSED;
1849df930be7Sderaadt 	if (fpcurproc == p)
1850df930be7Sderaadt 		fpcurproc = NULL;
1851df930be7Sderaadt 
1852df930be7Sderaadt 	retval[0] = retval[1] = 0;
1853df930be7Sderaadt }
1854df930be7Sderaadt 
1855df930be7Sderaadt void
1856df930be7Sderaadt netintr()
1857df930be7Sderaadt {
185850ce9ee0Sniklas 	int n, s;
185950ce9ee0Sniklas 
186050ce9ee0Sniklas 	s = splhigh();
186150ce9ee0Sniklas 	n = netisr;
186250ce9ee0Sniklas 	netisr = 0;
186350ce9ee0Sniklas 	splx(s);
186450ce9ee0Sniklas 
186550ce9ee0Sniklas #define	DONETISR(bit, fn)						\
186650ce9ee0Sniklas 	do {								\
186750ce9ee0Sniklas 		if (n & (1 << (bit)))					\
1868*aed035abSart 			fn();						\
186950ce9ee0Sniklas 	} while (0)
187050ce9ee0Sniklas 
1871*aed035abSart #include <net/netisr_dispatch.h>
187250ce9ee0Sniklas 
187350ce9ee0Sniklas #undef DONETISR
1874df930be7Sderaadt }
1875df930be7Sderaadt 
1876df930be7Sderaadt void
1877df930be7Sderaadt do_sir()
1878df930be7Sderaadt {
18793a630e3fSniklas 	u_int64_t n;
1880df930be7Sderaadt 
1881*aed035abSart 	while ((n = atomic_loadlatch_ulong(&ssir, 0)) != 0) {
1882*aed035abSart #define	COUNT_SOFT	uvmexp.softs++
18833a630e3fSniklas 
18843a630e3fSniklas #define	DO_SIR(bit, fn)							\
18853a630e3fSniklas 		do {							\
18863a630e3fSniklas 			if (n & (bit)) {				\
1887*aed035abSart 				COUNT_SOFT;				\
18883a630e3fSniklas 				fn;					\
18893a630e3fSniklas 			}						\
18903a630e3fSniklas 		} while (0)
18913a630e3fSniklas 
18923a630e3fSniklas 		DO_SIR(SIR_NET, netintr());
18933a630e3fSniklas 		DO_SIR(SIR_CLOCK, softclock());
18943a630e3fSniklas 
1895*aed035abSart #undef COUNT_SOFT
18963a630e3fSniklas #undef DO_SIR
1897*aed035abSart 	}
1898df930be7Sderaadt }
1899df930be7Sderaadt 
1900df930be7Sderaadt int
1901df930be7Sderaadt spl0()
1902df930be7Sderaadt {
1903df930be7Sderaadt 
1904*aed035abSart 	if (ssir) {
1905*aed035abSart 		(void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT);
1906*aed035abSart 		do_sir();
1907*aed035abSart 	}
1908df930be7Sderaadt 
190950ce9ee0Sniklas 	return (alpha_pal_swpipl(ALPHA_PSL_IPL_0));
1910df930be7Sderaadt }
1911df930be7Sderaadt 
1912df930be7Sderaadt /*
1913df930be7Sderaadt  * The following primitives manipulate the run queues.  _whichqs tells which
1914df930be7Sderaadt  * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
1915e464495eSniklas  * into queues, Remrunqueue removes them from queues.  The running process is
1916e464495eSniklas  * on no queue, other processes are on a queue related to p->p_priority,
1917e464495eSniklas  * divided by 4 actually to shrink the 0-127 range of priorities into the 32
1918e464495eSniklas  * available queues.
1919df930be7Sderaadt  */
1920df930be7Sderaadt /*
1921df930be7Sderaadt  * setrunqueue(p)
1922df930be7Sderaadt  *	proc *p;
1923df930be7Sderaadt  *
1924df930be7Sderaadt  * Call should be made at splclock(), and p->p_stat should be SRUN.
1925df930be7Sderaadt  */
1926df930be7Sderaadt 
1927df930be7Sderaadt void
1928df930be7Sderaadt setrunqueue(p)
1929df930be7Sderaadt 	struct proc *p;
1930df930be7Sderaadt {
1931df930be7Sderaadt 	int bit;
1932df930be7Sderaadt 
1933df930be7Sderaadt 	/* firewall: p->p_back must be NULL */
1934df930be7Sderaadt 	if (p->p_back != NULL)
1935df930be7Sderaadt 		panic("setrunqueue");
1936df930be7Sderaadt 
1937df930be7Sderaadt 	bit = p->p_priority >> 2;
1938df930be7Sderaadt 	whichqs |= (1 << bit);
1939df930be7Sderaadt 	p->p_forw = (struct proc *)&qs[bit];
1940df930be7Sderaadt 	p->p_back = qs[bit].ph_rlink;
1941df930be7Sderaadt 	p->p_back->p_forw = p;
1942df930be7Sderaadt 	qs[bit].ph_rlink = p;
1943df930be7Sderaadt }
1944df930be7Sderaadt 
1945df930be7Sderaadt /*
1946e464495eSniklas  * remrunqueue(p)
1947df930be7Sderaadt  *
1948df930be7Sderaadt  * Call should be made at splclock().
1949df930be7Sderaadt  */
1950df930be7Sderaadt void
1951d3cbbad5Skstailey remrunqueue(p)
1952df930be7Sderaadt 	struct proc *p;
1953df930be7Sderaadt {
1954df930be7Sderaadt 	int bit;
1955df930be7Sderaadt 
1956df930be7Sderaadt 	bit = p->p_priority >> 2;
1957df930be7Sderaadt 	if ((whichqs & (1 << bit)) == 0)
1958d3cbbad5Skstailey 		panic("remrunqueue");
1959df930be7Sderaadt 
1960df930be7Sderaadt 	p->p_back->p_forw = p->p_forw;
1961df930be7Sderaadt 	p->p_forw->p_back = p->p_back;
1962df930be7Sderaadt 	p->p_back = NULL;	/* for firewall checking. */
1963df930be7Sderaadt 
1964df930be7Sderaadt 	if ((struct proc *)&qs[bit] == qs[bit].ph_link)
1965df930be7Sderaadt 		whichqs &= ~(1 << bit);
1966df930be7Sderaadt }
1967df930be7Sderaadt 
1968df930be7Sderaadt /*
1969df930be7Sderaadt  * Return the best possible estimate of the time in the timeval
1970df930be7Sderaadt  * to which tvp points.  Unfortunately, we can't read the hardware registers.
1971df930be7Sderaadt  * We guarantee that the time will be greater than the value obtained by a
1972df930be7Sderaadt  * previous call.
1973df930be7Sderaadt  */
1974df930be7Sderaadt void
1975df930be7Sderaadt microtime(tvp)
1976df930be7Sderaadt 	register struct timeval *tvp;
1977df930be7Sderaadt {
1978df930be7Sderaadt 	int s = splclock();
1979df930be7Sderaadt 	static struct timeval lasttime;
1980df930be7Sderaadt 
1981df930be7Sderaadt 	*tvp = time;
1982df930be7Sderaadt #ifdef notdef
1983df930be7Sderaadt 	tvp->tv_usec += clkread();
19844c891e15Spjanzen 	while (tvp->tv_usec >= 1000000) {
1985df930be7Sderaadt 		tvp->tv_sec++;
1986df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1987df930be7Sderaadt 	}
1988df930be7Sderaadt #endif
1989df930be7Sderaadt 	if (tvp->tv_sec == lasttime.tv_sec &&
1990df930be7Sderaadt 	    tvp->tv_usec <= lasttime.tv_usec &&
19914c891e15Spjanzen 	    (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
1992df930be7Sderaadt 		tvp->tv_sec++;
1993df930be7Sderaadt 		tvp->tv_usec -= 1000000;
1994df930be7Sderaadt 	}
1995df930be7Sderaadt 	lasttime = *tvp;
1996df930be7Sderaadt 	splx(s);
1997df930be7Sderaadt }
1998df930be7Sderaadt 
1999417eba8cSderaadt /*
2000417eba8cSderaadt  * Wait "n" microseconds.
2001417eba8cSderaadt  */
200250ce9ee0Sniklas void
2003417eba8cSderaadt delay(n)
200450ce9ee0Sniklas 	unsigned long n;
2005417eba8cSderaadt {
2006417eba8cSderaadt 	long N = cycles_per_usec * (n);
2007417eba8cSderaadt 
2008*aed035abSart 	/*
2009*aed035abSart 	 * XXX Should be written to use RPCC?
2010*aed035abSart 	 */
2011*aed035abSart 
2012*aed035abSart 	__asm __volatile(
2013*aed035abSart 		"# The 2 corresponds to the insn count\n"
2014*aed035abSart 		"1:	subq	%2, %1, %0	\n"
2015*aed035abSart 		"	bgt	%0, 1b"
2016*aed035abSart 		: "=r" (N)
2017*aed035abSart 		: "i" (2), "0" (N));
2018417eba8cSderaadt }
2019417eba8cSderaadt 
2020df930be7Sderaadt #if defined(COMPAT_OSF1) || 1		/* XXX */
20213a630e3fSniklas void	cpu_exec_ecoff_setregs __P((struct proc *, struct exec_package *,
20223a630e3fSniklas 	    u_long, register_t *));
20233a630e3fSniklas 
2024df930be7Sderaadt void
2025417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval)
2026df930be7Sderaadt 	struct proc *p;
2027417eba8cSderaadt 	struct exec_package *epp;
2028df930be7Sderaadt 	u_long stack;
2029df930be7Sderaadt 	register_t *retval;
2030df930be7Sderaadt {
2031417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
2032df930be7Sderaadt 
2033417eba8cSderaadt 	setregs(p, epp, stack, retval);
203450ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value;
2035df930be7Sderaadt }
2036df930be7Sderaadt 
2037df930be7Sderaadt /*
2038df930be7Sderaadt  * cpu_exec_ecoff_hook():
2039df930be7Sderaadt  *	cpu-dependent ECOFF format hook for execve().
2040df930be7Sderaadt  *
2041df930be7Sderaadt  * Do any machine-dependent diddling of the exec package when doing ECOFF.
2042df930be7Sderaadt  *
2043df930be7Sderaadt  */
2044df930be7Sderaadt int
2045417eba8cSderaadt cpu_exec_ecoff_hook(p, epp)
2046df930be7Sderaadt 	struct proc *p;
2047df930be7Sderaadt 	struct exec_package *epp;
2048df930be7Sderaadt {
2049417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
2050*aed035abSart 	extern struct emul emul_native, emul_osf1;
2051*aed035abSart 	int error;
2052*aed035abSart 	extern int osf1_exec_ecoff_hook(struct proc *p,
2053*aed035abSart 					struct exec_package *epp);
2054df930be7Sderaadt 
2055417eba8cSderaadt 	switch (execp->f.f_magic) {
2056df930be7Sderaadt #ifdef COMPAT_OSF1
2057df930be7Sderaadt 	case ECOFF_MAGIC_ALPHA:
2058df930be7Sderaadt 		epp->ep_emul = &emul_osf1;
2059df930be7Sderaadt 		break;
2060df930be7Sderaadt #endif
2061df930be7Sderaadt 
206250ce9ee0Sniklas 	case ECOFF_MAGIC_NATIVE_ALPHA:
2063a2f8ce8dSderaadt 		epp->ep_emul = &emul_native;
2064*aed035abSart 		error = 0;
2065df930be7Sderaadt 		break;
2066df930be7Sderaadt 
2067df930be7Sderaadt 	default:
2068*aed035abSart 		error = ENOEXEC;
2069df930be7Sderaadt 	}
2070*aed035abSart 	return (error);
2071df930be7Sderaadt }
2072df930be7Sderaadt #endif
2073e464495eSniklas 
2074*aed035abSart int
2075*aed035abSart alpha_pa_access(pa)
2076*aed035abSart 	u_long pa;
2077*aed035abSart {
2078*aed035abSart 	int i;
2079*aed035abSart 
2080*aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
2081*aed035abSart 		if (pa < mem_clusters[i].start)
2082*aed035abSart 			continue;
2083*aed035abSart 		if ((pa - mem_clusters[i].start) >=
2084*aed035abSart 		    (mem_clusters[i].size & ~PAGE_MASK))
2085*aed035abSart 			continue;
2086*aed035abSart 		return (mem_clusters[i].size & PAGE_MASK);	/* prot */
2087*aed035abSart 	}
2088*aed035abSart 
2089*aed035abSart 	/*
2090*aed035abSart 	 * Address is not a memory address.  If we're secure, disallow
2091*aed035abSart 	 * access.  Otherwise, grant read/write.
2092*aed035abSart 	 */
2093*aed035abSart 	if (securelevel > 0)
2094*aed035abSart 		return (VM_PROT_NONE);
2095*aed035abSart 	else
2096*aed035abSart 		return (VM_PROT_READ | VM_PROT_WRITE);
2097*aed035abSart }
2098*aed035abSart 
2099e464495eSniklas /* XXX XXX BEGIN XXX XXX */
2100*aed035abSart paddr_t alpha_XXX_dmamap_or;					/* XXX */
2101e464495eSniklas 								/* XXX */
2102*aed035abSart paddr_t								/* XXX */
2103e464495eSniklas alpha_XXX_dmamap(v)						/* XXX */
2104*aed035abSart 	vaddr_t v;						/* XXX */
2105e464495eSniklas {								/* XXX */
2106e464495eSniklas 								/* XXX */
2107e464495eSniklas 	return (vtophys(v) | alpha_XXX_dmamap_or);		/* XXX */
2108e464495eSniklas }								/* XXX */
2109e464495eSniklas /* XXX XXX END XXX XXX */
2110*aed035abSart 
2111*aed035abSart char *
2112*aed035abSart dot_conv(x)
2113*aed035abSart 	unsigned long x;
2114*aed035abSart {
2115*aed035abSart 	int i;
2116*aed035abSart 	char *xc;
2117*aed035abSart 	static int next;
2118*aed035abSart 	static char space[2][20];
2119*aed035abSart 
2120*aed035abSart 	xc = space[next ^= 1] + sizeof space[0];
2121*aed035abSart 	*--xc = '\0';
2122*aed035abSart 	for (i = 0;; ++i) {
2123*aed035abSart 		if (i && (i & 3) == 0)
2124*aed035abSart 			*--xc = '.';
2125*aed035abSart 		*--xc = "0123456789abcdef"[x & 0xf];
2126*aed035abSart 		x >>= 4;
2127*aed035abSart 		if (x == 0)
2128*aed035abSart 			break;
2129*aed035abSart 	}
2130*aed035abSart 	return xc;
2131*aed035abSart }
2132