Home | History | Annotate | Line # | Download | only in virt68k
      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) */
    105 char	machine[] = MACHINE;	/* from <machine/param.h> */
    106 
    107 /* Our exported CPU info; we can have only one. */
    108 struct cpu_info cpu_info_store;
    109 
    110 struct vm_map *phys_map = NULL;
    111 
    112 paddr_t msgbufpa;		/* PA of message buffer */
    113 
    114 // int	maxmem;			/* max memory per process */
    115 
    116 extern	short exframesize[];
    117 
    118 /* prototypes for local functions */
    119 void	identifycpu(void);
    120 void	initcpu(void);
    121 void	dumpsys(void);
    122 
    123 int	cpu_dumpsize(void);
    124 int	cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
    125 void	cpu_init_kcore_hdr(void);
    126 u_long	cpu_dump_mempagecnt(void);
    127 int	cpu_exec_aout_makecmds(struct lwp *, struct exec_package *);
    128 void	straytrap(int, u_short);
    129 
    130 /*
    131  * Machine-independent crash dump header info.
    132  */
    133 cpu_kcore_hdr_t cpu_kcore_hdr;
    134 
    135 /* Machine-dependent initialization routines. */
    136 void	virt68k_init(void);
    137 
    138 /*
    139  * Machine-dependent bootinfo "console attach" routine.
    140  */
    141 void
    142 bootinfo_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  */
    159 void
    160 virt68k_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  */
    226 void
    227 consinit(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  */
    245 void
    246 cpu_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 
    301 static const char *
    302 mmu_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 
    319 static const char *
    320 fpu_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 
    338 void
    339 identifycpu(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  */
    414 SYSCTL_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 
    432 int	waittime = -1;
    433 
    434 static void (*cpu_reset_func)(void *, int);
    435 static void *cpu_reset_func_arg;
    436 
    437 void
    438 cpu_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 
    446 void
    447 cpu_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  */
    518 void
    519 cpu_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 
    587 int
    588 cpu_dumpsize(void)
    589 {
    590 
    591 	return btodb(MDHDRSIZE);
    592 }
    593 
    594 /*
    595  * Calculate size of RAM (in pages) to be dumped.
    596  */
    597 u_long
    598 cpu_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  */
    611 int
    612 cpu_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  */
    636 uint32_t dumpmag = 0x8fca0101;	/* magic number */
    637 int	dumpsize = 0;		/* pages */
    638 long	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  */
    647 void
    648 cpu_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  */
    681 void
    682 dumpsys(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 
    797 void
    798 initcpu(void)
    799 {
    800 	/* No work to do. */
    801 }
    802 
    803 void
    804 straytrap(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  */
    818 int
    819 nmihand(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  */
    834 int
    835 cpu_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  */
    845 void
    846 module_init_md(void)
    847 {
    848 }
    849 #endif
    850 
    851 const 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 
    862 int
    863 mm_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