Home | History | Annotate | Line # | Download | only in m68k
      1 /*	$NetBSD: m68k_machdep.c,v 1.26 2026/10/31 20:59:27 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997, 2026 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * Copyright (c) 1988 University of Utah.
     31  * Copyright (c) 1982, 1986, 1990, 1993
     32  *	The Regents of the University of California.  All rights reserved.
     33  *
     34  * This code is derived from software contributed to Berkeley by
     35  * the Systems Programming Group of the University of Utah Computer
     36  * Science Department.
     37  *
     38  * Redistribution and use in source and binary forms, with or without
     39  * modification, are permitted provided that the following conditions
     40  * are met:
     41  * 1. Redistributions of source code must retain the above copyright
     42  *    notice, this list of conditions and the following disclaimer.
     43  * 2. Redistributions in binary form must reproduce the above copyright
     44  *    notice, this list of conditions and the following disclaimer in the
     45  *    documentation and/or other materials provided with the distribution.
     46  * 3. Neither the name of the University nor the names of its contributors
     47  *    may be used to endorse or promote products derived from this software
     48  *    without specific prior written permission.
     49  *
     50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     60  * SUCH DAMAGE.
     61  *
     62  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
     63  *
     64  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
     65  */
     66 
     67 #include <sys/cdefs.h>
     68 __KERNEL_RCSID(0, "$NetBSD: m68k_machdep.c,v 1.26 2026/10/31 20:59:27 thorpej Exp $");
     69 
     70 #include "opt_compat_netbsd.h"
     71 #include "opt_compat_sunos.h"
     72 #include "opt_execfmt.h"
     73 #include "opt_m68k_arch.h"
     74 #include "opt_fpu_emulate.h"
     75 
     76 #include <sys/param.h>
     77 #include <sys/cpu.h>
     78 #include <sys/exec.h>
     79 #include <sys/lwp.h>
     80 #include <sys/proc.h>
     81 #include <sys/msgbuf.h>
     82 #include <sys/reboot.h>
     83 #include <sys/device.h>
     84 #include <sys/vnode.h>
     85 #include <sys/kernel.h>
     86 #include <sys/kcore.h>
     87 
     88 #include <dev/cons.h>
     89 
     90 #ifdef EXEC_AOUT
     91 #include <sys/exec_aout.h>	/* for cpu_exec_aout_makecmds() prototype */
     92 #endif
     93 
     94 #include <uvm/uvm_extern.h>
     95 
     96 #include <m68k/m68k.h>
     97 #include <m68k/kcore.h>
     98 #include <m68k/frame.h>
     99 #include <m68k/pcb.h>
    100 #include <m68k/reg.h>
    101 #ifdef M68060
    102 #include <m68k/pcr.h>
    103 #endif
    104 #include <m68k/seglist.h>
    105 
    106 /* the following is used externally (sysctl_hw) */
    107 char	machine[] = MACHINE;		/* from <machine/param.h> */
    108 char	machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
    109 
    110 /* Our exported CPU info; we can have only one. */
    111 struct cpu_info cpu_info_store;
    112 
    113 /* cpu speed in kHz */
    114 int	cpuspeed_khz;
    115 
    116 #if defined(M68020) || defined(M68030)
    117 /* fpu speed in kHz */
    118 int	fpuspeed_khz;
    119 #endif
    120 
    121 #ifdef M68K_EC
    122 /* external cache size in bytes */
    123 int	ecsize;
    124 #endif
    125 
    126 /*
    127  * Physical memory segments.  These segments are included in kernel
    128  * crash dumps, and the available ranges of the segments are loaded
    129  * into the VM system as managed pages.
    130  */
    131 phys_seg_list_t phys_seg_list[VM_PHYSSEG_MAX];
    132 
    133 /*
    134  * __HAVE_M68K_PRIVATE_MSGSBUF is a hook for the Sun platforms that
    135  * are re-using PROM mappings of memory for the messsage buffer that
    136  * are not guaranteed to be physically contiguous.
    137  *
    138  * How we act on this: We don't care about the PA of the message buffer
    139  * at all, and we assume that the message buffer has already been mapped
    140  * as part of the VM bootstrap.
    141  */
    142 #ifndef __HAVE_M68K_PRIVATE_MSGSBUF
    143 paddr_t	msgbufpa = (paddr_t)-1;		/* PA of message buffer */
    144 #endif
    145 void	*msgbufaddr;
    146 
    147 vaddr_t m68k_usrstack;
    148 
    149 /*
    150  * Common tasks for machine_init().
    151  */
    152 void
    153 machine_init_common(paddr_t nextpa)
    154 {
    155 	extern paddr_t avail_start, avail_end;
    156 	int i;
    157 #ifndef __HAVE_M68K_PRIVATE_MSGSBUF
    158 	int end_seg = 0;
    159 #endif
    160 
    161 	/*
    162 	 * Compute the boundaries of available memory.
    163 	 */
    164 	avail_start = UINT_MAX;
    165 	avail_end = 0;
    166 	for (i = 0; i < VM_PHYSSEG_MAX; i++) {
    167 		/*
    168 		 * Make sure the memory segment begins/ends on
    169 		 * page boundaries.
    170 		 *
    171 		 * If ps_avail_start and ps_avail_end have not already
    172 		 * been initialized, go ahead and validate those.
    173 		 */
    174 		phys_seg_list[i].ps_start =
    175 		    m68k_round_page(phys_seg_list[i].ps_start);
    176 		phys_seg_list[i].ps_end =
    177 		    m68k_trunc_page(phys_seg_list[i].ps_end);
    178 
    179 		if (phys_seg_list[i].ps_avail_start == 0 &&
    180 		    phys_seg_list[i].ps_avail_end == 0) {
    181 			phys_seg_list[i].ps_avail_start =
    182 			    phys_seg_list[i].ps_start;
    183 			phys_seg_list[i].ps_avail_end =
    184 			    phys_seg_list[i].ps_end;
    185 		}
    186 
    187 		if (phys_seg_list[i].ps_start == phys_seg_list[i].ps_end) {
    188 			/* Empty segment. */
    189 			continue;
    190 		}
    191 
    192 		/*
    193 		 * nextpa represents the next available page after
    194 		 * the pages already consumed by the bootstrap
    195 		 * process.  If it falls within this physical segment,
    196 		 * just the available range as necessary.
    197 		 */
    198 		if (nextpa >= phys_seg_list[i].ps_start &&
    199 		    /* this <= is intentional */
    200 		    nextpa <= phys_seg_list[i].ps_end &&
    201 		    nextpa > phys_seg_list[i].ps_avail_start) {
    202 			phys_seg_list[i].ps_avail_start = nextpa;
    203 		}
    204 
    205 		if (phys_seg_list[i].ps_avail_start ==
    206 		    phys_seg_list[i].ps_avail_end) {
    207 			/* Segment has been completely gobbled up. */
    208 			continue;
    209 		}
    210 
    211 		if (phys_seg_list[i].ps_avail_start < avail_start) {
    212 			avail_start = phys_seg_list[i].ps_avail_start;
    213 		}
    214 		if (phys_seg_list[i].ps_avail_end > avail_end) {
    215 			avail_end = phys_seg_list[i].ps_avail_end;
    216 #ifndef __HAVE_M68K_PRIVATE_MSGSBUF
    217 			end_seg = i;
    218 #endif
    219 		}
    220 	}
    221 
    222 #ifndef __HAVE_M68K_PRIVATE_MSGSBUF
    223 	/*
    224 	 * If the message buffer has not already been allocated,
    225 	 * allocate it from the end of physical memory.
    226 	 */
    227 	if (msgbufpa == (paddr_t)-1) {
    228 		KASSERT((phys_seg_list[end_seg].ps_avail_end
    229 			 - phys_seg_list[end_seg].ps_avail_start)
    230 			>= round_page(MSGBUFSIZE));
    231 		phys_seg_list[end_seg].ps_avail_end -= round_page(MSGBUFSIZE);
    232 		msgbufpa = phys_seg_list[end_seg].ps_avail_end;
    233 	}
    234 #endif
    235 
    236 #ifndef VM_PHYS_SEG_TO_FREELIST
    237 #define	VM_PHYS_SEG_TO_FREELIST(s) VM_FREELIST_DEFAULT
    238 #endif
    239 
    240 	/*
    241 	 * Now load the pages into the VM system.
    242 	 */
    243 	for (i = 0; i < VM_PHYSSEG_MAX; i++) {
    244 		if (phys_seg_list[i].ps_avail_start ==
    245 		    phys_seg_list[i].ps_avail_end) {
    246 			/* Segment has been completely gobbled up. */
    247 			continue;
    248 		}
    249 		uvm_page_physload(atop(phys_seg_list[i].ps_avail_start),
    250 				  atop(phys_seg_list[i].ps_avail_end),
    251 				  atop(phys_seg_list[i].ps_avail_start),
    252 				  atop(phys_seg_list[i].ps_avail_end),
    253 				  VM_PHYS_SEG_TO_FREELIST(i));
    254 	}
    255 
    256 	/*
    257 	 * Initialize the kernel message buffer.
    258 	 */
    259 #ifndef __HAVE_M68K_PRIVATE_MSGSBUF
    260 	for (i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) {
    261 		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
    262 			       msgbufpa + i * PAGE_SIZE,
    263 			       VM_PROT_READ|VM_PROT_WRITE, 0);
    264 	}
    265 	pmap_update(pmap_kernel());
    266 #endif
    267 	initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
    268 }
    269 
    270 /*
    271  * Common tasks for cpu_startup().
    272  */
    273 void
    274 cpu_startup_common(void)
    275 {
    276 	vaddr_t minaddr, maxaddr;
    277 	char pbuf[9];
    278 
    279 	/*
    280 	 * For the benefit of modules that need USRSTACK (such
    281 	 * as compat exec modules).  Initialized here because
    282 	 * USRSTACK may not be a compile-time constant.
    283 	 */
    284 	m68k_usrstack = USRSTACK;
    285 
    286 	/* Initialize the FPU, if present. */
    287 	fpu_init();
    288 
    289 	/* Set the model info. */
    290 	machine_set_model();
    291 
    292 	/*
    293 	 * Good {morning,afternoon,evening,night}.
    294 	 * XXX Should augment banner() and then switch to using it.
    295 	 */
    296 	printf("%s%s", copyright, version);
    297 #ifdef __HAVE_CPU_STARTUP_PRINT_MACHINE_MODEL
    298 	cpu_startup_print_machine_model(printf);
    299 #endif
    300 #ifdef __HAVE_CPU_STARTUP_PRINT_TOTAL_MEMORY
    301 	cpu_startup_print_total_memory(printf);
    302 #else
    303 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
    304 	printf("total memory = %s\n", pbuf);
    305 #endif
    306 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
    307 	printf("avail memory = %s\n", pbuf);
    308 
    309 	/*
    310 	 * Allocate a submap for physio
    311 	 */
    312 	minaddr = 0;
    313 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    314 	    VM_PHYS_SIZE, 0, false, NULL);
    315 }
    316 __weak_alias(cpu_startup, cpu_startup_common);
    317 
    318 static const char *
    319 mhz_string_from_khz(int speed_khz, char *buf, size_t bufsize)
    320 {
    321 	int whole_mhz = speed_khz / 1000;
    322 	int frac_mhz = (speed_khz % 1000) / 10;
    323 	if ((frac_mhz % 10) == 0) {
    324 		frac_mhz /= 10;
    325 	}
    326 	if (frac_mhz == 0) {
    327 		snprintf(buf, bufsize, " @ %dMHz", whole_mhz);
    328 	} else {
    329 		snprintf(buf, bufsize, " @ %d.%dMHz", whole_mhz, frac_mhz);
    330 	}
    331 	return buf;
    332 }
    333 
    334 void
    335 cpu_startup_print_machine_model(void (*pr)(const char *, ...)
    336 				__printflike(1, 2))
    337 {
    338 	char speed_str[sizeof("@ xxx.xxxMHz")] = { 0 };
    339 
    340 	/*
    341 	 * Caller should have set the system model already.  We
    342 	 * will print the CPU information after, like so:
    343 	 *
    344 	 * MODEL
    345 	 * CPU MMU FPU CACHE
    346 	 *
    347 	 * Examples:
    348 
    349   Qemu 10.1.2 Virt platform
    350   MC68040+MMU+FPU, 4k+4k on-chip I/D caches
    351 
    352   Motorola MVME-147
    353   MC68030 CPU+MMU @ 25MHz, MC68882 FPU
    354 
    355   HP 9000/433s
    356   MC68040 CPU+MMU+FPU @ 33MHz, 4K+4K on-chip I/D caches
    357 
    358   HP 9000/320
    359   MC68020 CPU @ 16.67MHz, HP MMU, MC68881 FPU
    360   External 16K virtual-address cache
    361 
    362   HP 9000/350
    363   MC68020 CPU @ 25MHz, HP MMU, MC68881 FPU @ 20MHz
    364   External 32K virtual-address cache
    365 
    366 	 * ^^^ Yes, there's at least one HP system where the FPU
    367 	 * has a different clock than the CPU.
    368 	 *
    369 	 * There is a hook that allows machine-specific code to print
    370 	 * a more informative model banner, such as:
    371 
    372   Model: sun3x 80
    373   MC68030 CPU+MMU @ 20MHz, MC68882 FPU
    374 
    375   Model: sun3 160
    376   MC68020 CPU @ 16.67MHz, Sun MMU, MC68881 FPU
    377 
    378   Model: sun2 {120,170}
    379   MC68010 CPU @ 10MHz, Sun MMU
    380 
    381   SONY NET WORK STATION, Model NWS-1710, Machine ID #123456
    382   MC68030 CPU+MMU @ 25MHz, MC68882 FPU
    383 
    384 	 * (In this last example, cpu_model() returns "NWS-1710".)
    385 	 * In the Sun examples, for historical reasons, the model
    386 	 * string is formatted a certain way for use by the installer
    387 	 * miniroot.
    388 	 *
    389 	 * This is a departure from how it has been on some NetBSD
    390 	 * systems historically, but this is intended to bring some
    391 	 * consistency to the platforms while maintaining a reasonable
    392 	 * aesthetic.
    393 	 */
    394 #ifdef __HAVE_M68K_MACHINE_PRINT_MODEL
    395 	machine_print_model(pr);
    396 #else
    397 	(*pr)("%s\n", cpu_getmodel());
    398 #endif
    399 
    400 	switch (cputype) {
    401 #ifdef M68010
    402 	case CPU_68010:
    403 		(*pr)("MC68010 CPU");
    404 		break;
    405 #endif
    406 #ifdef M68020
    407 	case CPU_68020:
    408 		(*pr)("MC68020 CPU");
    409 		break;
    410 #endif
    411 #ifdef M68030
    412 	case CPU_68030:
    413 		(*pr)("MC68030 CPU+MMU");
    414 		break;
    415 #endif
    416 #ifdef M68040
    417 	case CPU_68040:
    418 		(*pr)("MC68040 CPU+MMU");
    419 		break;
    420 #endif
    421 #ifdef M68060
    422 	case CPU_68060: {
    423 		u_int pcr = get_pcr();
    424 		(*pr)("MC68%s060 rev.%d CPU+MMU",
    425 		    (PCR_ID(pcr) & 1) ? "LC" : "",
    426 		    (int)PCR_REVISION(pcr));
    427 		if (pcr & PCR_DFP) {
    428 			(*pr)("+FPU(disabled)");
    429 		}
    430 		break;
    431 	    }
    432 #endif
    433 	default:
    434 		(*pr)("unknown CPU type\n");
    435 		panic("startup");
    436 	}
    437 
    438 #if defined(M68040) || defined(M68060)
    439 	switch (fputype) {
    440 	case FPU_68040:
    441 	case FPU_68060:
    442 		(*pr)("+FPU");
    443 		break;
    444 	default:
    445 		break;
    446 	}
    447 #endif
    448 
    449 	if (cpuspeed_khz) {
    450 		(*pr)("%s",
    451 		    mhz_string_from_khz(cpuspeed_khz,
    452 					speed_str, sizeof(speed_str)));
    453 	}
    454 
    455 	switch (mmutype) {
    456 #ifdef M68K_MMU_68851
    457 	case MMU_68851:
    458 		(*pr)(", MC68851 MMU");
    459 		break;
    460 #endif
    461 #ifdef M68K_MMU_HP
    462 	case MMU_HP:
    463 		(*pr)(", HP MMU");
    464 		break;
    465 #endif
    466 #ifdef M68K_MMU_SUN
    467 	case MMU_SUN:
    468 		(*pr)(", Sun MMU");
    469 		break;
    470 #endif
    471 #ifdef M68K_MMU_CUSTOM
    472 	case MMU_CUSTOM:
    473 		(*pr)(", custom MMU");
    474 		break;
    475 #endif
    476 	default:
    477 		break;
    478 	}
    479 
    480 	switch (fputype) {
    481 #ifdef FPU_EMULATE
    482 	case FPU_NONE:
    483 		(*pr)(", emulated FPU");
    484 		break;
    485 #endif
    486 #if defined(M68020) || defined(M68030)
    487 	case FPU_68881:
    488 		(*pr)(", MC68881 FPU");
    489 		break;
    490 
    491 	case FPU_68882:
    492 		(*pr)(", MC68882 FPU");
    493 		break;
    494 #endif
    495 	default:
    496 		break;
    497 	}
    498 
    499 #if defined(M68020) || defined(M68030)
    500 	if (fpuspeed_khz != 0 && fpuspeed_khz != cpuspeed_khz) {
    501 		(*pr)("%s",
    502 		    mhz_string_from_khz(fpuspeed_khz,
    503 					speed_str, sizeof(speed_str)));
    504 	}
    505 #endif
    506 
    507 	switch (cputype) {
    508 #if defined(M68040) || defined(M68060)
    509 	case CPU_68040:
    510 	case CPU_68060:
    511 		(*pr)(", %dK+%dK on-chip I/D caches",
    512 		    cputype == CPU_68040 ? 4 : 8,
    513 		    cputype == CPU_68040 ? 4 : 8);
    514 		break;
    515 #endif
    516 	default:
    517 #ifdef M68K_EC
    518 		if (ectype != EC_NONE) {
    519 			(*pr)("\nExternal ");
    520 			if (ecsize >= 1024) {
    521 				(*pr)("%dK ", ecsize / 1024);
    522 			}
    523 			(*pr)("%s-address cache",
    524 			    ectype == EC_PHYS ? "physical" : "virtual");
    525 		}
    526 #endif
    527 		break;
    528 	}
    529 	(*pr)("\n");
    530 }
    531 
    532 int
    533 mm_md_physacc_regular(paddr_t pa, vm_prot_t prot)
    534 {
    535 	int i;
    536 
    537 	for (i = 0; i < VM_PHYSSEG_MAX; i++) {
    538 		if (phys_seg_list[i].ps_start == phys_seg_list[i].ps_end) {
    539 			continue;
    540 		}
    541 		if (pa < phys_seg_list[i].ps_start) {
    542 			continue;
    543 		}
    544 		if (pa >= phys_seg_list[i].ps_end) {
    545 			continue;
    546 		}
    547 		return 0;
    548 	}
    549 	return EFAULT;
    550 }
    551 
    552 int
    553 cpu_reboot_poll_console(bool wait)
    554 {
    555 	int rv;
    556 
    557 	cnpollc(true);
    558 	/* If there is no console input device, cngetc() returns 0. */
    559 	while ((rv = cngetc()) == 0 && wait) {
    560 		delay(100000);
    561 	}
    562 	cnpollc(false);
    563 
    564 	return rv;
    565 }
    566 
    567 void
    568 machine_powerdown_default(void)
    569 {
    570 	/* zip, nada, nothing */
    571 }
    572 __weak_alias(machine_powerdown,machine_powerdown_default);
    573 
    574 void
    575 machine_halt_default(void)
    576 {
    577 	printf("Please press any key to reboot.\n");
    578 
    579 	cpu_reboot_poll_console(true);
    580 }
    581 __weak_alias(machine_halt,machine_halt_default);
    582 
    583 int	waittime = -1;
    584 
    585 void
    586 bootsync(void)
    587 {
    588 	if (waittime < 0) {
    589 		waittime = 0;
    590 		vfs_shutdown();
    591 	}
    592 }
    593 
    594 void
    595 cpu_reboot_common(int howto, char *bootstr)
    596 {
    597 	struct pcb *pcb = lwp_getpcb(curlwp);
    598 
    599 	/* take a snap shot before clobbering any registers */
    600 	if (pcb != NULL) {
    601 		savectx(pcb);
    602 	}
    603 
    604 	/* If system is hold, just halt. */
    605 	if (cold) {
    606 		howto |= RB_HALT;
    607 		goto haltsys;
    608 	}
    609 
    610 	/* Un-blank the screen if appropriate. */
    611 	cnpollc(true);
    612 
    613 	boothowto = howto;
    614 	if ((howto & RB_NOSYNC) == 0) {
    615 		bootsync();
    616 	}
    617 
    618 	/* Disable interrupts. */
    619 	splhigh();
    620 
    621 	/* If rebooting and a dump is requested, do it. */
    622 	if (howto & RB_DUMP) {
    623 		dumpsys();
    624 	}
    625 
    626  haltsys:
    627 	/* Run any shutdown hooks. */
    628 	doshutdownhooks();
    629 
    630 	pmf_system_shutdown(boothowto);
    631 
    632 #if defined(PANICWAIT) && !defined(DDB)
    633 	if ((howto & RB_HALT) == 0 && panicstr) {
    634 		printf("hit any key to reboot...\n");
    635 		cpu_reboot_poll_console(false);
    636 		printf("\n");
    637 	}
    638 #endif
    639 
    640 	/* Finally, halt/reboot the system. */
    641 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
    642 		machine_powerdown();
    643 	}
    644 	if (howto & RB_HALT) {
    645 		printf("The operating system has halted.\n");
    646 		machine_halt();
    647 	}
    648 
    649 	printf("rebooting...\n");
    650 	delay(1000000);
    651 	machine_reboot(howto, bootstr);
    652 	printf("WARNING: system reboot failed, holding here.\n\n");
    653 	for (;;) {
    654 		/* spin forever. */
    655 	}
    656 }
    657 __weak_alias(cpu_reboot,cpu_reboot_common);
    658 
    659 /*
    660  * mm_md_physacc_common is the standard implementation for all
    661  * m68k platforms, and covers regular physical memory.  If a
    662  * platform wants to include other ranges, it can simply
    663  * define its own mm_md_physacc(), call mm_md_physacc_common()
    664  * first, and then check its own ranges if mm_md_physacc_common()
    665  * does not return 0.
    666  */
    667 __weak_alias(mm_md_physacc, mm_md_physacc_regular);
    668 
    669 /*
    670  * Set registers on exec.
    671  */
    672 void
    673 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
    674 {
    675 	struct trapframe *tf = (struct trapframe *)l->l_md.md_regs;
    676 	struct pcb *pcb = lwp_getpcb(l);
    677 
    678 	memset(tf, 0, sizeof(*tf));
    679 
    680 	tf->tf_sr = PSL_USERSET;
    681 	tf->tf_pc = pack->ep_entry & ~1;
    682 	tf->tf_regs[D0] = 0;
    683 	tf->tf_regs[D1] = 0;
    684 	tf->tf_regs[D2] = 0;
    685 	tf->tf_regs[D3] = 0;
    686 	tf->tf_regs[D4] = 0;
    687 	tf->tf_regs[D5] = 0;
    688 	tf->tf_regs[D6] = 0;
    689 	tf->tf_regs[D7] = 0;
    690 	tf->tf_regs[A0] = 0;
    691 	tf->tf_regs[A1] = 0;
    692 	tf->tf_regs[A2] = l->l_proc->p_psstrp;
    693 	tf->tf_regs[A3] = 0;
    694 	tf->tf_regs[A4] = 0;
    695 	tf->tf_regs[A5] = 0;
    696 	tf->tf_regs[A6] = 0;
    697 	tf->tf_regs[SP] = stack;
    698 
    699 	/* restore a null state frame */
    700 	pcb->pcb_fpregs.fpf_null = 0;
    701 #if !defined(__mc68010__)
    702 	if (fputype)
    703 		fpu_restore(&pcb->pcb_fpregs);
    704 #endif
    705 
    706 #ifdef COMPAT_SUNOS
    707 	/* see m68k/sunos_syscall.c */
    708 	l->l_md.md_flags = 0;
    709 #endif
    710 }
    711 
    712 #ifdef EXEC_AOUT
    713 /*
    714  * cpu_exec_aout_makecmds():
    715  *	cpu-dependent a.out format hook for execve().
    716  *
    717  * Determine of the given exec package refers to something which we
    718  * understand and, if so, set up the vmcmds for it.
    719  *
    720  * XXX what are the special cases for the hp300?
    721  * XXX why is this COMPAT_NOMID?  was something generating
    722  *	hp300 binaries with an a_mid of 0?  i thought that was only
    723  *	done on little-endian machines...  -- cgd
    724  * XXX perhaps this whole thing should be relegated to a smoking crater?
    725  */
    726 int
    727 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
    728 {
    729 #ifdef __mc68010__
    730 	/* There were never native a.out binaries for NetBSD on 68010. */
    731 	return ENOEXEC;
    732 #elif defined(COMPAT_NOMID) || defined(COMPAT_44)
    733 	struct exec *execp = epp->ep_hdr;
    734 	u_long midmag, magic;
    735 	u_short mid;
    736 	int error;
    737 
    738 	midmag = ntohl(execp->a_midmag);
    739 	mid = (midmag >> 16) & 0xffff;
    740 	magic = midmag & 0xffff;
    741 
    742 	midmag = mid << 16 | magic;
    743 
    744 	switch (midmag) {
    745 #ifdef COMPAT_NOMID
    746 	case (MID_ZERO << 16) | ZMAGIC:
    747 		error = exec_aout_prep_oldzmagic(l, epp);
    748 		break;
    749 #endif
    750 #ifdef COMPAT_44
    751 	case (MID_HP300 << 16) | ZMAGIC:
    752 		error = exec_aout_prep_oldzmagic(l, epp);
    753 		break;
    754 #endif
    755 	default:
    756 		error = ENOEXEC;
    757 	}
    758 	return error;
    759 #else /* COMPAT_NOMID || COMPAT_44 */
    760 	return ENOEXEC;
    761 #endif
    762 }
    763 #endif /* EXEC_AOUT */
    764