1 1.112 thorpej /* $NetBSD: machdep.c,v 1.112 2024/03/05 14:15:32 thorpej Exp $ */ 2 1.1 nisimura 3 1.1 nisimura /*- 4 1.1 nisimura * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 1.1 nisimura * All rights reserved. 6 1.1 nisimura * 7 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation 8 1.1 nisimura * by Tohru Nishimura. 9 1.1 nisimura * 10 1.1 nisimura * Redistribution and use in source and binary forms, with or without 11 1.1 nisimura * modification, are permitted provided that the following conditions 12 1.1 nisimura * are met: 13 1.1 nisimura * 1. Redistributions of source code must retain the above copyright 14 1.1 nisimura * notice, this list of conditions and the following disclaimer. 15 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 nisimura * notice, this list of conditions and the following disclaimer in the 17 1.1 nisimura * documentation and/or other materials provided with the distribution. 18 1.1 nisimura * 19 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE. 30 1.1 nisimura */ 31 1.1 nisimura 32 1.1 nisimura #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 33 1.1 nisimura 34 1.112 thorpej __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.112 2024/03/05 14:15:32 thorpej Exp $"); 35 1.1 nisimura 36 1.1 nisimura #include "opt_ddb.h" 37 1.16 lukem #include "opt_kgdb.h" 38 1.31 martin #include "opt_compat_sunos.h" 39 1.63 apb #include "opt_modular.h" 40 1.31 martin #include "opt_panicbutton.h" 41 1.75 mrg #include "opt_m68k_arch.h" 42 1.1 nisimura 43 1.1 nisimura #include <sys/param.h> 44 1.1 nisimura #include <sys/systm.h> 45 1.1 nisimura #include <sys/kernel.h> 46 1.1 nisimura #include <sys/proc.h> 47 1.1 nisimura #include <sys/buf.h> 48 1.1 nisimura #include <sys/reboot.h> 49 1.1 nisimura #include <sys/conf.h> 50 1.1 nisimura #include <sys/file.h> 51 1.1 nisimura #include <sys/device.h> 52 1.1 nisimura #include <sys/mbuf.h> 53 1.1 nisimura #include <sys/msgbuf.h> 54 1.1 nisimura #include <sys/ioctl.h> 55 1.1 nisimura #include <sys/tty.h> 56 1.1 nisimura #include <sys/mount.h> 57 1.1 nisimura #include <sys/exec.h> 58 1.70 matt #include <sys/exec_aout.h> /* for MID_* */ 59 1.1 nisimura #include <sys/core.h> 60 1.80 rmind #include <sys/kauth.h> 61 1.1 nisimura #include <sys/kcore.h> 62 1.1 nisimura #include <sys/vnode.h> 63 1.1 nisimura #include <sys/syscallargs.h> 64 1.28 ragge #include <sys/ksyms.h> 65 1.76 tsutsui #include <sys/module.h> 66 1.1 nisimura #ifdef KGDB 67 1.1 nisimura #include <sys/kgdb.h> 68 1.1 nisimura #endif 69 1.12 jdolecek #include <sys/boot_flag.h> 70 1.94 tsutsui #include <sys/exec_elf.h> 71 1.98 christos #include <sys/cpu.h> 72 1.1 nisimura 73 1.1 nisimura #include <uvm/uvm_extern.h> 74 1.1 nisimura 75 1.1 nisimura #include <sys/sysctl.h> 76 1.1 nisimura 77 1.96 tsutsui #include <machine/bootinfo.h> 78 1.103 tsutsui #include <machine/board.h> 79 1.1 nisimura #include <machine/cpu.h> 80 1.1 nisimura #include <machine/reg.h> 81 1.77 tsutsui #include <machine/pcb.h> 82 1.1 nisimura #include <machine/psl.h> 83 1.1 nisimura #include <machine/pte.h> 84 1.1 nisimura #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 85 1.1 nisimura 86 1.107 tsutsui #include <luna68k/dev/siottyvar.h> 87 1.99 christos 88 1.1 nisimura #include <dev/cons.h> 89 1.80 rmind #include <dev/mm.h> 90 1.1 nisimura 91 1.1 nisimura #if defined(DDB) 92 1.1 nisimura #include <machine/db_machdep.h> 93 1.1 nisimura #include <ddb/db_sym.h> 94 1.1 nisimura #include <ddb/db_extern.h> 95 1.1 nisimura #endif 96 1.1 nisimura 97 1.28 ragge #include "ksyms.h" 98 1.28 ragge 99 1.1 nisimura /* 100 1.1 nisimura * Info for CTL_HW 101 1.1 nisimura */ 102 1.1 nisimura char machine[] = MACHINE; 103 1.7 thorpej 104 1.95 tsutsui /* Our exported CPU info; we can have only one. */ 105 1.7 thorpej struct cpu_info cpu_info_store; 106 1.1 nisimura 107 1.17 chs struct vm_map *phys_map = NULL; 108 1.1 nisimura 109 1.1 nisimura int maxmem; /* max memory per process */ 110 1.1 nisimura 111 1.80 rmind extern u_int lowram; 112 1.80 rmind 113 1.64 dsl void luna68k_init(void); 114 1.64 dsl void identifycpu(void); 115 1.64 dsl void dumpsys(void); 116 1.64 dsl 117 1.64 dsl void straytrap(int, u_short); 118 1.64 dsl void nmihand(struct frame); 119 1.64 dsl 120 1.64 dsl int cpu_dumpsize(void); 121 1.64 dsl int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 122 1.64 dsl void cpu_init_kcore_hdr(void); 123 1.1 nisimura 124 1.94 tsutsui #if NKSYMS || defined(DDB) || defined(MODULAR) 125 1.94 tsutsui vsize_t symtab_size(vaddr_t); 126 1.94 tsutsui #endif 127 1.94 tsutsui extern char end[]; 128 1.94 tsutsui extern void *esym; 129 1.94 tsutsui 130 1.1 nisimura /* 131 1.1 nisimura * Machine-independent crash dump header info. 132 1.1 nisimura */ 133 1.1 nisimura cpu_kcore_hdr_t cpu_kcore_hdr; 134 1.1 nisimura 135 1.1 nisimura int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */ 136 1.1 nisimura int sysconsole; /* console: 0 for ttya, 1 for video */ 137 1.1 nisimura 138 1.64 dsl extern void omfb_cnattach(void); 139 1.64 dsl extern void ws_cnattach(void); 140 1.1 nisimura 141 1.1 nisimura /* 142 1.1 nisimura * On the 68020/68030, the value of delay_divisor is roughly 143 1.1 nisimura * 2048 / cpuspeed (where cpuspeed is in MHz). 144 1.1 nisimura * 145 1.1 nisimura * On the 68040/68060(?), the value of delay_divisor is roughly 146 1.1 nisimura * 759 / cpuspeed (where cpuspeed is in MHz). 147 1.1 nisimura * XXX -- is the above formula correct? 148 1.1 nisimura */ 149 1.1 nisimura int cpuspeed = 25; /* only used for printing later */ 150 1.85 tsutsui int delay_divisor = 30; /* for delay() loop count */ 151 1.1 nisimura 152 1.1 nisimura /* 153 1.1 nisimura * Early initialization, before main() is called. 154 1.1 nisimura */ 155 1.1 nisimura void 156 1.81 tsutsui luna68k_init(void) 157 1.1 nisimura { 158 1.103 tsutsui volatile uint8_t *pio0 = (void *)OBIO_PIO0_BASE; 159 1.13 nisimura int sw1, i; 160 1.13 nisimura char *cp; 161 1.13 nisimura extern char bootarg[64]; 162 1.1 nisimura 163 1.1 nisimura extern paddr_t avail_start, avail_end; 164 1.1 nisimura 165 1.93 tsutsui /* initialize cn_tab for early console */ 166 1.93 tsutsui #if 1 167 1.107 tsutsui cn_tab = &siottycons; 168 1.93 tsutsui #else 169 1.93 tsutsui cn_tab = &romcons; 170 1.93 tsutsui #endif 171 1.93 tsutsui 172 1.1 nisimura /* 173 1.1 nisimura * Tell the VM system about available physical memory. The 174 1.1 nisimura * luna68k only has one segment. 175 1.1 nisimura */ 176 1.1 nisimura uvm_page_physload(atop(avail_start), atop(avail_end), 177 1.1 nisimura atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 178 1.1 nisimura 179 1.1 nisimura /* 180 1.1 nisimura * Initialize error message buffer (at end of core). 181 1.1 nisimura * avail_end was pre-decremented in pmap_bootstrap to compensate. 182 1.1 nisimura */ 183 1.1 nisimura for (i = 0; i < btoc(MSGBUFSIZE); i++) 184 1.88 tsutsui pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 185 1.88 tsutsui avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); 186 1.19 chris pmap_update(pmap_kernel()); 187 1.1 nisimura initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 188 1.1 nisimura 189 1.1 nisimura 190 1.1 nisimura pio0[3] = 0xb6; 191 1.1 nisimura pio0[2] = 1 << 6; /* enable parity check */ 192 1.1 nisimura pio0[3] = 0xb6; 193 1.81 tsutsui sw1 = pio0[0]; /* dip sw1 value */ 194 1.1 nisimura sw1 ^= 0xff; 195 1.1 nisimura sysconsole = !(sw1 & 0x2); /* console selection */ 196 1.1 nisimura 197 1.96 tsutsui /* 198 1.96 tsutsui * Check if boothowto and bootdev values are passed by our bootloader. 199 1.96 tsutsui */ 200 1.96 tsutsui if ((bootdev & B_MAGICMASK) == B_DEVMAGIC) { 201 1.96 tsutsui /* Valid value is set; no need to parse bootarg. */ 202 1.96 tsutsui return; 203 1.96 tsutsui } 204 1.97 tsutsui 205 1.96 tsutsui /* 206 1.96 tsutsui * No valid bootdev value is set. 207 1.96 tsutsui * Assume we are booted by ROM monitor directly using a.out kernel 208 1.96 tsutsui * and we have to parse bootarg passed from the monitor to set 209 1.96 tsutsui * proper boothowto and check netboot. 210 1.96 tsutsui */ 211 1.96 tsutsui 212 1.96 tsutsui /* set default to "sd0a" with no howto flags */ 213 1.96 tsutsui bootdev = MAKEBOOTDEV(0, LUNA68K_BOOTADPT_SPC, 0, 0, 0); 214 1.1 nisimura boothowto = 0; 215 1.96 tsutsui 216 1.1 nisimura /* 217 1.91 tsutsui * 'bootarg' on LUNA has: 218 1.1 nisimura * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>" 219 1.1 nisimura * where <addr> is MAC address of which network loader used (not 220 1.1 nisimura * necessarily same as one at 0x4101.FFE0), <host> and <name> 221 1.91 tsutsui * are the values of HOST and SERVER environment variables. 222 1.91 tsutsui * 223 1.91 tsutsui * 'bootarg' on LUNA-II has "<args of x command>" only. 224 1.1 nisimura * 225 1.111 andvar * NetBSD/luna68k cares only the first argument; any of "sda". 226 1.1 nisimura */ 227 1.96 tsutsui bootarg[63] = '\0'; 228 1.96 tsutsui for (cp = bootarg; *cp != '\0'; cp++) { 229 1.96 tsutsui if (*cp == '-') { 230 1.96 tsutsui char c; 231 1.96 tsutsui while ((c = *cp) != '\0' && c != ' ') { 232 1.96 tsutsui BOOT_FLAG(c, boothowto); 233 1.96 tsutsui cp++; 234 1.96 tsutsui } 235 1.96 tsutsui } else if (*cp == 'E' && memcmp("ENADDR=", cp, 7) == 0) { 236 1.96 tsutsui bootdev = 237 1.96 tsutsui MAKEBOOTDEV(0, LUNA68K_BOOTADPT_LANCE, 0, 0, 0); 238 1.96 tsutsui } 239 1.1 nisimura } 240 1.13 nisimura } 241 1.1 nisimura 242 1.13 nisimura /* 243 1.13 nisimura * Console initialization: called early on from main, 244 1.13 nisimura */ 245 1.13 nisimura void 246 1.67 cegger consinit(void) 247 1.13 nisimura { 248 1.81 tsutsui 249 1.107 tsutsui if (sysconsole == 0) { 250 1.107 tsutsui cn_tab = &siottycons; 251 1.107 tsutsui (*cn_tab->cn_init)(cn_tab); 252 1.107 tsutsui } else { 253 1.1 nisimura omfb_cnattach(); 254 1.1 nisimura ws_cnattach(); 255 1.1 nisimura } 256 1.1 nisimura 257 1.57 ad #if NKSYMS || defined(DDB) || defined(MODULAR) 258 1.94 tsutsui ksyms_addsyms_elf((esym != NULL) ? 1 : 0, (void *)&end, esym); 259 1.28 ragge #endif 260 1.28 ragge #ifdef DDB 261 1.1 nisimura if (boothowto & RB_KDB) 262 1.1 nisimura cpu_Debugger(); 263 1.1 nisimura #endif 264 1.1 nisimura } 265 1.1 nisimura 266 1.94 tsutsui #if NKSYMS || defined(DDB) || defined(MODULAR) 267 1.94 tsutsui 268 1.94 tsutsui /* 269 1.94 tsutsui * Check and compute size of DDB symbols and strings. 270 1.94 tsutsui * 271 1.94 tsutsui * Note this function could be called from locore.s before MMU is turned on 272 1.94 tsutsui * so we should avoid global variables and function calls. 273 1.94 tsutsui */ 274 1.94 tsutsui vsize_t 275 1.94 tsutsui symtab_size(vaddr_t hdr) 276 1.94 tsutsui { 277 1.94 tsutsui int i; 278 1.94 tsutsui Elf_Ehdr *ehdr; 279 1.94 tsutsui Elf_Shdr *shp; 280 1.94 tsutsui vaddr_t maxsym; 281 1.94 tsutsui 282 1.94 tsutsui /* 283 1.94 tsutsui * Check the ELF headers. 284 1.94 tsutsui */ 285 1.94 tsutsui 286 1.94 tsutsui ehdr = (void *)hdr; 287 1.94 tsutsui if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || 288 1.94 tsutsui ehdr->e_ident[EI_MAG1] != ELFMAG1 || 289 1.94 tsutsui ehdr->e_ident[EI_MAG2] != ELFMAG2 || 290 1.94 tsutsui ehdr->e_ident[EI_MAG3] != ELFMAG3 || 291 1.94 tsutsui ehdr->e_ident[EI_CLASS] != ELFCLASS32) { 292 1.94 tsutsui return 0; 293 1.94 tsutsui } 294 1.94 tsutsui 295 1.94 tsutsui /* 296 1.94 tsutsui * Find the end of the symbols and strings. 297 1.94 tsutsui */ 298 1.94 tsutsui 299 1.94 tsutsui maxsym = 0; 300 1.94 tsutsui shp = (Elf_Shdr *)(hdr + ehdr->e_shoff); 301 1.94 tsutsui for (i = 0; i < ehdr->e_shnum; i++) { 302 1.94 tsutsui if (shp[i].sh_type != SHT_SYMTAB && 303 1.94 tsutsui shp[i].sh_type != SHT_STRTAB) { 304 1.94 tsutsui continue; 305 1.94 tsutsui } 306 1.102 riastrad maxsym = uimax(maxsym, shp[i].sh_offset + shp[i].sh_size); 307 1.94 tsutsui } 308 1.94 tsutsui 309 1.94 tsutsui return maxsym; 310 1.94 tsutsui } 311 1.94 tsutsui #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */ 312 1.94 tsutsui 313 1.1 nisimura /* 314 1.1 nisimura * cpu_startup: allocate memory for variable-sized tables. 315 1.1 nisimura */ 316 1.1 nisimura void 317 1.67 cegger cpu_startup(void) 318 1.1 nisimura { 319 1.1 nisimura vaddr_t minaddr, maxaddr; 320 1.1 nisimura char pbuf[9]; 321 1.1 nisimura 322 1.26 thorpej if (fputype != FPU_NONE) 323 1.26 thorpej m68k_make_fpu_idle_frame(); 324 1.26 thorpej 325 1.1 nisimura /* 326 1.1 nisimura * Initialize the kernel crash dump header. 327 1.1 nisimura */ 328 1.1 nisimura cpu_init_kcore_hdr(); 329 1.1 nisimura 330 1.1 nisimura /* 331 1.1 nisimura * Good {morning,afternoon,evening,night}. 332 1.1 nisimura */ 333 1.40 lukem printf("%s%s", copyright, version); 334 1.1 nisimura identifycpu(); 335 1.1 nisimura 336 1.1 nisimura format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 337 1.1 nisimura printf("total memory = %s\n", pbuf); 338 1.1 nisimura 339 1.36 pk minaddr = 0; 340 1.1 nisimura 341 1.1 nisimura /* 342 1.1 nisimura * Allocate a submap for physio 343 1.1 nisimura */ 344 1.1 nisimura phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 345 1.81 tsutsui VM_PHYS_SIZE, 0, false, NULL); 346 1.1 nisimura 347 1.106 ad format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 348 1.1 nisimura printf("avail memory = %s\n", pbuf); 349 1.1 nisimura } 350 1.1 nisimura 351 1.1 nisimura void 352 1.67 cegger identifycpu(void) 353 1.1 nisimura { 354 1.1 nisimura extern int cputype; 355 1.86 tsutsui const char *model, *fpu; 356 1.1 nisimura 357 1.1 nisimura switch (cputype) { 358 1.1 nisimura case CPU_68030: 359 1.84 tsutsui model ="LUNA-I"; 360 1.86 tsutsui switch (fputype) { 361 1.86 tsutsui case FPU_68881: 362 1.86 tsutsui fpu = "MC68881"; 363 1.86 tsutsui break; 364 1.86 tsutsui case FPU_68882: 365 1.86 tsutsui fpu = "MC68882"; 366 1.86 tsutsui break; 367 1.86 tsutsui case FPU_NONE: 368 1.86 tsutsui fpu = "no"; 369 1.86 tsutsui break; 370 1.86 tsutsui default: 371 1.86 tsutsui fpu = "unknown"; 372 1.86 tsutsui break; 373 1.86 tsutsui } 374 1.98 christos cpu_setmodel("%s (MC68030 CPU+MMU, %s FPU)", model, fpu); 375 1.1 nisimura machtype = LUNA_I; 376 1.81 tsutsui /* 20MHz 68030 */ 377 1.81 tsutsui cpuspeed = 20; 378 1.81 tsutsui delay_divisor = 102; 379 1.1 nisimura hz = 60; 380 1.1 nisimura break; 381 1.13 nisimura #if defined(M68040) 382 1.1 nisimura case CPU_68040: 383 1.84 tsutsui model ="LUNA-II"; 384 1.98 christos cpu_setmodel( 385 1.86 tsutsui "%s (MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches)", 386 1.86 tsutsui model); 387 1.1 nisimura machtype = LUNA_II; 388 1.81 tsutsui /* 25MHz 68040 */ 389 1.81 tsutsui cpuspeed = 25; 390 1.85 tsutsui delay_divisor = 30; 391 1.85 tsutsui /* hz = 100 on LUNA-II */ 392 1.1 nisimura break; 393 1.1 nisimura #endif 394 1.1 nisimura default: 395 1.1 nisimura panic("unknown CPU type"); 396 1.1 nisimura } 397 1.98 christos printf("%s\n", cpu_getmodel()); 398 1.1 nisimura } 399 1.1 nisimura 400 1.1 nisimura /* 401 1.1 nisimura * machine dependent system variables. 402 1.1 nisimura */ 403 1.35 atatat SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 404 1.1 nisimura { 405 1.1 nisimura 406 1.38 atatat sysctl_createv(clog, 0, NULL, NULL, 407 1.38 atatat CTLFLAG_PERMANENT, 408 1.35 atatat CTLTYPE_NODE, "machdep", NULL, 409 1.35 atatat NULL, 0, NULL, 0, 410 1.35 atatat CTL_MACHDEP, CTL_EOL); 411 1.35 atatat 412 1.38 atatat sysctl_createv(clog, 0, NULL, NULL, 413 1.38 atatat CTLFLAG_PERMANENT, 414 1.35 atatat CTLTYPE_STRUCT, "console_device", NULL, 415 1.35 atatat sysctl_consdev, 0, NULL, sizeof(dev_t), 416 1.35 atatat CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 417 1.1 nisimura } 418 1.1 nisimura 419 1.1 nisimura int waittime = -1; 420 1.1 nisimura 421 1.1 nisimura void 422 1.81 tsutsui cpu_reboot(int howto, char *bootstr) 423 1.1 nisimura { 424 1.72 rmind struct pcb *pcb = lwp_getpcb(curlwp); 425 1.64 dsl extern void doboot(void); 426 1.1 nisimura 427 1.1 nisimura /* take a snap shot before clobbering any registers */ 428 1.72 rmind if (pcb != NULL) 429 1.72 rmind savectx(pcb); 430 1.1 nisimura 431 1.1 nisimura /* If system is hold, just halt. */ 432 1.1 nisimura if (cold) { 433 1.1 nisimura howto |= RB_HALT; 434 1.1 nisimura goto haltsys; 435 1.1 nisimura } 436 1.1 nisimura 437 1.1 nisimura boothowto = howto; 438 1.1 nisimura if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 439 1.1 nisimura waittime = 0; 440 1.1 nisimura vfs_shutdown(); 441 1.1 nisimura } 442 1.1 nisimura 443 1.1 nisimura /* Disable interrupts. */ 444 1.1 nisimura splhigh(); 445 1.1 nisimura 446 1.1 nisimura /* If rebooting and a dump is requested, do it. */ 447 1.1 nisimura if (howto & RB_DUMP) 448 1.1 nisimura dumpsys(); 449 1.1 nisimura 450 1.1 nisimura haltsys: 451 1.1 nisimura /* Run any shutdown hooks. */ 452 1.1 nisimura doshutdownhooks(); 453 1.1 nisimura 454 1.56 dyoung pmf_system_shutdown(boothowto); 455 1.56 dyoung 456 1.1 nisimura /* Finally, halt/reboot the system. */ 457 1.1 nisimura if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 458 1.103 tsutsui volatile uint8_t *pio = (void *)OBIO_PIO1_BASE; 459 1.1 nisimura 460 1.1 nisimura printf("power is going down.\n"); 461 1.1 nisimura DELAY(100000); 462 1.1 nisimura pio[3] = 0x94; 463 1.1 nisimura pio[2] = 0 << 4; 464 1.81 tsutsui for (;;) 465 1.81 tsutsui /* NOP */; 466 1.1 nisimura } 467 1.1 nisimura if (howto & RB_HALT) { 468 1.1 nisimura printf("System halted. Hit any key to reboot.\n\n"); 469 1.108 tsutsui cnpollc(1); 470 1.1 nisimura (void)cngetc(); 471 1.108 tsutsui cnpollc(0); 472 1.1 nisimura } 473 1.1 nisimura 474 1.1 nisimura printf("rebooting...\n"); 475 1.1 nisimura DELAY(100000); 476 1.1 nisimura doboot(); 477 1.1 nisimura /*NOTREACHED*/ 478 1.81 tsutsui for (;;) 479 1.81 tsutsui ; 480 1.1 nisimura } 481 1.1 nisimura 482 1.1 nisimura /* 483 1.1 nisimura * Initialize the kernel crash dump header. 484 1.1 nisimura */ 485 1.1 nisimura void 486 1.67 cegger cpu_init_kcore_hdr(void) 487 1.1 nisimura { 488 1.1 nisimura cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 489 1.1 nisimura struct m68k_kcore_hdr *m = &h->un._m68k; 490 1.1 nisimura 491 1.95 tsutsui memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 492 1.1 nisimura 493 1.1 nisimura /* 494 1.1 nisimura * Initialize the `dispatcher' portion of the header. 495 1.1 nisimura */ 496 1.1 nisimura strcpy(h->name, machine); 497 1.27 thorpej h->page_size = PAGE_SIZE; 498 1.1 nisimura h->kernbase = KERNBASE; 499 1.1 nisimura 500 1.1 nisimura /* 501 1.1 nisimura * Fill in information about our MMU configuration. 502 1.1 nisimura */ 503 1.1 nisimura m->mmutype = mmutype; 504 1.1 nisimura m->sg_v = SG_V; 505 1.1 nisimura m->sg_frame = SG_FRAME; 506 1.1 nisimura m->sg_ishift = SG_ISHIFT; 507 1.1 nisimura m->sg_pmask = SG_PMASK; 508 1.1 nisimura m->sg40_shift1 = SG4_SHIFT1; 509 1.1 nisimura m->sg40_mask2 = SG4_MASK2; 510 1.1 nisimura m->sg40_shift2 = SG4_SHIFT2; 511 1.1 nisimura m->sg40_mask3 = SG4_MASK3; 512 1.1 nisimura m->sg40_shift3 = SG4_SHIFT3; 513 1.1 nisimura m->sg40_addr1 = SG4_ADDR1; 514 1.1 nisimura m->sg40_addr2 = SG4_ADDR2; 515 1.1 nisimura m->pg_v = PG_V; 516 1.1 nisimura m->pg_frame = PG_FRAME; 517 1.1 nisimura 518 1.1 nisimura /* 519 1.1 nisimura * Initialize pointer to kernel segment table. 520 1.1 nisimura */ 521 1.81 tsutsui m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); 522 1.1 nisimura 523 1.1 nisimura /* 524 1.1 nisimura * Initialize relocation value such that: 525 1.1 nisimura * 526 1.1 nisimura * pa = (va - KERNBASE) + reloc 527 1.1 nisimura * 528 1.1 nisimura * Since we're linked and loaded at the same place, 529 1.1 nisimura * and the kernel is mapped va == pa, this is 0. 530 1.1 nisimura */ 531 1.1 nisimura m->reloc = 0; 532 1.1 nisimura 533 1.1 nisimura /* 534 1.1 nisimura * Define the end of the relocatable range. 535 1.1 nisimura */ 536 1.81 tsutsui m->relocend = (uint32_t)end; 537 1.1 nisimura 538 1.1 nisimura /* 539 1.1 nisimura * The luna68k has one contiguous memory segment. 540 1.1 nisimura */ 541 1.1 nisimura m->ram_segs[0].start = 0 /* lowram */; 542 1.1 nisimura m->ram_segs[0].size = ctob(physmem); 543 1.1 nisimura } 544 1.1 nisimura 545 1.1 nisimura /* 546 1.1 nisimura * Compute the size of the machine-dependent crash dump header. 547 1.1 nisimura * Returns size in disk blocks. 548 1.1 nisimura */ 549 1.42 chs 550 1.42 chs #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 551 1.42 chs #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 552 1.42 chs 553 1.1 nisimura int 554 1.67 cegger cpu_dumpsize(void) 555 1.1 nisimura { 556 1.1 nisimura 557 1.42 chs return btodb(MDHDRSIZE); 558 1.1 nisimura } 559 1.1 nisimura 560 1.1 nisimura /* 561 1.1 nisimura * Called by dumpsys() to dump the machine-dependent header. 562 1.1 nisimura */ 563 1.1 nisimura int 564 1.81 tsutsui cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 565 1.1 nisimura { 566 1.95 tsutsui int buf[MDHDRSIZE / sizeof(int)]; 567 1.1 nisimura cpu_kcore_hdr_t *chdr; 568 1.1 nisimura kcore_seg_t *kseg; 569 1.1 nisimura int error; 570 1.1 nisimura 571 1.1 nisimura kseg = (kcore_seg_t *)buf; 572 1.1 nisimura chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 573 1.1 nisimura sizeof(int)]; 574 1.1 nisimura 575 1.1 nisimura /* Create the segment header. */ 576 1.1 nisimura CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 577 1.42 chs kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 578 1.1 nisimura 579 1.71 cegger memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 580 1.50 christos error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 581 1.1 nisimura *blknop += btodb(sizeof(buf)); 582 1.81 tsutsui return error; 583 1.1 nisimura } 584 1.1 nisimura 585 1.1 nisimura /* 586 1.1 nisimura * These variables are needed by /sbin/savecore 587 1.1 nisimura */ 588 1.81 tsutsui uint32_t dumpmag = 0x8fca0101; /* magic number */ 589 1.1 nisimura int dumpsize = 0; /* pages */ 590 1.1 nisimura long dumplo = 0; /* blocks */ 591 1.1 nisimura 592 1.1 nisimura /* 593 1.1 nisimura * This is called by main to set dumplo and dumpsize. 594 1.27 thorpej * Dumps always skip the first PAGE_SIZE of disk space 595 1.1 nisimura * in case there might be a disk label stored there. 596 1.1 nisimura * If there is extra space, put dump at the end to 597 1.1 nisimura * reduce the chance that swapping trashes it. 598 1.1 nisimura */ 599 1.1 nisimura void 600 1.67 cegger cpu_dumpconf(void) 601 1.1 nisimura { 602 1.1 nisimura int chdrsize; /* size of dump header */ 603 1.1 nisimura int nblks; /* size of dump area */ 604 1.1 nisimura 605 1.1 nisimura if (dumpdev == NODEV) 606 1.1 nisimura return; 607 1.89 mrg nblks = bdev_size(dumpdev); 608 1.1 nisimura chdrsize = cpu_dumpsize(); 609 1.1 nisimura 610 1.1 nisimura dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); 611 1.1 nisimura 612 1.1 nisimura /* 613 1.1 nisimura * Check do see if we will fit. Note we always skip the 614 1.27 thorpej * first PAGE_SIZE in case there is a disk label there. 615 1.1 nisimura */ 616 1.1 nisimura if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 617 1.1 nisimura dumpsize = 0; 618 1.1 nisimura dumplo = -1; 619 1.1 nisimura return; 620 1.1 nisimura } 621 1.1 nisimura 622 1.1 nisimura /* 623 1.1 nisimura * Put dump at the end of the partition. 624 1.1 nisimura */ 625 1.1 nisimura dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 626 1.1 nisimura } 627 1.1 nisimura 628 1.1 nisimura /* 629 1.1 nisimura * Dump physical memory onto the dump device. Called by cpu_reboot(). 630 1.1 nisimura */ 631 1.1 nisimura void 632 1.67 cegger dumpsys(void) 633 1.1 nisimura { 634 1.23 gehenna const struct bdevsw *bdev; 635 1.1 nisimura daddr_t blkno; /* current block to write */ 636 1.1 nisimura /* dump routine */ 637 1.64 dsl int (*dump)(dev_t, daddr_t, void *, size_t); 638 1.1 nisimura int pg; /* page being dumped */ 639 1.1 nisimura paddr_t maddr; /* PA being dumped */ 640 1.1 nisimura int error; /* error code from (*dump)() */ 641 1.1 nisimura 642 1.1 nisimura /* XXX initialized here because of gcc lossage */ 643 1.1 nisimura maddr = 0 /* lowram */; 644 1.1 nisimura pg = 0; 645 1.1 nisimura 646 1.1 nisimura /* Make sure dump device is valid. */ 647 1.1 nisimura if (dumpdev == NODEV) 648 1.1 nisimura return; 649 1.23 gehenna bdev = bdevsw_lookup(dumpdev); 650 1.23 gehenna if (bdev == NULL) 651 1.23 gehenna return; 652 1.1 nisimura if (dumpsize == 0) { 653 1.1 nisimura cpu_dumpconf(); 654 1.1 nisimura if (dumpsize == 0) 655 1.1 nisimura return; 656 1.1 nisimura } 657 1.1 nisimura if (dumplo <= 0) { 658 1.62 he printf("\ndump to dev %u,%u not possible\n", 659 1.60 he major(dumpdev), minor(dumpdev)); 660 1.1 nisimura return; 661 1.1 nisimura } 662 1.23 gehenna dump = bdev->d_dump; 663 1.1 nisimura blkno = dumplo; 664 1.1 nisimura 665 1.62 he printf("\ndumping to dev %u,%u offset %ld\n", 666 1.60 he major(dumpdev), minor(dumpdev), dumplo); 667 1.1 nisimura 668 1.1 nisimura printf("dump "); 669 1.1 nisimura 670 1.1 nisimura /* Write the dump header. */ 671 1.1 nisimura error = cpu_dump(dump, &blkno); 672 1.1 nisimura if (error) 673 1.1 nisimura goto bad; 674 1.1 nisimura 675 1.1 nisimura for (pg = 0; pg < dumpsize; pg++) { 676 1.27 thorpej #define NPGMB (1024*1024/PAGE_SIZE) 677 1.1 nisimura /* print out how many MBs we have dumped */ 678 1.1 nisimura if (pg && (pg % NPGMB) == 0) 679 1.1 nisimura printf("%d ", pg / NPGMB); 680 1.1 nisimura #undef NPGMB 681 1.1 nisimura pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 682 1.1 nisimura VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 683 1.1 nisimura 684 1.19 chris pmap_update(pmap_kernel()); 685 1.27 thorpej error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 686 1.1 nisimura bad: 687 1.1 nisimura switch (error) { 688 1.1 nisimura case 0: 689 1.27 thorpej maddr += PAGE_SIZE; 690 1.27 thorpej blkno += btodb(PAGE_SIZE); 691 1.1 nisimura break; 692 1.1 nisimura 693 1.1 nisimura case ENXIO: 694 1.1 nisimura printf("device bad\n"); 695 1.1 nisimura return; 696 1.1 nisimura 697 1.1 nisimura case EFAULT: 698 1.1 nisimura printf("device not ready\n"); 699 1.1 nisimura return; 700 1.1 nisimura 701 1.1 nisimura case EINVAL: 702 1.1 nisimura printf("area improper\n"); 703 1.1 nisimura return; 704 1.1 nisimura 705 1.1 nisimura case EIO: 706 1.1 nisimura printf("i/o error\n"); 707 1.1 nisimura return; 708 1.1 nisimura 709 1.1 nisimura case EINTR: 710 1.1 nisimura printf("aborted from console\n"); 711 1.1 nisimura return; 712 1.1 nisimura 713 1.1 nisimura default: 714 1.1 nisimura printf("error %d\n", error); 715 1.1 nisimura return; 716 1.1 nisimura } 717 1.1 nisimura } 718 1.1 nisimura printf("succeeded\n"); 719 1.1 nisimura } 720 1.1 nisimura 721 1.1 nisimura void 722 1.65 dsl straytrap(int pc, u_short evec) 723 1.1 nisimura { 724 1.81 tsutsui 725 1.1 nisimura printf("unexpected trap (vector offset %x) from %x\n", 726 1.81 tsutsui evec & 0xFFF, pc); 727 1.1 nisimura } 728 1.1 nisimura 729 1.1 nisimura int *nofault; 730 1.1 nisimura 731 1.1 nisimura int 732 1.65 dsl badaddr(register void *addr, int nbytes) 733 1.1 nisimura { 734 1.98 christos int i; 735 1.1 nisimura label_t faultbuf; 736 1.1 nisimura 737 1.81 tsutsui nofault = (int *)&faultbuf; 738 1.1 nisimura if (setjmp((label_t *)nofault)) { 739 1.81 tsutsui nofault = (int *)0; 740 1.81 tsutsui return 1; 741 1.1 nisimura } 742 1.1 nisimura 743 1.1 nisimura switch (nbytes) { 744 1.1 nisimura case 1: 745 1.81 tsutsui i = *(volatile int8_t *)addr; 746 1.1 nisimura break; 747 1.1 nisimura 748 1.1 nisimura case 2: 749 1.81 tsutsui i = *(volatile int16_t *)addr; 750 1.1 nisimura break; 751 1.1 nisimura 752 1.1 nisimura case 4: 753 1.81 tsutsui i = *(volatile int32_t *)addr; 754 1.1 nisimura break; 755 1.1 nisimura 756 1.1 nisimura default: 757 1.1 nisimura panic("badaddr: bad request"); 758 1.1 nisimura } 759 1.98 christos __USE(i); 760 1.81 tsutsui nofault = (int *)0; 761 1.81 tsutsui return 0; 762 1.1 nisimura } 763 1.1 nisimura 764 1.64 dsl void luna68k_abort(const char *); 765 1.1 nisimura 766 1.1 nisimura static int innmihand; /* simple mutex */ 767 1.1 nisimura 768 1.1 nisimura /* 769 1.1 nisimura * Level 7 interrupts are caused by e.g. the ABORT switch. 770 1.1 nisimura * 771 1.1 nisimura * If we have DDB, then break into DDB on ABORT. In a production 772 1.1 nisimura * environment, bumping the ABORT switch would be bad, so we enable 773 1.1 nisimura * panic'ing on ABORT with the kernel option "PANICBUTTON". 774 1.1 nisimura */ 775 1.1 nisimura void 776 1.65 dsl nmihand(struct frame frame) 777 1.1 nisimura { 778 1.81 tsutsui 779 1.1 nisimura /* Prevent unwanted recursion */ 780 1.1 nisimura if (innmihand) 781 1.1 nisimura return; 782 1.1 nisimura innmihand = 1; 783 1.1 nisimura 784 1.1 nisimura luna68k_abort("ABORT SWITCH"); 785 1.87 tsutsui 786 1.87 tsutsui innmihand = 0; 787 1.1 nisimura } 788 1.1 nisimura 789 1.1 nisimura /* 790 1.1 nisimura * Common code for handling ABORT signals from buttons, switches, 791 1.1 nisimura * serial lines, etc. 792 1.1 nisimura */ 793 1.1 nisimura void 794 1.65 dsl luna68k_abort(const char *cp) 795 1.1 nisimura { 796 1.81 tsutsui 797 1.1 nisimura #ifdef DDB 798 1.1 nisimura printf("%s\n", cp); 799 1.1 nisimura cpu_Debugger(); 800 1.1 nisimura #else 801 1.1 nisimura #ifdef PANICBUTTON 802 1.1 nisimura panic(cp); 803 1.1 nisimura #else 804 1.1 nisimura printf("%s ignored\n", cp); 805 1.1 nisimura #endif /* PANICBUTTON */ 806 1.1 nisimura #endif /* DDB */ 807 1.1 nisimura } 808 1.1 nisimura 809 1.1 nisimura /* 810 1.1 nisimura * cpu_exec_aout_makecmds(): 811 1.37 wiz * CPU-dependent a.out format hook for execve(). 812 1.95 tsutsui * 813 1.1 nisimura * Determine of the given exec package refers to something which we 814 1.1 nisimura * understand and, if so, set up the vmcmds for it. 815 1.1 nisimura */ 816 1.1 nisimura int 817 1.65 dsl cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 818 1.1 nisimura { 819 1.109 andvar return ENOEXEC; 820 1.1 nisimura } 821 1.1 nisimura 822 1.76 tsutsui #ifdef MODULAR 823 1.76 tsutsui /* 824 1.76 tsutsui * Push any modules loaded by the bootloader etc. 825 1.76 tsutsui */ 826 1.76 tsutsui void 827 1.76 tsutsui module_init_md(void) 828 1.76 tsutsui { 829 1.76 tsutsui } 830 1.76 tsutsui #endif 831 1.76 tsutsui 832 1.93 tsutsui #ifdef notyet 833 1.1 nisimura /* 834 1.1 nisimura * romcons is useful until m68k TC register is initialized. 835 1.1 nisimura */ 836 1.64 dsl int romcngetc(dev_t); 837 1.64 dsl void romcnputc(dev_t, int); 838 1.1 nisimura 839 1.1 nisimura struct consdev romcons = { 840 1.1 nisimura NULL, 841 1.1 nisimura NULL, 842 1.1 nisimura romcngetc, 843 1.1 nisimura romcnputc, 844 1.1 nisimura nullcnpollc, 845 1.1 nisimura makedev(7, 0), /* XXX */ 846 1.1 nisimura CN_DEAD, 847 1.1 nisimura }; 848 1.1 nisimura 849 1.103 tsutsui #define __ ((int **)PROM_ADDR) 850 1.2 nisimura #define GETC() (*(int (*)())__[6])() 851 1.2 nisimura #define PUTC(x) (*(void (*)())__[7])(x) 852 1.2 nisimura 853 1.2 nisimura #define ROMPUTC(x) \ 854 1.2 nisimura ({ \ 855 1.2 nisimura register _r; \ 856 1.44 perry __asm volatile (" \ 857 1.18 chs movc %%vbr,%0 ; \ 858 1.18 chs movel %0,%%sp@- ; \ 859 1.2 nisimura clrl %0 ; \ 860 1.18 chs movc %0,%%vbr" \ 861 1.2 nisimura : "=r" (_r)); \ 862 1.2 nisimura PUTC(x); \ 863 1.44 perry __asm volatile (" \ 864 1.18 chs movel %%sp@+,%0 ; \ 865 1.18 chs movc %0,%%vbr" \ 866 1.2 nisimura : "=r" (_r)); \ 867 1.2 nisimura }) 868 1.2 nisimura 869 1.2 nisimura #define ROMGETC() \ 870 1.2 nisimura ({ \ 871 1.2 nisimura register _r, _c; \ 872 1.44 perry __asm volatile (" \ 873 1.18 chs movc %%vbr,%0 ; \ 874 1.18 chs movel %0,%%sp@- ; \ 875 1.2 nisimura clrl %0 ; \ 876 1.18 chs movc %0,%%vbr" \ 877 1.2 nisimura : "=r" (_r)); \ 878 1.2 nisimura _c = GETC(); \ 879 1.44 perry __asm volatile (" \ 880 1.18 chs movel %%sp@+,%0 ; \ 881 1.18 chs movc %0,%%vbr" \ 882 1.2 nisimura : "=r" (_r)); \ 883 1.2 nisimura _c; \ 884 1.2 nisimura }) 885 1.1 nisimura 886 1.1 nisimura void 887 1.65 dsl romcnputc(dev_t dev, int c) 888 1.1 nisimura { 889 1.2 nisimura int s; 890 1.2 nisimura 891 1.2 nisimura s = splhigh(); 892 1.1 nisimura ROMPUTC(c); 893 1.2 nisimura splx(s); 894 1.1 nisimura } 895 1.1 nisimura 896 1.1 nisimura int 897 1.65 dsl romcngetc(dev_t dev) 898 1.1 nisimura { 899 1.2 nisimura int s, c; 900 1.1 nisimura 901 1.1 nisimura do { 902 1.2 nisimura s = splhigh(); 903 1.1 nisimura c = ROMGETC(); 904 1.2 nisimura splx(s); 905 1.1 nisimura } while (c == -1); 906 1.1 nisimura return c; 907 1.1 nisimura } 908 1.1 nisimura #endif 909 1.80 rmind 910 1.80 rmind int 911 1.80 rmind mm_md_physacc(paddr_t pa, vm_prot_t prot) 912 1.80 rmind { 913 1.80 rmind 914 1.80 rmind return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0; 915 1.80 rmind } 916