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