Home | History | Annotate | Line # | Download | only in virt68k
      1 /*	$NetBSD: machdep.c,v 1.45 2026/07/14 13:37:21 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.45 2026/07/14 13:37:21 thorpej Exp $");
     43 
     44 #include "opt_m68k_arch.h"
     45 
     46 #define	_M68K_BUS_SPACE_PRIVATE
     47 
     48 #include <sys/param.h>
     49 #include <sys/systm.h>
     50 #include <sys/bus.h>
     51 #include <sys/cpu.h>
     52 #include <sys/boot_flag.h>
     53 
     54 #include <uvm/uvm_extern.h>
     55 
     56 #include <sys/sysctl.h>
     57 
     58 #include <machine/psl.h>
     59 #include <m68k/linux_bootinfo.h>
     60 #include <dev/cons.h>
     61 #include <dev/mm.h>
     62 
     63 #ifdef DDB
     64 #include <ddb/ddb.h>
     65 #endif
     66 
     67 #include "gftty.h"
     68 #if NGFTTY > 0
     69 #include <dev/goldfish/gfttyvar.h>
     70 #endif
     71 
     72 /* Machine-dependent initialization routines. */
     73 void	machine_init(paddr_t);
     74 
     75 /*
     76  * Clamp the kernel virtual address space to keep it out of the
     77  * TT ranges we use for devices.
     78  */
     79 struct pmap_bootmap machine_bootmap[] = {
     80 	{ .pmbm_vaddr = VIRT68K_IO_BASE,
     81 	  .pmbm_size  = VIRT68K_IO_SIZE,
     82 	  .pmbm_flags = PMBM_F_KEEPOUT },
     83 
     84 	{ .pmbm_vaddr = -1 },
     85 };
     86 
     87 static void
     88 machine_cnattach(void (*func)(bus_space_tag_t, bus_space_handle_t),
     89     paddr_t addr, paddr_t size)
     90 {
     91 	extern paddr_t consdev_addr;
     92 	bus_space_tag_t bst = &m68k_simple_bus_space;
     93 	bus_space_handle_t bsh;
     94 
     95 	if (bus_space_map(bst, addr, size, 0, &bsh) == 0) {
     96 		func(bst, bsh);
     97 	}
     98 	consdev_addr = addr;
     99 }
    100 
    101 /*
    102  * Early initialization, right before main is called.
    103  */
    104 void
    105 machine_init(paddr_t nextpa)
    106 {
    107 	struct bi_record *bi __unused;
    108 
    109 	extern paddr_t msgbufpa;
    110 
    111 	/*
    112 	 * Find the console in the bootinfo and attach it.
    113 	 */
    114 #if NGFTTY > 0
    115 	bi = bootinfo_find(BI_VIRT_GF_TTY_BASE);
    116 	if (bi != NULL) {
    117 		struct bi_virt_dev *vd = bootinfo_dataptr(bi);
    118 		machine_cnattach(gftty_cnattach, vd->vd_mmio_base, 0x1000);
    119 		printf("Initialized Goldfish TTY console @ 0x%08x\n",
    120 		    vd->vd_mmio_base);
    121 	}
    122 #endif /* NGFTTY > 0 */
    123 
    124 	/*
    125 	 * Pass 2 at parsing bootinfo now that the MMU is enabled.
    126 	 */
    127 	bootinfo_startup2(nextpa);
    128 
    129 	/*
    130 	 * Just use the default pager_map_size for now.  We may decide
    131 	 * to make it larger for large memory configs.
    132 	 */
    133 
    134 	/*
    135 	 * We've arranged the kernel to be linked at >= 0x2000,
    136 	 * so we can steal the first 8KB of RAM for the kernel
    137 	 * message buffer.
    138 	 */
    139 	KASSERT(MSGBUFSIZE <= 8192);
    140 	msgbufpa = 0;
    141 
    142 	machine_init_common(nextpa);
    143 
    144 	/* Check for RND seed from the loader. */
    145 	bootinfo_setup_rndseed();
    146 
    147 	char flags[32];
    148 	if (bootinfo_getarg("flags", flags, sizeof(flags))) {
    149 		for (const char *cp = flags; *cp != '\0'; cp++) {
    150 			/* Consume 'm' in favor of BI_RAMDISK. */
    151 			if (*cp == 'm') {
    152 				continue;
    153 			}
    154 			BOOT_FLAG(*cp, boothowto);
    155 		}
    156 	}
    157 }
    158 
    159 /*
    160  * Console initialization: called early on from main,
    161  * before vm init or startup.  Do enough configuration
    162  * to choose and initialize a console.
    163  */
    164 void
    165 consinit(void)
    166 {
    167 #ifdef DDB
    168 	if (boothowto & RB_KDB)
    169 		Debugger();
    170 #endif
    171 }
    172 
    173 /*
    174  * cpu_startup: allocate memory for variable-sized tables,
    175  * initialize CPU, and do autoconfiguration.
    176  */
    177 void
    178 cpu_startup(void)
    179 {
    180 	struct bootinfo_data *bid = bootinfo_data();
    181 
    182 	cpu_startup_common();
    183 
    184 	if (bid->bootinfo_mem_segments_ignored) {
    185 		printf("WARNING: ignored %zd bytes of memory in %d segments.\n",
    186 		    bid->bootinfo_mem_segments_ignored_bytes,
    187 		    bid->bootinfo_mem_segments_ignored);
    188 	}
    189 }
    190 
    191 void
    192 machine_set_model(void)
    193 {
    194 	struct bi_record *bi = bootinfo_find(BI_VIRT_QEMU_VERSION);
    195 	if (bi != NULL) {
    196 		uint32_t qvers = bootinfo_get_u32(bi);
    197 		cpu_setmodel("Qemu %d.%d.%d Virt platform",
    198 		    (qvers >> 24) & 0xff,
    199 		    (qvers >> 16) & 0xff,
    200 		    (qvers >> 8)  & 0xff);
    201 	} else {
    202 		/* XXX Assume Nono. */
    203 		cpu_setmodel("Nono Virt platform");
    204 	}
    205 }
    206 
    207 /*
    208  * machine dependent system variables.
    209  */
    210 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    211 {
    212 	/*
    213 	 * virt68k obviously does not have a non-working /RMC, but we
    214 	 * provide this as a r/w node in order to faciliate testing.
    215 	 */
    216 	static bool broken_rmc;
    217 
    218 	sysctl_createv(clog, 0, NULL, NULL,
    219 		       CTLFLAG_PERMANENT,
    220 		       CTLTYPE_NODE, "machdep", NULL,
    221 		       NULL, 0, NULL, 0,
    222 		       CTL_MACHDEP, CTL_EOL);
    223 
    224 	sysctl_createv(clog, 0, NULL, NULL,
    225 		       CTLFLAG_PERMANENT,
    226 		       CTLTYPE_STRUCT, "console_device", NULL,
    227 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    228 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    229 
    230 	sysctl_createv(clog, 0, NULL, NULL,
    231 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    232 		       CTLTYPE_BOOL, "broken_rmc", NULL,
    233 		       NULL, 0, &broken_rmc, 0,
    234 		       CTL_MACHDEP, CPU_BROKEN_RMC, CTL_EOL);
    235 }
    236 
    237 static void
    238 default_reset_func(void *arg, int howto)
    239 {
    240 	printf("WARNING: No reset handler, holding here.\n\n");
    241 	for (;;) {
    242 		/* spin forever. */
    243 	}
    244 }
    245 
    246 static void (*cpu_reset_func)(void *, int) = default_reset_func;
    247 static void *cpu_reset_func_arg;
    248 
    249 void
    250 cpu_set_reset_func(void (*func)(void *, int), void *arg)
    251 {
    252 	if (cpu_reset_func == default_reset_func && func != NULL) {
    253 		cpu_reset_func = func;
    254 		cpu_reset_func_arg = arg;
    255 	}
    256 }
    257 
    258 void
    259 machine_halt(void)
    260 {
    261 	(*cpu_reset_func)(cpu_reset_func_arg, RB_HALT);
    262 }
    263 
    264 void
    265 machine_reboot(int howto, char *bootstr)
    266 {
    267 	(*cpu_reset_func)(cpu_reset_func_arg, RB_AUTOBOOT);
    268 }
    269 
    270 /*
    271  * Level 7 interrupts are caused by e.g. the ABORT switch.
    272  *
    273  * If we have DDB, then break into DDB on ABORT.  In a production
    274  * environment, bumping the ABORT switch would be bad, so we enable
    275  * panic'ing on ABORT with the kernel option "PANICBUTTON".
    276  */
    277 int
    278 nmihand(void *arg)
    279 {
    280 
    281 	printf("NMI ignored.\n");
    282 
    283 	return 1;
    284 }
    285 
    286 const uint16_t ipl2psl_table[NIPL] = {
    287 	[IPL_NONE]       = PSL_S | PSL_IPL0,
    288 	[IPL_SOFTCLOCK]  = PSL_S | PSL_IPL1,
    289 	[IPL_SOFTBIO]    = PSL_S | PSL_IPL1,
    290 	[IPL_SOFTNET]    = PSL_S | PSL_IPL1,
    291 	[IPL_SOFTSERIAL] = PSL_S | PSL_IPL1,
    292 	[IPL_VM]         = PSL_S | PSL_IPL5,
    293 	[IPL_SCHED]      = PSL_S | PSL_IPL6,
    294 	[IPL_HIGH]       = PSL_S | PSL_IPL7,
    295 };
    296