1/*	$NetBSD: machdep.c,v 1.223 2011/06/12 03:35:40 rmind Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah $Hdr: machdep.c 1.74 92/12/20$
37 *
38 *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
39 */
40
41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.223 2011/06/12 03:35:40 rmind Exp $");
43
44#include "opt_ddb.h"
45#include "opt_compat_netbsd.h"
46#include "opt_modular.h"
47#include "opt_panicbutton.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/callout.h>
52#include <sys/buf.h>
53#include <sys/conf.h>
54#include <sys/exec.h>
55#include <sys/exec_aout.h>		/* for MID_* */
56#include <sys/file.h>
57#include <sys/ioctl.h>
58#include <sys/kernel.h>
59#include <sys/device.h>
60#include <sys/malloc.h>
61#include <sys/mbuf.h>
62#include <sys/mount.h>
63#include <sys/msgbuf.h>
64#include <sys/proc.h>
65#include <sys/reboot.h>
66#include <sys/signalvar.h>
67#include <sys/syscallargs.h>
68#include <sys/tty.h>
69#include <sys/core.h>
70#include <sys/kcore.h>
71#include <sys/vnode.h>
72#include <sys/ksyms.h>
73#include <sys/module.h>
74
75#ifdef DDB
76#include <machine/db_machdep.h>
77#include <ddb/db_sym.h>
78#include <ddb/db_extern.h>
79#endif /* DDB */
80#ifdef __ELF__
81#include <sys/exec_elf.h>
82#endif
83
84#include <machine/autoconf.h>
85#include <machine/bootinfo.h>
86#include <machine/bus.h>
87#include <machine/cpu.h>
88#include <machine/hp300spu.h>
89#include <machine/reg.h>
90#include <machine/pcb.h>
91#include <machine/psl.h>
92#include <machine/pte.h>
93
94#include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
95
96#include <dev/cons.h>
97#include <dev/mm.h>
98
99#define	MAXMEM	64*1024	/* XXX - from cmap.h */
100#include <uvm/uvm_extern.h>
101
102#include <sys/sysctl.h>
103
104#include "opt_useleds.h"
105
106#ifdef USELEDS
107#include <hp300/hp300/leds.h>
108#endif
109
110#include "ksyms.h"
111
112/* the following is used externally (sysctl_hw) */
113char	machine[] = MACHINE;	/* from <machine/param.h> */
114
115/* Our exported CPU info; we can have only one. */
116struct cpu_info cpu_info_store;
117
118struct vm_map *phys_map = NULL;
119
120extern paddr_t avail_end;
121
122/*
123 * bootinfo base (physical and virtual).  The bootinfo is placed, by
124 * the boot loader, into the first page of kernel text, which is zero
125 * filled (see locore.s) and not mapped at 0.  It is remapped to a
126 * different address in pmap_bootstrap().
127 */
128paddr_t	bootinfo_pa;
129vaddr_t	bootinfo_va;
130
131int	maxmem;			/* max memory per process */
132int	physmem = MAXMEM;	/* max supported memory, changes to actual */
133/*
134 * safepri is a safe priority for sleep to set for a spin-wait
135 * during autoconfiguration or after a panic.
136 */
137int	safepri = PSL_LOWIPL;
138
139extern	u_int lowram;
140extern	short exframesize[];
141
142/* prototypes for local functions */
143static void	parityenable(void);
144static int	parityerror(struct frame *);
145static int	parityerrorfind(void);
146static void	identifycpu(void);
147static void	initcpu(void);
148
149static int	cpu_dumpsize(void);
150static int	cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
151static void	cpu_init_kcore_hdr(void);
152
153/* functions called from locore.s */
154void    dumpsys(void);
155void	hp300_init(void);
156void    straytrap(int, u_short);
157void	nmihand(struct frame);
158
159/*
160 * Machine-dependent crash dump header info.
161 */
162static cpu_kcore_hdr_t cpu_kcore_hdr;
163
164/*
165 * Note that the value of delay_divisor is roughly
166 * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
167 * and 68030 systems.  See clock.c for the delay
168 * calibration algorithm.
169 */
170int	cpuspeed;		/* relative CPU speed; XXX skewed on 68040 */
171int	delay_divisor;		/* delay constant */
172
173/*
174 * Early initialization, before main() is called.
175 */
176void
177hp300_init(void)
178{
179	struct btinfo_magic *bt_mag;
180	int i;
181
182	extern paddr_t avail_start, avail_end;
183
184#ifdef CACHE_HAVE_VAC
185	/*
186	 * Determine VA aliasing distance if any
187	 */
188	switch (machineid) {
189	case HP_320:
190		pmap_aliasmask = 0x3fff;	/* 16KB */
191		break;
192	case HP_350:
193		pmap_aliasmask = 0x7fff;	/* 32KB */
194		break;
195	default:
196		break;
197	}
198#endif
199
200	/*
201	 * Tell the VM system about available physical memory.  The
202	 * hp300 only has one segment.
203	 */
204	uvm_page_physload(atop(avail_start), atop(avail_end),
205	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
206
207	/* Calibrate the delay loop. */
208	hp300_calibrate_delay();
209
210	/*
211	 * Initialize error message buffer (at end of core).
212	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
213	 */
214	for (i = 0; i < btoc(MSGBUFSIZE); i++)
215		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
216		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
217	pmap_update(pmap_kernel());
218	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
219
220	/*
221	 * Map in the bootinfo page, and make sure the bootinfo
222	 * exists by searching for the MAGIC record.  If it's not
223	 * there, disable bootinfo.
224	 */
225	bootinfo_va = virtual_avail;
226	virtual_avail += PAGE_SIZE;
227	pmap_enter(pmap_kernel(), bootinfo_va, bootinfo_pa,
228	    VM_PROT_READ|VM_PROT_WRITE,
229	    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
230	pmap_update(pmap_kernel());
231	bt_mag = lookup_bootinfo(BTINFO_MAGIC);
232	if (bt_mag == NULL ||
233	    bt_mag->magic1 != BOOTINFO_MAGIC1 ||
234	    bt_mag->magic2 != BOOTINFO_MAGIC2) {
235		pmap_remove(pmap_kernel(), bootinfo_va,
236		    bootinfo_va + PAGE_SIZE);
237		pmap_update(pmap_kernel());
238		virtual_avail -= PAGE_SIZE;
239		bootinfo_va = 0;
240	}
241}
242
243/*
244 * Console initialization: called early on from main,
245 * before vm init or startup.  Do enough configuration
246 * to choose and initialize a console.
247 */
248void
249consinit(void)
250{
251
252	/*
253	 * Initialize the external I/O extent map.
254	 */
255	iomap_init();
256
257	/*
258	 * Initialize the console before we print anything out.
259	 */
260
261	hp300_cninit();
262
263	/*
264	 * Issue a warning if the boot loader didn't provide bootinfo.
265	 */
266	if (bootinfo_va != 0)
267		printf("bootinfo found at 0x%08lx\n", bootinfo_pa);
268	else
269		printf("WARNING: boot loader did not provide bootinfo\n");
270
271#if NKSYMS || defined(DDB) || defined(MODULAR)
272	{
273		extern int end;
274		extern int *esym;
275
276		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
277		    (void *)&end, esym);
278	}
279#endif
280#ifdef DDB
281	if (boothowto & RB_KDB)
282		Debugger();
283#endif
284}
285
286/*
287 * cpu_startup: allocate memory for variable-sized tables,
288 * initialize CPU
289 */
290void
291cpu_startup(void)
292{
293	vaddr_t minaddr, maxaddr;
294	char pbuf[9];
295#ifdef DEBUG
296	extern int pmapdebug;
297	int opmapdebug = pmapdebug;
298
299	pmapdebug = 0;
300#endif
301
302	if (fputype != FPU_NONE)
303		m68k_make_fpu_idle_frame();
304
305	/*
306	 * Initialize the kernel crash dump header.
307	 */
308	cpu_init_kcore_hdr();
309
310	/*
311	 * Good {morning,afternoon,evening,night}.
312	 */
313	printf("%s%s", copyright, version);
314	identifycpu();
315	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
316	printf("total memory = %s\n", pbuf);
317
318	minaddr = 0;
319
320	/*
321	 * Allocate a submap for physio
322	 */
323	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
324	    VM_PHYS_SIZE, 0, false, NULL);
325
326#ifdef DEBUG
327	pmapdebug = opmapdebug;
328#endif
329	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
330	printf("avail memory = %s\n", pbuf);
331
332	/*
333	 * Set up CPU-specific registers, cache, etc.
334	 */
335	initcpu();
336
337	/* Safe to use malloc for extio_ex now. */
338	extio_ex_malloc_safe = 1;
339}
340
341/*
342 * Info for CTL_HW
343 */
344char cpu_model[120];
345
346struct hp300_model {
347	int id;
348	int mmuid;
349	const char *name;
350	const char *speed;
351};
352
353static const struct hp300_model hp300_models[] = {
354	{ HP_320,	-1,		"320",		"16.67"	},
355	{ HP_330,	-1,		"318/319/330",	"16.67"	},
356	{ HP_340,	-1,		"340",		"16.67"	},
357	{ HP_345,	-1,		"345",		"50"	},
358	{ HP_350,	-1,		"350",		"25"	},
359	{ HP_360,	-1,		"360",		"25"	},
360	{ HP_362,	-1,		"362",		"25"	},
361	{ HP_370,	-1,		"370",		"33.33"	},
362	{ HP_375,	-1,		"375",		"50"	},
363	{ HP_380,	-1,		"380",		"25"	},
364	{ HP_382,	-1,		"382",		"25"	},
365	{ HP_385,	-1,		"385",		"33"	},
366	{ HP_400,	-1,		"400",		"50"	},
367	{ HP_425,	MMUID_425_T,	"425t",		"25"	},
368	{ HP_425,	MMUID_425_S,	"425s",		"25"	},
369	{ HP_425,	MMUID_425_E,	"425e",		"25"	},
370	{ HP_425,	-1,		"425",		"25"	},
371	{ HP_433,	MMUID_433_T,	"433t",		"33"	},
372	{ HP_433,	MMUID_433_S,	"433s",		"33"	},
373	{ HP_433,	-1,		"433",		"33"	},
374	{ 0,		-1,		NULL,		NULL	},
375};
376
377static void
378identifycpu(void)
379{
380	const char *t, *mc, *s;
381	int i, len;
382
383	/*
384	 * Find the model number.
385	 */
386	for (t = s = NULL, i = 0; hp300_models[i].name != NULL; i++) {
387		if (hp300_models[i].id == machineid) {
388			if (hp300_models[i].mmuid != -1 &&
389			    hp300_models[i].mmuid != mmuid)
390				continue;
391			t = hp300_models[i].name;
392			s = hp300_models[i].speed;
393			break;
394		}
395	}
396	if (t == NULL) {
397		printf("\nunknown machineid %d\n", machineid);
398		goto lose;
399	}
400
401	/*
402	 * ...and the CPU type.
403	 */
404	switch (cputype) {
405	case CPU_68040:
406		mc = "40";
407		break;
408	case CPU_68030:
409		mc = "30";
410		break;
411	case CPU_68020:
412		mc = "20";
413		break;
414	default:
415		printf("\nunknown cputype %d\n", cputype);
416		goto lose;
417	}
418
419	sprintf(cpu_model, "HP 9000/%s (%sMHz MC680%s CPU", t, s, mc);
420
421	/*
422	 * ...and the MMU type.
423	 */
424	switch (mmutype) {
425	case MMU_68040:
426	case MMU_68030:
427		strcat(cpu_model, "+MMU");
428		break;
429	case MMU_68851:
430		strcat(cpu_model, ", MC68851 MMU");
431		break;
432	case MMU_HP:
433		strcat(cpu_model, ", HP MMU");
434		break;
435	default:
436		printf("%s\nunknown MMU type %d\n", cpu_model, mmutype);
437		panic("startup");
438	}
439
440	len = strlen(cpu_model);
441
442	/*
443	 * ...and the FPU type.
444	 */
445	switch (fputype) {
446	case FPU_68040:
447		len += sprintf(cpu_model + len, "+FPU");
448		break;
449	case FPU_68882:
450		len += sprintf(cpu_model + len, ", %sMHz MC68882 FPU", s);
451		break;
452	case FPU_68881:
453		len += sprintf(cpu_model + len, ", %sMHz MC68881 FPU",
454		    machineid == HP_350 ? "20" : "16.67");
455		break;
456	default:
457		len += sprintf(cpu_model + len, ", unknown FPU");
458	}
459
460	/*
461	 * ...and finally, the cache type.
462	 */
463	if (cputype == CPU_68040)
464		sprintf(cpu_model + len, ", 4k on-chip physical I/D caches");
465	else {
466		switch (ectype) {
467		case EC_VIRT:
468			sprintf(cpu_model + len,
469			    ", %dK virtual-address cache",
470			    machineid == HP_320 ? 16 : 32);
471			break;
472		case EC_PHYS:
473			sprintf(cpu_model + len,
474			    ", %dK physical-address cache",
475			    machineid == HP_370 ? 64 : 32);
476			break;
477		}
478	}
479
480	strcat(cpu_model, ")");
481	printf("%s\n", cpu_model);
482#ifdef DIAGNOSTIC
483	printf("cpu: delay divisor %d", delay_divisor);
484	if (mmuid)
485		printf(", mmuid %d", mmuid);
486	printf("\n");
487#endif
488
489	/*
490	 * Now that we have told the user what they have,
491	 * let them know if that machine type isn't configured.
492	 */
493	switch (machineid) {
494	case -1:		/* keep compilers happy */
495#if !defined(HP320)
496	case HP_320:
497#endif
498#if !defined(HP330)
499	case HP_330:
500#endif
501#if !defined(HP340)
502	case HP_340:
503#endif
504#if !defined(HP345)
505	case HP_345:
506#endif
507#if !defined(HP350)
508	case HP_350:
509#endif
510#if !defined(HP360)
511	case HP_360:
512#endif
513#if !defined(HP362)
514	case HP_362:
515#endif
516#if !defined(HP370)
517	case HP_370:
518#endif
519#if !defined(HP375)
520	case HP_375:
521#endif
522#if !defined(HP380)
523	case HP_380:
524#endif
525#if !defined(HP382)
526	case HP_382:
527#endif
528#if !defined(HP385)
529	case HP_385:
530#endif
531#if !defined(HP400)
532	case HP_400:
533#endif
534#if !defined(HP425)
535	case HP_425:
536#endif
537#if !defined(HP433)
538	case HP_433:
539#endif
540		panic("SPU type not configured");
541	default:
542		break;
543	}
544
545	return;
546 lose:
547	panic("startup");
548}
549
550/*
551 * machine dependent system variables.
552 */
553SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
554{
555
556	sysctl_createv(clog, 0, NULL, NULL,
557	    CTLFLAG_PERMANENT,
558	    CTLTYPE_NODE, "machdep", NULL,
559	    NULL, 0, NULL, 0,
560	    CTL_MACHDEP, CTL_EOL);
561
562	sysctl_createv(clog, 0, NULL, NULL,
563	    CTLFLAG_PERMANENT,
564	    CTLTYPE_STRUCT, "console_device", NULL,
565	    sysctl_consdev, 0, NULL, sizeof(dev_t),
566	    CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
567}
568
569int	waittime = -1;
570
571void
572cpu_reboot(int howto, char *bootstr)
573{
574	struct pcb *pcb = lwp_getpcb(curlwp);
575
576	/* take a snap shot before clobbering any registers */
577	if (pcb != NULL)
578		savectx(pcb);
579
580	/* If system is cold, just halt. */
581	if (cold) {
582		howto |= RB_HALT;
583		goto haltsys;
584	}
585
586	boothowto = howto;
587	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
588		waittime = 0;
589		vfs_shutdown();
590		/*
591		 * If we've been adjusting the clock, the todr
592		 * will be out of synch; adjust it now.
593		 */
594		resettodr();
595	}
596
597	/* Disable interrupts. */
598	splhigh();
599
600	/* If rebooting and a dump is requested do it. */
601	if (howto & RB_DUMP)
602		dumpsys();
603
604 haltsys:
605	/* Run any shutdown hooks. */
606	doshutdownhooks();
607
608	pmf_system_shutdown(boothowto);
609
610#if defined(PANICWAIT) && !defined(DDB)
611	if ((howto & RB_HALT) == 0 && panicstr) {
612		printf("hit any key to reboot...\n");
613		(void)cngetc();
614		printf("\n");
615	}
616#endif
617
618	/* Finally, halt/reboot the system. */
619	if (howto & RB_HALT) {
620		printf("System halted.  Hit any key to reboot.\n\n");
621		(void)cngetc();
622	}
623
624	printf("rebooting...\n");
625	DELAY(1000000);
626	doboot();
627	/* NOTREACHED */
628}
629
630/*
631 * Initialize the kernel crash dump header.
632 */
633static void
634cpu_init_kcore_hdr(void)
635{
636	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
637	struct m68k_kcore_hdr *m = &h->un._m68k;
638	extern int end;
639
640	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
641
642	/*
643	 * Initialize the `dispatcher' portion of the header.
644	 */
645	strcpy(h->name, machine);
646	h->page_size = PAGE_SIZE;
647	h->kernbase = KERNBASE;
648
649	/*
650	 * Fill in information about our MMU configuration.
651	 */
652	m->mmutype	= mmutype;
653	m->sg_v		= SG_V;
654	m->sg_frame	= SG_FRAME;
655	m->sg_ishift	= SG_ISHIFT;
656	m->sg_pmask	= SG_PMASK;
657	m->sg40_shift1	= SG4_SHIFT1;
658	m->sg40_mask2	= SG4_MASK2;
659	m->sg40_shift2	= SG4_SHIFT2;
660	m->sg40_mask3	= SG4_MASK3;
661	m->sg40_shift3	= SG4_SHIFT3;
662	m->sg40_addr1	= SG4_ADDR1;
663	m->sg40_addr2	= SG4_ADDR2;
664	m->pg_v		= PG_V;
665	m->pg_frame	= PG_FRAME;
666
667	/*
668	 * Initialize pointer to kernel segment table.
669	 */
670	m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
671
672	/*
673	 * Initialize relocation value such that:
674	 *
675	 *	pa = (va - KERNBASE) + reloc
676	 */
677	m->reloc = lowram;
678
679	/*
680	 * Define the end of the relocatable range.
681	 */
682	m->relocend = (uint32_t)&end;
683
684	/*
685	 * hp300 has one contiguous memory segment.
686	 */
687	m->ram_segs[0].start = lowram;
688	m->ram_segs[0].size  = ctob(physmem);
689}
690
691/*
692 * Compute the size of the machine-dependent crash dump header.
693 * Returns size in disk blocks.
694 */
695
696#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
697#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
698
699static int
700cpu_dumpsize(void)
701{
702
703	return btodb(MDHDRSIZE);
704}
705
706/*
707 * Called by dumpsys() to dump the machine-dependent header.
708 */
709static int
710cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
711{
712	int buf[MDHDRSIZE / sizeof(int)];
713	cpu_kcore_hdr_t *chdr;
714	kcore_seg_t *kseg;
715	int error;
716
717	kseg = (kcore_seg_t *)buf;
718	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
719	    sizeof(int)];
720
721	/* Create the segment header. */
722	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
723	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
724
725	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
726	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
727	*blknop += btodb(sizeof(buf));
728	return error;
729}
730
731/*
732 * These variables are needed by /sbin/savecore
733 */
734uint32_t dumpmag = 0x8fca0101;	/* magic number */
735int	dumpsize = 0;		/* pages */
736long	dumplo = 0;		/* blocks */
737
738/*
739 * This is called by main to set dumplo and dumpsize.
740 * Dumps always skip the first PAGE_SIZE of disk space
741 * in case there might be a disk label stored there.
742 * If there is extra space, put dump at the end to
743 * reduce the chance that swapping trashes it.
744 */
745void
746cpu_dumpconf(void)
747{
748	int chdrsize;	/* size of dump header */
749	int nblks;	/* size of dump area */
750
751	if (dumpdev == NODEV)
752		return;
753	nblks = bdev_size(dumpdev);
754	chdrsize = cpu_dumpsize();
755
756	dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
757
758	/*
759	 * Check do see if we will fit.  Note we always skip the
760	 * first PAGE_SIZE in case there is a disk label there.
761	 */
762	if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
763		dumpsize = 0;
764		dumplo = -1;
765		return;
766	}
767
768	/*
769	 * Put dump at the end of the partition.
770	 */
771	dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
772}
773
774/*
775 * Dump physical memory onto the dump device.  Called by cpu_reboot().
776 */
777void
778dumpsys(void)
779{
780	const struct bdevsw *bdev;
781	daddr_t blkno;		/* current block to write */
782				/* dump routine */
783	int (*dump)(dev_t, daddr_t, void *, size_t);
784	int pg;			/* page being dumped */
785	paddr_t maddr;		/* PA being dumped */
786	int error;		/* error code from (*dump)() */
787
788	/* XXX initialized here because of gcc lossage */
789	maddr = lowram;
790	pg = 0;
791
792	/* Make sure dump device is valid. */
793	if (dumpdev == NODEV)
794		return;
795	bdev = bdevsw_lookup(dumpdev);
796	if (bdev == NULL)
797		return;
798	if (dumpsize == 0) {
799		cpu_dumpconf();
800		if (dumpsize == 0)
801			return;
802	}
803	if (dumplo <= 0) {
804		printf("\ndump to dev %u,%u not possible\n",
805		    major(dumpdev), minor(dumpdev));
806		return;
807	}
808	dump = bdev->d_dump;
809	blkno = dumplo;
810
811	printf("\ndumping to dev %u,%u offset %ld\n",
812	    major(dumpdev), minor(dumpdev), dumplo);
813
814	printf("dump ");
815
816	/* Write the dump header. */
817	error = cpu_dump(dump, &blkno);
818	if (error)
819		goto bad;
820
821	for (pg = 0; pg < dumpsize; pg++) {
822#define NPGMB	(1024*1024/PAGE_SIZE)
823		/* print out how many MBs we have dumped */
824		if (pg && (pg % NPGMB) == 0)
825			printf("%d ", pg / NPGMB);
826#undef NPGMB
827		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
828		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
829
830		pmap_update(pmap_kernel());
831		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
832 bad:
833		switch (error) {
834		case 0:
835			maddr += PAGE_SIZE;
836			blkno += btodb(PAGE_SIZE);
837			break;
838
839		case ENXIO:
840			printf("device bad\n");
841			return;
842
843		case EFAULT:
844			printf("device not ready\n");
845			return;
846
847		case EINVAL:
848			printf("area improper\n");
849			return;
850
851		case EIO:
852			printf("i/o error\n");
853			return;
854
855		case EINTR:
856			printf("aborted from console\n");
857			return;
858
859		default:
860			printf("error %d\n", error);
861			return;
862		}
863	}
864	printf("succeeded\n");
865}
866
867static void
868initcpu(void)
869{
870
871#ifdef MAPPEDCOPY
872	/*
873	 * Initialize lower bound for doing copyin/copyout using
874	 * page mapping (if not already set).  We don't do this on
875	 * VAC machines as it loses big time.
876	 */
877	if (ectype == EC_VIRT)
878		mappedcopysize = -1;	/* in case it was patched */
879	else
880		mappedcopysize = PAGE_SIZE;
881#endif
882	parityenable();
883#ifdef USELEDS
884	ledinit();
885#endif
886}
887
888void
889straytrap(int pc, u_short evec)
890{
891	printf("unexpected trap (vector offset %x) from %x\n",
892	       evec & 0xFFF, pc);
893}
894
895/* XXX should change the interface, and make one badaddr() function */
896
897int	*nofault;
898
899int
900badaddr(void *addr)
901{
902	int i;
903	label_t	faultbuf;
904
905	nofault = (int *)&faultbuf;
906	if (setjmp((label_t *)nofault)) {
907		nofault = (int *)0;
908		return 1;
909	}
910	i = *(volatile short *)addr;
911	nofault = (int *)0;
912	return 0;
913}
914
915int
916badbaddr(void *addr)
917{
918	int i;
919	label_t	faultbuf;
920
921	nofault = (int *)&faultbuf;
922	if (setjmp((label_t *)nofault)) {
923		nofault = (int *)0;
924		return 1;
925	}
926	i = *(volatile char *)addr;
927	nofault = (int *) 0;
928	return 0;
929}
930
931/*
932 * lookup_bootinfo:
933 *
934 *	Look up information in bootinfo from boot loader.
935 */
936void *
937lookup_bootinfo(int type)
938{
939	struct btinfo_common *bt;
940	char *help = (char *)bootinfo_va;
941
942	/* Check for a bootinfo record first. */
943	if (help == NULL)
944		return NULL;
945
946	do {
947		bt = (struct btinfo_common *)help;
948		if (bt->type == type)
949			return help;
950		help += bt->next;
951	} while (bt->next != 0 &&
952		 (size_t)help < (size_t)bootinfo_va + BOOTINFO_SIZE);
953
954	return NULL;
955}
956
957#if defined(PANICBUTTON) && !defined(DDB)
958/*
959 * Declare these so they can be patched.
960 */
961int panicbutton = 1;	/* non-zero if panic buttons are enabled */
962int candbdiv = 2;	/* give em half a second (hz / candbdiv) */
963
964static void	candbtimer(void *);
965
966int crashandburn;
967
968callout_t candbtimer_ch;
969
970void
971candbtimer(void *arg)
972{
973
974	crashandburn = 0;
975}
976#endif /* PANICBUTTON & !DDB */
977
978static int innmihand;	/* simple mutex */
979
980/*
981 * Level 7 interrupts can be caused by HIL keyboards (in cooked mode only,
982 * but we run them in raw mode) or parity errors.
983 */
984void
985nmihand(struct frame frame)
986{
987
988	/* Prevent unwanted recursion. */
989	if (innmihand)
990		return;
991	innmihand = 1;
992
993	if (parityerror(&frame))
994		return;
995	/* panic?? */
996	printf("unexpected level 7 interrupt ignored\n");
997
998	innmihand = 0;
999}
1000
1001/*
1002 * Parity error section.  Contains magic.
1003 */
1004#define PARREG		((volatile short *)IIOV(0x5B0000))
1005static int gotparmem = 0;
1006#ifdef DEBUG
1007int ignorekperr = 0;	/* ignore kernel parity errors */
1008#endif
1009
1010/*
1011 * Enable parity detection
1012 */
1013static void
1014parityenable(void)
1015{
1016	label_t	faultbuf;
1017
1018	nofault = (int *)&faultbuf;
1019	if (setjmp((label_t *)nofault)) {
1020		nofault = (int *)0;
1021		printf("Parity detection disabled\n");
1022		return;
1023	}
1024	*PARREG = 1;
1025	nofault = (int *)0;
1026	gotparmem = 1;
1027}
1028
1029/*
1030 * Determine if level 7 interrupt was caused by a parity error
1031 * and deal with it if it was.  Returns 1 if it was a parity error.
1032 */
1033static int
1034parityerror(struct frame *fp)
1035{
1036	if (!gotparmem)
1037		return 0;
1038	*PARREG = 0;
1039	DELAY(10);
1040	*PARREG = 1;
1041	if (panicstr) {
1042		printf("parity error after panic ignored\n");
1043		return 1;
1044	}
1045	if (!parityerrorfind())
1046		printf("WARNING: transient parity error ignored\n");
1047	else if (USERMODE(fp->f_sr)) {
1048		printf("pid %d: parity error\n", curproc->p_pid);
1049		uprintf("sorry, pid %d killed due to memory parity error\n",
1050		    curproc->p_pid);
1051		psignal(curproc, SIGKILL);
1052#ifdef DEBUG
1053	} else if (ignorekperr) {
1054		printf("WARNING: kernel parity error ignored\n");
1055#endif
1056	} else {
1057		regdump((struct trapframe *)fp, 128);
1058		panic("kernel parity error");
1059	}
1060	return 1;
1061}
1062
1063/*
1064 * Yuk!  There has got to be a better way to do this!
1065 * Searching all of memory with interrupts blocked can lead to disaster.
1066 */
1067static int
1068parityerrorfind(void)
1069{
1070	static label_t parcatch;
1071	static int looking = 0;
1072	volatile int pg, o, s;
1073	volatile int *ip;
1074	int i;
1075	int found;
1076
1077#ifdef lint
1078	i = o = pg = 0;
1079	if (i)
1080		return 0;
1081#endif
1082	/*
1083	 * If looking is true we are searching for a known parity error
1084	 * and it has just occurred.  All we do is return to the higher
1085	 * level invocation.
1086	 */
1087	if (looking)
1088		longjmp(&parcatch);
1089	s = splhigh();
1090	/*
1091	 * If setjmp returns true, the parity error we were searching
1092	 * for has just occurred (longjmp above) at the current pg+o
1093	 */
1094	if (setjmp(&parcatch)) {
1095		printf("Parity error at 0x%x\n", ctob(pg)|o);
1096		found = 1;
1097		goto done;
1098	}
1099	/*
1100	 * If we get here, a parity error has occurred for the first time
1101	 * and we need to find it.  We turn off any external caches and
1102	 * loop thru memory, testing every longword til a fault occurs and
1103	 * we regain control at setjmp above.  Note that because of the
1104	 * setjmp, pg and o need to be volatile or their values will be lost.
1105	 */
1106	looking = 1;
1107	ecacheoff();
1108	for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) {
1109		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, ctob(pg),
1110		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
1111		pmap_update(pmap_kernel());
1112		ip = (int *)vmmap;
1113		for (o = 0; o < PAGE_SIZE; o += sizeof(int))
1114			i = *ip++;
1115	}
1116	/*
1117	 * Getting here implies no fault was found.  Should never happen.
1118	 */
1119	printf("Couldn't locate parity error\n");
1120	found = 0;
1121 done:
1122	looking = 0;
1123	pmap_remove(pmap_kernel(), (vaddr_t)vmmap, (vaddr_t)&vmmap[PAGE_SIZE]);
1124	pmap_update(pmap_kernel());
1125	ecacheon();
1126	splx(s);
1127	return found;
1128}
1129
1130/*
1131 * cpu_exec_aout_makecmds():
1132 *	CPU-dependent a.out format hook for execve().
1133 *
1134 * Determine of the given exec package refers to something which we
1135 * understand and, if so, set up the vmcmds for it.
1136 *
1137 * XXX what are the special cases for the hp300?
1138 * XXX why is this COMPAT_NOMID?  was something generating
1139 *	hp300 binaries with an a_mid of 0?  i thought that was only
1140 *	done on little-endian machines...  -- cgd
1141 */
1142int
1143cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
1144{
1145#if defined(COMPAT_NOMID) || defined(COMPAT_44)
1146	u_long midmag, magic;
1147	u_short mid;
1148	int error;
1149	struct exec *execp = epp->ep_hdr;
1150
1151	midmag = ntohl(execp->a_midmag);
1152	mid = (midmag >> 16) & 0xffff;
1153	magic = midmag & 0xffff;
1154
1155	midmag = mid << 16 | magic;
1156
1157	switch (midmag) {
1158#ifdef COMPAT_NOMID
1159	case (MID_ZERO << 16) | ZMAGIC:
1160		error = exec_aout_prep_oldzmagic(l, epp);
1161		return error;
1162#endif
1163#ifdef COMPAT_44
1164	case (MID_HP300 << 16) | ZMAGIC:
1165		error = exec_aout_prep_oldzmagic(l, epp);
1166		return error;
1167#endif
1168	}
1169#endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
1170
1171	return ENOEXEC;
1172}
1173
1174int
1175mm_md_physacc(paddr_t pa, vm_prot_t prot)
1176{
1177
1178	return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0;
1179}
1180
1181int
1182mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
1183{
1184
1185	/*
1186	 * Do not allow reading intio or dio device space.  This could lead
1187	 * to corruption of device registers.
1188	 */
1189	*handled = false;
1190	return (ISIIOVA(ptr) || ((uint8_t *)ptr >= extiobase &&
1191	    (uint8_t *)ptr < extiobase + (EIOMAPSIZE * PAGE_SIZE)))
1192	    ? EFAULT : 0;
1193}
1194
1195#ifdef MODULAR
1196/*
1197 * Push any modules loaded by the bootloader etc.
1198 */
1199void
1200module_init_md(void)
1201{
1202}
1203#endif
1204