xref: /openbsd/sys/arch/alpha/alpha/machdep.c (revision 4fa86cc0)
1*4fa86cc0Smiod /* $OpenBSD: machdep.c,v 1.148 2014/02/04 21:52:42 miod 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  *
21aed035abSart  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22aed035abSart  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23aed035abSart  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24aed035abSart  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25aed035abSart  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26aed035abSart  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27aed035abSart  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28aed035abSart  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29aed035abSart  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30aed035abSart  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31aed035abSart  * POSSIBILITY OF SUCH DAMAGE.
32aed035abSart  */
33df930be7Sderaadt 
34df930be7Sderaadt /*
35417eba8cSderaadt  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
36df930be7Sderaadt  * All rights reserved.
37df930be7Sderaadt  *
38df930be7Sderaadt  * Author: Chris G. Demetriou
39df930be7Sderaadt  *
40df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
41df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
42df930be7Sderaadt  * notice and this permission notice appear in all copies of the
43df930be7Sderaadt  * software, derivative works or modified versions, and any portions
44df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
45df930be7Sderaadt  *
46df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
48df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49df930be7Sderaadt  *
50df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
51df930be7Sderaadt  *
52df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
53df930be7Sderaadt  *  School of Computer Science
54df930be7Sderaadt  *  Carnegie Mellon University
55df930be7Sderaadt  *  Pittsburgh PA 15213-3890
56df930be7Sderaadt  *
57df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
58df930be7Sderaadt  * rights to redistribute these changes.
59df930be7Sderaadt  */
60df930be7Sderaadt 
61df930be7Sderaadt #include <sys/param.h>
62df930be7Sderaadt #include <sys/systm.h>
63df930be7Sderaadt #include <sys/signalvar.h>
64df930be7Sderaadt #include <sys/kernel.h>
65df930be7Sderaadt #include <sys/proc.h>
667d9ca166Sderaadt #include <sys/socket.h>
672a2685f2Sart #include <sys/sched.h>
68df930be7Sderaadt #include <sys/buf.h>
69df930be7Sderaadt #include <sys/reboot.h>
70417eba8cSderaadt #include <sys/device.h>
71df930be7Sderaadt #include <sys/conf.h>
72df930be7Sderaadt #include <sys/file.h>
73d66eba84Sart #include <sys/timeout.h>
74df930be7Sderaadt #include <sys/malloc.h>
75df930be7Sderaadt #include <sys/mbuf.h>
76df930be7Sderaadt #include <sys/msgbuf.h>
77df930be7Sderaadt #include <sys/ioctl.h>
78df930be7Sderaadt #include <sys/tty.h>
79df930be7Sderaadt #include <sys/user.h>
80df930be7Sderaadt #include <sys/exec.h>
81df930be7Sderaadt #include <sys/sysctl.h>
8250ce9ee0Sniklas #include <sys/core.h>
8350ce9ee0Sniklas #include <sys/kcore.h>
847d9ca166Sderaadt 
857d9ca166Sderaadt #include <net/if.h>
867d9ca166Sderaadt #include <uvm/uvm.h>
877d9ca166Sderaadt 
8850ce9ee0Sniklas #include <machine/kcore.h>
89433075b6Spvalchev #ifndef NO_IEEE
90433075b6Spvalchev #include <machine/fpu.h>
91433075b6Spvalchev #endif
921f87e7b7Sart #include <sys/timetc.h>
93df930be7Sderaadt 
94df930be7Sderaadt #include <sys/mount.h>
95df930be7Sderaadt #include <sys/syscallargs.h>
96df930be7Sderaadt 
97df930be7Sderaadt #include <dev/cons.h>
98df930be7Sderaadt 
9950ce9ee0Sniklas #include <machine/autoconf.h>
100df930be7Sderaadt #include <machine/cpu.h>
101df930be7Sderaadt #include <machine/reg.h>
102df930be7Sderaadt #include <machine/rpb.h>
103df930be7Sderaadt #include <machine/prom.h>
1043a630e3fSniklas #include <machine/cpuconf.h>
105433075b6Spvalchev #ifndef NO_IEEE
106433075b6Spvalchev #include <machine/ieeefp.h>
107433075b6Spvalchev #endif
108df930be7Sderaadt 
10945e5a1a0Sart #include <dev/pci/pcivar.h>
11045e5a1a0Sart 
11112f8bbedSniklas #ifdef DDB
11212f8bbedSniklas #include <machine/db_machdep.h>
11312f8bbedSniklas #include <ddb/db_extern.h>
11421c23d01Smiod #include <ddb/db_interface.h>
11512f8bbedSniklas #endif
11612f8bbedSniklas 
117a072164aSmiod #include "ioasic.h"
118a072164aSmiod 
119a072164aSmiod #if NIOASIC > 0
120a072164aSmiod #include <machine/tc_machdep.h>
121a072164aSmiod #include <dev/tc/tcreg.h>
122a072164aSmiod #include <dev/tc/ioasicvar.h>
123a072164aSmiod #endif
124a072164aSmiod 
12565c47ec0Sderaadt #ifdef BROKEN_PROM_CONSOLE
12665c47ec0Sderaadt extern void sio_intr_shutdown(void);
12765c47ec0Sderaadt #endif
12865c47ec0Sderaadt 
129c4071fd1Smillert int	cpu_dump(void);
130c4071fd1Smillert int	cpu_dumpsize(void);
131c4071fd1Smillert u_long	cpu_dump_mempagecnt(void);
132c4071fd1Smillert void	dumpsys(void);
133c4071fd1Smillert void	identifycpu(void);
134c4071fd1Smillert void	regdump(struct trapframe *framep);
135c4071fd1Smillert void	printregs(struct reg *);
136df930be7Sderaadt 
137b426ab7bSthib struct uvm_constraint_range  isa_constraint = { 0x0, 0x00ffffffUL };
138b426ab7bSthib struct uvm_constraint_range  dma_constraint = { 0x0, (paddr_t)-1 };
139b426ab7bSthib struct uvm_constraint_range *uvm_md_constraints[] = {
140b426ab7bSthib 	&isa_constraint,
141b426ab7bSthib 	NULL
142b426ab7bSthib };
143b426ab7bSthib 
144ab8e80c5Sart struct vm_map *exec_map = NULL;
145ab8e80c5Sart struct vm_map *phys_map = NULL;
146aed035abSart 
147c72644a3Sderaadt /*
148c72644a3Sderaadt  * safepri is a safe priority for sleep to set for a spin-wait
149c72644a3Sderaadt  * during autoconfiguration or after a panic.
150c72644a3Sderaadt  */
151c72644a3Sderaadt int   safepri = 0;
152c72644a3Sderaadt 
15327626149Smatthieu #ifdef APERTURE
15427626149Smatthieu #ifdef INSECURE
15527626149Smatthieu int allowaperture = 1;
15627626149Smatthieu #else
15727626149Smatthieu int allowaperture = 0;
15827626149Smatthieu #endif
15927626149Smatthieu #endif
16027626149Smatthieu 
161df930be7Sderaadt int	totalphysmem;		/* total amount of physical memory in system */
16274652a67Sniklas int	physmem;		/* physical mem used by OpenBSD + some rsvd */
163df930be7Sderaadt int	resvmem;		/* amount of memory reserved for PROM */
164df930be7Sderaadt int	unusedmem;		/* amount of memory for OS that we don't use */
165df930be7Sderaadt int	unknownmem;		/* amount of memory with an unknown use */
166df930be7Sderaadt 
167df930be7Sderaadt int	cputype;		/* system type, from the RPB */
168df930be7Sderaadt 
1692a2685f2Sart int	bootdev_debug = 0;	/* patchable, or from DDB */
1702a2685f2Sart 
171df930be7Sderaadt /* the following is used externally (sysctl_hw) */
172aed035abSart char	machine[] = MACHINE;		/* from <machine/param.h> */
173417eba8cSderaadt char	cpu_model[128];
174df930be7Sderaadt 
175df930be7Sderaadt struct	user *proc0paddr;
176df930be7Sderaadt 
177df930be7Sderaadt /* Number of machine cycles per microsecond */
178df930be7Sderaadt u_int64_t	cycles_per_usec;
179df930be7Sderaadt 
180aed035abSart struct bootinfo_kernel bootinfo;
181aed035abSart 
182b1560ceaSmiod struct consdev *cn_tab;
183b1560ceaSmiod 
184aed035abSart /* For built-in TCDS */
185aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
186aed035abSart u_int8_t	dec_3000_scsiid[2], dec_3000_scsifast[2];
187aed035abSart #endif
188aed035abSart 
189aed035abSart struct platform platform;
190417eba8cSderaadt 
191417eba8cSderaadt /* for cpu_sysctl() */
19250ce9ee0Sniklas int	alpha_unaligned_print = 1;	/* warn about unaligned accesses */
19350ce9ee0Sniklas int	alpha_unaligned_fix = 1;	/* fix up unaligned accesses */
194881c1eabSart int	alpha_unaligned_sigbus = 1;	/* SIGBUS on fixed-up accesses */
195433075b6Spvalchev #ifndef NO_IEEE
196433075b6Spvalchev int	alpha_fp_sync_complete = 0;	/* fp fixup if sync even without /s */
197433075b6Spvalchev #endif
198a072164aSmiod #if NIOASIC > 0
199a072164aSmiod int	alpha_led_blink = 0;
200a072164aSmiod #endif
20150ce9ee0Sniklas 
202b3cee53eSmartin /* used by hw_sysctl */
203b3cee53eSmartin extern char *hw_serial;
204b3cee53eSmartin 
205aed035abSart /*
206aed035abSart  * XXX This should be dynamically sized, but we have the chicken-egg problem!
207aed035abSart  * XXX it should also be larger than it is, because not all of the mddt
208aed035abSart  * XXX clusters end up being used for VM.
209aed035abSart  */
210aed035abSart phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];	/* low size bits overloaded */
211aed035abSart int	mem_cluster_cnt;
212aed035abSart 
2133a630e3fSniklas void
214dd3e8537Smiod alpha_init(unused, ptb, bim, bip, biv)
215dd3e8537Smiod 	u_long unused;
216df930be7Sderaadt 	u_long ptb;		/* PFN of current level 1 page table */
217aed035abSart 	u_long bim;		/* bootinfo magic */
218aed035abSart 	u_long bip;		/* bootinfo pointer */
219aed035abSart 	u_long biv;		/* bootinfo version */
220df930be7Sderaadt {
221aed035abSart 	extern char kernel_text[], _end[];
222df930be7Sderaadt 	struct mddt *mddtp;
223aed035abSart 	struct mddt_cluster *memc;
224df930be7Sderaadt 	int i, mddtweird;
225aed035abSart 	struct vm_physseg *vps;
226aed035abSart 	vaddr_t kernstart, kernend;
227aed035abSart 	paddr_t kernstartpfn, kernendpfn, pfn0, pfn1;
228df930be7Sderaadt 	char *p;
2292a2685f2Sart 	const char *bootinfo_msg;
230aed035abSart 	const struct cpuinit *c;
231aed035abSart 	extern caddr_t esym;
232aed035abSart 	struct cpu_info *ci;
233aed035abSart 	cpuid_t cpu_id;
234df930be7Sderaadt 
235aed035abSart 	/* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */
236f3914c62Sniklas 
237df930be7Sderaadt 	/*
238aed035abSart 	 * Turn off interrupts (not mchecks) and floating point.
239df930be7Sderaadt 	 * Make sure the instruction and data streams are consistent.
240df930be7Sderaadt 	 */
241aed035abSart 	(void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
24250ce9ee0Sniklas 	alpha_pal_wrfen(0);
24350ce9ee0Sniklas 	ALPHA_TBIA();
24450ce9ee0Sniklas 	alpha_pal_imb();
245df930be7Sderaadt 
246c62181b1Sbrad 	/* Initialize the SCB. */
247c62181b1Sbrad 	scb_init();
248c62181b1Sbrad 
249aed035abSart 	cpu_id = cpu_number();
250aed035abSart 
251aed035abSart #if defined(MULTIPROCESSOR)
252df930be7Sderaadt 	/*
253aed035abSart 	 * Set our SysValue to the address of our cpu_info structure.
254aed035abSart 	 * Secondary processors do this in their spinup trampoline.
255df930be7Sderaadt 	 */
25621c23d01Smiod 	alpha_pal_wrval((u_long)&cpu_info_primary);
25721c23d01Smiod 	cpu_info[cpu_id] = &cpu_info_primary;
258aed035abSart #endif
259aed035abSart 
260aed035abSart 	ci = curcpu();
261aed035abSart 	ci->ci_cpuid = cpu_id;
262aed035abSart 
263aed035abSart 	/*
264aed035abSart 	 * Get critical system information (if possible, from the
265aed035abSart 	 * information provided by the boot program).
266aed035abSart 	 */
267aed035abSart 	bootinfo_msg = NULL;
268aed035abSart 	if (bim == BOOTINFO_MAGIC) {
269aed035abSart 		if (biv == 0) {		/* backward compat */
270aed035abSart 			biv = *(u_long *)bip;
271aed035abSart 			bip += 8;
272aed035abSart 		}
273aed035abSart 		switch (biv) {
274aed035abSart 		case 1: {
275aed035abSart 			struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip;
276aed035abSart 
277aed035abSart 			bootinfo.ssym = v1p->ssym;
278aed035abSart 			bootinfo.esym = v1p->esym;
279aed035abSart 			/* hwrpb may not be provided by boot block in v1 */
280aed035abSart 			if (v1p->hwrpb != NULL) {
281aed035abSart 				bootinfo.hwrpb_phys =
282aed035abSart 				    ((struct rpb *)v1p->hwrpb)->rpb_phys;
283aed035abSart 				bootinfo.hwrpb_size = v1p->hwrpbsize;
284aed035abSart 			} else {
285aed035abSart 				bootinfo.hwrpb_phys =
286aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_phys;
287aed035abSart 				bootinfo.hwrpb_size =
288aed035abSart 				    ((struct rpb *)HWRPB_ADDR)->rpb_size;
289aed035abSart 			}
290aed035abSart 			bcopy(v1p->boot_flags, bootinfo.boot_flags,
291aed035abSart 			    min(sizeof v1p->boot_flags,
292aed035abSart 			      sizeof bootinfo.boot_flags));
293aed035abSart 			bcopy(v1p->booted_kernel, bootinfo.booted_kernel,
294aed035abSart 			    min(sizeof v1p->booted_kernel,
295aed035abSart 			      sizeof bootinfo.booted_kernel));
296aed035abSart 			/* booted dev not provided in bootinfo */
297aed035abSart 			init_prom_interface((struct rpb *)
298aed035abSart 			    ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys));
299aed035abSart                 	prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
300aed035abSart 			    sizeof bootinfo.booted_dev);
301aed035abSart 			break;
302aed035abSart 		}
303aed035abSart 		default:
304aed035abSart 			bootinfo_msg = "unknown bootinfo version";
305aed035abSart 			goto nobootinfo;
306aed035abSart 		}
307aed035abSart 	} else {
308aed035abSart 		bootinfo_msg = "boot program did not pass bootinfo";
309aed035abSart nobootinfo:
310aed035abSart 		bootinfo.ssym = (u_long)_end;
311aed035abSart 		bootinfo.esym = (u_long)_end;
312aed035abSart 		bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys;
313aed035abSart 		bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size;
314aed035abSart 		init_prom_interface((struct rpb *)HWRPB_ADDR);
315aed035abSart 		prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags,
316aed035abSart 		    sizeof bootinfo.boot_flags);
317aed035abSart 		prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel,
318aed035abSart 		    sizeof bootinfo.booted_kernel);
319aed035abSart 		prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev,
320aed035abSart 		    sizeof bootinfo.booted_dev);
321aed035abSart 	}
322aed035abSart 
323aed035abSart 	esym = (caddr_t)bootinfo.esym;
324aed035abSart 	/*
325aed035abSart 	 * Initialize the kernel's mapping of the RPB.  It's needed for
326aed035abSart 	 * lots of things.
327aed035abSart 	 */
328aed035abSart 	hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys);
329aed035abSart 
330aed035abSart #if defined(DEC_3000_300) || defined(DEC_3000_500)
331aed035abSart 	if (hwrpb->rpb_type == ST_DEC_3000_300 ||
332aed035abSart 	    hwrpb->rpb_type == ST_DEC_3000_500) {
333aed035abSart 		prom_getenv(PROM_E_SCSIID, dec_3000_scsiid,
334aed035abSart 		    sizeof(dec_3000_scsiid));
335aed035abSart 		prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast,
336aed035abSart 		    sizeof(dec_3000_scsifast));
337aed035abSart 	}
338aed035abSart #endif
339df930be7Sderaadt 
340df930be7Sderaadt 	/*
341df930be7Sderaadt 	 * Remember how many cycles there are per microsecond,
342df930be7Sderaadt 	 * so that we can use delay().  Round up, for safety.
343df930be7Sderaadt 	 */
344df930be7Sderaadt 	cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000;
345df930be7Sderaadt 
346df930be7Sderaadt 	/*
3479e71c994Saaron 	 * Initialize the (temporary) bootstrap console interface, so
348aed035abSart 	 * we can use printf until the VM system starts being setup.
349aed035abSart 	 * The real console is initialized before then.
350df930be7Sderaadt 	 */
351aed035abSart 	init_bootstrap_console();
352aed035abSart 
353aed035abSart 	/* OUTPUT NOW ALLOWED */
354aed035abSart 
355aed035abSart 	/* delayed from above */
356aed035abSart 	if (bootinfo_msg)
357aed035abSart 		printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n",
358aed035abSart 		    bootinfo_msg, bim, bip, biv);
359aed035abSart 
360aed035abSart 	/* Initialize the trap vectors on the primary processor. */
361aed035abSart 	trap_init();
362df930be7Sderaadt 
363df930be7Sderaadt 	/*
364aed035abSart 	 * Find out what hardware we're on, and do basic initialization.
365df930be7Sderaadt 	 */
366aed035abSart 	cputype = hwrpb->rpb_type;
367aed035abSart 	if (cputype < 0) {
368aed035abSart 		/*
369aed035abSart 		 * At least some white-box systems have SRM which
370aed035abSart 		 * reports a systype that's the negative of their
371aed035abSart 		 * blue-box counterpart.
372aed035abSart 		 */
373aed035abSart 		cputype = -cputype;
374aed035abSart 	}
375aed035abSart 	c = platform_lookup(cputype);
376aed035abSart 	if (c == NULL) {
377aed035abSart 		platform_not_supported();
378aed035abSart 		/* NOTREACHED */
379aed035abSart 	}
380aed035abSart 	(*c->init)();
381094fa01fSderaadt 	strlcpy(cpu_model, platform.model, sizeof cpu_model);
38250ce9ee0Sniklas 
38350ce9ee0Sniklas 	/*
3849e71c994Saaron 	 * Initialize the real console, so that the bootstrap console is
385aed035abSart 	 * no longer necessary.
38650ce9ee0Sniklas 	 */
387aed035abSart 	(*platform.cons_init)();
388aed035abSart 
389a55851f4Sderaadt #if 0
390aed035abSart 	/* Paranoid sanity checking */
391aed035abSart 
392aed035abSart 	assert(hwrpb->rpb_primary_cpu_id == alpha_pal_whami());
393aed035abSart 
394aed035abSart 	/*
395aed035abSart 	 * On single-CPU systypes, the primary should always be CPU 0,
396aed035abSart 	 * except on Alpha 8200 systems where the CPU id is related
397aed035abSart 	 * to the VID, which is related to the Turbo Laser node id.
398aed035abSart 	 */
399aed035abSart 	if (cputype != ST_DEC_21000)
400aed035abSart 		assert(hwrpb->rpb_primary_cpu_id == 0);
401aed035abSart #endif
402aed035abSart 
403aed035abSart 	/* NO MORE FIRMWARE ACCESS ALLOWED */
404aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
405aed035abSart 	/*
406aed035abSart 	 * XXX (unless _PMAP_MAY_USE_PROM_CONSOLE is defined and
407aed035abSart 	 * XXX pmap_uses_prom_console() evaluates to non-zero.)
408aed035abSart 	 */
409aed035abSart #endif
410aed035abSart 
411cfcdef40Smiod #ifndef SMALL_KERNEL
412cfcdef40Smiod 	/*
413cfcdef40Smiod 	 * If we run on a BWX-capable processor, override cpu_switch
414cfcdef40Smiod 	 * with a faster version.
415cfcdef40Smiod 	 * We do this now because the kernel text might be mapped
416cfcdef40Smiod 	 * read-only eventually (although this is not the case at the moment).
417cfcdef40Smiod 	 */
418cfcdef40Smiod 	if (alpha_implver() >= ALPHA_IMPLVER_EV5) {
419cfcdef40Smiod 		if (~alpha_amask(ALPHA_AMASK_BWX) != 0) {
420cfcdef40Smiod 			extern vaddr_t __bwx_switch0, __bwx_switch1,
421cfcdef40Smiod 			    __bwx_switch2, __bwx_switch3;
422cfcdef40Smiod 			u_int32_t *dst, *src, *end;
423cfcdef40Smiod 
424cfcdef40Smiod 			src = (u_int32_t *)&__bwx_switch2;
425cfcdef40Smiod 			end = (u_int32_t *)&__bwx_switch3;
426cfcdef40Smiod 			dst = (u_int32_t *)&__bwx_switch0;
427cfcdef40Smiod 			while (src != end)
428cfcdef40Smiod 				*dst++ = *src++;
429cfcdef40Smiod 			src = (u_int32_t *)&__bwx_switch1;
430cfcdef40Smiod 			end = (u_int32_t *)&__bwx_switch2;
431cfcdef40Smiod 			while (src != end)
432cfcdef40Smiod 				*dst++ = *src++;
433cfcdef40Smiod 		}
434cfcdef40Smiod 	}
435cfcdef40Smiod #endif
436cfcdef40Smiod 
437aed035abSart 	/*
438aed035abSart 	 * find out this system's page size
439aed035abSart 	 */
44073b9fe7cSart 	if ((uvmexp.pagesize = hwrpb->rpb_page_size) != 8192)
44173b9fe7cSart 		panic("page size %d != 8192?!", uvmexp.pagesize);
442aed035abSart 
443aed035abSart 	uvm_setpagesize();
444aed035abSart 
445aed035abSart 	/*
446aed035abSart 	 * Find the beginning and end of the kernel (and leave a
447aed035abSart 	 * bit of space before the beginning for the bootstrap
448aed035abSart 	 * stack).
449aed035abSart 	 */
450aed035abSart 	kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE;
451aed035abSart 	kernend = (vaddr_t)round_page((vaddr_t)bootinfo.esym);
452aed035abSart 
453aed035abSart 	kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart));
454aed035abSart 	kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend));
455df930be7Sderaadt 
456df930be7Sderaadt 	/*
457df930be7Sderaadt 	 * Find out how much memory is available, by looking at
458df930be7Sderaadt 	 * the memory cluster descriptors.  This also tries to do
459df930be7Sderaadt 	 * its best to detect things things that have never been seen
460df930be7Sderaadt 	 * before...
461df930be7Sderaadt 	 */
462df930be7Sderaadt 	mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off);
463df930be7Sderaadt 
464aed035abSart 	/* MDDT SANITY CHECKING */
465df930be7Sderaadt 	mddtweird = 0;
466aed035abSart 	if (mddtp->mddt_cluster_cnt < 2) {
467df930be7Sderaadt 		mddtweird = 1;
468aed035abSart 		printf("WARNING: weird number of mem clusters: %lu\n",
469aed035abSart 		    mddtp->mddt_cluster_cnt);
470df930be7Sderaadt 	}
471df930be7Sderaadt 
472aed035abSart #if 0
473aed035abSart 	printf("Memory cluster count: %d\n", mddtp->mddt_cluster_cnt);
474aed035abSart #endif
475df930be7Sderaadt 
476aed035abSart 	for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
477aed035abSart 		memc = &mddtp->mddt_clusters[i];
478aed035abSart #if 0
479aed035abSart 		printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i,
480aed035abSart 		    memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage);
481aed035abSart #endif
482aed035abSart 		totalphysmem += memc->mddt_pg_cnt;
483aed035abSart 		if (mem_cluster_cnt < VM_PHYSSEG_MAX) {	/* XXX */
484aed035abSart 			mem_clusters[mem_cluster_cnt].start =
485aed035abSart 			    ptoa(memc->mddt_pfn);
486aed035abSart 			mem_clusters[mem_cluster_cnt].size =
487aed035abSart 			    ptoa(memc->mddt_pg_cnt);
488aed035abSart 			if (memc->mddt_usage & MDDT_mbz ||
489aed035abSart 			    memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */
490aed035abSart 			    memc->mddt_usage & MDDT_PALCODE)
491aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
492aed035abSart 				    VM_PROT_READ;
493aed035abSart 			else
494aed035abSart 				mem_clusters[mem_cluster_cnt].size |=
495aed035abSart 				    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
496aed035abSart 			mem_cluster_cnt++;
497ee2d823aSmiod 		} /* XXX else print something! */
498aed035abSart 
499aed035abSart 		if (memc->mddt_usage & MDDT_mbz) {
500aed035abSart 			mddtweird = 1;
501aed035abSart 			printf("WARNING: mem cluster %d has weird "
502aed035abSart 			    "usage 0x%lx\n", i, memc->mddt_usage);
503aed035abSart 			unknownmem += memc->mddt_pg_cnt;
504aed035abSart 			continue;
505aed035abSart 		}
506aed035abSart 		if (memc->mddt_usage & MDDT_NONVOLATILE) {
507aed035abSart 			/* XXX should handle these... */
508aed035abSart 			printf("WARNING: skipping non-volatile mem "
509aed035abSart 			    "cluster %d\n", i);
510aed035abSart 			unusedmem += memc->mddt_pg_cnt;
511aed035abSart 			continue;
512aed035abSart 		}
513aed035abSart 		if (memc->mddt_usage & MDDT_PALCODE) {
514aed035abSart 			resvmem += memc->mddt_pg_cnt;
515aed035abSart 			continue;
516aed035abSart 		}
517aed035abSart 
518aed035abSart 		/*
519aed035abSart 		 * We have a memory cluster available for system
520aed035abSart 		 * software use.  We must determine if this cluster
521aed035abSart 		 * holds the kernel.
522aed035abSart 		 */
523aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
524aed035abSart 		/*
525aed035abSart 		 * XXX If the kernel uses the PROM console, we only use the
526aed035abSart 		 * XXX memory after the kernel in the first system segment,
527aed035abSart 		 * XXX to avoid clobbering prom mapping, data, etc.
528aed035abSart 		 */
529aed035abSart 	    if (!pmap_uses_prom_console() || physmem == 0) {
530aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
531aed035abSart 		physmem += memc->mddt_pg_cnt;
532aed035abSart 		pfn0 = memc->mddt_pfn;
533aed035abSart 		pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt;
534aed035abSart 		if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) {
535aed035abSart 			/*
536aed035abSart 			 * Must compute the location of the kernel
537aed035abSart 			 * within the segment.
538aed035abSart 			 */
539aed035abSart #if 0
540aed035abSart 			printf("Cluster %d contains kernel\n", i);
541aed035abSart #endif
542aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
543aed035abSart 		    if (!pmap_uses_prom_console()) {
544aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
545aed035abSart 			if (pfn0 < kernstartpfn) {
546aed035abSart 				/*
547aed035abSart 				 * There is a chunk before the kernel.
548aed035abSart 				 */
549aed035abSart #if 0
550aed035abSart 				printf("Loading chunk before kernel: "
551aed035abSart 				    "0x%lx / 0x%lx\n", pfn0, kernstartpfn);
552aed035abSart #endif
553aed035abSart 				uvm_page_physload(pfn0, kernstartpfn,
5542ce3b4a8Soga 				    pfn0, kernstartpfn, 0);
555aed035abSart 			}
556aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
557aed035abSart 		    }
558aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
559aed035abSart 			if (kernendpfn < pfn1) {
560aed035abSart 				/*
561aed035abSart 				 * There is a chunk after the kernel.
562aed035abSart 				 */
563aed035abSart #if 0
564aed035abSart 				printf("Loading chunk after kernel: "
565aed035abSart 				    "0x%lx / 0x%lx\n", kernendpfn, pfn1);
566aed035abSart #endif
567aed035abSart 				uvm_page_physload(kernendpfn, pfn1,
5682ce3b4a8Soga 				    kernendpfn, pfn1, 0);
569aed035abSart 			}
570aed035abSart 		} else {
571aed035abSart 			/*
572aed035abSart 			 * Just load this cluster as one chunk.
573aed035abSart 			 */
574aed035abSart #if 0
575aed035abSart 			printf("Loading cluster %d: 0x%lx / 0x%lx\n", i,
576aed035abSart 			    pfn0, pfn1);
577aed035abSart #endif
5782ce3b4a8Soga 			uvm_page_physload(pfn0, pfn1, pfn0, pfn1, 0);
579aed035abSart 		}
580aed035abSart #ifdef _PMAP_MAY_USE_PROM_CONSOLE
581aed035abSart 	    }
582aed035abSart #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
583aed035abSart 	}
584aed035abSart 
585a37778bcSderaadt #ifdef DEBUG
586aed035abSart 	/*
587aed035abSart 	 * Dump out the MDDT if it looks odd...
588aed035abSart 	 */
589df930be7Sderaadt 	if (mddtweird) {
590df930be7Sderaadt 		printf("\n");
591df930be7Sderaadt 		printf("complete memory cluster information:\n");
592df930be7Sderaadt 		for (i = 0; i < mddtp->mddt_cluster_cnt; i++) {
593df930be7Sderaadt 			printf("mddt %d:\n", i);
594df930be7Sderaadt 			printf("\tpfn %lx\n",
595df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pfn);
596df930be7Sderaadt 			printf("\tcnt %lx\n",
597df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_cnt);
598df930be7Sderaadt 			printf("\ttest %lx\n",
599df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_pg_test);
600df930be7Sderaadt 			printf("\tbva %lx\n",
601df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_v_bitaddr);
602df930be7Sderaadt 			printf("\tbpa %lx\n",
603df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_p_bitaddr);
604df930be7Sderaadt 			printf("\tbcksum %lx\n",
605df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_bit_cksum);
606df930be7Sderaadt 			printf("\tusage %lx\n",
607df930be7Sderaadt 			    mddtp->mddt_clusters[i].mddt_usage);
608df930be7Sderaadt 		}
609df930be7Sderaadt 		printf("\n");
610df930be7Sderaadt 	}
611a37778bcSderaadt #endif
612df930be7Sderaadt 
613df930be7Sderaadt 	if (totalphysmem == 0)
614df930be7Sderaadt 		panic("can't happen: system seems to have no memory!");
615df930be7Sderaadt #if 0
616f46637d1Sderaadt 	printf("totalphysmem = %u\n", totalphysmem);
617f46637d1Sderaadt 	printf("physmem = %u\n", physmem);
618df930be7Sderaadt 	printf("resvmem = %d\n", resvmem);
619df930be7Sderaadt 	printf("unusedmem = %d\n", unusedmem);
620df930be7Sderaadt 	printf("unknownmem = %d\n", unknownmem);
621df930be7Sderaadt #endif
622df930be7Sderaadt 
623df930be7Sderaadt 	/*
624aed035abSart 	 * Initialize error message buffer (at end of core).
625df930be7Sderaadt 	 */
626aed035abSart 	{
627aed035abSart 		vsize_t sz = (vsize_t)round_page(MSGBUFSIZE);
628aed035abSart 		vsize_t reqsz = sz;
629df930be7Sderaadt 
630aed035abSart 		vps = &vm_physmem[vm_nphysseg - 1];
631e1da84e1Salex 
632aed035abSart 		/* shrink so that it'll fit in the last segment */
633aed035abSart 		if ((vps->avail_end - vps->avail_start) < atop(sz))
634aed035abSart 			sz = ptoa(vps->avail_end - vps->avail_start);
635aed035abSart 
636aed035abSart 		vps->end -= atop(sz);
637aed035abSart 		vps->avail_end -= atop(sz);
638aed035abSart 		initmsgbuf((caddr_t) ALPHA_PHYS_TO_K0SEG(ptoa(vps->end)), sz);
639aed035abSart 
640aed035abSart 		/* Remove the last segment if it now has no pages. */
641aed035abSart 		if (vps->start == vps->end)
642aed035abSart 			vm_nphysseg--;
643aed035abSart 
644aed035abSart 		/* warn if the message buffer had to be shrunk */
645aed035abSart 		if (sz != reqsz)
646aed035abSart 			printf("WARNING: %ld bytes not available for msgbuf "
647aed035abSart 			    "in last cluster (%ld used)\n", reqsz, sz);
648aed035abSart 
649aed035abSart 	}
650aed035abSart 
651df930be7Sderaadt 	/*
652df930be7Sderaadt 	 * Init mapping for u page(s) for proc 0
653df930be7Sderaadt 	 */
654aed035abSart 	proc0.p_addr = proc0paddr =
655aed035abSart 	    (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE, NULL, NULL);
656df930be7Sderaadt 
657df930be7Sderaadt 	/*
658df930be7Sderaadt 	 * Initialize the virtual memory system, and set the
659df930be7Sderaadt 	 * page table base register in proc 0's PCB.
660df930be7Sderaadt 	 */
661aed035abSart 	pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT),
662aed035abSart 	    hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt);
663df930be7Sderaadt 
664df930be7Sderaadt 	/*
665df930be7Sderaadt 	 * Initialize the rest of proc 0's PCB, and cache its physical
666df930be7Sderaadt 	 * address.
667df930be7Sderaadt 	 */
668df930be7Sderaadt 	proc0.p_md.md_pcbpaddr =
669aed035abSart 	    (struct pcb *)ALPHA_K0SEG_TO_PHYS((vaddr_t)&proc0paddr->u_pcb);
670df930be7Sderaadt 
671df930be7Sderaadt 	/*
672df930be7Sderaadt 	 * Set the kernel sp, reserving space for an (empty) trapframe,
673df930be7Sderaadt 	 * and make proc0's trapframe pointer point to it for sanity.
674df930be7Sderaadt 	 */
67550ce9ee0Sniklas 	proc0paddr->u_pcb.pcb_hw.apcb_ksp =
676df930be7Sderaadt 	    (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
67774652a67Sniklas 	proc0.p_md.md_tf =
67874652a67Sniklas 	    (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
67950ce9ee0Sniklas 
680aed035abSart 	/*
681aed035abSart 	 * Initialize the primary CPU's idle PCB to proc0's.  In a
682aed035abSart 	 * MULTIPROCESSOR configuration, each CPU will later get
683aed035abSart 	 * its own idle PCB when autoconfiguration runs.
684aed035abSart 	 */
685aed035abSart 	ci->ci_idle_pcb = &proc0paddr->u_pcb;
686aed035abSart 	ci->ci_idle_pcb_paddr = (u_long)proc0.p_md.md_pcbpaddr;
687df930be7Sderaadt 
688df930be7Sderaadt 	/*
689df930be7Sderaadt 	 * Look at arguments passed to us and compute boothowto.
690df930be7Sderaadt 	 */
691417eba8cSderaadt 
692df930be7Sderaadt #ifdef KADB
693df930be7Sderaadt 	boothowto |= RB_KDB;
694df930be7Sderaadt #endif
695aed035abSart 	for (p = bootinfo.boot_flags; p && *p != '\0'; p++) {
696417eba8cSderaadt 		/*
697417eba8cSderaadt 		 * Note that we'd really like to differentiate case here,
698417eba8cSderaadt 		 * but the Alpha AXP Architecture Reference Manual
699417eba8cSderaadt 		 * says that we shouldn't.
700417eba8cSderaadt 		 */
701df930be7Sderaadt 		switch (*p) {
702371c77f5Smartin 		case 'a': /* Ignore */
703417eba8cSderaadt 		case 'A':
704df930be7Sderaadt 			break;
705df930be7Sderaadt 
70612f8bbedSniklas 		case 'b': /* Enter DDB as soon as the console is initialised */
70712f8bbedSniklas 		case 'B':
70812f8bbedSniklas 			boothowto |= RB_KDB;
70912f8bbedSniklas 			break;
71012f8bbedSniklas 
71150ce9ee0Sniklas 		case 'c': /* enter user kernel configuration */
71250ce9ee0Sniklas 		case 'C':
71350ce9ee0Sniklas 			boothowto |= RB_CONFIG;
71450ce9ee0Sniklas 			break;
71550ce9ee0Sniklas 
71650ce9ee0Sniklas #ifdef DEBUG
71750ce9ee0Sniklas 		case 'd': /* crash dump immediately after autoconfig */
71850ce9ee0Sniklas 		case 'D':
71950ce9ee0Sniklas 			boothowto |= RB_DUMP;
72050ce9ee0Sniklas 			break;
72150ce9ee0Sniklas #endif
72250ce9ee0Sniklas 
72350ce9ee0Sniklas 		case 'h': /* always halt, never reboot */
72450ce9ee0Sniklas 		case 'H':
72550ce9ee0Sniklas 			boothowto |= RB_HALT;
726df930be7Sderaadt 			break;
727df930be7Sderaadt 
728417eba8cSderaadt #if 0
729417eba8cSderaadt 		case 'm': /* mini root present in memory */
730417eba8cSderaadt 		case 'M':
731417eba8cSderaadt 			boothowto |= RB_MINIROOT;
732417eba8cSderaadt 			break;
733417eba8cSderaadt #endif
73450ce9ee0Sniklas 
73550ce9ee0Sniklas 		case 'n': /* askname */
73650ce9ee0Sniklas 		case 'N':
73750ce9ee0Sniklas 			boothowto |= RB_ASKNAME;
73850ce9ee0Sniklas 			break;
739aed035abSart 
740371c77f5Smartin 		case 's': /* single-user */
741aed035abSart 		case 'S':
742aed035abSart 			boothowto |= RB_SINGLE;
743aed035abSart 			break;
744aed035abSart 
745aed035abSart 		case '-':
746aed035abSart 			/*
747aed035abSart 			 * Just ignore this.  It's not required, but it's
748aed035abSart 			 * common for it to be passed regardless.
749aed035abSart 			 */
750aed035abSart 			break;
751aed035abSart 
752aed035abSart 		default:
753aed035abSart 			printf("Unrecognized boot flag '%c'.\n", *p);
754aed035abSart 			break;
755df930be7Sderaadt 		}
756df930be7Sderaadt 	}
757df930be7Sderaadt 
758aed035abSart 
759df930be7Sderaadt 	/*
760df930be7Sderaadt 	 * Figure out the number of cpus in the box, from RPB fields.
761df930be7Sderaadt 	 * Really.  We mean it.
762df930be7Sderaadt 	 */
76331326ec3Smiod 	for (ncpusfound = 0, i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
764df930be7Sderaadt 		struct pcs *pcsp;
765df930be7Sderaadt 
766aed035abSart 		pcsp = LOCATE_PCS(hwrpb, i);
767df930be7Sderaadt 		if ((pcsp->pcs_flags & PCS_PP) != 0)
76831326ec3Smiod 			ncpusfound++;
769df930be7Sderaadt 	}
770aed035abSart 
771aed035abSart 	/*
772aed035abSart 	 * Initialize debuggers, and break into them if appropriate.
773aed035abSart 	 */
774aed035abSart #ifdef DDB
77521c23d01Smiod 	db_machine_init();
776aed035abSart 	ddb_init();
777aed035abSart 
778aed035abSart 	if (boothowto & RB_KDB)
779aed035abSart 		Debugger();
780aed035abSart #endif
781aed035abSart #ifdef KGDB
782aed035abSart 	if (boothowto & RB_KDB)
783aed035abSart 		kgdb_connect(0);
784aed035abSart #endif
785aed035abSart 	/*
786aed035abSart 	 * Figure out our clock frequency, from RPB fields.
787aed035abSart 	 */
788aed035abSart 	hz = hwrpb->rpb_intr_freq >> 12;
789aed035abSart 	if (!(60 <= hz && hz <= 10240)) {
790aed035abSart #ifdef DIAGNOSTIC
791aed035abSart 		printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n",
792aed035abSart 			hwrpb->rpb_intr_freq, hz);
793aed035abSart #endif
794dd3e8537Smiod 		hz = 1024;
795aed035abSart 	}
796aed035abSart }
797aed035abSart 
798417eba8cSderaadt void
799df930be7Sderaadt consinit()
800df930be7Sderaadt {
801aed035abSart 
802aed035abSart 	/*
803aed035abSart 	 * Everything related to console initialization is done
804aed035abSart 	 * in alpha_init().
805aed035abSart 	 */
806aed035abSart #if defined(DIAGNOSTIC) && defined(_PMAP_MAY_USE_PROM_CONSOLE)
807aed035abSart 	printf("consinit: %susing prom console\n",
808aed035abSart 	    pmap_uses_prom_console() ? "" : "not ");
80912f8bbedSniklas #endif
810df930be7Sderaadt }
811df930be7Sderaadt 
812417eba8cSderaadt void
813df930be7Sderaadt cpu_startup()
814df930be7Sderaadt {
815aed035abSart 	vaddr_t minaddr, maxaddr;
81650ce9ee0Sniklas #if defined(DEBUG)
817df930be7Sderaadt 	extern int pmapdebug;
818df930be7Sderaadt 	int opmapdebug = pmapdebug;
819df930be7Sderaadt 
820df930be7Sderaadt 	pmapdebug = 0;
821df930be7Sderaadt #endif
822df930be7Sderaadt 
823df930be7Sderaadt 	/*
824df930be7Sderaadt 	 * Good {morning,afternoon,evening,night}.
825df930be7Sderaadt 	 */
826df930be7Sderaadt 	printf(version);
827df930be7Sderaadt 	identifycpu();
828701cd583Smiod 	printf("real mem = %lu (%luMB)\n", ptoa((psize_t)totalphysmem),
829701cd583Smiod 	    ptoa((psize_t)totalphysmem) / 1024 / 1024);
830701cd583Smiod 	printf("rsvd mem = %lu (%luMB)\n", ptoa((psize_t)resvmem),
831701cd583Smiod 	    ptoa((psize_t)resvmem) / 1024 / 1024);
832aed035abSart 	if (unusedmem) {
833701cd583Smiod 		printf("WARNING: unused memory = %lu (%luMB)\n",
834701cd583Smiod 		    ptoa((psize_t)unusedmem),
835701cd583Smiod 		    ptoa((psize_t)unusedmem) / 1024 / 1024);
836aed035abSart 	}
837aed035abSart 	if (unknownmem) {
838701cd583Smiod 		printf("WARNING: %lu (%luMB) of memory with unknown purpose\n",
839701cd583Smiod 		    ptoa((psize_t)unknownmem),
840701cd583Smiod 		    ptoa((psize_t)unknownmem) / 1024 / 1024);
841aed035abSart 	}
842df930be7Sderaadt 
843df930be7Sderaadt 	/*
844df930be7Sderaadt 	 * Allocate a submap for exec arguments.  This map effectively
845df930be7Sderaadt 	 * limits the number of processes exec'ing at any time.
846df930be7Sderaadt 	 */
8477c10a71dSdrahn 	minaddr = vm_map_min(kernel_map);
848aed035abSart 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
849aed035abSart 	    16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
850df930be7Sderaadt 
851df930be7Sderaadt 	/*
852df930be7Sderaadt 	 * Allocate a submap for physio
853df930be7Sderaadt 	 */
854aed035abSart 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
855aed035abSart 	    VM_PHYS_SIZE, 0, FALSE, NULL);
856df930be7Sderaadt 
85750ce9ee0Sniklas #if defined(DEBUG)
858df930be7Sderaadt 	pmapdebug = opmapdebug;
859df930be7Sderaadt #endif
860701cd583Smiod 	printf("avail mem = %lu (%luMB)\n", ptoa((psize_t)uvmexp.free),
861701cd583Smiod 	    ptoa((psize_t)uvmexp.free) / 1024 / 1024);
862aed035abSart #if 0
863aed035abSart 	{
864aed035abSart 		extern u_long pmap_pages_stolen;
865aed035abSart 
866aed035abSart 		printf("stolen memory for VM structures = %d\n", pmap_pages_stolen * PAGE_SIZE);
867aed035abSart 	}
868aed035abSart #endif
869df930be7Sderaadt 
870df930be7Sderaadt 	/*
871df930be7Sderaadt 	 * Set up buffers, so they can be used to read disk labels.
872df930be7Sderaadt 	 */
873df930be7Sderaadt 	bufinit();
874df930be7Sderaadt 
875df930be7Sderaadt 	/*
876df930be7Sderaadt 	 * Configure the system.
877df930be7Sderaadt 	 */
87841033391Sderaadt 	if (boothowto & RB_CONFIG) {
87941033391Sderaadt #ifdef BOOT_CONFIG
88041033391Sderaadt 		user_config();
88141033391Sderaadt #else
88241033391Sderaadt 		printf("kernel does not support -c; continuing..\n");
88341033391Sderaadt #endif
88441033391Sderaadt 	}
88550ce9ee0Sniklas 
88650ce9ee0Sniklas 	/*
887aed035abSart 	 * Set up the HWPCB so that it's safe to configure secondary
888aed035abSart 	 * CPUs.
88950ce9ee0Sniklas 	 */
890aed035abSart 	hwrpb_primary_init();
891aed035abSart }
892aed035abSart 
893aed035abSart /*
894aed035abSart  * Retrieve the platform name from the DSR.
895aed035abSart  */
896aed035abSart const char *
897aed035abSart alpha_dsr_sysname()
898aed035abSart {
899aed035abSart 	struct dsrdb *dsr;
900aed035abSart 	const char *sysname;
901aed035abSart 
902aed035abSart 	/*
903aed035abSart 	 * DSR does not exist on early HWRPB versions.
904aed035abSart 	 */
905aed035abSart 	if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS)
906aed035abSart 		return (NULL);
907aed035abSart 
908aed035abSart 	dsr = (struct dsrdb *)(((caddr_t)hwrpb) + hwrpb->rpb_dsrdb_off);
909aed035abSart 	sysname = (const char *)((caddr_t)dsr + (dsr->dsr_sysname_off +
910aed035abSart 	    sizeof(u_int64_t)));
911aed035abSart 	return (sysname);
912aed035abSart }
913aed035abSart 
914aed035abSart /*
915aed035abSart  * Lookup the system specified system variation in the provided table,
916aed035abSart  * returning the model string on match.
917aed035abSart  */
918aed035abSart const char *
919aed035abSart alpha_variation_name(variation, avtp)
920aed035abSart 	u_int64_t variation;
921aed035abSart 	const struct alpha_variation_table *avtp;
922aed035abSart {
923aed035abSart 	int i;
924aed035abSart 
925aed035abSart 	for (i = 0; avtp[i].avt_model != NULL; i++)
926aed035abSart 		if (avtp[i].avt_variation == variation)
927aed035abSart 			return (avtp[i].avt_model);
928aed035abSart 	return (NULL);
929aed035abSart }
930aed035abSart 
931aed035abSart /*
932aed035abSart  * Generate a default platform name based for unknown system variations.
933aed035abSart  */
934aed035abSart const char *
935aed035abSart alpha_unknown_sysname()
936aed035abSart {
937aed035abSart 	static char s[128];		/* safe size */
938aed035abSart 
939d5eb2d9aSderaadt 	snprintf(s, sizeof s, "%s family, unknown model variation 0x%lx",
940aed035abSart 	    platform.family, hwrpb->rpb_variation & SV_ST_MASK);
941aed035abSart 	return ((const char *)s);
942df930be7Sderaadt }
943df930be7Sderaadt 
94450ce9ee0Sniklas void
945df930be7Sderaadt identifycpu()
946df930be7Sderaadt {
947aed035abSart 	char *s;
948b3cee53eSmartin 	int slen;
949df930be7Sderaadt 
950df930be7Sderaadt 	/*
951df930be7Sderaadt 	 * print out CPU identification information.
952df930be7Sderaadt 	 */
953aed035abSart 	printf("%s", cpu_model);
954aed035abSart 	for(s = cpu_model; *s; ++s)
955aed035abSart 		if(strncasecmp(s, "MHz", 3) == 0)
956aed035abSart 			goto skipMHz;
957aed035abSart 	printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000);
958aed035abSart skipMHz:
959b3cee53eSmartin 	/* fill in hw_serial if a serial number is known */
960b3cee53eSmartin 	slen = strlen(hwrpb->rpb_ssn) + 1;
961b3cee53eSmartin 	if (slen > 1) {
962b3cee53eSmartin 		hw_serial = malloc(slen, M_SYSCTL, M_NOWAIT);
963b3cee53eSmartin 		if (hw_serial)
964b3cee53eSmartin 			strlcpy(hw_serial, (char *)hwrpb->rpb_ssn, slen);
965b3cee53eSmartin 	}
966b3cee53eSmartin 
967aed035abSart 	printf("\n");
96850ce9ee0Sniklas 	printf("%ld byte page size, %d processor%s.\n",
96931326ec3Smiod 	    hwrpb->rpb_page_size, ncpusfound, ncpusfound == 1 ? "" : "s");
970df930be7Sderaadt #if 0
971b3cee53eSmartin 	/* this is not particularly useful! */
972df930be7Sderaadt 	printf("variation: 0x%lx, revision 0x%lx\n",
973df930be7Sderaadt 	    hwrpb->rpb_variation, *(long *)hwrpb->rpb_revision);
974df930be7Sderaadt #endif
975df930be7Sderaadt }
976df930be7Sderaadt 
977df930be7Sderaadt int	waittime = -1;
978df930be7Sderaadt struct pcb dumppcb;
979df930be7Sderaadt 
980417eba8cSderaadt void
981aed035abSart boot(howto)
982df930be7Sderaadt 	int howto;
983df930be7Sderaadt {
984aed035abSart #if defined(MULTIPROCESSOR)
98521c23d01Smiod 	u_long wait_mask;
98621c23d01Smiod 	int i;
987aed035abSart #endif
988aed035abSart 
989df930be7Sderaadt 	/* If system is cold, just halt. */
990df930be7Sderaadt 	if (cold) {
991c9ad5066Stom 		/* (Unless the user explicitly asked for reboot.) */
992c9ad5066Stom 		if ((howto & RB_USERREQ) == 0)
993df930be7Sderaadt 			howto |= RB_HALT;
994df930be7Sderaadt 		goto haltsys;
995df930be7Sderaadt 	}
996df930be7Sderaadt 
99750ce9ee0Sniklas 	/* If "always halt" was specified as a boot flag, obey. */
99850ce9ee0Sniklas 	if ((boothowto & RB_HALT) != 0)
99950ce9ee0Sniklas 		howto |= RB_HALT;
100050ce9ee0Sniklas 
1001df930be7Sderaadt 	boothowto = howto;
1002df930be7Sderaadt 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1003df930be7Sderaadt 		waittime = 0;
1004df930be7Sderaadt 		vfs_shutdown();
1005df930be7Sderaadt 		/*
1006df930be7Sderaadt 		 * If we've been adjusting the clock, the todr
10072417125dSmiod 		 * will be out of synch; adjust it now unless
10082417125dSmiod 		 * the system has been sitting in ddb.
1009df930be7Sderaadt 		 */
10102417125dSmiod 		if ((howto & RB_TIMEBAD) == 0) {
1011df930be7Sderaadt 			resettodr();
10122417125dSmiod 		} else {
10132417125dSmiod 			printf("WARNING: not updating battery clock\n");
10142417125dSmiod 		}
1015df930be7Sderaadt 	}
10167d9ca166Sderaadt 	if_downall();
1017df930be7Sderaadt 
1018c98e8b29Sderaadt 	uvm_shutdown();
1019c98e8b29Sderaadt 	splhigh();		/* Disable interrupts. */
1020df930be7Sderaadt 
102121c23d01Smiod #if defined(MULTIPROCESSOR)
102221c23d01Smiod 	/*
102321c23d01Smiod 	 * Halt all other CPUs.
102421c23d01Smiod 	 */
102521c23d01Smiod 	wait_mask = (1UL << hwrpb->rpb_primary_cpu_id);
102621c23d01Smiod 	alpha_broadcast_ipi(ALPHA_IPI_HALT);
102721c23d01Smiod 
102821c23d01Smiod 	/* Ensure any CPUs paused by DDB resume execution so they can halt */
102921c23d01Smiod 	cpus_paused = 0;
103021c23d01Smiod 
103121c23d01Smiod 	for (i = 0; i < 10000; i++) {
103221c23d01Smiod 		alpha_mb();
103321c23d01Smiod 		if (cpus_running == wait_mask)
103421c23d01Smiod 			break;
103521c23d01Smiod 		delay(1000);
103621c23d01Smiod 	}
103721c23d01Smiod 	alpha_mb();
103821c23d01Smiod 	if (cpus_running != wait_mask)
103921c23d01Smiod 		printf("WARNING: Unable to halt secondary CPUs (0x%lx)\n",
104021c23d01Smiod 		    cpus_running);
104121c23d01Smiod #endif
104221c23d01Smiod 
1043df930be7Sderaadt 	/* If rebooting and a dump is requested do it. */
104450ce9ee0Sniklas 	if (howto & RB_DUMP)
1045df930be7Sderaadt 		dumpsys();
1046df930be7Sderaadt 
104734fbf6deSderaadt haltsys:
1048df930be7Sderaadt 	doshutdownhooks();
10497313f802Smiod 	if (!TAILQ_EMPTY(&alldevs))
10501e4b376cSderaadt 		config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN);
1051df930be7Sderaadt 
105265c47ec0Sderaadt #ifdef BROKEN_PROM_CONSOLE
105365c47ec0Sderaadt 	sio_intr_shutdown(NULL);
105465c47ec0Sderaadt #endif
105565c47ec0Sderaadt 
1056df930be7Sderaadt #ifdef BOOTKEY
1057df930be7Sderaadt 	printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot");
1058aed035abSart 	cnpollc(1);	/* for proper keyboard command handling */
1059df930be7Sderaadt 	cngetc();
1060aed035abSart 	cnpollc(0);
1061df930be7Sderaadt 	printf("\n");
1062df930be7Sderaadt #endif
1063df930be7Sderaadt 
1064aed035abSart 	/* Finally, powerdown/halt/reboot the system. */
1065aed035abSart 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN &&
1066aed035abSart 	    platform.powerdown != NULL) {
1067aed035abSart 		(*platform.powerdown)();
1068aed035abSart 		printf("WARNING: powerdown failed!\n");
1069aed035abSart 	}
1070df930be7Sderaadt 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
1071df930be7Sderaadt 	prom_halt(howto & RB_HALT);
1072df930be7Sderaadt 	/*NOTREACHED*/
1073df930be7Sderaadt }
1074df930be7Sderaadt 
1075df930be7Sderaadt /*
1076df930be7Sderaadt  * These variables are needed by /sbin/savecore
1077df930be7Sderaadt  */
1078df930be7Sderaadt u_long	dumpmag = 0x8fca0101;	/* magic number */
1079df930be7Sderaadt int 	dumpsize = 0;		/* pages */
1080df930be7Sderaadt long	dumplo = 0; 		/* blocks */
1081df930be7Sderaadt 
1082df930be7Sderaadt /*
108350ce9ee0Sniklas  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
108450ce9ee0Sniklas  */
108550ce9ee0Sniklas int
108650ce9ee0Sniklas cpu_dumpsize()
108750ce9ee0Sniklas {
108850ce9ee0Sniklas 	int size;
108950ce9ee0Sniklas 
1090aed035abSart 	size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
1091aed035abSart 	    ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
109250ce9ee0Sniklas 	if (roundup(size, dbtob(1)) != dbtob(1))
109350ce9ee0Sniklas 		return -1;
109450ce9ee0Sniklas 
109550ce9ee0Sniklas 	return (1);
109650ce9ee0Sniklas }
109750ce9ee0Sniklas 
109850ce9ee0Sniklas /*
1099aed035abSart  * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped.
1100aed035abSart  */
1101aed035abSart u_long
1102aed035abSart cpu_dump_mempagecnt()
1103aed035abSart {
1104aed035abSart 	u_long i, n;
1105aed035abSart 
1106aed035abSart 	n = 0;
1107aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++)
1108aed035abSart 		n += atop(mem_clusters[i].size);
1109aed035abSart 	return (n);
1110aed035abSart }
1111aed035abSart 
1112aed035abSart /*
111350ce9ee0Sniklas  * cpu_dump: dump machine-dependent kernel core dump headers.
111450ce9ee0Sniklas  */
111550ce9ee0Sniklas int
111650ce9ee0Sniklas cpu_dump()
111750ce9ee0Sniklas {
11181abdbfdeSderaadt 	int (*dump)(dev_t, daddr_t, caddr_t, size_t);
1119aed035abSart 	char buf[dbtob(1)];
112050ce9ee0Sniklas 	kcore_seg_t *segp;
112150ce9ee0Sniklas 	cpu_kcore_hdr_t *cpuhdrp;
1122aed035abSart 	phys_ram_seg_t *memsegp;
1123aed035abSart 	int i;
112450ce9ee0Sniklas 
112550ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
112650ce9ee0Sniklas 
1127aed035abSart 	bzero(buf, sizeof buf);
112850ce9ee0Sniklas 	segp = (kcore_seg_t *)buf;
1129aed035abSart 	cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
1130aed035abSart 	memsegp = (phys_ram_seg_t *)&buf[ALIGN(sizeof(*segp)) +
1131aed035abSart 	    ALIGN(sizeof(*cpuhdrp))];
113250ce9ee0Sniklas 
113350ce9ee0Sniklas 	/*
113450ce9ee0Sniklas 	 * Generate a segment header.
113550ce9ee0Sniklas 	 */
113650ce9ee0Sniklas 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
113750ce9ee0Sniklas 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
113850ce9ee0Sniklas 
113950ce9ee0Sniklas 	/*
1140aed035abSart 	 * Add the machine-dependent header info.
114150ce9ee0Sniklas 	 */
1142aed035abSart 	cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map);
114350ce9ee0Sniklas 	cpuhdrp->page_size = PAGE_SIZE;
1144aed035abSart 	cpuhdrp->nmemsegs = mem_cluster_cnt;
1145aed035abSart 
1146aed035abSart 	/*
1147aed035abSart 	 * Fill in the memory segment descriptors.
1148aed035abSart 	 */
1149aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
1150aed035abSart 		memsegp[i].start = mem_clusters[i].start;
1151aed035abSart 		memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK;
1152aed035abSart 	}
115350ce9ee0Sniklas 
115450ce9ee0Sniklas 	return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
115550ce9ee0Sniklas }
115650ce9ee0Sniklas 
115750ce9ee0Sniklas /*
1158aed035abSart  * This is called by main to set dumplo and dumpsize.
1159194dd68bSbrad  * Dumps always skip the first PAGE_SIZE of disk space
1160df930be7Sderaadt  * in case there might be a disk label stored there.
1161df930be7Sderaadt  * If there is extra space, put dump at the end to
1162df930be7Sderaadt  * reduce the chance that swapping trashes it.
1163df930be7Sderaadt  */
1164df930be7Sderaadt void
1165e17d3b39Sderaadt dumpconf(void)
1166df930be7Sderaadt {
116750ce9ee0Sniklas 	int nblks, dumpblks;	/* size of dump area */
1168df930be7Sderaadt 
1169e17d3b39Sderaadt 	if (dumpdev == NODEV ||
1170e17d3b39Sderaadt 	    (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
1171e17d3b39Sderaadt 		return;
1172df930be7Sderaadt 	if (nblks <= ctod(1))
1173e17d3b39Sderaadt 		return;
117450ce9ee0Sniklas 
117550ce9ee0Sniklas 	dumpblks = cpu_dumpsize();
117650ce9ee0Sniklas 	if (dumpblks < 0)
1177e17d3b39Sderaadt 		return;
1178aed035abSart 	dumpblks += ctod(cpu_dump_mempagecnt());
117950ce9ee0Sniklas 
118050ce9ee0Sniklas 	/* If dump won't fit (incl. room for possible label), punt. */
118150ce9ee0Sniklas 	if (dumpblks > (nblks - ctod(1)))
1182e17d3b39Sderaadt 		return;
118350ce9ee0Sniklas 
118450ce9ee0Sniklas 	/* Put dump at end of partition */
118550ce9ee0Sniklas 	dumplo = nblks - dumpblks;
118650ce9ee0Sniklas 
118750ce9ee0Sniklas 	/* dumpsize is in page units, and doesn't include headers. */
1188aed035abSart 	dumpsize = cpu_dump_mempagecnt();
1189df930be7Sderaadt }
1190df930be7Sderaadt 
1191df930be7Sderaadt /*
119250ce9ee0Sniklas  * Dump the kernel's image to the swap partition.
1193df930be7Sderaadt  */
1194194dd68bSbrad #define	BYTES_PER_DUMP	PAGE_SIZE
119550ce9ee0Sniklas 
1196df930be7Sderaadt void
1197df930be7Sderaadt dumpsys()
1198df930be7Sderaadt {
1199aed035abSart 	u_long totalbytesleft, bytes, i, n, memcl;
1200aed035abSart 	u_long maddr;
1201aed035abSart 	int psize;
12021abdbfdeSderaadt 	daddr_t blkno;
12031abdbfdeSderaadt 	int (*dump)(dev_t, daddr_t, caddr_t, size_t);
120450ce9ee0Sniklas 	int error;
1205067cbd75Sderaadt 	extern int msgbufmapped;
1206df930be7Sderaadt 
120750ce9ee0Sniklas 	/* Save registers. */
120850ce9ee0Sniklas 	savectx(&dumppcb);
120950ce9ee0Sniklas 
121050ce9ee0Sniklas 	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
1211df930be7Sderaadt 	if (dumpdev == NODEV)
1212df930be7Sderaadt 		return;
121350ce9ee0Sniklas 
121450ce9ee0Sniklas 	/*
121550ce9ee0Sniklas 	 * For dumps during autoconfiguration,
121650ce9ee0Sniklas 	 * if dump device has already configured...
121750ce9ee0Sniklas 	 */
1218df930be7Sderaadt 	if (dumpsize == 0)
121950ce9ee0Sniklas 		dumpconf();
122050ce9ee0Sniklas 	if (dumplo <= 0) {
1221aed035abSart 		printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
1222aed035abSart 		    minor(dumpdev));
1223df930be7Sderaadt 		return;
1224df930be7Sderaadt 	}
1225aed035abSart 	printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
1226aed035abSart 	    minor(dumpdev), dumplo);
1227df930be7Sderaadt 
12281b720b8bSmiod #ifdef UVM_SWAP_ENCRYPT
12291b720b8bSmiod 	uvm_swap_finicrypt_all();
12301b720b8bSmiod #endif
12311b720b8bSmiod 
123250ce9ee0Sniklas 	psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1233df930be7Sderaadt 	printf("dump ");
123450ce9ee0Sniklas 	if (psize == -1) {
123550ce9ee0Sniklas 		printf("area unavailable\n");
123650ce9ee0Sniklas 		return;
123750ce9ee0Sniklas 	}
123850ce9ee0Sniklas 
123950ce9ee0Sniklas 	/* XXX should purge all outstanding keystrokes. */
124050ce9ee0Sniklas 
124150ce9ee0Sniklas 	if ((error = cpu_dump()) != 0)
124250ce9ee0Sniklas 		goto err;
124350ce9ee0Sniklas 
1244aed035abSart 	totalbytesleft = ptoa(cpu_dump_mempagecnt());
124550ce9ee0Sniklas 	blkno = dumplo + cpu_dumpsize();
124650ce9ee0Sniklas 	dump = bdevsw[major(dumpdev)].d_dump;
124750ce9ee0Sniklas 	error = 0;
1248aed035abSart 
1249aed035abSart 	for (memcl = 0; memcl < mem_cluster_cnt; memcl++) {
1250aed035abSart 		maddr = mem_clusters[memcl].start;
1251aed035abSart 		bytes = mem_clusters[memcl].size & ~PAGE_MASK;
1252aed035abSart 
1253aed035abSart 		for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
125450ce9ee0Sniklas 
125550ce9ee0Sniklas 			/* Print out how many MBs we to go. */
1256aed035abSart 			if ((totalbytesleft % (1024*1024)) == 0)
1257aed035abSart 				printf("%ld ", totalbytesleft / (1024 * 1024));
125850ce9ee0Sniklas 
125950ce9ee0Sniklas 			/* Limit size for next transfer. */
1260aed035abSart 			n = bytes - i;
126150ce9ee0Sniklas 			if (n > BYTES_PER_DUMP)
126250ce9ee0Sniklas 				n =  BYTES_PER_DUMP;
126350ce9ee0Sniklas 
126450ce9ee0Sniklas 			error = (*dump)(dumpdev, blkno,
126550ce9ee0Sniklas 			    (caddr_t)ALPHA_PHYS_TO_K0SEG(maddr), n);
126650ce9ee0Sniklas 			if (error)
1267aed035abSart 				goto err;
126850ce9ee0Sniklas 			maddr += n;
126950ce9ee0Sniklas 			blkno += btodb(n);			/* XXX? */
127050ce9ee0Sniklas 
127150ce9ee0Sniklas 			/* XXX should look for keystrokes, to cancel. */
127250ce9ee0Sniklas 		}
1273aed035abSart 	}
127450ce9ee0Sniklas 
127550ce9ee0Sniklas err:
127650ce9ee0Sniklas 	switch (error) {
1277a37778bcSderaadt #ifdef DEBUG
1278df930be7Sderaadt 	case ENXIO:
1279df930be7Sderaadt 		printf("device bad\n");
1280df930be7Sderaadt 		break;
1281df930be7Sderaadt 
1282df930be7Sderaadt 	case EFAULT:
1283df930be7Sderaadt 		printf("device not ready\n");
1284df930be7Sderaadt 		break;
1285df930be7Sderaadt 
1286df930be7Sderaadt 	case EINVAL:
1287df930be7Sderaadt 		printf("area improper\n");
1288df930be7Sderaadt 		break;
1289df930be7Sderaadt 
1290df930be7Sderaadt 	case EIO:
1291df930be7Sderaadt 		printf("i/o error\n");
1292df930be7Sderaadt 		break;
1293df930be7Sderaadt 
1294df930be7Sderaadt 	case EINTR:
1295df930be7Sderaadt 		printf("aborted from console\n");
1296df930be7Sderaadt 		break;
1297a37778bcSderaadt #endif /* DEBUG */
129850ce9ee0Sniklas 	case 0:
1299df930be7Sderaadt 		printf("succeeded\n");
1300df930be7Sderaadt 		break;
130150ce9ee0Sniklas 
130250ce9ee0Sniklas 	default:
130350ce9ee0Sniklas 		printf("error %d\n", error);
130450ce9ee0Sniklas 		break;
1305df930be7Sderaadt 	}
1306df930be7Sderaadt 	printf("\n\n");
1307df930be7Sderaadt 	delay(1000);
1308df930be7Sderaadt }
1309df930be7Sderaadt 
1310df930be7Sderaadt void
1311df930be7Sderaadt frametoreg(framep, regp)
1312df930be7Sderaadt 	struct trapframe *framep;
1313df930be7Sderaadt 	struct reg *regp;
1314df930be7Sderaadt {
1315df930be7Sderaadt 
1316df930be7Sderaadt 	regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0];
1317df930be7Sderaadt 	regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0];
1318df930be7Sderaadt 	regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1];
1319df930be7Sderaadt 	regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2];
1320df930be7Sderaadt 	regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3];
1321df930be7Sderaadt 	regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4];
1322df930be7Sderaadt 	regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5];
1323df930be7Sderaadt 	regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6];
1324df930be7Sderaadt 	regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7];
1325df930be7Sderaadt 	regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0];
1326df930be7Sderaadt 	regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1];
1327df930be7Sderaadt 	regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2];
1328df930be7Sderaadt 	regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3];
1329df930be7Sderaadt 	regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4];
1330df930be7Sderaadt 	regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5];
1331df930be7Sderaadt 	regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6];
133250ce9ee0Sniklas 	regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0];
133350ce9ee0Sniklas 	regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1];
133450ce9ee0Sniklas 	regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2];
1335df930be7Sderaadt 	regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3];
1336df930be7Sderaadt 	regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4];
1337df930be7Sderaadt 	regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5];
1338df930be7Sderaadt 	regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8];
1339df930be7Sderaadt 	regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9];
1340df930be7Sderaadt 	regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10];
1341df930be7Sderaadt 	regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11];
1342df930be7Sderaadt 	regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA];
1343df930be7Sderaadt 	regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12];
1344df930be7Sderaadt 	regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT];
134550ce9ee0Sniklas 	regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP];
134650ce9ee0Sniklas 	/* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */
1347df930be7Sderaadt 	regp->r_regs[R_ZERO] = 0;
1348df930be7Sderaadt }
1349df930be7Sderaadt 
1350df930be7Sderaadt void
1351df930be7Sderaadt regtoframe(regp, framep)
1352df930be7Sderaadt 	struct reg *regp;
1353df930be7Sderaadt 	struct trapframe *framep;
1354df930be7Sderaadt {
1355df930be7Sderaadt 
1356df930be7Sderaadt 	framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0];
1357df930be7Sderaadt 	framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0];
1358df930be7Sderaadt 	framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1];
1359df930be7Sderaadt 	framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2];
1360df930be7Sderaadt 	framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3];
1361df930be7Sderaadt 	framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4];
1362df930be7Sderaadt 	framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5];
1363df930be7Sderaadt 	framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6];
1364df930be7Sderaadt 	framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7];
1365df930be7Sderaadt 	framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0];
1366df930be7Sderaadt 	framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1];
1367df930be7Sderaadt 	framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2];
1368df930be7Sderaadt 	framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3];
1369df930be7Sderaadt 	framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4];
1370df930be7Sderaadt 	framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5];
1371df930be7Sderaadt 	framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6];
137250ce9ee0Sniklas 	framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0];
137350ce9ee0Sniklas 	framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1];
137450ce9ee0Sniklas 	framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2];
1375df930be7Sderaadt 	framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3];
1376df930be7Sderaadt 	framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4];
1377df930be7Sderaadt 	framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5];
1378df930be7Sderaadt 	framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8];
1379df930be7Sderaadt 	framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9];
1380df930be7Sderaadt 	framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10];
1381df930be7Sderaadt 	framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11];
1382df930be7Sderaadt 	framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA];
1383df930be7Sderaadt 	framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12];
1384df930be7Sderaadt 	framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT];
138550ce9ee0Sniklas 	framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP];
138650ce9ee0Sniklas 	/* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */
1387df930be7Sderaadt 	/* ??? = regp->r_regs[R_ZERO]; */
1388df930be7Sderaadt }
1389df930be7Sderaadt 
1390df930be7Sderaadt void
1391df930be7Sderaadt printregs(regp)
1392df930be7Sderaadt 	struct reg *regp;
1393df930be7Sderaadt {
1394df930be7Sderaadt 	int i;
1395df930be7Sderaadt 
1396df930be7Sderaadt 	for (i = 0; i < 32; i++)
1397df930be7Sderaadt 		printf("R%d:\t0x%016lx%s", i, regp->r_regs[i],
1398df930be7Sderaadt 		   i & 1 ? "\n" : "\t");
1399df930be7Sderaadt }
1400df930be7Sderaadt 
1401df930be7Sderaadt void
1402df930be7Sderaadt regdump(framep)
1403df930be7Sderaadt 	struct trapframe *framep;
1404df930be7Sderaadt {
1405df930be7Sderaadt 	struct reg reg;
1406df930be7Sderaadt 
1407df930be7Sderaadt 	frametoreg(framep, &reg);
140850ce9ee0Sniklas 	reg.r_regs[R_SP] = alpha_pal_rdusp();
140950ce9ee0Sniklas 
1410df930be7Sderaadt 	printf("REGISTERS:\n");
1411df930be7Sderaadt 	printregs(&reg);
1412df930be7Sderaadt }
1413df930be7Sderaadt 
1414df930be7Sderaadt #ifdef DEBUG
1415df930be7Sderaadt int sigdebug = 0;
141672830333Sokan pid_t sigpid = 0;
1417df930be7Sderaadt #define	SDB_FOLLOW	0x01
1418df930be7Sderaadt #define	SDB_KSTACK	0x02
1419df930be7Sderaadt #endif
1420df930be7Sderaadt 
1421df930be7Sderaadt /*
1422df930be7Sderaadt  * Send an interrupt to process.
1423df930be7Sderaadt  */
1424df930be7Sderaadt void
14255e1760a6Sderaadt sendsig(catcher, sig, mask, code, type, val)
1426df930be7Sderaadt 	sig_t catcher;
1427df930be7Sderaadt 	int sig, mask;
1428df930be7Sderaadt 	u_long code;
14295e1760a6Sderaadt 	int type;
14305e1760a6Sderaadt 	union sigval val;
1431df930be7Sderaadt {
1432df930be7Sderaadt 	struct proc *p = curproc;
1433df930be7Sderaadt 	struct sigcontext *scp, ksc;
1434e7e08221Smiod 	struct fpreg *fpregs = (struct fpreg *)&ksc.sc_fpregs;
1435df930be7Sderaadt 	struct trapframe *frame;
1436df930be7Sderaadt 	struct sigacts *psp = p->p_sigacts;
14371eaa59e7Sguenther 	unsigned long oldsp;
14381eaa59e7Sguenther 	int fsize, rndfsize, kscsize;
14392bf9c155Sderaadt 	siginfo_t *sip, ksi;
1440df930be7Sderaadt 
14411eaa59e7Sguenther 	oldsp = alpha_pal_rdusp();
1442df930be7Sderaadt 	frame = p->p_md.md_tf;
1443df930be7Sderaadt 	fsize = sizeof ksc;
1444df930be7Sderaadt 	rndfsize = ((fsize + 15) / 16) * 16;
14452bf9c155Sderaadt 	kscsize = rndfsize;
14462bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
14472bf9c155Sderaadt 		fsize += sizeof ksi;
14482bf9c155Sderaadt 		rndfsize = ((fsize + 15) / 16) * 16;
14492bf9c155Sderaadt 	}
145074652a67Sniklas 
1451df930be7Sderaadt 	/*
1452df930be7Sderaadt 	 * Allocate and validate space for the signal handler
1453df930be7Sderaadt 	 * context. Note that if the stack is in P0 space, the
1454aed035abSart 	 * call to uvm_grow() is a nop, and the useracc() check
1455df930be7Sderaadt 	 * will fail if the process has not already allocated
1456df930be7Sderaadt 	 * the space with a `brk'.
1457df930be7Sderaadt 	 */
14581eaa59e7Sguenther 	if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
14591eaa59e7Sguenther 	    !sigonstack(oldsp) && (psp->ps_sigonstack & sigmask(sig)))
14602725daddSguenther 		scp = (struct sigcontext *)(p->p_sigstk.ss_sp +
14612725daddSguenther 		    p->p_sigstk.ss_size - rndfsize);
14621eaa59e7Sguenther 	else
14631eaa59e7Sguenther 		scp = (struct sigcontext *)(oldsp - rndfsize);
146476d52da2Smartin 	if ((u_long)scp <= USRSTACK - ptoa(p->p_vmspace->vm_ssize))
1465aed035abSart 		(void)uvm_grow(p, (u_long)scp);
1466df930be7Sderaadt #ifdef DEBUG
1467df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
146850ce9ee0Sniklas 		printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
14691eaa59e7Sguenther 		    sig, &ksc, scp);
1470df930be7Sderaadt #endif
1471df930be7Sderaadt 
1472df930be7Sderaadt 	/*
1473df930be7Sderaadt 	 * Build the signal context to be used by sigreturn.
1474df930be7Sderaadt 	 */
14751eaa59e7Sguenther 	bzero(&ksc, sizeof(ksc));
1476df930be7Sderaadt 	ksc.sc_mask = mask;
147750ce9ee0Sniklas 	ksc.sc_pc = frame->tf_regs[FRAME_PC];
147850ce9ee0Sniklas 	ksc.sc_ps = frame->tf_regs[FRAME_PS];
1479df930be7Sderaadt 
1480df930be7Sderaadt 	/* copy the registers. */
1481df930be7Sderaadt 	frametoreg(frame, (struct reg *)ksc.sc_regs);
1482df930be7Sderaadt 	ksc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
14831eaa59e7Sguenther 	ksc.sc_regs[R_SP] = oldsp;
1484df930be7Sderaadt 
1485df930be7Sderaadt 	/* save the floating-point state, if necessary, then copy it. */
1486433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1487433075b6Spvalchev 		fpusave_proc(p, 1);
1488df930be7Sderaadt 	ksc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
1489e7e08221Smiod 	memcpy(/*ksc.sc_*/fpregs, &p->p_addr->u_pcb.pcb_fp,
1490df930be7Sderaadt 	    sizeof(struct fpreg));
1491433075b6Spvalchev #ifndef NO_IEEE
1492433075b6Spvalchev 	ksc.sc_fp_control = alpha_read_fp_c(p);
1493433075b6Spvalchev #else
1494433075b6Spvalchev 	ksc.sc_fp_control = 0;
1495433075b6Spvalchev #endif
1496433075b6Spvalchev 	memset(ksc.sc_reserved, 0, sizeof ksc.sc_reserved);	/* XXX */
1497433075b6Spvalchev 	memset(ksc.sc_xxx, 0, sizeof ksc.sc_xxx);		/* XXX */
1498df930be7Sderaadt 
14992bf9c155Sderaadt 	if (psp->ps_siginfo & sigmask(sig)) {
15002bf9c155Sderaadt 		initsiginfo(&ksi, sig, code, type, val);
15012bf9c155Sderaadt 		sip = (void *)scp + kscsize;
1502679ebc41Smiod 		if (copyout((caddr_t)&ksi, (caddr_t)sip, fsize - kscsize) != 0)
1503679ebc41Smiod 			goto trash;
1504aa540fb8Sart 	} else
1505aa540fb8Sart 		sip = NULL;
15062bf9c155Sderaadt 
1507df930be7Sderaadt 	/*
1508df930be7Sderaadt 	 * copy the frame out to userland.
1509df930be7Sderaadt 	 */
1510679ebc41Smiod 	if (copyout((caddr_t)&ksc, (caddr_t)scp, kscsize) != 0) {
1511679ebc41Smiod trash:
1512679ebc41Smiod #ifdef DEBUG
1513679ebc41Smiod 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1514679ebc41Smiod 			printf("sendsig(%d): copyout failed on sig %d\n",
1515679ebc41Smiod 			    p->p_pid, sig);
1516679ebc41Smiod #endif
1517679ebc41Smiod 		/*
1518679ebc41Smiod 		 * Process has trashed its stack; give it an illegal
1519679ebc41Smiod 		 * instruction to halt it in its tracks.
1520679ebc41Smiod 		 */
152186fd84b3Smiod 		sigexit(p, SIGILL);
152286fd84b3Smiod 		/* NOTREACHED */
1523679ebc41Smiod 	}
1524df930be7Sderaadt #ifdef DEBUG
1525df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
152650ce9ee0Sniklas 		printf("sendsig(%d): sig %d scp %p code %lx\n", p->p_pid, sig,
1527df930be7Sderaadt 		    scp, code);
1528df930be7Sderaadt #endif
1529df930be7Sderaadt 
1530df930be7Sderaadt 	/*
1531df930be7Sderaadt 	 * Set up the registers to return to sigcode.
1532df930be7Sderaadt 	 */
15334a5480feSart 	frame->tf_regs[FRAME_PC] = p->p_sigcode;
153450ce9ee0Sniklas 	frame->tf_regs[FRAME_A0] = sig;
1535aa540fb8Sart 	frame->tf_regs[FRAME_A1] = (u_int64_t)sip;
153650ce9ee0Sniklas 	frame->tf_regs[FRAME_A2] = (u_int64_t)scp;
1537df930be7Sderaadt 	frame->tf_regs[FRAME_T12] = (u_int64_t)catcher;		/* t12 is pv */
153850ce9ee0Sniklas 	alpha_pal_wrusp((unsigned long)scp);
1539df930be7Sderaadt 
1540df930be7Sderaadt #ifdef DEBUG
1541df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1542df930be7Sderaadt 		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
154350ce9ee0Sniklas 		    frame->tf_regs[FRAME_PC], frame->tf_regs[FRAME_A3]);
1544df930be7Sderaadt 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1545df930be7Sderaadt 		printf("sendsig(%d): sig %d returns\n",
1546df930be7Sderaadt 		    p->p_pid, sig);
1547df930be7Sderaadt #endif
1548df930be7Sderaadt }
1549df930be7Sderaadt 
1550df930be7Sderaadt /*
1551df930be7Sderaadt  * System call to cleanup state after a signal
1552df930be7Sderaadt  * has been taken.  Reset signal mask and
1553df930be7Sderaadt  * stack state from context left by sendsig (above).
1554df930be7Sderaadt  * Return to previous pc and psl as specified by
1555df930be7Sderaadt  * context left by sendsig. Check carefully to
1556df930be7Sderaadt  * make sure that the user has not modified the
1557125cd19fSderaadt  * psl to gain improper privileges or to cause
1558df930be7Sderaadt  * a machine fault.
1559df930be7Sderaadt  */
1560df930be7Sderaadt /* ARGSUSED */
1561df930be7Sderaadt int
1562df930be7Sderaadt sys_sigreturn(p, v, retval)
1563df930be7Sderaadt 	struct proc *p;
1564df930be7Sderaadt 	void *v;
1565df930be7Sderaadt 	register_t *retval;
1566df930be7Sderaadt {
1567df930be7Sderaadt 	struct sys_sigreturn_args /* {
1568df930be7Sderaadt 		syscallarg(struct sigcontext *) sigcntxp;
1569df930be7Sderaadt 	} */ *uap = v;
1570aa540fb8Sart 	struct sigcontext ksc;
1571e7e08221Smiod 	struct fpreg *fpregs = (struct fpreg *)&ksc.sc_fpregs;
157260959295Smartin #ifdef DEBUG
157360959295Smartin 	struct sigcontext *scp;
157460959295Smartin #endif
1575aa540fb8Sart 	int error;
1576df930be7Sderaadt 
1577df930be7Sderaadt #ifdef DEBUG
1578df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
157950ce9ee0Sniklas 	    printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
1580df930be7Sderaadt #endif
1581df930be7Sderaadt 
1582df930be7Sderaadt 	/*
1583df930be7Sderaadt 	 * Test and fetch the context structure.
1584df930be7Sderaadt 	 * We grab it all at once for speed.
1585df930be7Sderaadt 	 */
1586aa540fb8Sart 	if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0)
1587aa540fb8Sart 		return (error);
1588df930be7Sderaadt 
1589df930be7Sderaadt 	if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)		/* magic number */
1590df930be7Sderaadt 		return (EINVAL);
1591df930be7Sderaadt 	/*
1592df930be7Sderaadt 	 * Restore the user-supplied information
1593df930be7Sderaadt 	 */
1594df930be7Sderaadt 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
1595df930be7Sderaadt 
159650ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
159750ce9ee0Sniklas 	p->p_md.md_tf->tf_regs[FRAME_PS] =
159850ce9ee0Sniklas 	    (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
1599df930be7Sderaadt 
1600df930be7Sderaadt 	regtoframe((struct reg *)ksc.sc_regs, p->p_md.md_tf);
160150ce9ee0Sniklas 	alpha_pal_wrusp(ksc.sc_regs[R_SP]);
1602df930be7Sderaadt 
1603df930be7Sderaadt 	/* XXX ksc.sc_ownedfp ? */
1604433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1605433075b6Spvalchev 		fpusave_proc(p, 0);
1606e7e08221Smiod 	memcpy(&p->p_addr->u_pcb.pcb_fp, /*ksc.sc_*/fpregs,
1607df930be7Sderaadt 	    sizeof(struct fpreg));
1608433075b6Spvalchev #ifndef NO_IEEE
1609433075b6Spvalchev 	p->p_addr->u_pcb.pcb_fp.fpr_cr = ksc.sc_fpcr;
1610433075b6Spvalchev 	p->p_md.md_flags = ksc.sc_fp_control & MDP_FP_C;
1611433075b6Spvalchev #endif
1612df930be7Sderaadt 
1613df930be7Sderaadt #ifdef DEBUG
1614df930be7Sderaadt 	if (sigdebug & SDB_FOLLOW)
1615df930be7Sderaadt 		printf("sigreturn(%d): returns\n", p->p_pid);
1616df930be7Sderaadt #endif
1617df930be7Sderaadt 	return (EJUSTRETURN);
1618df930be7Sderaadt }
1619df930be7Sderaadt 
1620df930be7Sderaadt /*
1621df930be7Sderaadt  * machine dependent system variables.
1622df930be7Sderaadt  */
162350ce9ee0Sniklas int
1624df930be7Sderaadt cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1625df930be7Sderaadt 	int *name;
1626df930be7Sderaadt 	u_int namelen;
1627df930be7Sderaadt 	void *oldp;
1628df930be7Sderaadt 	size_t *oldlenp;
1629df930be7Sderaadt 	void *newp;
1630df930be7Sderaadt 	size_t newlen;
1631df930be7Sderaadt 	struct proc *p;
1632df930be7Sderaadt {
1633df930be7Sderaadt 	dev_t consdev;
1634a072164aSmiod #if NIOASIC > 0
1635a072164aSmiod 	int oldval, ret;
1636a072164aSmiod #endif
1637df930be7Sderaadt 
163845e5a1a0Sart 	if (name[0] != CPU_CHIPSET && namelen != 1)
1639df930be7Sderaadt 		return (ENOTDIR);		/* overloaded */
1640df930be7Sderaadt 
1641df930be7Sderaadt 	switch (name[0]) {
1642df930be7Sderaadt 	case CPU_CONSDEV:
1643df930be7Sderaadt 		if (cn_tab != NULL)
1644df930be7Sderaadt 			consdev = cn_tab->cn_dev;
1645df930be7Sderaadt 		else
1646df930be7Sderaadt 			consdev = NODEV;
1647df930be7Sderaadt 		return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
1648df930be7Sderaadt 			sizeof consdev));
1649417eba8cSderaadt 
1650a37778bcSderaadt #ifndef SMALL_KERNEL
165150ce9ee0Sniklas 	case CPU_UNALIGNED_PRINT:
165250ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
165350ce9ee0Sniklas 		    &alpha_unaligned_print));
165450ce9ee0Sniklas 
165550ce9ee0Sniklas 	case CPU_UNALIGNED_FIX:
165650ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
165750ce9ee0Sniklas 		    &alpha_unaligned_fix));
165850ce9ee0Sniklas 
165950ce9ee0Sniklas 	case CPU_UNALIGNED_SIGBUS:
166050ce9ee0Sniklas 		return (sysctl_int(oldp, oldlenp, newp, newlen,
166150ce9ee0Sniklas 		    &alpha_unaligned_sigbus));
166250ce9ee0Sniklas 
16633a630e3fSniklas 	case CPU_BOOTED_KERNEL:
1664aed035abSart 		return (sysctl_rdstring(oldp, oldlenp, newp,
1665aed035abSart 		    bootinfo.booted_kernel));
16663a630e3fSniklas 
166745e5a1a0Sart 	case CPU_CHIPSET:
166845e5a1a0Sart 		return (alpha_sysctl_chipset(name + 1, namelen - 1, oldp,
166945e5a1a0Sart 		    oldlenp));
1670a37778bcSderaadt #endif /* SMALL_KERNEL */
1671433075b6Spvalchev 
1672433075b6Spvalchev #ifndef NO_IEEE
1673433075b6Spvalchev 	case CPU_FP_SYNC_COMPLETE:
1674433075b6Spvalchev 		return (sysctl_int(oldp, oldlenp, newp, newlen,
1675433075b6Spvalchev 		    &alpha_fp_sync_complete));
1676433075b6Spvalchev #endif
167727626149Smatthieu 	case CPU_ALLOWAPERTURE:
167827626149Smatthieu #ifdef APERTURE
167927626149Smatthieu 		if (securelevel > 0)
16801546ceefSderaadt 			return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
16811546ceefSderaadt 			    &allowaperture));
168227626149Smatthieu                 else
168327626149Smatthieu                         return (sysctl_int(oldp, oldlenp, newp, newlen,
168427626149Smatthieu                             &allowaperture));
168527626149Smatthieu #else
168627626149Smatthieu 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
168727626149Smatthieu #endif
1688a072164aSmiod #if NIOASIC > 0
1689a072164aSmiod 	case CPU_LED_BLINK:
1690a072164aSmiod 		oldval = alpha_led_blink;
1691a072164aSmiod 		ret = sysctl_int(oldp, oldlenp, newp, newlen, &alpha_led_blink);
1692a072164aSmiod 		if (oldval != alpha_led_blink)
1693a072164aSmiod 			ioasic_led_blink(NULL);
1694a072164aSmiod 		return (ret);
1695a072164aSmiod #endif
1696df930be7Sderaadt 	default:
1697df930be7Sderaadt 		return (EOPNOTSUPP);
1698df930be7Sderaadt 	}
1699df930be7Sderaadt 	/* NOTREACHED */
1700df930be7Sderaadt }
1701df930be7Sderaadt 
1702df930be7Sderaadt /*
1703df930be7Sderaadt  * Set registers on exec.
1704df930be7Sderaadt  */
1705df930be7Sderaadt void
1706df930be7Sderaadt setregs(p, pack, stack, retval)
1707df930be7Sderaadt 	register struct proc *p;
1708df930be7Sderaadt 	struct exec_package *pack;
1709df930be7Sderaadt 	u_long stack;
1710df930be7Sderaadt 	register_t *retval;
1711df930be7Sderaadt {
1712df930be7Sderaadt 	struct trapframe *tfp = p->p_md.md_tf;
17133a630e3fSniklas #ifdef DEBUG
17143a630e3fSniklas 	int i;
17153a630e3fSniklas #endif
1716df930be7Sderaadt 
1717df930be7Sderaadt #ifdef DEBUG
171850ce9ee0Sniklas 	/*
171950ce9ee0Sniklas 	 * Crash and dump, if the user requested it.
172050ce9ee0Sniklas 	 */
172150ce9ee0Sniklas 	if (boothowto & RB_DUMP)
172250ce9ee0Sniklas 		panic("crash requested by boot flags");
172350ce9ee0Sniklas #endif
172450ce9ee0Sniklas 
172550ce9ee0Sniklas #ifdef DEBUG
172650ce9ee0Sniklas 	for (i = 0; i < FRAME_SIZE; i++)
1727df930be7Sderaadt 		tfp->tf_regs[i] = 0xbabefacedeadbeef;
17286334622bSguenther 	tfp->tf_regs[FRAME_A1] = 0;
1729df930be7Sderaadt #else
173050ce9ee0Sniklas 	bzero(tfp->tf_regs, FRAME_SIZE * sizeof tfp->tf_regs[0]);
1731df930be7Sderaadt #endif
1732df930be7Sderaadt 	bzero(&p->p_addr->u_pcb.pcb_fp, sizeof p->p_addr->u_pcb.pcb_fp);
173350ce9ee0Sniklas 	alpha_pal_wrusp(stack);
173450ce9ee0Sniklas 	tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET;
173550ce9ee0Sniklas 	tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3;
1736df930be7Sderaadt 
173750ce9ee0Sniklas 	tfp->tf_regs[FRAME_A0] = stack;
173850ce9ee0Sniklas 	/* a1 and a2 already zeroed */
173950ce9ee0Sniklas 	tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC];	/* a.k.a. PV */
174050ce9ee0Sniklas 
174150ce9ee0Sniklas 	p->p_md.md_flags &= ~MDP_FPUSED;
1742433075b6Spvalchev #ifndef NO_IEEE
1743433075b6Spvalchev 	if (__predict_true((p->p_md.md_flags & IEEE_INHERIT) == 0)) {
1744433075b6Spvalchev 		p->p_md.md_flags &= ~MDP_FP_C;
1745433075b6Spvalchev 		p->p_addr->u_pcb.pcb_fp.fpr_cr = FPCR_DYN(FP_RN);
1746433075b6Spvalchev 	}
1747433075b6Spvalchev #endif
1748433075b6Spvalchev 	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
1749433075b6Spvalchev 		fpusave_proc(p, 0);
1750ee2d823aSmiod 
1751ee2d823aSmiod 	retval[1] = 0;
1752433075b6Spvalchev }
1753df930be7Sderaadt 
1754433075b6Spvalchev /*
1755433075b6Spvalchev  * Release the FPU.
1756433075b6Spvalchev  */
1757433075b6Spvalchev void
1758433075b6Spvalchev fpusave_cpu(struct cpu_info *ci, int save)
1759433075b6Spvalchev {
1760433075b6Spvalchev 	struct proc *p;
176121c23d01Smiod #if defined(MULTIPROCESSOR)
176221c23d01Smiod 	int s;
176321c23d01Smiod #endif
1764433075b6Spvalchev 
1765433075b6Spvalchev 	KDASSERT(ci == curcpu());
1766433075b6Spvalchev 
1767433075b6Spvalchev #if defined(MULTIPROCESSOR)
176821c23d01Smiod 	/* Need to block IPIs */
17692d7472daSmiod 	s = splipi();
1770433075b6Spvalchev 	atomic_setbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
1771433075b6Spvalchev #endif
1772433075b6Spvalchev 
1773433075b6Spvalchev 	p = ci->ci_fpcurproc;
1774433075b6Spvalchev 	if (p == NULL)
1775433075b6Spvalchev 		goto out;
1776433075b6Spvalchev 
1777433075b6Spvalchev 	if (save) {
1778433075b6Spvalchev 		alpha_pal_wrfen(1);
1779433075b6Spvalchev 		savefpstate(&p->p_addr->u_pcb.pcb_fp);
1780433075b6Spvalchev 	}
1781433075b6Spvalchev 
1782433075b6Spvalchev 	alpha_pal_wrfen(0);
1783433075b6Spvalchev 
1784433075b6Spvalchev 	p->p_addr->u_pcb.pcb_fpcpu = NULL;
1785433075b6Spvalchev 	ci->ci_fpcurproc = NULL;
1786433075b6Spvalchev 
1787433075b6Spvalchev out:
1788433075b6Spvalchev #if defined(MULTIPROCESSOR)
1789433075b6Spvalchev 	atomic_clearbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
1790*4fa86cc0Smiod 	alpha_pal_swpipl(s);
1791433075b6Spvalchev #endif
1792433075b6Spvalchev 	return;
1793433075b6Spvalchev }
1794433075b6Spvalchev 
1795433075b6Spvalchev /*
1796433075b6Spvalchev  * Synchronize FP state for this process.
1797433075b6Spvalchev  */
1798433075b6Spvalchev void
1799433075b6Spvalchev fpusave_proc(struct proc *p, int save)
1800433075b6Spvalchev {
1801433075b6Spvalchev 	struct cpu_info *ci = curcpu();
1802433075b6Spvalchev 	struct cpu_info *oci;
1803433075b6Spvalchev #if defined(MULTIPROCESSOR)
1804433075b6Spvalchev 	u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU;
18052d7472daSmiod 	int s;
1806433075b6Spvalchev #endif
1807433075b6Spvalchev 
1808433075b6Spvalchev 	KDASSERT(p->p_addr != NULL);
1809433075b6Spvalchev 
18102d7472daSmiod 	for (;;) {
181121c23d01Smiod #if defined(MULTIPROCESSOR)
181221c23d01Smiod 		/* Need to block IPIs */
18132d7472daSmiod 		s = splipi();
181421c23d01Smiod #endif
181521c23d01Smiod 
1816433075b6Spvalchev 		oci = p->p_addr->u_pcb.pcb_fpcpu;
1817433075b6Spvalchev 		if (oci == NULL) {
181821c23d01Smiod #if defined(MULTIPROCESSOR)
1819*4fa86cc0Smiod 			alpha_pal_swpipl(s);
182021c23d01Smiod #endif
1821433075b6Spvalchev 			return;
1822433075b6Spvalchev 		}
1823433075b6Spvalchev 
1824433075b6Spvalchev #if defined(MULTIPROCESSOR)
1825433075b6Spvalchev 		if (oci == ci) {
1826433075b6Spvalchev 			KASSERT(ci->ci_fpcurproc == p);
1827*4fa86cc0Smiod 			alpha_pal_swpipl(s);
1828433075b6Spvalchev 			fpusave_cpu(ci, save);
1829433075b6Spvalchev 			return;
1830433075b6Spvalchev 		}
1831433075b6Spvalchev 
18322d7472daSmiod 		/*
18332d7472daSmiod 		 * The other cpu may still be running and could have
18342d7472daSmiod 		 * discarded the fpu context on its own.
18352d7472daSmiod 		 */
18362d7472daSmiod 		if (oci->ci_fpcurproc != p)
18372d7472daSmiod 			continue;
18382d7472daSmiod 
1839433075b6Spvalchev 		alpha_send_ipi(oci->ci_cpuid, ipi);
1840*4fa86cc0Smiod 		alpha_pal_swpipl(s);
1841433075b6Spvalchev 
18422d7472daSmiod 		while (p->p_addr->u_pcb.pcb_fpcpu != NULL)
18432d7472daSmiod 			SPINLOCK_SPIN_HOOK;
1844433075b6Spvalchev #else
1845433075b6Spvalchev 		KASSERT(ci->ci_fpcurproc == p);
1846433075b6Spvalchev 		fpusave_cpu(ci, save);
1847433075b6Spvalchev #endif /* MULTIPROCESSOR */
18482d7472daSmiod 
18492d7472daSmiod 		break;
18502d7472daSmiod 	}
1851df930be7Sderaadt }
1852df930be7Sderaadt 
1853df930be7Sderaadt int
1854df930be7Sderaadt spl0()
1855df930be7Sderaadt {
1856df930be7Sderaadt 
1857aed035abSart 	if (ssir) {
1858aed035abSart 		(void) alpha_pal_swpipl(ALPHA_PSL_IPL_SOFT);
18592a2685f2Sart 		softintr_dispatch();
1860aed035abSart 	}
1861df930be7Sderaadt 
186250ce9ee0Sniklas 	return (alpha_pal_swpipl(ALPHA_PSL_IPL_0));
1863df930be7Sderaadt }
1864df930be7Sderaadt 
1865df930be7Sderaadt /*
1866417eba8cSderaadt  * Wait "n" microseconds.
1867417eba8cSderaadt  */
186850ce9ee0Sniklas void
1869417eba8cSderaadt delay(n)
187050ce9ee0Sniklas 	unsigned long n;
1871417eba8cSderaadt {
18725d097e9eSmiod 	unsigned long pcc0, pcc1, curcycle, cycles, usec;
18735d097e9eSmiod 
18745d097e9eSmiod 	if (n == 0)
18755d097e9eSmiod 		return;
18765d097e9eSmiod 
18775d097e9eSmiod 	pcc0 = alpha_rpcc() & 0xffffffffUL;
18785d097e9eSmiod 	cycles = 0;
18795d097e9eSmiod 	usec = 0;
18805d097e9eSmiod 
18815d097e9eSmiod 	while (usec <= n) {
18825d097e9eSmiod 		/*
18835d097e9eSmiod 		 * Get the next CPU cycle count - assumes that we can not
18845d097e9eSmiod 		 * have had more than one 32 bit overflow.
18855d097e9eSmiod 		 */
18865d097e9eSmiod 		pcc1 = alpha_rpcc() & 0xffffffffUL;
18875d097e9eSmiod 		if (pcc1 < pcc0)
18885d097e9eSmiod 			curcycle = (pcc1 + 0x100000000UL) - pcc0;
18895d097e9eSmiod 		else
18905d097e9eSmiod 			curcycle = pcc1 - pcc0;
1891417eba8cSderaadt 
1892aed035abSart 		/*
18935d097e9eSmiod 		 * We now have the number of processor cycles since we
18945d097e9eSmiod 		 * last checked. Add the current cycle count to the
18955d097e9eSmiod 		 * running total. If it's over cycles_per_usec, increment
18965d097e9eSmiod 		 * the usec counter.
1897aed035abSart 		 */
18985d097e9eSmiod 		cycles += curcycle;
189921c23d01Smiod 		while (cycles >= cycles_per_usec) {
19005d097e9eSmiod 			usec++;
19015d097e9eSmiod 			cycles -= cycles_per_usec;
19025d097e9eSmiod 		}
19035d097e9eSmiod 		pcc0 = pcc1;
19045d097e9eSmiod 	}
1905417eba8cSderaadt }
1906417eba8cSderaadt 
1907aed035abSart int
1908aed035abSart alpha_pa_access(pa)
1909aed035abSart 	u_long pa;
1910aed035abSart {
1911aed035abSart 	int i;
1912aed035abSart 
1913aed035abSart 	for (i = 0; i < mem_cluster_cnt; i++) {
1914aed035abSart 		if (pa < mem_clusters[i].start)
1915aed035abSart 			continue;
1916aed035abSart 		if ((pa - mem_clusters[i].start) >=
1917aed035abSart 		    (mem_clusters[i].size & ~PAGE_MASK))
1918aed035abSart 			continue;
1919aed035abSart 		return (mem_clusters[i].size & PAGE_MASK);	/* prot */
1920aed035abSart 	}
1921aed035abSart 
1922aed035abSart 	/*
1923aed035abSart 	 * Address is not a memory address.  If we're secure, disallow
1924aed035abSart 	 * access.  Otherwise, grant read/write.
1925aed035abSart 	 */
1926aed035abSart 	if (securelevel > 0)
1927aed035abSart 		return (VM_PROT_NONE);
1928aed035abSart 	else
1929aed035abSart 		return (VM_PROT_READ | VM_PROT_WRITE);
1930aed035abSart }
1931aed035abSart 
1932e464495eSniklas /* XXX XXX BEGIN XXX XXX */
1933aed035abSart paddr_t alpha_XXX_dmamap_or;					/* XXX */
1934e464495eSniklas 								/* XXX */
1935aed035abSart paddr_t								/* XXX */
1936e464495eSniklas alpha_XXX_dmamap(v)						/* XXX */
1937aed035abSart 	vaddr_t v;						/* XXX */
1938e464495eSniklas {								/* XXX */
1939e464495eSniklas 								/* XXX */
1940e464495eSniklas 	return (vtophys(v) | alpha_XXX_dmamap_or);		/* XXX */
1941e464495eSniklas }								/* XXX */
1942e464495eSniklas /* XXX XXX END XXX XXX */
1943