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