1/*	$NetBSD: machdep.c,v 1.9 2024/03/05 14:15:36 thorpej 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.9 2024/03/05 14:15:36 thorpej Exp $");
43
44#include "opt_ddb.h"
45#include "opt_m060sp.h"
46#include "opt_modular.h"
47#include "opt_m68k_arch.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/signalvar.h>
52#include <sys/kernel.h>
53#include <sys/proc.h>
54#include <sys/buf.h>
55#include <sys/reboot.h>
56#include <sys/conf.h>
57#include <sys/file.h>
58#include <sys/mbuf.h>
59#include <sys/msgbuf.h>
60#include <sys/ioctl.h>
61#include <sys/tty.h>
62#include <sys/mount.h>
63#include <sys/exec.h>
64#include <sys/exec_aout.h>		/* for MID_* */
65#include <sys/core.h>
66#include <sys/kcore.h>
67#include <sys/vnode.h>
68#include <sys/syscallargs.h>
69#include <sys/ksyms.h>
70#include <sys/module.h>
71#include <sys/device.h>
72#include <sys/cpu.h>
73#include <sys/boot_flag.h>
74
75#include "ksyms.h"
76
77#if NKSYMS || defined(DDB) || defined(MODULAR)
78#include <sys/exec_elf.h>
79#endif
80
81#include <uvm/uvm_extern.h>
82
83#include <sys/sysctl.h>
84
85#include <machine/bootinfo.h>
86#include <machine/cpu.h>
87#include <machine/bus.h>
88#include <machine/pcb.h>
89#include <machine/psl.h>
90#include <machine/pte.h>
91#include <machine/vmparam.h>
92#include <m68k/include/cacheops.h>
93#include <dev/cons.h>
94#include <dev/mm.h>
95
96#include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
97
98#ifdef DDB
99#include <machine/db_machdep.h>
100#include <ddb/db_extern.h>
101#include <ddb/db_output.h>
102#endif
103
104/* the following is used externally (sysctl_hw) */
105char	machine[] = MACHINE;	/* from <machine/param.h> */
106
107/* Our exported CPU info; we can have only one. */
108struct cpu_info cpu_info_store;
109
110struct vm_map *phys_map = NULL;
111
112paddr_t msgbufpa;		/* PA of message buffer */
113
114// int	maxmem;			/* max memory per process */
115
116extern	short exframesize[];
117
118/* prototypes for local functions */
119void	identifycpu(void);
120void	initcpu(void);
121void	dumpsys(void);
122
123int	cpu_dumpsize(void);
124int	cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
125void	cpu_init_kcore_hdr(void);
126u_long	cpu_dump_mempagecnt(void);
127int	cpu_exec_aout_makecmds(struct lwp *, struct exec_package *);
128void	straytrap(int, u_short);
129
130/*
131 * Machine-independent crash dump header info.
132 */
133cpu_kcore_hdr_t cpu_kcore_hdr;
134
135/* Machine-dependent initialization routines. */
136void	virt68k_init(void);
137
138/*
139 * Machine-dependent bootinfo "console attach" routine.
140 */
141void
142bootinfo_md_cnattach(void (*func)(bus_space_tag_t, bus_space_handle_t),
143    paddr_t addr, paddr_t size)
144{
145	extern struct virt68k_bus_space_tag _mainbus_space_tag;
146	extern paddr_t consdev_addr;
147	bus_space_tag_t bst = &_mainbus_space_tag;
148	bus_space_handle_t bsh;
149
150	if (bus_space_map(bst, addr, size, 0, &bsh) == 0) {
151		func(bst, bsh);
152	}
153	consdev_addr = addr;
154}
155
156/*
157 * Early initialization, right before main is called.
158 */
159void
160virt68k_init(void)
161{
162	int i;
163
164	/*
165	 * Just use the default pager_map_size for now.  We may decide
166	 * to make it larger for large memory configs.
167	 */
168
169	/*
170	 * Tell the VM system about available physical memory.
171	 */
172	for (i = 0; i < bootinfo_mem_nsegments_avail; i++) {
173		if (bootinfo_mem_segments_avail[i].mem_size < PAGE_SIZE) {
174			/*
175			 * Segment has been completely gobbled up.
176			 */
177			continue;
178		}
179
180		paddr_t start = bootinfo_mem_segments_avail[i].mem_addr;
181		psize_t size  = bootinfo_mem_segments_avail[i].mem_size;
182
183		printf("Memory segment %d: addr=0x%08lx size=0x%08lx\n", i,
184		    start, size);
185
186		KASSERT(atop(start + size) == atop(start) + atop(size));
187
188		uvm_page_physload(atop(start),
189				  atop(start) + atop(size),
190				  atop(start),
191				  atop(start) + atop(size),
192				  VM_FREELIST_DEFAULT);
193	}
194
195	/*
196	 * Initialize error message buffer (just before kernel text).
197	 */
198	for (i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) {
199		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
200			       msgbufpa + i * PAGE_SIZE,
201			       VM_PROT_READ|VM_PROT_WRITE, 0);
202	}
203	initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
204	pmap_update(pmap_kernel());
205
206	/* Check for RND seed from the loader. */
207	bootinfo_setup_rndseed();
208
209	char flags[32];
210	if (bootinfo_getarg("flags", flags, sizeof(flags))) {
211		for (const char *cp = flags; *cp != '\0'; cp++) {
212			/* Consume 'm' in favor of BI_RAMDISK. */
213			if (*cp == 'm') {
214				continue;
215			}
216			BOOT_FLAG(*cp, boothowto);
217		}
218	}
219}
220
221/*
222 * Console initialization: called early on from main,
223 * before vm init or startup.  Do enough configuration
224 * to choose and initialize a console.
225 */
226void
227consinit(void)
228{
229
230	/*
231	 * The Goldfish TTY console has already been attached when
232	 * the bootinfo was parsed.
233	 */
234
235#ifdef DDB
236	if (boothowto & RB_KDB)
237		Debugger();
238#endif
239}
240
241/*
242 * cpu_startup: allocate memory for variable-sized tables,
243 * initialize CPU, and do autoconfiguration.
244 */
245void
246cpu_startup(void)
247{
248	vaddr_t minaddr, maxaddr;
249	char pbuf[9];
250#ifdef DEBUG
251	extern int pmapdebug;
252	int opmapdebug = pmapdebug;
253
254	pmapdebug = 0;
255#endif
256
257	/*
258	 * If we have an FPU, initialise the cached idle frame
259	 */
260	if (fputype != FPU_NONE)
261		m68k_make_fpu_idle_frame();
262
263	/*
264	 * Initialize the kernel crash dump header.
265	 */
266	cpu_init_kcore_hdr();
267
268	/*
269	 * Good {morning,afternoon,evening,night}.
270	 */
271	printf("%s%s", copyright, version);
272	identifycpu();
273	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
274	printf("total memory = %s\n", pbuf);
275
276	minaddr = 0;
277	/*
278	 * Allocate a submap for physio
279	 */
280	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
281	    VM_PHYS_SIZE, 0, false, NULL);
282
283#ifdef DEBUG
284	pmapdebug = opmapdebug;
285#endif
286	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
287	printf("avail memory = %s\n", pbuf);
288
289	if (bootinfo_mem_segments_ignored) {
290		printf("WARNING: ignored %zd bytes of memory in %d segments.\n",
291		    bootinfo_mem_segments_ignored_bytes,
292		    bootinfo_mem_segments_ignored);
293	}
294
295	/*
296	 * Set up CPU-specific registers, cache, etc.
297	 */
298	initcpu();
299}
300
301static const char *
302mmu_string(void)
303{
304	switch (mmutype) {
305	case MMU_68851:
306		return ", MC68851 MMU";
307		break;
308
309	case MMU_68030:
310	case MMU_68040:
311	case MMU_68060:
312		return "+MMU";
313
314	default:
315		return "";
316	}
317}
318
319static const char *
320fpu_string(void)
321{
322	switch (fputype) {
323	case FPU_68881:
324		return ", MC68881 FPU";
325
326	case FPU_68882:
327		return ", MC68882 FPU";
328
329	case FPU_68040:
330	case FPU_68060:
331		return "+FPU";
332
333	default:
334		return "";
335	}
336}
337
338void
339identifycpu(void)
340{
341	const char *cpu_str, *mmu_str, *fpu_str, *cache_str;
342	struct bi_record *bi;
343	uint32_t qvers;
344
345	/* Fill in the CPU string. */
346	switch (cputype) {
347#ifdef M68020
348	case CPU_68020:
349		cpu_str = "MC68020";
350		break;
351#endif
352
353#ifdef M68030
354	case CPU_68030:
355		cpu_str = "MC68030";
356		break;
357#endif
358
359#ifdef M68040
360	case CPU_68040:
361		cpu_str = "MC68040";
362		break;
363#endif
364
365#ifdef M68060
366	case CPU_68060:
367		cpu_str = "MC68060";
368		break;
369#endif
370
371	default:
372		printf("unknown CPU type");
373		panic("startup");
374	}
375
376	mmu_str = mmu_string();
377	fpu_str = fpu_string();
378
379	switch (cputype) {
380#if defined(M68040)
381	case CPU_68040:
382		cache_str = ", 4k+4k on-chip physical I/D caches";
383		break;
384#endif
385#if defined(M68060)
386	case CPU_68060:
387		cache_str = ", 8k+8k on-chip physical I/D caches";
388		break;
389#endif
390	default:
391		cache_str = "";
392		break;
393	}
394
395	bi = bootinfo_find(BI_VIRT_QEMU_VERSION);
396	if (bi != NULL) {
397		qvers = bootinfo_get_u32(bi);
398	} else {
399		qvers = 0;
400	}
401
402	cpu_setmodel("Qemu %d.%d.%d: %s%s%s%s",
403	    (qvers >> 24) & 0xff,
404	    (qvers >> 16) & 0xff,
405	    (qvers >> 8)  & 0xff,
406	    cpu_str, mmu_str, fpu_str, cache_str);
407
408	printf("%s\n", cpu_getmodel());
409}
410
411/*
412 * machine dependent system variables.
413 */
414SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
415{
416
417	sysctl_createv(clog, 0, NULL, NULL,
418		       CTLFLAG_PERMANENT,
419		       CTLTYPE_NODE, "machdep", NULL,
420		       NULL, 0, NULL, 0,
421		       CTL_MACHDEP, CTL_EOL);
422
423	sysctl_createv(clog, 0, NULL, NULL,
424		       CTLFLAG_PERMANENT,
425		       CTLTYPE_STRUCT, "console_device", NULL,
426		       sysctl_consdev, 0, NULL, sizeof(dev_t),
427		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
428}
429
430/* See: sig_machdep.c */
431
432int	waittime = -1;
433
434static void (*cpu_reset_func)(void *, int);
435static void *cpu_reset_func_arg;
436
437void
438cpu_set_reset_func(void (*func)(void *, int), void *arg)
439{
440	if (cpu_reset_func == NULL) {
441		cpu_reset_func = func;
442		cpu_reset_func_arg = arg;
443	}
444}
445
446void
447cpu_reboot(int howto, char *bootstr)
448{
449	struct pcb *pcb = lwp_getpcb(curlwp);
450
451	/* take a snap shot before clobbering any registers */
452	if (pcb != NULL)
453		savectx(pcb);
454
455	/* If system is hold, just halt. */
456	if (cold) {
457		howto |= RB_HALT;
458		goto haltsys;
459	}
460
461	boothowto = howto;
462	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
463		waittime = 0;
464		vfs_shutdown();
465	}
466
467	/* Disable interrupts. */
468	splhigh();
469
470	/* If rebooting and a dump is requested, do it. */
471	if (howto & RB_DUMP)
472		dumpsys();
473
474 haltsys:
475	/* Run any shutdown hooks. */
476	doshutdownhooks();
477
478	pmf_system_shutdown(boothowto);
479
480#if defined(PANICWAIT) && !defined(DDB)
481	if ((howto & RB_HALT) == 0 && panicstr) {
482		printf("hit any key to reboot...\n");
483		cnpollc(1);
484		(void)cngetc();
485		cnpollc(0);
486		printf("\n");
487	}
488#endif
489
490	if (cpu_reset_func == NULL) {
491		printf("WARNING: No reset handler, holding here.\n\n");
492		for (;;) {
493			/* spin forever. */
494		}
495	}
496
497	/* Finally, halt/reboot the system. */
498	if (howto & RB_HALT) {
499		printf("halted\n\n");
500		(*cpu_reset_func)(cpu_reset_func_arg, RB_HALT);
501		/* NOTREACHED */
502	} else {
503		printf("rebooting...\n");
504		delay(1000000);
505		(*cpu_reset_func)(cpu_reset_func_arg, RB_AUTOBOOT);
506		/* NOTREACHED */
507	}
508	/* ...but just in case it is... */
509	printf("WARNING: System reset handler failed, holding here.\n\n");
510	for (;;) {
511		/* spin forever. */
512	}
513}
514
515/*
516 * Initialize the kernel crash dump header.
517 */
518void
519cpu_init_kcore_hdr(void)
520{
521	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
522	struct m68k_kcore_hdr *m = &h->un._m68k;
523	int i;
524	extern char end[];
525
526	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
527
528	/*
529	 * Initialize the `dispatcher' portion of the header.
530	 */
531	strcpy(h->name, machine);
532	h->page_size = PAGE_SIZE;
533	h->kernbase = KERNBASE;
534
535	/*
536	 * Fill in information about our MMU configuration.
537	 */
538	m->mmutype	= mmutype;
539	m->sg_v		= SG_V;
540	m->sg_frame	= SG_FRAME;
541	m->sg_ishift	= SG_ISHIFT;
542	m->sg_pmask	= SG_PMASK;
543	m->sg40_shift1	= SG4_SHIFT1;
544	m->sg40_mask2	= SG4_MASK2;
545	m->sg40_shift2	= SG4_SHIFT2;
546	m->sg40_mask3	= SG4_MASK3;
547	m->sg40_shift3	= SG4_SHIFT3;
548	m->sg40_addr1	= SG4_ADDR1;
549	m->sg40_addr2	= SG4_ADDR2;
550	m->pg_v		= PG_V;
551	m->pg_frame	= PG_FRAME;
552
553	/*
554	 * Initialize pointer to kernel segment table.
555	 */
556	m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
557
558	/*
559	 * Initialize relocation value such that:
560	 *
561	 *	pa = (va - KERNBASE) + reloc
562	 *
563	 * Since we're linked and loaded at the same place,
564	 * and the kernel is mapped va == pa, this is 0.
565	 */
566	m->reloc = 0;
567
568	/*
569	 * Define the end of the relocatable range.
570	 */
571	m->relocend = (uint32_t)end;
572
573	for (i = 0; i < bootinfo_mem_nsegments; i++) {
574		m->ram_segs[i].start = bootinfo_mem_segments[i].mem_addr;
575		m->ram_segs[i].size  = bootinfo_mem_segments[i].mem_size;
576	}
577}
578
579/*
580 * Compute the size of the machine-dependent crash dump header.
581 * Returns size in disk blocks.
582 */
583
584#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
585#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
586
587int
588cpu_dumpsize(void)
589{
590
591	return btodb(MDHDRSIZE);
592}
593
594/*
595 * Calculate size of RAM (in pages) to be dumped.
596 */
597u_long
598cpu_dump_mempagecnt(void)
599{
600	u_long i, n;
601
602	n = 0;
603	for (i = 0; i < bootinfo_mem_nsegments; i++)
604		n += atop(bootinfo_mem_segments[i].mem_size);
605	return n;
606}
607
608/*
609 * Called by dumpsys() to dump the machine-dependent header.
610 */
611int
612cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
613{
614	int buf[MDHDRSIZE / sizeof(int)];
615	cpu_kcore_hdr_t *chdr;
616	kcore_seg_t *kseg;
617	int error;
618
619	kseg = (kcore_seg_t *)buf;
620	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
621	    sizeof(int)];
622
623	/* Create the segment header. */
624	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
625	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
626
627	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
628	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
629	*blknop += btodb(sizeof(buf));
630	return error;
631}
632
633/*
634 * These variables are needed by /sbin/savecore
635 */
636uint32_t dumpmag = 0x8fca0101;	/* magic number */
637int	dumpsize = 0;		/* pages */
638long	dumplo = 0;		/* blocks */
639
640/*
641 * This is called by main to set dumplo and dumpsize.
642 * Dumps always skip the first PAGE_SIZE of disk space
643 * in case there might be a disk label stored there.
644 * If there is extra space, put dump at the end to
645 * reduce the chance that swapping trashes it.
646 */
647void
648cpu_dumpconf(void)
649{
650	int nblks, dumpblks;	/* size of dump area */
651
652	if (dumpdev == NODEV)
653		goto bad;
654	nblks = bdev_size(dumpdev);
655	if (nblks <= ctod(1))
656		goto bad;
657
658	dumpblks = cpu_dumpsize();
659	if (dumpblks < 0)
660		goto bad;
661	dumpblks += ctod(cpu_dump_mempagecnt());
662
663	/* If dump won't fit (incl. room for possible label), punt. */
664	if (dumpblks > (nblks - ctod(1)))
665		goto bad;
666
667	/* Put dump at end of partition */
668	dumplo = nblks - dumpblks;
669
670	/* dumpsize is in page units, and doesn't include headers. */
671	dumpsize = cpu_dump_mempagecnt();
672	return;
673
674 bad:
675	dumpsize = 0;
676}
677
678/*
679 * Dump physical memory onto the dump device.  Called by cpu_reboot().
680 */
681void
682dumpsys(void)
683{
684	const struct bdevsw *bdev;
685	u_long totalbytesleft, bytes, i, n, memcl;
686	u_long maddr;
687	int psize;
688	daddr_t blkno;
689	int (*dump)(dev_t, daddr_t, void *, size_t);
690	int error;
691
692	/* XXX Should save registers. */
693
694	if (dumpdev == NODEV)
695		return;
696	bdev = bdevsw_lookup(dumpdev);
697	if (bdev == NULL || bdev->d_psize == NULL)
698		return;
699
700	/*
701	 * For dumps during autoconfiguration,
702	 * if dump device has already configured...
703	 */
704	if (dumpsize == 0)
705		cpu_dumpconf();
706	if (dumplo <= 0) {
707		printf("\ndump to dev %u,%u not possible\n",
708		    major(dumpdev), minor(dumpdev));
709		return;
710	}
711	printf("\ndumping to dev %u,%u offset %ld\n",
712	    major(dumpdev), minor(dumpdev), dumplo);
713
714	psize = bdev_size(dumpdev);
715	printf("dump ");
716	if (psize == -1) {
717		printf("area unavailable\n");
718		return;
719	}
720
721	/* XXX should purge all outstanding keystrokes. */
722
723	dump = bdev->d_dump;
724	blkno = dumplo;
725
726	if ((error = cpu_dump(dump, &blkno)) != 0)
727		goto err;
728
729	totalbytesleft = ptoa(cpu_dump_mempagecnt());
730
731	for (memcl = 0; memcl < bootinfo_mem_nsegments; memcl++) {
732		maddr = bootinfo_mem_segments[memcl].mem_addr;
733		bytes = bootinfo_mem_segments[memcl].mem_size;
734
735		for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
736
737			/* Print out how many MBs we have left to go. */
738			if ((totalbytesleft % (1024*1024)) == 0)
739				printf_nolog("%ld ",
740				    totalbytesleft / (1024 * 1024));
741
742			/* Limit size for next transfer. */
743			n = bytes - i;
744			if (n > PAGE_SIZE)
745				n = PAGE_SIZE;
746
747			pmap_kenter_pa((vaddr_t)vmmap, maddr, VM_PROT_READ, 0);
748			pmap_update(pmap_kernel());
749
750			error = (*dump)(dumpdev, blkno, vmmap, n);
751			if (error)
752				goto err;
753
754			pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
755			pmap_update(pmap_kernel());
756
757			maddr += n;
758			blkno += btodb(n);
759		}
760	}
761
762 err:
763	switch (error) {
764
765	case ENXIO:
766		printf("device bad\n");
767		break;
768
769	case EFAULT:
770		printf("device not ready\n");
771		break;
772
773	case EINVAL:
774		printf("area improper\n");
775		break;
776
777	case EIO:
778		printf("i/o error\n");
779		break;
780
781	case EINTR:
782		printf("aborted from console\n");
783		break;
784
785	case 0:
786		printf("succeeded\n");
787		break;
788
789	default:
790		printf("error %d\n", error);
791		break;
792	}
793	printf("\n\n");
794	delay(5000);
795}
796
797void
798initcpu(void)
799{
800	/* No work to do. */
801}
802
803void
804straytrap(int pc, u_short evec)
805{
806
807	printf("unexpected trap (vector offset %x) from %x\n",
808	    evec & 0xFFF, pc);
809}
810
811/*
812 * Level 7 interrupts are caused by e.g. the ABORT switch.
813 *
814 * If we have DDB, then break into DDB on ABORT.  In a production
815 * environment, bumping the ABORT switch would be bad, so we enable
816 * panic'ing on ABORT with the kernel option "PANICBUTTON".
817 */
818int
819nmihand(void *arg)
820{
821
822	printf("NMI ignored.\n");
823
824	return 1;
825}
826
827/*
828 * cpu_exec_aout_makecmds():
829 *	CPU-dependent a.out format hook for execve().
830 *
831 * Determine of the given exec package refers to something which we
832 * understand and, if so, set up the vmcmds for it.
833 */
834int
835cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
836{
837
838    return ENOEXEC;
839}
840
841#ifdef MODULAR
842/*
843 * Push any modules loaded by the bootloader etc.
844 */
845void
846module_init_md(void)
847{
848}
849#endif
850
851const uint16_t ipl2psl_table[NIPL] = {
852	[IPL_NONE]       = PSL_S | PSL_IPL0,
853	[IPL_SOFTCLOCK]  = PSL_S | PSL_IPL1,
854	[IPL_SOFTBIO]    = PSL_S | PSL_IPL1,
855	[IPL_SOFTNET]    = PSL_S | PSL_IPL1,
856	[IPL_SOFTSERIAL] = PSL_S | PSL_IPL1,
857	[IPL_VM]         = PSL_S | PSL_IPL5,
858	[IPL_SCHED]      = PSL_S | PSL_IPL6,
859	[IPL_HIGH]       = PSL_S | PSL_IPL7,
860};
861
862int
863mm_md_physacc(paddr_t pa, vm_prot_t prot)
864{
865	psize_t size;
866	int i;
867
868	for (i = 0; i < bootinfo_mem_nsegments; i++) {
869		if (pa < bootinfo_mem_segments[i].mem_addr) {
870			continue;
871		}
872		size = trunc_page(bootinfo_mem_segments[i].mem_size);
873		if (pa >= bootinfo_mem_segments[i].mem_addr + size) {
874			continue;
875		}
876		return 0;
877	}
878	return EFAULT;
879}
880