xref: /openbsd/sys/arch/alpha/alpha/machdep.c (revision 27626149)
1*27626149Smatthieu /* $OpenBSD: machdep.c,v 1.77 2002/08/24 17:21:44 matthieu Exp $ */
22a2685f2Sart /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */
3aed035abSart 
4aed035abSart /*-
5aed035abSart  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
6aed035abSart  * All rights reserved.
7aed035abSart  *
8aed035abSart  * This code is derived from software contributed to The NetBSD Foundation
9aed035abSart  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10aed035abSart  * NASA Ames Research Center and by Chris G. Demetriou.
11aed035abSart  *
12aed035abSart  * Redistribution and use in source and binary forms, with or without
13aed035abSart  * modification, are permitted provided that the following conditions
14aed035abSart  * are met:
15aed035abSart  * 1. Redistributions of source code must retain the above copyright
16aed035abSart  *    notice, this list of conditions and the following disclaimer.
17aed035abSart  * 2. Redistributions in binary form must reproduce the above copyright
18aed035abSart  *    notice, this list of conditions and the following disclaimer in the
19aed035abSart  *    documentation and/or other materials provided with the distribution.
20aed035abSart  * 3. All advertising materials mentioning features or use of this software
21aed035abSart  *    must display the following acknowledgement:
22aed035abSart  *	This product includes software developed by the NetBSD
23aed035abSart  *	Foundation, Inc. and its contributors.
24aed035abSart  * 4. Neither the name of The NetBSD Foundation nor the names of its
25aed035abSart  *    contributors may be used to endorse or promote products derived
26aed035abSart  *    from this software without specific prior written permission.
27aed035abSart  *
28aed035abSart  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29aed035abSart  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30aed035abSart  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31aed035abSart  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32aed035abSart  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33aed035abSart  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34aed035abSart  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35aed035abSart  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36aed035abSart  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37aed035abSart  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38aed035abSart  * POSSIBILITY OF SUCH DAMAGE.
39aed035abSart  */
40df930be7Sderaadt 
41df930be7Sderaadt /*
42417eba8cSderaadt  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
43df930be7Sderaadt  * All rights reserved.
44df930be7Sderaadt  *
45df930be7Sderaadt  * Author: Chris G. Demetriou
46df930be7Sderaadt  *
47df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
48df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
49df930be7Sderaadt  * notice and this permission notice appear in all copies of the
50df930be7Sderaadt  * software, derivative works or modified versions, and any portions
51df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
52df930be7Sderaadt  *
53df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
54df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
55df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
56df930be7Sderaadt  *
57df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
58df930be7Sderaadt  *
59df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
60df930be7Sderaadt  *  School of Computer Science
61df930be7Sderaadt  *  Carnegie Mellon University
62df930be7Sderaadt  *  Pittsburgh PA 15213-3890
63df930be7Sderaadt  *
64df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
65df930be7Sderaadt  * rights to redistribute these changes.
66df930be7Sderaadt  */
67df930be7Sderaadt 
68df930be7Sderaadt #include <sys/param.h>
69df930be7Sderaadt #include <sys/systm.h>
70df930be7Sderaadt #include <sys/signalvar.h>
71df930be7Sderaadt #include <sys/kernel.h>
72df930be7Sderaadt #include <sys/proc.h>
732a2685f2Sart #include <sys/sched.h>
74df930be7Sderaadt #include <sys/buf.h>
75df930be7Sderaadt #include <sys/reboot.h>
76417eba8cSderaadt #include <sys/device.h>
77df930be7Sderaadt #include <sys/conf.h>
78df930be7Sderaadt #include <sys/file.h>
79d66eba84Sart #include <sys/timeout.h>
80df930be7Sderaadt #include <sys/malloc.h>
81df930be7Sderaadt #include <sys/mbuf.h>
82df930be7Sderaadt #include <sys/msgbuf.h>
83df930be7Sderaadt #include <sys/ioctl.h>
84df930be7Sderaadt #include <sys/tty.h>
85df930be7Sderaadt #include <sys/user.h>
86df930be7Sderaadt #include <sys/exec.h>
87df930be7Sderaadt #include <sys/exec_ecoff.h>
88489e49f9Smiod #include <uvm/uvm_extern.h>
89df930be7Sderaadt #include <sys/sysctl.h>
9050ce9ee0Sniklas #include <sys/core.h>
9150ce9ee0Sniklas #include <sys/kcore.h>
9250ce9ee0Sniklas #include <machine/kcore.h>
93433075b6Spvalchev #ifndef NO_IEEE
94433075b6Spvalchev #include <machine/fpu.h>
95433075b6Spvalchev #endif
96df930be7Sderaadt #ifdef SYSVMSG
97df930be7Sderaadt #include <sys/msg.h>
98df930be7Sderaadt #endif
99df930be7Sderaadt #ifdef SYSVSEM
100df930be7Sderaadt #include <sys/sem.h>
101df930be7Sderaadt #endif
102df930be7Sderaadt #ifdef SYSVSHM
103df930be7Sderaadt #include <sys/shm.h>
104df930be7Sderaadt #endif
105df930be7Sderaadt 
106df930be7Sderaadt #include <sys/mount.h>
107df930be7Sderaadt #include <sys/syscallargs.h>
108df930be7Sderaadt 
109aed035abSart #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>
119433075b6Spvalchev #ifndef NO_IEEE
120433075b6Spvalchev #include <machine/ieeefp.h>
121433075b6Spvalchev #endif
122df930be7Sderaadt 
12345e5a1a0Sart #include <dev/pci/pcivar.h>
12445e5a1a0Sart 
12512f8bbedSniklas #ifdef DDB
12612f8bbedSniklas #include <machine/db_machdep.h>
12712f8bbedSniklas #include <ddb/db_access.h>
12812f8bbedSniklas #include <ddb/db_sym.h>
12912f8bbedSniklas #include <ddb/db_extern.h>
13012f8bbedSniklas #endif
13112f8bbedSniklas 
132c4071fd1Smillert int	cpu_dump(void);
133c4071fd1Smillert int	cpu_dumpsize(void);
134c4071fd1Smillert u_long	cpu_dump_mempagecnt(void);
135c4071fd1Smillert void	dumpsys(void);
136c4071fd1Smillert caddr_t allocsys(caddr_t);
137c4071fd1Smillert void	identifycpu(void);
138c4071fd1Smillert void	regdump(struct trapframe *framep);
139c4071fd1Smillert void	printregs(struct reg *);
140df930be7Sderaadt 
141df930be7Sderaadt /*
142df930be7Sderaadt  * Declare these as initialized data so we can patch them.
143df930be7Sderaadt  */
144df930be7Sderaadt #ifdef	NBUF
145df930be7Sderaadt int	nbuf = NBUF;
146df930be7Sderaadt #else
147df930be7Sderaadt int	nbuf = 0;
148df930be7Sderaadt #endif
14960535ec9Smaja 
15060535ec9Smaja #ifndef BUFCACHEPERCENT
15160535ec9Smaja #define BUFCACHEPERCENT 10
15260535ec9Smaja #endif
15360535ec9Smaja 
154df930be7Sderaadt #ifdef	BUFPAGES
155df930be7Sderaadt int	bufpages = BUFPAGES;
156df930be7Sderaadt #else
157df930be7Sderaadt int	bufpages = 0;
158df930be7Sderaadt #endif
15960535ec9Smaja int	bufcachepercent = BUFCACHEPERCENT;
160aed035abSart 
161ab8e80c5Sart struct vm_map *exec_map = NULL;
162ab8e80c5Sart struct vm_map *phys_map = NULL;
163aed035abSart 
164*27626149Smatthieu #ifdef APERTURE
165*27626149Smatthieu #ifdef INSECURE
166*27626149Smatthieu int allowaperture = 1;
167*27626149Smatthieu #else
168*27626149Smatthieu int allowaperture = 0;
169*27626149Smatthieu #endif
170*27626149Smatthieu #endif
171*27626149Smatthieu 
172df930be7Sderaadt int	maxmem;			/* max memory per process */
173df930be7Sderaadt 
174df930be7Sderaadt int	totalphysmem;		/* total amount of physical memory in system */
17574652a67Sniklas int	physmem;		/* physical mem used by OpenBSD + some rsvd */
176df930be7Sderaadt int	resvmem;		/* amount of memory reserved for PROM */
177df930be7Sderaadt int	unusedmem;		/* amount of memory for OS that we don't use */
178df930be7Sderaadt int	unknownmem;		/* amount of memory with an unknown use */
179df930be7Sderaadt 
180df930be7Sderaadt int	cputype;		/* system type, from the RPB */
181df930be7Sderaadt 
1822a2685f2Sart int	bootdev_debug = 0;	/* patchable, or from DDB */
1832a2685f2Sart 
184df930be7Sderaadt /*
185df930be7Sderaadt  * XXX We need an address to which we can assign things so that they
186df930be7Sderaadt  * won't be optimized away because we didn't use the value.
187df930be7Sderaadt  */
188df930be7Sderaadt u_int32_t no_optimize;
189df930be7Sderaadt 
190df930be7Sderaadt /* the following is used externally (sysctl_hw) */
191aed035abSart char	machine[] = MACHINE;		/* from <machine/param.h> */
192417eba8cSderaadt char	cpu_model[128];
193aed035abSart char	root_device[17];
194df930be7Sderaadt 
195df930be7Sderaadt struct	user *proc0paddr;
196df930be7Sderaadt 
197df930be7Sderaadt /* Number of machine cycles per microsecond */
198df930be7Sderaadt u_int64_t	cycles_per_usec;
199df930be7Sderaadt 
200df930be7Sderaadt /* number of cpus in the box.  really! */
201df930be7Sderaadt int		ncpus;
202df930be7Sderaadt 
203aed035abSart struct bootinfo_kernel bootinfo;
204aed035abSart 
205aed035abSart /* For built-in TCDS */
206aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
207aed035abSart u_int8_t	dec_3000_scsiid[2], dec_3000_scsifast[2];
208aed035abSart #endif
209aed035abSart 
210aed035abSart struct platform platform;
211417eba8cSderaadt 
212417eba8cSderaadt /* for cpu_sysctl() */
21350ce9ee0Sniklas int	alpha_unaligned_print = 1;	/* warn about unaligned accesses */
21450ce9ee0Sniklas int	alpha_unaligned_fix = 1;	/* fix up unaligned accesses */
215881c1eabSart int	alpha_unaligned_sigbus = 1;	/* SIGBUS on fixed-up accesses */
216433075b6Spvalchev #ifndef NO_IEEE
217433075b6Spvalchev int	alpha_fp_sync_complete = 0;	/* fp fixup if sync even without /s */
218433075b6Spvalchev #endif
21950ce9ee0Sniklas 
220aed035abSart /*
221aed035abSart  * XXX This should be dynamically sized, but we have the chicken-egg problem!
222aed035abSart  * XXX it should also be larger than it is, because not all of the mddt
223aed035abSart  * XXX clusters end up being used for VM.
224aed035abSart  */
225aed035abSart phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];	/* low size bits overloaded */
226aed035abSart int	mem_cluster_cnt;
227aed035abSart 
2283a630e3fSniklas void
229aed035abSart alpha_init(pfn, ptb, bim, bip, biv)
230df930be7Sderaadt 	u_long pfn;		/* first free PFN number */
231df930be7Sderaadt 	u_long ptb;		/* PFN of current level 1 page table */
232aed035abSart 	u_long bim;		/* bootinfo magic */
233aed035abSart 	u_long bip;		/* bootinfo pointer */
234aed035abSart 	u_long biv;		/* bootinfo version */
235df930be7Sderaadt {
236aed035abSart 	extern char kernel_text[], _end[];
237df930be7Sderaadt 	struct mddt *mddtp;
238aed035abSart 	struct mddt_cluster *memc;
239df930be7Sderaadt 	int i, mddtweird;
240aed035abSart 	struct vm_physseg *vps;
241aed035abSart 	vaddr_t kernstart, kernend;
242aed035abSart 	paddr_t kernstartpfn, kernendpfn, pfn0, pfn1;
243aed035abSart 	vsize_t size;
244df930be7Sderaadt 	char *p;
245aed035abSart 	caddr_t v;
2462a2685f2Sart 	const char *bootinfo_msg;
247aed035abSart 	const struct cpuinit *c;
248aed035abSart 	extern caddr_t esym;
249aed035abSart 	struct cpu_info *ci;
250aed035abSart 	cpuid_t cpu_id;
251df930be7Sderaadt 
252aed035abSart 	/* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */
253f3914c62Sniklas 
254df930be7Sderaadt 	/*
255aed035abSart 	 * Turn off interrupts (not mchecks) and floating point.
256df930be7Sderaadt 	 * Make sure the instruction and data streams are consistent.
257df930be7Sderaadt 	 */
258aed035abSart 	(void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
25950ce9ee0Sniklas 	alpha_pal_wrfen(0);
26050ce9ee0Sniklas 	ALPHA_TBIA();
26150ce9ee0Sniklas 	alpha_pal_imb();
262df930be7Sderaadt 
263aed035abSart 	cpu_id = cpu_number();
264aed035abSart 
265aed035abSart #if defined(MULTIPROCESSOR)
266df930be7Sderaadt 	/*
267aed035abSart 	 * Set our SysValue to the address of our cpu_info structure.
268aed035abSart 	 * Secondary processors do this in their spinup trampoline.
269df930be7Sderaadt 	 */
270aed035abSart 	alpha_pal_wrval((u_long)&cpu_info[cpu_id]);
271aed035abSart #endif
272aed035abSart 
273aed035abSart 	ci = curcpu();
274aed035abSart 	ci->ci_cpuid = cpu_id;
275aed035abSart 
276aed035abSart 	/*
277aed035abSart 	 * Get critical system information (if possible, from the
278aed035abSart 	 * information provided by the boot program).
279aed035abSart 	 */
280aed035abSart 	bootinfo_msg = NULL;
281aed035abSart 	if (bim == BOOTINFO_MAGIC) {
282aed035abSart 		if (biv == 0) {		/* backward compat */
283aed035abSart 			biv = *(u_long *)bip;
284aed035abSart 			bip += 8;
285aed035abSart 		}
286aed035abSart 		switch (biv) {
287aed035abSart 		case 1: {
288aed035abSart 			struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip;
289aed035abSart 
290aed035abSart 			bootinfo.ssym = v1p->ssym;
291aed035abSart 			bootinfo.esym = v1p->esym;
292aed035abSart 			/* hwrpb may not be provided by boot block in v1 */
293aed035abSart 			if (v1p->hwrpb != NULL) {
294aed035abSart 				bootinfo.hwrpb_phys =
295aed035abSart 				    ((struct rpb *)v1p->hwrpb)->rpb_phys;
296aed035abSart 				bootinfo.hwrpb_size = v1p->hwrpbsize;
297aed035abSart 			} else {
298aed035abSart 				bootinfo.hwrpb_phys =
299aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_phys;
300aed035abSart 				bootinfo.hwrpb_size =
301aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_size;
302aed035abSart 			}
303aed035abSart 			bcopy(v1p->boot_flags, bootinfo.boot_flags,
304aed035abSart 			    min(sizeof v1p->boot_flags,
305aed035abSart 			      sizeof bootinfo.boot_flags));
306aed035abSart 			bcopy(v1p->booted_kernel, bootinfo.booted_kernel,
307aed035abSart 			    min(sizeof v1p->booted_kernel,
308aed035abSart 			      sizeof bootinfo.booted_kernel));
309aed035abSart 			/* booted dev not provided in bootinfo */
310aed035abSart 			init_prom_interface((struct rpb *)
311aed035abSart 			    ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys));
312aed035abSart                 	prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
313aed035abSart 			    sizeof bootinfo.booted_dev);
314aed035abSart 			break;
315aed035abSart 		}
316aed035abSart 		default:
317aed035abSart 			bootinfo_msg = "unknown bootinfo version";
318aed035abSart 			goto nobootinfo;
319aed035abSart 		}
320aed035abSart 	} else {
321aed035abSart 		bootinfo_msg = "boot program did not pass bootinfo";
322aed035abSart nobootinfo:
323aed035abSart 		bootinfo.ssym = (u_long)_end;
324aed035abSart 		bootinfo.esym = (u_long)_end;
325aed035abSart 		bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys;
326aed035abSart 		bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size;
327aed035abSart 		init_prom_interface((struct rpb *)HWRPB_ADDR);
328aed035abSart 		prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
329aed035abSart 		    sizeof bootinfo.boot_flags);
330aed035abSart 		prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
331aed035abSart 		    sizeof bootinfo.booted_kernel);
332aed035abSart 		prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
333aed035abSart 		    sizeof bootinfo.booted_dev);
334aed035abSart 	}
335aed035abSart 
336aed035abSart 	esym = (caddr_t)bootinfo.esym;
337aed035abSart 	/*
338aed035abSart 	 * Initialize the kernel's mapping of the RPB.  It's needed for
339aed035abSart 	 * lots of things.
340aed035abSart 	 */
341aed035abSart 	hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys);
342aed035abSart 
343aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
344aed035abSart 	if (hwrpb->rpb_type == ST_DEC_3000_300 ||
345aed035abSart 	    hwrpb->rpb_type == ST_DEC_3000_500) {
346aed035abSart 		prom_getenv(PROM_E_SCSIID, dec_3000_scsiid,
347aed035abSart 		    sizeof(dec_3000_scsiid));
348aed035abSart 		prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast,
349aed035abSart 		    sizeof(dec_3000_scsifast));
350aed035abSart 	}
351aed035abSart #endif
352df930be7Sderaadt 
353df930be7Sderaadt 	/*
354df930be7Sderaadt 	 * Remember how many cycles there are per microsecond,
355df930be7Sderaadt 	 * so that we can use delay().  Round up, for safety.
356df930be7Sderaadt 	 */
357df930be7Sderaadt 	cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
358df930be7Sderaadt 
359df930be7Sderaadt 	/*
3609e71c994Saaron 	 * Initialize the (temporary) bootstrap console interface, so
361aed035abSart 	 * we can use printf until the VM system starts being setup.
362aed035abSart 	 * The real console is initialized before then.
363df930be7Sderaadt 	 */
364aed035abSart 	init_bootstrap_console();
365aed035abSart 
366aed035abSart 	/* OUTPUT NOW ALLOWED */
367aed035abSart 
368aed035abSart 	/* delayed from above */
369aed035abSart 	if (bootinfo_msg)
370aed035abSart 		printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n",
371aed035abSart 		    bootinfo_msg, bim, bip, biv);
372aed035abSart 
373aed035abSart 	/* Initialize the trap vectors on the primary processor. */
374aed035abSart 	trap_init();
375df930be7Sderaadt 
376df930be7Sderaadt 	/*
377aed035abSart 	 * Find out what hardware we're on, and do basic initialization.
378df930be7Sderaadt 	 */
379aed035abSart 	cputype = hwrpb->rpb_type;
380aed035abSart 	if (cputype < 0) {
381aed035abSart 		/*
382aed035abSart 		 * At least some white-box systems have SRM which
383aed035abSart 		 * reports a systype that's the negative of their
384aed035abSart 		 * blue-box counterpart.
385aed035abSart 		 */
386aed035abSart 		cputype = -cputype;
387aed035abSart 	}
388aed035abSart 	c = platform_lookup(cputype);
389aed035abSart 	if (c == NULL) {
390aed035abSart 		platform_not_supported();
391aed035abSart 		/* NOTREACHED */
392aed035abSart 	}
393aed035abSart 	(*c->init)();
394aed035abSart 	strcpy(cpu_model, platform.model);
39550ce9ee0Sniklas 
39650ce9ee0Sniklas 	/*
3979e71c994Saaron 	 * Initialize the real console, so that the bootstrap console is
398aed035abSart 	 * no longer necessary.
39950ce9ee0Sniklas 	 */
400aed035abSart 	(*platform.cons_init)();
401aed035abSart 
402aed035abSart #ifdef DIAGNOSTIC
403aed035abSart 	/* Paranoid sanity checking */
404aed035abSart 
405aed035abSart 	/* We should always be running on the primary. */
406aed035abSart 	assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami());
407aed035abSart 
408aed035abSart 	/*
409aed035abSart 	 * On single-CPU systypes, the primary should always be CPU 0,
410aed035abSart 	 * except on Alpha 8200 systems where the CPU id is related
411aed035abSart 	 * to the VID, which is related to the Turbo Laser node id.
412aed035abSart 	 */
413aed035abSart 	if (cputype != ST_DEC_21000)
414aed035abSart 		assert(hwrpb->rpb_primary_cpu_id == 0);
415aed035abSart #endif
416aed035abSart 
417aed035abSart 	/* NO MORE FIRMWARE ACCESS ALLOWED */
418aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
419aed035abSart 	/*
420aed035abSart 	 * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and
421aed035abSart 	 * XXX pmap_uses_prom_console() evaluates to non-zero.)
422aed035abSart 	 */
423aed035abSart #endif
424aed035abSart 
425aed035abSart 	/*
426aed035abSart 	 * find out this system's page size
427aed035abSart 	 */
42873b9fe7cSart 	if ((uvmexp.pagesize = hwrpb->rpb_page_size) != 8192)
42973b9fe7cSart 		panic("page size %d != 8192?!", uvmexp.pagesize);
430aed035abSart 
431aed035abSart 	uvm_setpagesize();
432aed035abSart 
433aed035abSart 	/*
434aed035abSart 	 * Find the beginning and end of the kernel (and leave a
435aed035abSart 	 * bit of space before the beginning for the bootstrap
436aed035abSart 	 * stack).
437aed035abSart 	 */
438aed035abSart 	kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE;
439aed035abSart 	kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym);
440aed035abSart 
441aed035abSart 	kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart));
442aed035abSart 	kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend));
443df930be7Sderaadt 
444df930be7Sderaadt 	/*
445df930be7Sderaadt 	 * Find out how much memory is available, by looking at
446df930be7Sderaadt 	 * the memory cluster descriptors.  This also tries to do
447df930be7Sderaadt 	 * its best to detect things things that have never been seen
448df930be7Sderaadt 	 * before...
449df930be7Sderaadt 	 */
450df930be7Sderaadt 	mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
451df930be7Sderaadt 
452aed035abSart 	/* MDDT SANITY CHECKING */
453df930be7Sderaadt 	mddtweird = 0;
454aed035abSart 	if (mddtp->mddt_cluster_cnt < 2) {
455df930be7Sderaadt 		mddtweird = 1;
456aed035abSart 		printf("WARNING: weird number of mem clusters: %lu\n",
457aed035abSart 		    mddtp->mddt_cluster_cnt);
458df930be7Sderaadt 	}
459df930be7Sderaadt 
460aed035abSart #if 0
461aed035abSart 	printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt);
462aed035abSart #endif
463df930be7Sderaadt 
464aed035abSart 	for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
465aed035abSart 		memc = &mddtp->mddt_clusters[i];
466aed035abSart #if 0
467aed035abSart 		printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i,
468aed035abSart 		    memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage);
469aed035abSart #endif
470aed035abSart 		totalphysmem += memc->mddt_pg_cnt;
471aed035abSart 		if (mem_cluster_cnt < VM_PHYSSEG_MAX) {	/* XXX */
472aed035abSart 			mem_clusters[mem_cluster_cnt].start =
473aed035abSart 			    ptoa(memc->mddt_pfn);
474aed035abSart 			mem_clusters[mem_cluster_cnt].size =
475aed035abSart 			    ptoa(memc->mddt_pg_cnt);
476aed035abSart 			if (memc->mddt_usage & MDDT_mbz ||
477aed035abSart 			    memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */
478aed035abSart 			    memc->mddt_usage & MDDT_PALCODE)
479aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
480aed035abSart 				    VM_PROT_READ;
481aed035abSart 			else
482aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
483aed035abSart 				    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
484aed035abSart 			mem_cluster_cnt++;
485aed035abSart 		}
486aed035abSart 
487aed035abSart 		if (memc->mddt_usage & MDDT_mbz) {
488aed035abSart 			mddtweird = 1;
489aed035abSart 			printf("WARNING: mem cluster %d has weird "
490aed035abSart 			    "usage 0x%lx\n", i, memc->mddt_usage);
491aed035abSart 			unknownmem += memc->mddt_pg_cnt;
492aed035abSart 			continue;
493aed035abSart 		}
494aed035abSart 		if (memc->mddt_usage & MDDT_NONVOLATILE) {
495aed035abSart 			/* XXX should handle these... */
496aed035abSart 			printf("WARNING: skipping non-volatile mem "
497aed035abSart 			    "cluster %d\n", i);
498aed035abSart 			unusedmem += memc->mddt_pg_cnt;
499aed035abSart 			continue;
500aed035abSart 		}
501aed035abSart 		if (memc->mddt_usage & MDDT_PALCODE) {
502aed035abSart 			resvmem += memc->mddt_pg_cnt;
503aed035abSart 			continue;
504aed035abSart 		}
505aed035abSart 
506aed035abSart 		/*
507aed035abSart 		 * We have a memory cluster available for system
508aed035abSart 		 * software use.  We must determine if this cluster
509aed035abSart 		 * holds the kernel.
510aed035abSart 		 */
511aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
512aed035abSart 		/*
513aed035abSart 		 * XXX If the kernel uses the PROM console, we only use the
514aed035abSart 		 * XXX memory after the kernel in the first system segment,
515aed035abSart 		 * XXX to avoid clobbering prom mapping, data, etc.
516aed035abSart 		 */
517aed035abSart 	    if (!pmap_uses_prom_console() || physmem == 0) {
518aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
519aed035abSart 		physmem += memc->mddt_pg_cnt;
520aed035abSart 		pfn0 = memc->mddt_pfn;
521aed035abSart 		pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt;
522aed035abSart 		if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) {
523aed035abSart 			/*
524aed035abSart 			 * Must compute the location of the kernel
525aed035abSart 			 * within the segment.
526aed035abSart 			 */
527aed035abSart #if 0
528aed035abSart 			printf("Cluster %d contains kernel\n", i);
529aed035abSart #endif
530aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
531aed035abSart 		    if (!pmap_uses_prom_console()) {
532aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
533aed035abSart 			if (pfn0 < kernstartpfn) {
534aed035abSart 				/*
535aed035abSart 				 * There is a chunk before the kernel.
536aed035abSart 				 */
537aed035abSart #if 0
538aed035abSart 				printf("Loading chunk before kernel: "
539aed035abSart 				    "0x%lx / 0x%lx\n", pfn0, kernstartpfn);
540aed035abSart #endif
541aed035abSart 				uvm_page_physload(pfn0, kernstartpfn,
542aed035abSart 				    pfn0, kernstartpfn, VM_FREELIST_DEFAULT);
543aed035abSart 			}
544aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
545aed035abSart 		    }
546aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
547aed035abSart 			if (kernendpfn < pfn1) {
548aed035abSart 				/*
549aed035abSart 				 * There is a chunk after the kernel.
550aed035abSart 				 */
551aed035abSart #if 0
552aed035abSart 				printf("Loading chunk after kernel: "
553aed035abSart 				    "0x%lx / 0x%lx\n", kernendpfn, pfn1);
554aed035abSart #endif
555aed035abSart 				uvm_page_physload(kernendpfn, pfn1,
556aed035abSart 				    kernendpfn, pfn1, VM_FREELIST_DEFAULT);
557aed035abSart 			}
558aed035abSart 		} else {
559aed035abSart 			/*
560aed035abSart 			 * Just load this cluster as one chunk.
561aed035abSart 			 */
562aed035abSart #if 0
563aed035abSart 			printf("Loading cluster %d: 0x%lx / 0x%lx\n", i,
564aed035abSart 			    pfn0, pfn1);
565aed035abSart #endif
566aed035abSart 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1,
567aed035abSart 			    VM_FREELIST_DEFAULT);
568aed035abSart 		}
569aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
570aed035abSart 	    }
571aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
572aed035abSart 	}
573aed035abSart 
574aed035abSart 	/*
575aed035abSart 	 * Dump out the MDDT if it looks odd...
576aed035abSart 	 */
577df930be7Sderaadt 	if (mddtweird) {
578df930be7Sderaadt 		printf("\n");
579df930be7Sderaadt 		printf("complete memory cluster information:\n");
580df930be7Sderaadt 		for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
581df930be7Sderaadt 			printf("mddt %d:\n", i);
582df930be7Sderaadt 			printf("\tpfn %lx\n",
583df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pfn);
584df930be7Sderaadt 			printf("\tcnt %lx\n",
585df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_cnt);
586df930be7Sderaadt 			printf("\ttest %lx\n",
587df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_test);
588df930be7Sderaadt 			printf("\tbva %lx\n",
589df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_v_bitaddr);
590df930be7Sderaadt 			printf("\tbpa %lx\n",
591df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_p_bitaddr);
592df930be7Sderaadt 			printf("\tbcksum %lx\n",
593df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_bit_cksum);
594df930be7Sderaadt 			printf("\tusage %lx\n",
595df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_usage);
596df930be7Sderaadt 		}
597df930be7Sderaadt 		printf("\n");
598df930be7Sderaadt 	}
599df930be7Sderaadt 
600df930be7Sderaadt 	if (totalphysmem == 0)
601df930be7Sderaadt 		panic("can't happen: system seems to have no memory!");
602df930be7Sderaadt 	maxmem = physmem;
603df930be7Sderaadt #if 0
604df930be7Sderaadt 	printf("totalphysmem = %d\n", totalphysmem);
605df930be7Sderaadt 	printf("physmem = %d\n", physmem);
606df930be7Sderaadt 	printf("resvmem = %d\n", resvmem);
607df930be7Sderaadt 	printf("unusedmem = %d\n", unusedmem);
608df930be7Sderaadt 	printf("unknownmem = %d\n", unknownmem);
609df930be7Sderaadt #endif
610df930be7Sderaadt 
611df930be7Sderaadt 	/*
612aed035abSart 	 * Initialize error message buffer (at end of core).
613df930be7Sderaadt 	 */
614aed035abSart 	{
615aed035abSart 		vsize_t sz = (vsize_t)round_page(MSGBUFSIZE);
616aed035abSart 		vsize_t reqsz = sz;
617df930be7Sderaadt 
618aed035abSart 		vps = &vm_physmem[vm_nphysseg - 1];
619e1da84e1Salex 
620aed035abSart 		/* shrink so that it'll fit in the last segment */
621aed035abSart 		if ((vps->avail_end - vps->avail_start) < atop(sz))
622aed035abSart 			sz = ptoa(vps->avail_end - vps->avail_start);
623aed035abSart 
624aed035abSart 		vps->end -= atop(sz);
625aed035abSart 		vps->avail_end -= atop(sz);
626aed035abSart 		initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz);
627aed035abSart 
628aed035abSart 		/* Remove the last segment if it now has no pages. */
629aed035abSart 		if (vps->start == vps->end)
630aed035abSart 			vm_nphysseg--;
631aed035abSart 
632aed035abSart 		/* warn if the message buffer had to be shrunk */
633aed035abSart 		if (sz != reqsz)
634aed035abSart 			printf("WARNING: %ld bytes not available for msgbuf "
635aed035abSart 			    "in last cluster (%ld used)\n", reqsz, sz);
636aed035abSart 
637aed035abSart 	}
638aed035abSart 
639df930be7Sderaadt 	/*
640df930be7Sderaadt 	 * Init mapping for u page(s) for proc 0
641df930be7Sderaadt 	 */
642aed035abSart 	proc0.p_addr = proc0paddr =
643aed035abSart 	    (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL);
644df930be7Sderaadt 
645df930be7Sderaadt 	/*
646aed035abSart 	 * Allocate space for system data structures.  These data structures
647aed035abSart 	 * are allocated here instead of cpu_startup() because physical
648aed035abSart 	 * memory is directly addressable.  We don't have to map these into
649aed035abSart 	 * virtual address space.
650df930be7Sderaadt 	 */
651aed035abSart 	size = (vsize_t)allocsys(NULL);
652aed035abSart 	v = (caddr_t)pmap_steal_memory(size, NULL, NULL);
653aed035abSart 	if ((allocsys(v) - v) != size)
654aed035abSart 		panic("alpha_init: table size inconsistency");
655df930be7Sderaadt 
656df930be7Sderaadt 	/*
657df930be7Sderaadt 	 * Clear allocated memory.
658df930be7Sderaadt 	 */
659aed035abSart 	bzero(v, size);
660df930be7Sderaadt 
661df930be7Sderaadt 	/*
662df930be7Sderaadt 	 * Initialize the virtual memory system, and set the
663df930be7Sderaadt 	 * page table base register in proc 0's PCB.
664df930be7Sderaadt 	 */
665aed035abSart 	pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT),
666aed035abSart 	    hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt);
667df930be7Sderaadt 
668df930be7Sderaadt 	/*
669df930be7Sderaadt 	 * Initialize the rest of proc 0's PCB, and cache its physical
670df930be7Sderaadt 	 * address.
671df930be7Sderaadt 	 */
672df930be7Sderaadt 	proc0.p_md.md_pcbpaddr =
673aed035abSart 	    (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb);
674df930be7Sderaadt 
675df930be7Sderaadt 	/*
676df930be7Sderaadt 	 * Set the kernel sp, reserving space for an (empty) trapframe,
677df930be7Sderaadt 	 * and make proc0's trapframe pointer point to it for sanity.
678df930be7Sderaadt 	 */
67950ce9ee0Sniklas 	proc0paddr->u_pcb.pcb_hw.apcb_ksp =
680df930be7Sderaadt 	    (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
68174652a67Sniklas 	proc0.p_md.md_tf =
68274652a67Sniklas 	    (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
68350ce9ee0Sniklas 
684aed035abSart 	/*
685aed035abSart 	 * Initialize the primary CPU's idle PCB to proc0's.  In a
686aed035abSart 	 * MULTIPROCESSOR configuration, each CPU will later get
687aed035abSart 	 * its own idle PCB when autoconfiguration runs.
688aed035abSart 	 */
689aed035abSart 	ci->ci_idle_pcb = &proc0paddr->u_pcb;
690aed035abSart 	ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr;
691df930be7Sderaadt 
692df930be7Sderaadt 	/*
693df930be7Sderaadt 	 * Look at arguments passed to us and compute boothowto.
694df930be7Sderaadt 	 */
695417eba8cSderaadt 
696417eba8cSderaadt 	boothowto = RB_SINGLE;
697df930be7Sderaadt #ifdef KADB
698df930be7Sderaadt 	boothowto |= RB_KDB;
699df930be7Sderaadt #endif
700aed035abSart 	for (p = bootinfo.boot_flags; p && *p != '\0'; p++) {
701417eba8cSderaadt 		/*
702417eba8cSderaadt 		 * Note that we'd really like to differentiate case here,
703417eba8cSderaadt 		 * but the Alpha AXP Architecture Reference Manual
704417eba8cSderaadt 		 * says that we shouldn't.
705417eba8cSderaadt 		 */
706df930be7Sderaadt 		switch (*p) {
707df930be7Sderaadt 		case 'a': /* autoboot */
708417eba8cSderaadt 		case 'A':
709df930be7Sderaadt 			boothowto &= ~RB_SINGLE;
710df930be7Sderaadt 			break;
711df930be7Sderaadt 
71212f8bbedSniklas 		case 'b': /* Enter DDB as soon as the console is initialised */
71312f8bbedSniklas 		case 'B':
71412f8bbedSniklas 			boothowto |= RB_KDB;
71512f8bbedSniklas 			break;
71612f8bbedSniklas 
71750ce9ee0Sniklas 		case 'c': /* enter user kernel configuration */
71850ce9ee0Sniklas 		case 'C':
71950ce9ee0Sniklas 			boothowto |= RB_CONFIG;
72050ce9ee0Sniklas 			break;
72150ce9ee0Sniklas 
72250ce9ee0Sniklas #ifdef DEBUG
72350ce9ee0Sniklas 		case 'd': /* crash dump immediately after autoconfig */
72450ce9ee0Sniklas 		case 'D':
72550ce9ee0Sniklas 			boothowto |= RB_DUMP;
72650ce9ee0Sniklas 			break;
72750ce9ee0Sniklas #endif
72850ce9ee0Sniklas 
72950ce9ee0Sniklas 		case 'h': /* always halt, never reboot */
73050ce9ee0Sniklas 		case 'H':
73150ce9ee0Sniklas 			boothowto |= RB_HALT;
732df930be7Sderaadt 			break;
733df930be7Sderaadt 
734417eba8cSderaadt #if 0
735417eba8cSderaadt 		case 'm': /* mini root present in memory */
736417eba8cSderaadt 		case 'M':
737417eba8cSderaadt 			boothowto |= RB_MINIROOT;
738417eba8cSderaadt 			break;
739417eba8cSderaadt #endif
74050ce9ee0Sniklas 
74150ce9ee0Sniklas 		case 'n': /* askname */
74250ce9ee0Sniklas 		case 'N':
74350ce9ee0Sniklas 			boothowto |= RB_ASKNAME;
74450ce9ee0Sniklas 			break;
745aed035abSart 
746aed035abSart 		case 's': /* single-user (default, supported for sanity) */
747aed035abSart 		case 'S':
748aed035abSart 			boothowto |= RB_SINGLE;
749aed035abSart 			break;
750aed035abSart 
751aed035abSart 		case '-':
752aed035abSart 			/*
753aed035abSart 			 * Just ignore this.  It's not required, but it's
754aed035abSart 			 * common for it to be passed regardless.
755aed035abSart 			 */
756aed035abSart 			break;
757aed035abSart 
758aed035abSart 		default:
759aed035abSart 			printf("Unrecognized boot flag '%c'.\n", *p);
760aed035abSart 			break;
761df930be7Sderaadt 		}
762df930be7Sderaadt 	}
763df930be7Sderaadt 
764aed035abSart 
765df930be7Sderaadt 	/*
766df930be7Sderaadt 	 * Figure out the number of cpus in the box, from RPB fields.
767df930be7Sderaadt 	 * Really.  We mean it.
768df930be7Sderaadt 	 */
769df930be7Sderaadt 	for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
770df930be7Sderaadt 		struct pcs *pcsp;
771df930be7Sderaadt 
772aed035abSart 		pcsp = LOCATE_PCS(hwrpb, i);
773df930be7Sderaadt 		if ((pcsp->pcs_flags & PCS_PP) != 0)
774df930be7Sderaadt 			ncpus++;
775df930be7Sderaadt 	}
776aed035abSart 
777aed035abSart 	/*
778aed035abSart 	 * Initialize debuggers, and break into them if appropriate.
779aed035abSart 	 */
780aed035abSart #ifdef DDB
781aed035abSart 	ddb_init();
782aed035abSart 
783aed035abSart 	if (boothowto & RB_KDB)
784aed035abSart 		Debugger();
785aed035abSart #endif
786aed035abSart #ifdef KGDB
787aed035abSart 	if (boothowto & RB_KDB)
788aed035abSart 		kgdb_connect(0);
789aed035abSart #endif
790aed035abSart 	/*
791aed035abSart 	 * Figure out our clock frequency, from RPB fields.
792aed035abSart 	 */
793aed035abSart 	hz = hwrpb->rpb_intr_freq >> 12;
794aed035abSart 	if (!(60 <= hz && hz <= 10240)) {
795aed035abSart 		hz = 1024;
796aed035abSart #ifdef DIAGNOSTIC
797aed035abSart 		printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n",
798aed035abSart 			hwrpb->rpb_intr_freq, hz);
799aed035abSart #endif
800aed035abSart 	}
801aed035abSart }
802aed035abSart 
803aed035abSart caddr_t
804aed035abSart allocsys(v)
805aed035abSart 	caddr_t v;
806aed035abSart {
807aed035abSart 	/*
808aed035abSart 	 * Allocate space for system data structures.
809aed035abSart 	 * The first available kernel virtual address is in "v".
810aed035abSart 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
811aed035abSart 	 *
812aed035abSart 	 * These data structures are allocated here instead of cpu_startup()
813aed035abSart 	 * because physical memory is directly addressable. We don't have
814aed035abSart 	 * to map these into virtual address space.
815aed035abSart 	 */
816aed035abSart #define valloc(name, type, num) \
817aed035abSart 	    (name) = (type *)v; v = (caddr_t)ALIGN((name)+(num))
818aed035abSart 
819aed035abSart #ifdef SYSVSHM
8205c6c8190Sespie 	shminfo.shmmax = shmmaxpgs;
8215c6c8190Sespie 	shminfo.shmall = shmmaxpgs;
8225c6c8190Sespie 	shminfo.shmseg = shmseg;
823aed035abSart 	valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
824aed035abSart #endif
825aed035abSart #ifdef SYSVSEM
826aed035abSart 	valloc(sema, struct semid_ds, seminfo.semmni);
827aed035abSart 	valloc(sem, struct sem, seminfo.semmns);
828aed035abSart 	/* This is pretty disgusting! */
829aed035abSart 	valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
830aed035abSart #endif
831aed035abSart #ifdef SYSVMSG
832aed035abSart 	valloc(msgpool, char, msginfo.msgmax);
833aed035abSart 	valloc(msgmaps, struct msgmap, msginfo.msgseg);
834aed035abSart 	valloc(msghdrs, struct msg, msginfo.msgtql);
835aed035abSart 	valloc(msqids, struct msqid_ds, msginfo.msgmni);
836aed035abSart #endif
837aed035abSart 
838aed035abSart 	/*
839aed035abSart 	 * Determine how many buffers to allocate.
840aed035abSart 	 * We allocate 10% of memory for buffer space.  Insure a
841aed035abSart 	 * minimum of 16 buffers.
842aed035abSart 	 */
843aed035abSart 	if (bufpages == 0)
84460535ec9Smaja 		bufpages = (physmem / (100/bufcachepercent));
845aed035abSart 	if (nbuf == 0) {
846aed035abSart 		nbuf = bufpages;
847aed035abSart 		if (nbuf < 16)
848aed035abSart 			nbuf = 16;
849aed035abSart 	}
850aed035abSart 	valloc(buf, struct buf, nbuf);
851aed035abSart 
852aed035abSart #undef valloc
853aed035abSart 
854aed035abSart 	return v;
855df930be7Sderaadt }
856df930be7Sderaadt 
857417eba8cSderaadt void
858df930be7Sderaadt consinit()
859df930be7Sderaadt {
860aed035abSart 
861aed035abSart 	/*
862aed035abSart 	 * Everything related to console initialization is done
863aed035abSart 	 * in alpha_init().
864aed035abSart 	 */
865aed035abSart #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE)
866aed035abSart 	printf("consinit: %susing prom console\n",
867aed035abSart 	    pmap_uses_prom_console() ? "" : "not ");
86812f8bbedSniklas #endif
869df930be7Sderaadt }
870df930be7Sderaadt 
8717ce9e539Sericj #include "pckbc.h"
8727ce9e539Sericj #include "pckbd.h"
8737ce9e539Sericj #if (NPCKBC > 0) && (NPCKBD == 0)
8747ce9e539Sericj 
8757ce9e539Sericj #include <dev/ic/pckbcvar.h>
8767ce9e539Sericj 
8777ce9e539Sericj /*
8788059aba4Sjason  * This is called by the pckbc driver if no pckbd is configured.
8797ce9e539Sericj  * On the i386, it is used to glue in the old, deprecated console
8807ce9e539Sericj  * code.  On the Alpha, it does nothing.
8817ce9e539Sericj  */
8827ce9e539Sericj int
8837ce9e539Sericj pckbc_machdep_cnattach(kbctag, kbcslot)
8847ce9e539Sericj 	pckbc_tag_t kbctag;
8857ce9e539Sericj 	pckbc_slot_t kbcslot;
8867ce9e539Sericj {
8877ce9e539Sericj 	return (ENXIO);
8887ce9e539Sericj }
8897ce9e539Sericj #endif /* NPCKBC > 0 && NPCKBD == 0 */
8907ce9e539Sericj 
891417eba8cSderaadt void
892df930be7Sderaadt cpu_startup()
893df930be7Sderaadt {
894df930be7Sderaadt 	register unsigned i;
895df930be7Sderaadt 	int base, residual;
896aed035abSart 	vaddr_t minaddr, maxaddr;
897aed035abSart 	vsize_t size;
89850ce9ee0Sniklas #if defined(DEBUG)
899df930be7Sderaadt 	extern int pmapdebug;
900df930be7Sderaadt 	int opmapdebug = pmapdebug;
901df930be7Sderaadt 
902df930be7Sderaadt 	pmapdebug = 0;
903df930be7Sderaadt #endif
904df930be7Sderaadt 
905df930be7Sderaadt 	/*
906df930be7Sderaadt 	 * Good {morning,afternoon,evening,night}.
907df930be7Sderaadt 	 */
908df930be7Sderaadt 	printf(version);
909df930be7Sderaadt 	identifycpu();
9103f4ce3b7Smiod 	printf("total memory = %ld (%ldK)\n", (long)ptoa(totalphysmem),
9113f4ce3b7Smiod 	    (long)ptoa(totalphysmem) / 1024);
9123f4ce3b7Smiod 	printf("(%ld reserved for PROM, ", (long)ptoa(resvmem));
9133f4ce3b7Smiod 	printf("%ld used by OpenBSD)\n", (long)ptoa(physmem));
914aed035abSart 	if (unusedmem) {
9153f4ce3b7Smiod 		printf("WARNING: unused memory = %ld (%ldK)\n",
9163f4ce3b7Smiod 		    (long)ptoa(unusedmem), (long)ptoa(unusedmem) / 1024);
917aed035abSart 	}
918aed035abSart 	if (unknownmem) {
9193f4ce3b7Smiod 		printf("WARNING: %ld (%ldK) of memory with unknown purpose\n",
9203f4ce3b7Smiod 		    (long)ptoa(unknownmem), (long)ptoa(unknownmem) / 1024);
921aed035abSart 	}
922df930be7Sderaadt 
923df930be7Sderaadt 	/*
924df930be7Sderaadt 	 * Allocate virtual address space for file I/O buffers.
925df930be7Sderaadt 	 * Note they are different than the array of headers, 'buf',
926df930be7Sderaadt 	 * and usually occupy more virtual memory than physical.
927df930be7Sderaadt 	 */
928df930be7Sderaadt 	size = MAXBSIZE * nbuf;
929aed035abSart 	if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
930198a4b3fSart 		    NULL, UVM_UNKNOWN_OFFSET, 0,
931aed035abSart 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
932738a5b4dSart 				UVM_ADV_NORMAL, 0)))
933aed035abSart 		panic("startup: cannot allocate VM for buffers");
934df930be7Sderaadt 	base = bufpages / nbuf;
935df930be7Sderaadt 	residual = bufpages % nbuf;
936df930be7Sderaadt 	for (i = 0; i < nbuf; i++) {
937aed035abSart 		vsize_t curbufsize;
938aed035abSart 		vaddr_t curbuf;
939aed035abSart 		struct vm_page *pg;
940df930be7Sderaadt 
941df930be7Sderaadt 		/*
942aed035abSart 		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
943aed035abSart 		 * that MAXBSIZE space, we allocate and map (base+1) pages
944aed035abSart 		 * for the first "residual" buffers, and then we allocate
945aed035abSart 		 * "base" pages for the rest.
946df930be7Sderaadt 		 */
947aed035abSart 		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
948aed035abSart 		curbufsize = NBPG * ((i < residual) ? (base+1) : base);
949aed035abSart 
950aed035abSart 		while (curbufsize) {
951aed035abSart 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
952aed035abSart 			if (pg == NULL)
953aed035abSart 				panic("cpu_startup: not enough memory for "
954aed035abSart 				    "buffer cache");
955aed035abSart 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
956aed035abSart 					VM_PROT_READ|VM_PROT_WRITE);
957aed035abSart 			curbuf += PAGE_SIZE;
958aed035abSart 			curbufsize -= PAGE_SIZE;
959aed035abSart 		}
9600e5798cfSart 		pmap_update(pmap_kernel());
961df930be7Sderaadt 	}
962df930be7Sderaadt 	/*
963df930be7Sderaadt 	 * Allocate a submap for exec arguments.  This map effectively
964df930be7Sderaadt 	 * limits the number of processes exec'ing at any time.
965df930be7Sderaadt 	 */
966aed035abSart 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
967aed035abSart 				   16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
968df930be7Sderaadt 
969df930be7Sderaadt 	/*
970df930be7Sderaadt 	 * Allocate a submap for physio
971df930be7Sderaadt 	 */
972aed035abSart 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
973aed035abSart 				   VM_PHYS_SIZE, 0, FALSE, NULL);
974df930be7Sderaadt 
97550ce9ee0Sniklas #if defined(DEBUG)
976df930be7Sderaadt 	pmapdebug = opmapdebug;
977df930be7Sderaadt #endif
9783f4ce3b7Smiod 	printf("avail memory = %ld (%ldK)\n", (long)ptoa(uvmexp.free),
9793f4ce3b7Smiod 	    (long)ptoa(uvmexp.free) / 1024);
980aed035abSart #if 0
981aed035abSart 	{
982aed035abSart 		extern u_long pmap_pages_stolen;
983aed035abSart 
984aed035abSart 		printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE);
985aed035abSart 	}
986aed035abSart #endif
9873f4ce3b7Smiod 	printf("using %ld buffers containing %ld bytes (%ldK) of memory\n",
9883f4ce3b7Smiod 	    (long)nbuf, (long)bufpages * NBPG, (long)bufpages * (NBPG / 1024));
989df930be7Sderaadt 
990df930be7Sderaadt 	/*
991df930be7Sderaadt 	 * Set up buffers, so they can be used to read disk labels.
992df930be7Sderaadt 	 */
993df930be7Sderaadt 	bufinit();
994df930be7Sderaadt 
995df930be7Sderaadt 	/*
996df930be7Sderaadt 	 * Configure the system.
997df930be7Sderaadt 	 */
99841033391Sderaadt 	if (boothowto & RB_CONFIG) {
99941033391Sderaadt #ifdef BOOT_CONFIG
100041033391Sderaadt 		user_config();
100141033391Sderaadt #else
100241033391Sderaadt 		printf("kernel does not support -c; continuing..\n");
100341033391Sderaadt #endif
100441033391Sderaadt 	}
100550ce9ee0Sniklas 
100650ce9ee0Sniklas 	/*
1007aed035abSart 	 * Set up the HWPCB so that it's safe to configure secondary
1008aed035abSart 	 * CPUs.
100950ce9ee0Sniklas 	 */
1010aed035abSart 	hwrpb_primary_init();
1011aed035abSart }
1012aed035abSart 
1013aed035abSart /*
1014aed035abSart  * Retrieve the platform name from the DSR.
1015aed035abSart  */
1016aed035abSart const char *
1017aed035abSart alpha_dsr_sysname()
1018aed035abSart {
1019aed035abSart 	struct dsrdb *dsr;
1020aed035abSart 	const char *sysname;
1021aed035abSart 
1022aed035abSart 	/*
1023aed035abSart 	 * DSR does not exist on early HWRPB versions.
1024aed035abSart 	 */
1025aed035abSart 	if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS)
1026aed035abSart 		return (NULL);
1027aed035abSart 
1028aed035abSart 	dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off);
1029aed035abSart 	sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off +
1030aed035abSart 	    sizeof(u_int64_t)));
1031aed035abSart 	return (sysname);
1032aed035abSart }
1033aed035abSart 
1034aed035abSart /*
1035aed035abSart  * Lookup the system specified system variation in the provided table,
1036aed035abSart  * returning the model string on match.
1037aed035abSart  */
1038aed035abSart const char *
1039aed035abSart alpha_variation_name(variation, avtp)
1040aed035abSart 	u_int64_t variation;
1041aed035abSart 	const struct alpha_variation_table *avtp;
1042aed035abSart {
1043aed035abSart 	int i;
1044aed035abSart 
1045aed035abSart 	for (i = 0; avtp[i].avt_model != NULL; i++)
1046aed035abSart 		if (avtp[i].avt_variation == variation)
1047aed035abSart 			return (avtp[i].avt_model);
1048aed035abSart 	return (NULL);
1049aed035abSart }
1050aed035abSart 
1051aed035abSart /*
1052aed035abSart  * Generate a default platform name based for unknown system variations.
1053aed035abSart  */
1054aed035abSart const char *
1055aed035abSart alpha_unknown_sysname()
1056aed035abSart {
1057aed035abSart 	static char s[128];		/* safe size */
1058aed035abSart 
1059aed035abSart 	sprintf(s, "%s family, unknown model variation 0x%lx",
1060aed035abSart 	    platform.family, hwrpb->rpb_variation & SV_ST_MASK);
1061aed035abSart 	return ((const char *)s);
1062df930be7Sderaadt }
1063df930be7Sderaadt 
106450ce9ee0Sniklas void
1065df930be7Sderaadt identifycpu()
1066df930be7Sderaadt {
1067aed035abSart 	char *s;
1068df930be7Sderaadt 
1069df930be7Sderaadt 	/*
1070df930be7Sderaadt 	 * print out CPU identification information.
1071df930be7Sderaadt 	 */
1072aed035abSart 	printf("%s", cpu_model);
1073aed035abSart 	for(s = cpu_model; *s; ++s)
1074aed035abSart 		if(strncasecmp(s, "MHz", 3) == 0)
1075aed035abSart 			goto skipMHz;
1076aed035abSart 	printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000);
1077aed035abSart skipMHz:
1078aed035abSart 	printf("\n");
107950ce9ee0Sniklas 	printf("%ld byte page size, %d processor%s.\n",
1080df930be7Sderaadt 	    hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s");
1081df930be7Sderaadt #if 0
1082df930be7Sderaadt 	/* this isn't defined for any systems that we run on? */
1083df930be7Sderaadt 	printf("serial number 0x%lx 0x%lx\n",
1084df930be7Sderaadt 	    ((long *)hwrpb->rpb_ssn)[0], ((long *)hwrpb->rpb_ssn)[1]);
1085df930be7Sderaadt 
1086df930be7Sderaadt 	/* and these aren't particularly useful! */
1087df930be7Sderaadt 	printf("variation: 0x%lx, revision 0x%lx\n",
1088df930be7Sderaadt 	    hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
1089df930be7Sderaadt #endif
1090df930be7Sderaadt }
1091df930be7Sderaadt 
1092df930be7Sderaadt int	waittime = -1;
1093df930be7Sderaadt struct pcb dumppcb;
1094df930be7Sderaadt 
1095417eba8cSderaadt void
1096aed035abSart boot(howto)
1097df930be7Sderaadt 	int howto;
1098df930be7Sderaadt {
1099aed035abSart #if defined(MULTIPROCESSOR)
1100aed035abSart #if 0 /* XXX See below. */
1101aed035abSart 	u_long cpu_id;
1102aed035abSart #endif
1103aed035abSart #endif
1104aed035abSart 
1105aed035abSart #if defined(MULTIPROCESSOR)
1106aed035abSart 	/* We must be running on the primary CPU. */
1107aed035abSart 	if (alpha_pal_whami() != hwrpb->rpb_primary_cpu_id)
1108aed035abSart 		panic("cpu_reboot: not on primary CPU!");
1109aed035abSart #endif
1110aed035abSart 
1111df930be7Sderaadt 	/* If system is cold, just halt. */
1112df930be7Sderaadt 	if (cold) {
1113df930be7Sderaadt 		howto |= RB_HALT;
1114df930be7Sderaadt 		goto haltsys;
1115df930be7Sderaadt 	}
1116df930be7Sderaadt 
111750ce9ee0Sniklas 	/* If "always halt" was specified as a boot flag, obey. */
111850ce9ee0Sniklas 	if ((boothowto & RB_HALT) != 0)
111950ce9ee0Sniklas 		howto |= RB_HALT;
112050ce9ee0Sniklas 
1121df930be7Sderaadt 	boothowto = howto;
1122df930be7Sderaadt 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1123df930be7Sderaadt 		waittime = 0;
1124df930be7Sderaadt 		vfs_shutdown();
1125df930be7Sderaadt 		/*
1126df930be7Sderaadt 		 * If we've been adjusting the clock, the todr
1127aed035abSart 		 * will be out of synch; adjust it now.
1128df930be7Sderaadt 		 */
1129df930be7Sderaadt 		resettodr();
1130df930be7Sderaadt 	}
1131df930be7Sderaadt 
1132df930be7Sderaadt 	/* Disable interrupts. */
1133df930be7Sderaadt 	splhigh();
1134df930be7Sderaadt 
1135df930be7Sderaadt 	/* If rebooting and a dump is requested do it. */
113650ce9ee0Sniklas 	if (howto & RB_DUMP)
1137df930be7Sderaadt 		dumpsys();
1138df930be7Sderaadt 
113934fbf6deSderaadt haltsys:
114034fbf6deSderaadt 
1141df930be7Sderaadt 	/* run any shutdown hooks */
1142df930be7Sderaadt 	doshutdownhooks();
1143df930be7Sderaadt 
1144aed035abSart #if defined(MULTIPROCESSOR)
1145aed035abSart #if 0 /* XXX doesn't work when called from here?! */
1146aed035abSart 	/* Kill off any secondary CPUs. */
1147aed035abSart 	for (cpu_id = 0; cpu_id < hwrpb->rpb_pcs_cnt; cpu_id++) {
1148aed035abSart 		if (cpu_id == hwrpb->rpb_primary_cpu_id ||
1149aed035abSart 		    cpu_info[cpu_id].ci_softc == NULL)
1150aed035abSart 			continue;
1151aed035abSart 		cpu_halt_secondary(cpu_id);
1152aed035abSart 	}
1153aed035abSart #endif
1154aed035abSart #endif
1155aed035abSart 
1156df930be7Sderaadt #ifdef BOOTKEY
1157df930be7Sderaadt 	printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
1158aed035abSart 	cnpollc(1);	/* for proper keyboard command handling */
1159df930be7Sderaadt 	cngetc();
1160aed035abSart 	cnpollc(0);
1161df930be7Sderaadt 	printf("\n");
1162df930be7Sderaadt #endif
1163df930be7Sderaadt 
1164aed035abSart 	/* Finally, powerdown/halt/reboot the system. */
1165aed035abSart 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN &&
1166aed035abSart 	    platform.powerdown != NULL) {
1167aed035abSart 		(*platform.powerdown)();
1168aed035abSart 		printf("WARNING: powerdown failed!\n");
1169aed035abSart 	}
1170df930be7Sderaadt 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
1171df930be7Sderaadt 	prom_halt(howto & RB_HALT);
1172df930be7Sderaadt 	/*NOTREACHED*/
1173df930be7Sderaadt }
1174df930be7Sderaadt 
1175df930be7Sderaadt /*
1176df930be7Sderaadt  * These variables are needed by /sbin/savecore
1177df930be7Sderaadt  */
1178df930be7Sderaadt u_long	dumpmag = 0x8fca0101;	/* magic number */
1179df930be7Sderaadt int 	dumpsize = 0;		/* pages */
1180df930be7Sderaadt long	dumplo = 0; 		/* blocks */
1181df930be7Sderaadt 
1182df930be7Sderaadt /*
118350ce9ee0Sniklas  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
118450ce9ee0Sniklas  */
118550ce9ee0Sniklas int
118650ce9ee0Sniklas cpu_dumpsize()
118750ce9ee0Sniklas {
118850ce9ee0Sniklas 	int size;
118950ce9ee0Sniklas 
1190aed035abSart 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
1191aed035abSart 	    ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
119250ce9ee0Sniklas 	if (roundup(size, dbtob(1)) != dbtob(1))
119350ce9ee0Sniklas 		return -1;
119450ce9ee0Sniklas 
119550ce9ee0Sniklas 	return (1);
119650ce9ee0Sniklas }
119750ce9ee0Sniklas 
119850ce9ee0Sniklas /*
1199aed035abSart  * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped.
1200aed035abSart  */
1201aed035abSart u_long
1202aed035abSart cpu_dump_mempagecnt()
1203aed035abSart {
1204aed035abSart 	u_long i, n;
1205aed035abSart 
1206aed035abSart 	n = 0;
1207aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++)
1208aed035abSart 		n += atop(mem_clusters[i].size);
1209aed035abSart 	return (n);
1210aed035abSart }
1211aed035abSart 
1212aed035abSart /*
121350ce9ee0Sniklas  * cpu_dump: dump machine-dependent kernel core dump headers.
121450ce9ee0Sniklas  */
121550ce9ee0Sniklas int
121650ce9ee0Sniklas cpu_dump()
121750ce9ee0Sniklas {
1218c4071fd1Smillert 	int (*dump)(dev_t, daddr_t, caddr_t, size_t);
1219aed035abSart 	char buf[dbtob(1)];
122050ce9ee0Sniklas 	kcore_seg_t *segp;
122150ce9ee0Sniklas 	cpu_kcore_hdr_t *cpuhdrp;
1222aed035abSart 	phys_ram_seg_t *memsegp;
1223aed035abSart 	int i;
122450ce9ee0Sniklas 
122550ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
122650ce9ee0Sniklas 
1227aed035abSart 	bzero(buf, sizeof buf);
122850ce9ee0Sniklas 	segp = (kcore_seg_t *)buf;
1229aed035abSart 	cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
1230aed035abSart 	memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) +
1231aed035abSart 	    ALIGN(sizeof(*cpuhdrp))];
123250ce9ee0Sniklas 
123350ce9ee0Sniklas 	/*
123450ce9ee0Sniklas 	 * Generate a segment header.
123550ce9ee0Sniklas 	 */
123650ce9ee0Sniklas 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
123750ce9ee0Sniklas 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
123850ce9ee0Sniklas 
123950ce9ee0Sniklas 	/*
1240aed035abSart 	 * Add the machine-dependent header info.
124150ce9ee0Sniklas 	 */
1242aed035abSart 	cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map);
124350ce9ee0Sniklas 	cpuhdrp->page_size = PAGE_SIZE;
1244aed035abSart 	cpuhdrp->nmemsegs = mem_cluster_cnt;
1245aed035abSart 
1246aed035abSart 	/*
1247aed035abSart 	 * Fill in the memory segment descriptors.
1248aed035abSart 	 */
1249aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
1250aed035abSart 		memsegp[i].start = mem_clusters[i].start;
1251aed035abSart 		memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK;
1252aed035abSart 	}
125350ce9ee0Sniklas 
125450ce9ee0Sniklas 	return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
125550ce9ee0Sniklas }
125650ce9ee0Sniklas 
125750ce9ee0Sniklas /*
1258aed035abSart  * This is called by main to set dumplo and dumpsize.
1259aed035abSart  * Dumps always skip the first NBPG of disk space
1260df930be7Sderaadt  * in case there might be a disk label stored there.
1261df930be7Sderaadt  * If there is extra space, put dump at the end to
1262df930be7Sderaadt  * reduce the chance that swapping trashes it.
1263df930be7Sderaadt  */
1264df930be7Sderaadt void
1265df930be7Sderaadt dumpconf()
1266df930be7Sderaadt {
126750ce9ee0Sniklas 	int nblks, dumpblks;	/* size of dump area */
1268df930be7Sderaadt 	int maj;
1269df930be7Sderaadt 
1270df930be7Sderaadt 	if (dumpdev == NODEV)
127150ce9ee0Sniklas 		goto bad;
1272df930be7Sderaadt 	maj = major(dumpdev);
1273df930be7Sderaadt 	if (maj < 0 || maj >= nblkdev)
1274df930be7Sderaadt 		panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1275df930be7Sderaadt 	if (bdevsw[maj].d_psize == NULL)
127650ce9ee0Sniklas 		goto bad;
1277df930be7Sderaadt 	nblks = (*bdevsw[maj].d_psize)(dumpdev);
1278df930be7Sderaadt 	if (nblks <= ctod(1))
127950ce9ee0Sniklas 		goto bad;
128050ce9ee0Sniklas 
128150ce9ee0Sniklas 	dumpblks = cpu_dumpsize();
128250ce9ee0Sniklas 	if (dumpblks < 0)
128350ce9ee0Sniklas 		goto bad;
1284aed035abSart 	dumpblks += ctod(cpu_dump_mempagecnt());
128550ce9ee0Sniklas 
128650ce9ee0Sniklas 	/* If dump won't fit (incl. room for possible label), punt. */
128750ce9ee0Sniklas 	if (dumpblks > (nblks - ctod(1)))
128850ce9ee0Sniklas 		goto bad;
128950ce9ee0Sniklas 
129050ce9ee0Sniklas 	/* Put dump at end of partition */
129150ce9ee0Sniklas 	dumplo = nblks - dumpblks;
129250ce9ee0Sniklas 
129350ce9ee0Sniklas 	/* dumpsize is in page units, and doesn't include headers. */
1294aed035abSart 	dumpsize = cpu_dump_mempagecnt();
1295df930be7Sderaadt 	return;
1296df930be7Sderaadt 
129750ce9ee0Sniklas bad:
129850ce9ee0Sniklas 	dumpsize = 0;
129950ce9ee0Sniklas 	return;
1300df930be7Sderaadt }
1301df930be7Sderaadt 
1302df930be7Sderaadt /*
130350ce9ee0Sniklas  * Dump the kernel's image to the swap partition.
1304df930be7Sderaadt  */
130550ce9ee0Sniklas #define	BYTES_PER_DUMP	NBPG
130650ce9ee0Sniklas 
1307df930be7Sderaadt void
1308df930be7Sderaadt dumpsys()
1309df930be7Sderaadt {
1310aed035abSart 	u_long totalbytesleft, bytes, i, n, memcl;
1311aed035abSart 	u_long maddr;
1312aed035abSart 	int psize;
131350ce9ee0Sniklas 	daddr_t blkno;
1314c4071fd1Smillert 	int (*dump)(dev_t, daddr_t, caddr_t, size_t);
131550ce9ee0Sniklas 	int error;
1316067cbd75Sderaadt 	extern int msgbufmapped;
1317df930be7Sderaadt 
131850ce9ee0Sniklas 	/* Save registers. */
131950ce9ee0Sniklas 	savectx(&dumppcb);
132050ce9ee0Sniklas 
132150ce9ee0Sniklas 	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
1322df930be7Sderaadt 	if (dumpdev == NODEV)
1323df930be7Sderaadt 		return;
132450ce9ee0Sniklas 
132550ce9ee0Sniklas 	/*
132650ce9ee0Sniklas 	 * For dumps during autoconfiguration,
132750ce9ee0Sniklas 	 * if dump device has already configured...
132850ce9ee0Sniklas 	 */
1329df930be7Sderaadt 	if (dumpsize == 0)
133050ce9ee0Sniklas 		dumpconf();
133150ce9ee0Sniklas 	if (dumplo <= 0) {
1332aed035abSart 		printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
1333aed035abSart 		    minor(dumpdev));
1334df930be7Sderaadt 		return;
1335df930be7Sderaadt 	}
1336aed035abSart 	printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
1337aed035abSart 	    minor(dumpdev), dumplo);
1338df930be7Sderaadt 
133950ce9ee0Sniklas 	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1340df930be7Sderaadt 	printf("dump ");
134150ce9ee0Sniklas 	if (psize == -1) {
134250ce9ee0Sniklas 		printf("area unavailable\n");
134350ce9ee0Sniklas 		return;
134450ce9ee0Sniklas 	}
134550ce9ee0Sniklas 
134650ce9ee0Sniklas 	/* XXX should purge all outstanding keystrokes. */
134750ce9ee0Sniklas 
134850ce9ee0Sniklas 	if ((error = cpu_dump()) != 0)
134950ce9ee0Sniklas 		goto err;
135050ce9ee0Sniklas 
1351aed035abSart 	totalbytesleft = ptoa(cpu_dump_mempagecnt());
135250ce9ee0Sniklas 	blkno = dumplo + cpu_dumpsize();
135350ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
135450ce9ee0Sniklas 	error = 0;
1355aed035abSart 
1356aed035abSart 	for (memcl = 0; memcl < mem_cluster_cnt; memcl++) {
1357aed035abSart 		maddr = mem_clusters[memcl].start;
1358aed035abSart 		bytes = mem_clusters[memcl].size & ~PAGE_MASK;
1359aed035abSart 
1360aed035abSart 		for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
136150ce9ee0Sniklas 
136250ce9ee0Sniklas 			/* Print out how many MBs we to go. */
1363aed035abSart 			if ((totalbytesleft % (1024*1024)) == 0)
1364aed035abSart 				printf("%ld ", totalbytesleft / (1024 * 1024));
136550ce9ee0Sniklas 
136650ce9ee0Sniklas 			/* Limit size for next transfer. */
1367aed035abSart 			n = bytes - i;
136850ce9ee0Sniklas 			if (n > BYTES_PER_DUMP)
136950ce9ee0Sniklas 				n =  BYTES_PER_DUMP;
137050ce9ee0Sniklas 
137150ce9ee0Sniklas 			error = (*dump)(dumpdev, blkno,
137250ce9ee0Sniklas 			    (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n);
137350ce9ee0Sniklas 			if (error)
1374aed035abSart 				goto err;
137550ce9ee0Sniklas 			maddr += n;
137650ce9ee0Sniklas 			blkno += btodb(n);			/* XXX? */
137750ce9ee0Sniklas 
137850ce9ee0Sniklas 			/* XXX should look for keystrokes, to cancel. */
137950ce9ee0Sniklas 		}
1380aed035abSart 	}
138150ce9ee0Sniklas 
138250ce9ee0Sniklas err:
138350ce9ee0Sniklas 	switch (error) {
1384df930be7Sderaadt 
1385df930be7Sderaadt 	case ENXIO:
1386df930be7Sderaadt 		printf("device bad\n");
1387df930be7Sderaadt 		break;
1388df930be7Sderaadt 
1389df930be7Sderaadt 	case EFAULT:
1390df930be7Sderaadt 		printf("device not ready\n");
1391df930be7Sderaadt 		break;
1392df930be7Sderaadt 
1393df930be7Sderaadt 	case EINVAL:
1394df930be7Sderaadt 		printf("area improper\n");
1395df930be7Sderaadt 		break;
1396df930be7Sderaadt 
1397df930be7Sderaadt 	case EIO:
1398df930be7Sderaadt 		printf("i/o error\n");
1399df930be7Sderaadt 		break;
1400df930be7Sderaadt 
1401df930be7Sderaadt 	case EINTR:
1402df930be7Sderaadt 		printf("aborted from console\n");
1403df930be7Sderaadt 		break;
1404df930be7Sderaadt 
140550ce9ee0Sniklas 	case 0:
1406df930be7Sderaadt 		printf("succeeded\n");
1407df930be7Sderaadt 		break;
140850ce9ee0Sniklas 
140950ce9ee0Sniklas 	default:
141050ce9ee0Sniklas 		printf("error %d\n", error);
141150ce9ee0Sniklas 		break;
1412df930be7Sderaadt 	}
1413df930be7Sderaadt 	printf("\n\n");
1414df930be7Sderaadt 	delay(1000);
1415df930be7Sderaadt }
1416df930be7Sderaadt 
1417df930be7Sderaadt void
1418df930be7Sderaadt frametoreg(framep, regp)
1419df930be7Sderaadt 	struct trapframe *framep;
1420df930be7Sderaadt 	struct reg *regp;
1421df930be7Sderaadt {
1422df930be7Sderaadt 
1423df930be7Sderaadt 	regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
1424df930be7Sderaadt 	regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
1425df930be7Sderaadt 	regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
1426df930be7Sderaadt 	regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
1427df930be7Sderaadt 	regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
1428df930be7Sderaadt 	regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
1429df930be7Sderaadt 	regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
1430df930be7Sderaadt 	regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
1431df930be7Sderaadt 	regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
1432df930be7Sderaadt 	regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
1433df930be7Sderaadt 	regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
1434df930be7Sderaadt 	regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
1435df930be7Sderaadt 	regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
1436df930be7Sderaadt 	regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
1437df930be7Sderaadt 	regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
1438df930be7Sderaadt 	regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
143950ce9ee0Sniklas 	regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0];
144050ce9ee0Sniklas 	regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1];
144150ce9ee0Sniklas 	regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2];
1442df930be7Sderaadt 	regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
1443df930be7Sderaadt 	regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
1444df930be7Sderaadt 	regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
1445df930be7Sderaadt 	regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
1446df930be7Sderaadt 	regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
1447df930be7Sderaadt 	regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
1448df930be7Sderaadt 	regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
1449df930be7Sderaadt 	regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
1450df930be7Sderaadt 	regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
1451df930be7Sderaadt 	regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
145250ce9ee0Sniklas 	regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP];
145350ce9ee0Sniklas 	/* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */
1454df930be7Sderaadt 	regp->r_regs[R_ZERO] = 0;
1455df930be7Sderaadt }
1456df930be7Sderaadt 
1457df930be7Sderaadt void
1458df930be7Sderaadt regtoframe(regp, framep)
1459df930be7Sderaadt 	struct reg *regp;
1460df930be7Sderaadt 	struct trapframe *framep;
1461df930be7Sderaadt {
1462df930be7Sderaadt 
1463df930be7Sderaadt 	framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
1464df930be7Sderaadt 	framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
1465df930be7Sderaadt 	framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
1466df930be7Sderaadt 	framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
1467df930be7Sderaadt 	framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
1468df930be7Sderaadt 	framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
1469df930be7Sderaadt 	framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
1470df930be7Sderaadt 	framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
1471df930be7Sderaadt 	framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
1472df930be7Sderaadt 	framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
1473df930be7Sderaadt 	framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
1474df930be7Sderaadt 	framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
1475df930be7Sderaadt 	framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
1476df930be7Sderaadt 	framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
1477df930be7Sderaadt 	framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
1478df930be7Sderaadt 	framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
147950ce9ee0Sniklas 	framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0];
148050ce9ee0Sniklas 	framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1];
148150ce9ee0Sniklas 	framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2];
1482df930be7Sderaadt 	framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
1483df930be7Sderaadt 	framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
1484df930be7Sderaadt 	framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
1485df930be7Sderaadt 	framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
1486df930be7Sderaadt 	framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
1487df930be7Sderaadt 	framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
1488df930be7Sderaadt 	framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
1489df930be7Sderaadt 	framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
1490df930be7Sderaadt 	framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
1491df930be7Sderaadt 	framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
149250ce9ee0Sniklas 	framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP];
149350ce9ee0Sniklas 	/* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */
1494df930be7Sderaadt 	/* ??? = regp->r_regs[R_ZERO]; */
1495df930be7Sderaadt }
1496df930be7Sderaadt 
1497df930be7Sderaadt void
1498df930be7Sderaadt printregs(regp)
1499df930be7Sderaadt 	struct reg *regp;
1500df930be7Sderaadt {
1501df930be7Sderaadt 	int i;
1502df930be7Sderaadt 
1503df930be7Sderaadt 	for (i = 0; i < 32; i++)
1504df930be7Sderaadt 		printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
1505df930be7Sderaadt 		   i & 1 ? "\n" : "\t");
1506df930be7Sderaadt }
1507df930be7Sderaadt 
1508df930be7Sderaadt void
1509df930be7Sderaadt regdump(framep)
1510df930be7Sderaadt 	struct trapframe *framep;
1511df930be7Sderaadt {
1512df930be7Sderaadt 	struct reg reg;
1513df930be7Sderaadt 
1514df930be7Sderaadt 	frametoreg(framep, &reg);
151550ce9ee0Sniklas 	reg.r_regs[R_SP] = alpha_pal_rdusp();
151650ce9ee0Sniklas 
1517df930be7Sderaadt 	printf("REGISTERS:\n");
1518df930be7Sderaadt 	printregs(&reg);
1519df930be7Sderaadt }
1520df930be7Sderaadt 
1521df930be7Sderaadt #ifdef DEBUG
1522df930be7Sderaadt int sigdebug = 0;
1523df930be7Sderaadt int sigpid = 0;
1524df930be7Sderaadt #define	SDB_FOLLOW	0x01
1525df930be7Sderaadt #define	SDB_KSTACK	0x02
1526df930be7Sderaadt #endif
1527df930be7Sderaadt 
1528df930be7Sderaadt /*
1529df930be7Sderaadt  * Send an interrupt to process.
1530df930be7Sderaadt  */
1531df930be7Sderaadt void
15325e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val)
1533df930be7Sderaadt 	sig_t catcher;
1534df930be7Sderaadt 	int sig, mask;
1535df930be7Sderaadt 	u_long code;
15365e1760a6Sderaadt 	int type;
15375e1760a6Sderaadt 	union sigval val;
1538df930be7Sderaadt {
1539df930be7Sderaadt 	struct proc *p = curproc;
1540df930be7Sderaadt 	struct sigcontext *scp, ksc;
1541df930be7Sderaadt 	struct trapframe *frame;
1542df930be7Sderaadt 	struct sigacts *psp = p->p_sigacts;
15432bf9c155Sderaadt 	int oonstack, fsize, rndfsize, kscsize;
15442bf9c155Sderaadt 	siginfo_t *sip, ksi;
1545df930be7Sderaadt 
1546df930be7Sderaadt 	frame = p->p_md.md_tf;
1547df930be7Sderaadt 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
1548df930be7Sderaadt 	fsize = sizeof ksc;
1549df930be7Sderaadt 	rndfsize = ((fsize + 15) / 16) * 16;
15502bf9c155Sderaadt 	kscsize = rndfsize;
15512bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
15522bf9c155Sderaadt 		fsize += sizeof ksi;
15532bf9c155Sderaadt 		rndfsize = ((fsize + 15) / 16) * 16;
15542bf9c155Sderaadt 	}
155574652a67Sniklas 
1556df930be7Sderaadt 	/*
1557df930be7Sderaadt 	 * Allocate and validate space for the signal handler
1558df930be7Sderaadt 	 * context. Note that if the stack is in P0 space, the
1559aed035abSart 	 * call to uvm_grow() is a nop, and the useracc() check
1560df930be7Sderaadt 	 * will fail if the process has not already allocated
1561df930be7Sderaadt 	 * the space with a `brk'.
1562df930be7Sderaadt 	 */
1563df930be7Sderaadt 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
1564df930be7Sderaadt 	    (psp->ps_sigonstack & sigmask(sig))) {
15658bc2093aSderaadt 		scp = (struct sigcontext *)(psp->ps_sigstk.ss_sp +
1566df930be7Sderaadt 		    psp->ps_sigstk.ss_size - rndfsize);
1567df930be7Sderaadt 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
1568df930be7Sderaadt 	} else
156950ce9ee0Sniklas 		scp = (struct sigcontext *)(alpha_pal_rdusp() - rndfsize);
1570df930be7Sderaadt 	if ((u_long)scp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
1571aed035abSart 		(void)uvm_grow(p, (u_long)scp);
1572df930be7Sderaadt #ifdef DEBUG
1573df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
157450ce9ee0Sniklas 		printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
1575df930be7Sderaadt 		    sig, &oonstack, scp);
1576df930be7Sderaadt #endif
1577aed035abSart 	if (uvm_useracc((caddr_t)scp, fsize, B_WRITE) == 0) {
1578df930be7Sderaadt #ifdef DEBUG
1579df930be7Sderaadt 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1580aed035abSart 			printf("sendsig(%d): uvm_useracc failed on sig %d\n",
1581df930be7Sderaadt 			    p->p_pid, sig);
1582df930be7Sderaadt #endif
1583df930be7Sderaadt 		/*
1584df930be7Sderaadt 		 * Process has trashed its stack; give it an illegal
1585df930be7Sderaadt 		 * instruction to halt it in its tracks.
1586df930be7Sderaadt 		 */
1587df930be7Sderaadt 		SIGACTION(p, SIGILL) = SIG_DFL;
1588df930be7Sderaadt 		sig = sigmask(SIGILL);
1589df930be7Sderaadt 		p->p_sigignore &= ~sig;
1590df930be7Sderaadt 		p->p_sigcatch &= ~sig;
1591df930be7Sderaadt 		p->p_sigmask &= ~sig;
1592df930be7Sderaadt 		psignal(p, SIGILL);
1593df930be7Sderaadt 		return;
1594df930be7Sderaadt 	}
1595df930be7Sderaadt 
1596df930be7Sderaadt 	/*
1597df930be7Sderaadt 	 * Build the signal context to be used by sigreturn.
1598df930be7Sderaadt 	 */
1599df930be7Sderaadt 	ksc.sc_onstack = oonstack;
1600df930be7Sderaadt 	ksc.sc_mask = mask;
160150ce9ee0Sniklas 	ksc.sc_pc = frame->tf_regs[FRAME_PC];
160250ce9ee0Sniklas 	ksc.sc_ps = frame->tf_regs[FRAME_PS];
1603df930be7Sderaadt 
1604df930be7Sderaadt 	/* copy the registers. */
1605df930be7Sderaadt 	frametoreg(frame, (struct reg *)ksc.sc_regs);
1606df930be7Sderaadt 	ksc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
160750ce9ee0Sniklas 	ksc.sc_regs[R_SP] = alpha_pal_rdusp();
1608df930be7Sderaadt 
1609df930be7Sderaadt 	/* save the floating-point state, if necessary, then copy it. */
1610433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1611433075b6Spvalchev 		fpusave_proc(p, 1);
1612df930be7Sderaadt 	ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
1613433075b6Spvalchev 	memcpy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
1614df930be7Sderaadt 	    sizeof(struct fpreg));
1615433075b6Spvalchev #ifndef NO_IEEE
1616433075b6Spvalchev 	ksc.sc_fp_control = alpha_read_fp_c(p);
1617433075b6Spvalchev #else
1618433075b6Spvalchev 	ksc.sc_fp_control = 0;
1619433075b6Spvalchev #endif
1620433075b6Spvalchev 	memset(ksc.sc_reserved, 0, sizeof ksc.sc_reserved);	/* XXX */
1621433075b6Spvalchev 	memset(ksc.sc_xxx, 0, sizeof ksc.sc_xxx);		/* XXX */
1622df930be7Sderaadt 
1623df930be7Sderaadt #ifdef COMPAT_OSF1
1624df930be7Sderaadt 	/*
1625df930be7Sderaadt 	 * XXX Create an OSF/1-style sigcontext and associated goo.
1626df930be7Sderaadt 	 */
1627df930be7Sderaadt #endif
1628df930be7Sderaadt 
16292bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
16302bf9c155Sderaadt 		initsiginfo(&ksi, sig, code, type, val);
16312bf9c155Sderaadt 		sip = (void *)scp + kscsize;
16322bf9c155Sderaadt 		(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize);
16332bf9c155Sderaadt 	}
16342bf9c155Sderaadt 
1635df930be7Sderaadt 	/*
1636df930be7Sderaadt 	 * copy the frame out to userland.
1637df930be7Sderaadt 	 */
16382bf9c155Sderaadt 	(void) copyout((caddr_t)&ksc, (caddr_t)scp, kscsize);
1639df930be7Sderaadt #ifdef DEBUG
1640df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
164150ce9ee0Sniklas 		printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig,
1642df930be7Sderaadt 		    scp, code);
1643df930be7Sderaadt #endif
1644df930be7Sderaadt 
1645df930be7Sderaadt 	/*
1646df930be7Sderaadt 	 * Set up the registers to return to sigcode.
1647df930be7Sderaadt 	 */
16484a5480feSart 	frame->tf_regs[FRAME_PC] = p->p_sigcode;
164950ce9ee0Sniklas 	frame->tf_regs[FRAME_A0] = sig;
16502bf9c155Sderaadt 	frame->tf_regs[FRAME_A1] = (psp->ps_siginfo & sigmask(sig)) ?
16512bf9c155Sderaadt 	    (u_int64_t)sip : NULL;
165250ce9ee0Sniklas 	frame->tf_regs[FRAME_A2] = (u_int64_t)scp;
1653df930be7Sderaadt 	frame->tf_regs[FRAME_T12] = (u_int64_t)catcher;		/* t12 is pv */
165450ce9ee0Sniklas 	alpha_pal_wrusp((unsigned long)scp);
1655df930be7Sderaadt 
1656df930be7Sderaadt #ifdef DEBUG
1657df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1658df930be7Sderaadt 		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
165950ce9ee0Sniklas 		    frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]);
1660df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1661df930be7Sderaadt 		printf("sendsig(%d): sig %d returns\n",
1662df930be7Sderaadt 		    p->p_pid, sig);
1663df930be7Sderaadt #endif
1664df930be7Sderaadt }
1665df930be7Sderaadt 
1666df930be7Sderaadt /*
1667df930be7Sderaadt  * System call to cleanup state after a signal
1668df930be7Sderaadt  * has been taken.  Reset signal mask and
1669df930be7Sderaadt  * stack state from context left by sendsig (above).
1670df930be7Sderaadt  * Return to previous pc and psl as specified by
1671df930be7Sderaadt  * context left by sendsig. Check carefully to
1672df930be7Sderaadt  * make sure that the user has not modified the
1673125cd19fSderaadt  * psl to gain improper privileges or to cause
1674df930be7Sderaadt  * a machine fault.
1675df930be7Sderaadt  */
1676df930be7Sderaadt /* ARGSUSED */
1677df930be7Sderaadt int
1678df930be7Sderaadt sys_sigreturn(p, v, retval)
1679df930be7Sderaadt 	struct proc *p;
1680df930be7Sderaadt 	void *v;
1681df930be7Sderaadt 	register_t *retval;
1682df930be7Sderaadt {
1683df930be7Sderaadt 	struct sys_sigreturn_args /* {
1684df930be7Sderaadt 		syscallarg(struct sigcontext *) sigcntxp;
1685df930be7Sderaadt 	} */ *uap = v;
1686df930be7Sderaadt 	struct sigcontext *scp, ksc;
1687df930be7Sderaadt 
1688df930be7Sderaadt 	scp = SCARG(uap, sigcntxp);
1689df930be7Sderaadt #ifdef DEBUG
1690df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
169150ce9ee0Sniklas 	    printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
1692df930be7Sderaadt #endif
1693df930be7Sderaadt 
1694df930be7Sderaadt 	if (ALIGN(scp) != (u_int64_t)scp)
1695df930be7Sderaadt 		return (EINVAL);
1696df930be7Sderaadt 
1697df930be7Sderaadt 	/*
1698df930be7Sderaadt 	 * Test and fetch the context structure.
1699df930be7Sderaadt 	 * We grab it all at once for speed.
1700df930be7Sderaadt 	 */
1701aed035abSart 	if (uvm_useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
1702df930be7Sderaadt 	    copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
1703df930be7Sderaadt 		return (EINVAL);
1704df930be7Sderaadt 
1705df930be7Sderaadt 	if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)		/* magic number */
1706df930be7Sderaadt 		return (EINVAL);
1707df930be7Sderaadt 	/*
1708df930be7Sderaadt 	 * Restore the user-supplied information
1709df930be7Sderaadt 	 */
1710df930be7Sderaadt 	if (ksc.sc_onstack)
1711df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
1712df930be7Sderaadt 	else
1713df930be7Sderaadt 		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1714df930be7Sderaadt 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1715df930be7Sderaadt 
171650ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
171750ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PS] =
171850ce9ee0Sniklas 	    (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
1719df930be7Sderaadt 
1720df930be7Sderaadt 	regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
172150ce9ee0Sniklas 	alpha_pal_wrusp(ksc.sc_regs[R_SP]);
1722df930be7Sderaadt 
1723df930be7Sderaadt 	/* XXX ksc.sc_ownedfp ? */
1724433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1725433075b6Spvalchev 		fpusave_proc(p, 0);
1726433075b6Spvalchev 	memcpy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksc.sc_fpregs,
1727df930be7Sderaadt 	    sizeof(struct fpreg));
1728433075b6Spvalchev #ifndef NO_IEEE
1729433075b6Spvalchev 	p->p_addr->u_pcb.pcb_fp.fpr_cr = ksc.sc_fpcr;
1730433075b6Spvalchev 	p->p_md.md_flags = ksc.sc_fp_control & MDP_FP_C;
1731433075b6Spvalchev #endif
1732df930be7Sderaadt 
1733df930be7Sderaadt #ifdef DEBUG
1734df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1735df930be7Sderaadt 		printf("sigreturn(%d): returns\n", p->p_pid);
1736df930be7Sderaadt #endif
1737df930be7Sderaadt 	return (EJUSTRETURN);
1738df930be7Sderaadt }
1739df930be7Sderaadt 
1740df930be7Sderaadt /*
1741df930be7Sderaadt  * machine dependent system variables.
1742df930be7Sderaadt  */
174350ce9ee0Sniklas int
1744df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1745df930be7Sderaadt 	int *name;
1746df930be7Sderaadt 	u_int namelen;
1747df930be7Sderaadt 	void *oldp;
1748df930be7Sderaadt 	size_t *oldlenp;
1749df930be7Sderaadt 	void *newp;
1750df930be7Sderaadt 	size_t newlen;
1751df930be7Sderaadt 	struct proc *p;
1752df930be7Sderaadt {
1753df930be7Sderaadt 	dev_t consdev;
1754df930be7Sderaadt 
175545e5a1a0Sart 	if (name[0] != CPU_CHIPSET && namelen != 1)
1756df930be7Sderaadt 		return (ENOTDIR);		/* overloaded */
1757df930be7Sderaadt 
1758df930be7Sderaadt 	switch (name[0]) {
1759df930be7Sderaadt 	case CPU_CONSDEV:
1760df930be7Sderaadt 		if (cn_tab != NULL)
1761df930be7Sderaadt 			consdev = cn_tab->cn_dev;
1762df930be7Sderaadt 		else
1763df930be7Sderaadt 			consdev = NODEV;
1764df930be7Sderaadt 		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1765df930be7Sderaadt 			sizeof consdev));
1766417eba8cSderaadt 
1767417eba8cSderaadt 	case CPU_ROOT_DEVICE:
1768aed035abSart 		return (sysctl_rdstring(oldp, oldlenp, newp,
1769aed035abSart 		    root_device));
1770417eba8cSderaadt 
177150ce9ee0Sniklas 	case CPU_UNALIGNED_PRINT:
177250ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
177350ce9ee0Sniklas 		    &alpha_unaligned_print));
177450ce9ee0Sniklas 
177550ce9ee0Sniklas 	case CPU_UNALIGNED_FIX:
177650ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
177750ce9ee0Sniklas 		    &alpha_unaligned_fix));
177850ce9ee0Sniklas 
177950ce9ee0Sniklas 	case CPU_UNALIGNED_SIGBUS:
178050ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
178150ce9ee0Sniklas 		    &alpha_unaligned_sigbus));
178250ce9ee0Sniklas 
17833a630e3fSniklas 	case CPU_BOOTED_KERNEL:
1784aed035abSart 		return (sysctl_rdstring(oldp, oldlenp, newp,
1785aed035abSart 		    bootinfo.booted_kernel));
17863a630e3fSniklas 
178745e5a1a0Sart 	case CPU_CHIPSET:
178845e5a1a0Sart 		return (alpha_sysctl_chipset(name + 1, namelen - 1, oldp,
178945e5a1a0Sart 		    oldlenp));
1790433075b6Spvalchev 
1791433075b6Spvalchev #ifndef NO_IEEE
1792433075b6Spvalchev 	case CPU_FP_SYNC_COMPLETE:
1793433075b6Spvalchev 		return (sysctl_int(oldp, oldlenp, newp, newlen,
1794433075b6Spvalchev 		    &alpha_fp_sync_complete));
1795433075b6Spvalchev #endif
1796*27626149Smatthieu 	case CPU_ALLOWAPERTURE:
1797*27626149Smatthieu #ifdef APERTURE
1798*27626149Smatthieu 		if (securelevel > 0)
1799*27626149Smatthieu                         return (sysctl_rdint(oldp, oldlenp, newp,
1800*27626149Smatthieu 				 allowaperture));
1801*27626149Smatthieu                 else
1802*27626149Smatthieu                         return (sysctl_int(oldp, oldlenp, newp, newlen,
1803*27626149Smatthieu                             &allowaperture));
1804*27626149Smatthieu #else
1805*27626149Smatthieu 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
1806*27626149Smatthieu #endif
1807df930be7Sderaadt 	default:
1808df930be7Sderaadt 		return (EOPNOTSUPP);
1809df930be7Sderaadt 	}
1810df930be7Sderaadt 	/* NOTREACHED */
1811df930be7Sderaadt }
1812df930be7Sderaadt 
1813df930be7Sderaadt /*
1814df930be7Sderaadt  * Set registers on exec.
1815df930be7Sderaadt  */
1816df930be7Sderaadt void
1817df930be7Sderaadt setregs(p, pack, stack, retval)
1818df930be7Sderaadt 	register struct proc *p;
1819df930be7Sderaadt 	struct exec_package *pack;
1820df930be7Sderaadt 	u_long stack;
1821df930be7Sderaadt 	register_t *retval;
1822df930be7Sderaadt {
1823df930be7Sderaadt 	struct trapframe *tfp = p->p_md.md_tf;
18243a630e3fSniklas #ifdef DEBUG
18253a630e3fSniklas 	int i;
18263a630e3fSniklas #endif
1827df930be7Sderaadt 
1828df930be7Sderaadt #ifdef DEBUG
182950ce9ee0Sniklas 	/*
183050ce9ee0Sniklas 	 * Crash and dump, if the user requested it.
183150ce9ee0Sniklas 	 */
183250ce9ee0Sniklas 	if (boothowto & RB_DUMP)
183350ce9ee0Sniklas 		panic("crash requested by boot flags");
183450ce9ee0Sniklas #endif
183550ce9ee0Sniklas 
183650ce9ee0Sniklas #ifdef DEBUG
183750ce9ee0Sniklas 	for (i = 0; i < FRAME_SIZE; i++)
1838df930be7Sderaadt 		tfp->tf_regs[i] = 0xbabefacedeadbeef;
1839df930be7Sderaadt #else
184050ce9ee0Sniklas 	bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
1841df930be7Sderaadt #endif
1842df930be7Sderaadt 	bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
184350ce9ee0Sniklas 	alpha_pal_wrusp(stack);
184450ce9ee0Sniklas 	tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
184550ce9ee0Sniklas 	tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
1846df930be7Sderaadt 
184750ce9ee0Sniklas 	tfp->tf_regs[FRAME_A0] = stack;
184850ce9ee0Sniklas 	/* a1 and a2 already zeroed */
184950ce9ee0Sniklas 	tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC];	/* a.k.a. PV */
185050ce9ee0Sniklas 
185150ce9ee0Sniklas 	p->p_md.md_flags &= ~MDP_FPUSED;
1852433075b6Spvalchev #ifndef NO_IEEE
1853433075b6Spvalchev 	if (__predict_true((p->p_md.md_flags & IEEE_INHERIT) == 0)) {
1854433075b6Spvalchev 		p->p_md.md_flags &= ~MDP_FP_C;
1855433075b6Spvalchev 		p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_DYN(FP_RN);
1856433075b6Spvalchev 	}
1857433075b6Spvalchev #endif
1858433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1859433075b6Spvalchev 		fpusave_proc(p, 0);
1860433075b6Spvalchev }
1861df930be7Sderaadt 
1862433075b6Spvalchev /*
1863433075b6Spvalchev  * Release the FPU.
1864433075b6Spvalchev  */
1865433075b6Spvalchev void
1866433075b6Spvalchev fpusave_cpu(struct cpu_info *ci, int save)
1867433075b6Spvalchev {
1868433075b6Spvalchev 	struct proc *p;
1869433075b6Spvalchev #if defined(MULTIPROCESSOR)
1870433075b6Spvalchev 	int s;
1871433075b6Spvalchev #endif
1872433075b6Spvalchev 
1873433075b6Spvalchev 	KDASSERT(ci == curcpu());
1874433075b6Spvalchev 
1875433075b6Spvalchev #if defined(MULTIPROCESSOR)
1876433075b6Spvalchev 	atomic_setbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
1877433075b6Spvalchev #endif
1878433075b6Spvalchev 
1879433075b6Spvalchev 	p = ci->ci_fpcurproc;
1880433075b6Spvalchev 	if (p == NULL)
1881433075b6Spvalchev 		goto out;
1882433075b6Spvalchev 
1883433075b6Spvalchev 	if (save) {
1884433075b6Spvalchev 		alpha_pal_wrfen(1);
1885433075b6Spvalchev 		savefpstate(&p->p_addr->u_pcb.pcb_fp);
1886433075b6Spvalchev 	}
1887433075b6Spvalchev 
1888433075b6Spvalchev 	alpha_pal_wrfen(0);
1889433075b6Spvalchev 
1890433075b6Spvalchev 	p->p_addr->u_pcb.pcb_fpcpu = NULL;
1891433075b6Spvalchev 	ci->ci_fpcurproc = NULL;
1892433075b6Spvalchev 
1893433075b6Spvalchev out:
1894433075b6Spvalchev #if defined(MULTIPROCESSOR)
1895433075b6Spvalchev 	atomic_clearbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
1896433075b6Spvalchev #endif
1897433075b6Spvalchev 	return;
1898433075b6Spvalchev }
1899433075b6Spvalchev 
1900433075b6Spvalchev /*
1901433075b6Spvalchev  * Synchronize FP state for this process.
1902433075b6Spvalchev  */
1903433075b6Spvalchev void
1904433075b6Spvalchev fpusave_proc(struct proc *p, int save)
1905433075b6Spvalchev {
1906433075b6Spvalchev 	struct cpu_info *ci = curcpu();
1907433075b6Spvalchev 	struct cpu_info *oci;
1908433075b6Spvalchev #if defined(MULTIPROCESSOR)
1909433075b6Spvalchev 	u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU;
1910433075b6Spvalchev 	int s, spincount;
1911433075b6Spvalchev #endif
1912433075b6Spvalchev 
1913433075b6Spvalchev 	KDASSERT(p->p_addr != NULL);
1914433075b6Spvalchev 	KDASSERT(p->p_flag & P_INMEM);
1915433075b6Spvalchev 
1916433075b6Spvalchev 	oci = p->p_addr->u_pcb.pcb_fpcpu;
1917433075b6Spvalchev 	if (oci == NULL) {
1918433075b6Spvalchev 		return;
1919433075b6Spvalchev 	}
1920433075b6Spvalchev 
1921433075b6Spvalchev #if defined(MULTIPROCESSOR)
1922433075b6Spvalchev 	if (oci == ci) {
1923433075b6Spvalchev 		KASSERT(ci->ci_fpcurproc == p);
1924433075b6Spvalchev 		fpusave_cpu(ci, save);
1925433075b6Spvalchev 		return;
1926433075b6Spvalchev 	}
1927433075b6Spvalchev 
1928433075b6Spvalchev 	KASSERT(oci->ci_fpcurproc == p);
1929433075b6Spvalchev 	alpha_send_ipi(oci->ci_cpuid, ipi);
1930433075b6Spvalchev 
1931433075b6Spvalchev 	spincount = 0;
1932433075b6Spvalchev 	while (p->p_addr->u_pcb.pcb_fpcpu != NULL) {
1933433075b6Spvalchev 		spincount++;
1934433075b6Spvalchev 		delay(1000);    /* XXX */
1935433075b6Spvalchev 		if (spincount > 10000)
1936433075b6Spvalchev 			panic("fpsave ipi didn't");
1937433075b6Spvalchev 	}
1938433075b6Spvalchev #else
1939433075b6Spvalchev 	KASSERT(ci->ci_fpcurproc == p);
1940433075b6Spvalchev 	fpusave_cpu(ci, save);
1941433075b6Spvalchev #endif /* MULTIPROCESSOR */
1942df930be7Sderaadt }
1943df930be7Sderaadt 
1944df930be7Sderaadt int
1945df930be7Sderaadt spl0()
1946df930be7Sderaadt {
1947df930be7Sderaadt 
1948aed035abSart 	if (ssir) {
1949aed035abSart 		(void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT);
19502a2685f2Sart 		softintr_dispatch();
1951aed035abSart 	}
1952df930be7Sderaadt 
195350ce9ee0Sniklas 	return (alpha_pal_swpipl(ALPHA_PSL_IPL_0));
1954df930be7Sderaadt }
1955df930be7Sderaadt 
1956df930be7Sderaadt /*
1957df930be7Sderaadt  * The following primitives manipulate the run queues.  _whichqs tells which
1958df930be7Sderaadt  * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
1959e464495eSniklas  * into queues, Remrunqueue removes them from queues.  The running process is
1960e464495eSniklas  * on no queue, other processes are on a queue related to p->p_priority,
1961e464495eSniklas  * divided by 4 actually to shrink the 0-127 range of priorities into the 32
1962e464495eSniklas  * available queues.
1963df930be7Sderaadt  */
1964df930be7Sderaadt /*
1965df930be7Sderaadt  * setrunqueue(p)
1966df930be7Sderaadt  *	proc *p;
1967df930be7Sderaadt  *
1968df930be7Sderaadt  * Call should be made at splclock(), and p->p_stat should be SRUN.
1969df930be7Sderaadt  */
1970df930be7Sderaadt 
19712a2685f2Sart /* XXXART - grmble */
19722a2685f2Sart #define sched_qs qs
19732a2685f2Sart #define sched_whichqs whichqs
19742a2685f2Sart 
1975df930be7Sderaadt void
1976df930be7Sderaadt setrunqueue(p)
1977df930be7Sderaadt 	struct proc *p;
1978df930be7Sderaadt {
1979df930be7Sderaadt 	int bit;
1980df930be7Sderaadt 
1981df930be7Sderaadt 	/* firewall: p->p_back must be NULL */
1982df930be7Sderaadt 	if (p->p_back != NULL)
1983df930be7Sderaadt 		panic("setrunqueue");
1984df930be7Sderaadt 
1985df930be7Sderaadt 	bit = p->p_priority >> 2;
19862a2685f2Sart 	sched_whichqs |= (1 << bit);
19872a2685f2Sart 	p->p_forw = (struct proc *)&sched_qs[bit];
19882a2685f2Sart 	p->p_back = sched_qs[bit].ph_rlink;
1989df930be7Sderaadt 	p->p_back->p_forw = p;
19902a2685f2Sart 	sched_qs[bit].ph_rlink = p;
1991df930be7Sderaadt }
1992df930be7Sderaadt 
1993df930be7Sderaadt /*
1994e464495eSniklas  * remrunqueue(p)
1995df930be7Sderaadt  *
1996df930be7Sderaadt  * Call should be made at splclock().
1997df930be7Sderaadt  */
1998df930be7Sderaadt void
1999d3cbbad5Skstailey remrunqueue(p)
2000df930be7Sderaadt 	struct proc *p;
2001df930be7Sderaadt {
2002df930be7Sderaadt 	int bit;
2003df930be7Sderaadt 
2004df930be7Sderaadt 	bit = p->p_priority >> 2;
20052a2685f2Sart 	if ((sched_whichqs & (1 << bit)) == 0)
2006d3cbbad5Skstailey 		panic("remrunqueue");
2007df930be7Sderaadt 
2008df930be7Sderaadt 	p->p_back->p_forw = p->p_forw;
2009df930be7Sderaadt 	p->p_forw->p_back = p->p_back;
2010df930be7Sderaadt 	p->p_back = NULL;	/* for firewall checking. */
2011df930be7Sderaadt 
20122a2685f2Sart 	if ((struct proc *)&sched_qs[bit] == sched_qs[bit].ph_link)
20132a2685f2Sart 		sched_whichqs &= ~(1 << bit);
2014df930be7Sderaadt }
2015df930be7Sderaadt 
2016df930be7Sderaadt /*
2017df930be7Sderaadt  * Return the best possible estimate of the time in the timeval
2018df930be7Sderaadt  * to which tvp points.  Unfortunately, we can't read the hardware registers.
2019df930be7Sderaadt  * We guarantee that the time will be greater than the value obtained by a
2020df930be7Sderaadt  * previous call.
2021df930be7Sderaadt  */
2022df930be7Sderaadt void
2023df930be7Sderaadt microtime(tvp)
2024df930be7Sderaadt 	register struct timeval *tvp;
2025df930be7Sderaadt {
2026df930be7Sderaadt 	int s = splclock();
2027df930be7Sderaadt 	static struct timeval lasttime;
2028df930be7Sderaadt 
2029df930be7Sderaadt 	*tvp = time;
2030df930be7Sderaadt #ifdef notdef
2031df930be7Sderaadt 	tvp->tv_usec += clkread();
20324c891e15Spjanzen 	while (tvp->tv_usec >= 1000000) {
2033df930be7Sderaadt 		tvp->tv_sec++;
2034df930be7Sderaadt 		tvp->tv_usec -= 1000000;
2035df930be7Sderaadt 	}
2036df930be7Sderaadt #endif
2037df930be7Sderaadt 	if (tvp->tv_sec == lasttime.tv_sec &&
2038df930be7Sderaadt 	    tvp->tv_usec <= lasttime.tv_usec &&
20394c891e15Spjanzen 	    (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) {
2040df930be7Sderaadt 		tvp->tv_sec++;
2041df930be7Sderaadt 		tvp->tv_usec -= 1000000;
2042df930be7Sderaadt 	}
2043df930be7Sderaadt 	lasttime = *tvp;
2044df930be7Sderaadt 	splx(s);
2045df930be7Sderaadt }
2046df930be7Sderaadt 
2047417eba8cSderaadt /*
2048417eba8cSderaadt  * Wait "n" microseconds.
2049417eba8cSderaadt  */
205050ce9ee0Sniklas void
2051417eba8cSderaadt delay(n)
205250ce9ee0Sniklas 	unsigned long n;
2053417eba8cSderaadt {
2054417eba8cSderaadt 	long N = cycles_per_usec * (n);
2055417eba8cSderaadt 
2056aed035abSart 	/*
2057aed035abSart 	 * XXX Should be written to use RPCC?
2058aed035abSart 	 */
2059aed035abSart 
2060aed035abSart 	__asm __volatile(
2061aed035abSart 		"# The 2 corresponds to the insn count\n"
2062aed035abSart 		"1:	subq	%2, %1, %0	\n"
2063aed035abSart 		"	bgt	%0, 1b"
2064aed035abSart 		: "=r" (N)
2065aed035abSart 		: "i" (2), "0" (N));
2066417eba8cSderaadt }
2067417eba8cSderaadt 
2068df930be7Sderaadt #if defined(COMPAT_OSF1) || 1		/* XXX */
2069c4071fd1Smillert void	cpu_exec_ecoff_setregs(struct proc *, struct exec_package *,
2070c4071fd1Smillert 	    u_long, register_t *);
20713a630e3fSniklas 
2072df930be7Sderaadt void
2073417eba8cSderaadt cpu_exec_ecoff_setregs(p, epp, stack, retval)
2074df930be7Sderaadt 	struct proc *p;
2075417eba8cSderaadt 	struct exec_package *epp;
2076df930be7Sderaadt 	u_long stack;
2077df930be7Sderaadt 	register_t *retval;
2078df930be7Sderaadt {
2079417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
2080df930be7Sderaadt 
2081417eba8cSderaadt 	setregs(p, epp, stack, retval);
208250ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value;
2083df930be7Sderaadt }
2084df930be7Sderaadt 
2085df930be7Sderaadt /*
2086df930be7Sderaadt  * cpu_exec_ecoff_hook():
2087df930be7Sderaadt  *	cpu-dependent ECOFF format hook for execve().
2088df930be7Sderaadt  *
2089df930be7Sderaadt  * Do any machine-dependent diddling of the exec package when doing ECOFF.
2090df930be7Sderaadt  *
2091df930be7Sderaadt  */
2092df930be7Sderaadt int
2093417eba8cSderaadt cpu_exec_ecoff_hook(p, epp)
2094df930be7Sderaadt 	struct proc *p;
2095df930be7Sderaadt 	struct exec_package *epp;
2096df930be7Sderaadt {
2097417eba8cSderaadt 	struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr;
2098c3114d5bSericj 	extern struct emul emul_native;
2099aed035abSart 	int error;
21004e8700e2Sericj 	extern int osf1_exec_ecoff_hook(struct proc *, struct exec_package *);
2101df930be7Sderaadt 
2102417eba8cSderaadt 	switch (execp->f.f_magic) {
2103df930be7Sderaadt #ifdef COMPAT_OSF1
2104df930be7Sderaadt 	case ECOFF_MAGIC_ALPHA:
21054e8700e2Sericj 		error = osf1_exec_ecoff_hook(p, epp);
2106df930be7Sderaadt 		break;
2107df930be7Sderaadt #endif
2108df930be7Sderaadt 
210950ce9ee0Sniklas 	case ECOFF_MAGIC_NATIVE_ALPHA:
2110a2f8ce8dSderaadt 		epp->ep_emul = &emul_native;
2111aed035abSart 		error = 0;
2112df930be7Sderaadt 		break;
2113df930be7Sderaadt 
2114df930be7Sderaadt 	default:
2115aed035abSart 		error = ENOEXEC;
2116df930be7Sderaadt 	}
2117aed035abSart 	return (error);
2118df930be7Sderaadt }
2119df930be7Sderaadt #endif
2120e464495eSniklas 
2121aed035abSart int
2122aed035abSart alpha_pa_access(pa)
2123aed035abSart 	u_long pa;
2124aed035abSart {
2125aed035abSart 	int i;
2126aed035abSart 
2127aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
2128aed035abSart 		if (pa < mem_clusters[i].start)
2129aed035abSart 			continue;
2130aed035abSart 		if ((pa - mem_clusters[i].start) >=
2131aed035abSart 		    (mem_clusters[i].size & ~PAGE_MASK))
2132aed035abSart 			continue;
2133aed035abSart 		return (mem_clusters[i].size & PAGE_MASK);	/* prot */
2134aed035abSart 	}
2135aed035abSart 
2136aed035abSart 	/*
2137aed035abSart 	 * Address is not a memory address.  If we're secure, disallow
2138aed035abSart 	 * access.  Otherwise, grant read/write.
2139aed035abSart 	 */
2140aed035abSart 	if (securelevel > 0)
2141aed035abSart 		return (VM_PROT_NONE);
2142aed035abSart 	else
2143aed035abSart 		return (VM_PROT_READ | VM_PROT_WRITE);
2144aed035abSart }
2145aed035abSart 
2146e464495eSniklas /* XXX XXX BEGIN XXX XXX */
2147aed035abSart paddr_t alpha_XXX_dmamap_or;					/* XXX */
2148e464495eSniklas 								/* XXX */
2149aed035abSart paddr_t								/* XXX */
2150e464495eSniklas alpha_XXX_dmamap(v)						/* XXX */
2151aed035abSart 	vaddr_t v;						/* XXX */
2152e464495eSniklas {								/* XXX */
2153e464495eSniklas 								/* XXX */
2154e464495eSniklas 	return (vtophys(v) | alpha_XXX_dmamap_or);		/* XXX */
2155e464495eSniklas }								/* XXX */
2156e464495eSniklas /* XXX XXX END XXX XXX */
2157aed035abSart 
2158aed035abSart char *
2159aed035abSart dot_conv(x)
2160aed035abSart 	unsigned long x;
2161aed035abSart {
2162aed035abSart 	int i;
2163aed035abSart 	char *xc;
2164aed035abSart 	static int next;
2165aed035abSart 	static char space[2][20];
2166aed035abSart 
2167aed035abSart 	xc = space[next ^= 1] + sizeof space[0];
2168aed035abSart 	*--xc = '\0';
2169aed035abSart 	for (i = 0;; ++i) {
2170aed035abSart 		if (i && (i & 3) == 0)
2171aed035abSart 			*--xc = '.';
2172aed035abSart 		*--xc = "0123456789abcdef"[x & 0xf];
2173aed035abSart 		x >>= 4;
2174aed035abSart 		if (x == 0)
2175aed035abSart 			break;
2176aed035abSart 	}
2177aed035abSart 	return xc;
2178aed035abSart }
2179