1 1.141 andvar /* $NetBSD: machdep.c,v 1.141 2025/06/11 21:20:37 andvar Exp $ */ 2 1.1 gwr 3 1.1 gwr /* 4 1.126 rmind * Copyright (c) 1988 University of Utah. 5 1.1 gwr * Copyright (c) 1982, 1986, 1990, 1993 6 1.1 gwr * The Regents of the University of California. All rights reserved. 7 1.1 gwr * 8 1.1 gwr * This code is derived from software contributed to Berkeley by 9 1.1 gwr * the Systems Programming Group of the University of Utah Computer 10 1.1 gwr * Science Department. 11 1.1 gwr * 12 1.1 gwr * Redistribution and use in source and binary forms, with or without 13 1.1 gwr * modification, are permitted provided that the following conditions 14 1.1 gwr * are met: 15 1.1 gwr * 1. Redistributions of source code must retain the above copyright 16 1.1 gwr * notice, this list of conditions and the following disclaimer. 17 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 gwr * notice, this list of conditions and the following disclaimer in the 19 1.1 gwr * documentation and/or other materials provided with the distribution. 20 1.91 agc * 3. Neither the name of the University nor the names of its contributors 21 1.91 agc * may be used to endorse or promote products derived from this software 22 1.91 agc * without specific prior written permission. 23 1.91 agc * 24 1.91 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.91 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.91 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.91 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.91 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.91 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.91 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.91 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.91 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.91 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.91 agc * SUCH DAMAGE. 35 1.91 agc * 36 1.91 agc * from: Utah Hdr: machdep.c 1.74 92/12/20 37 1.91 agc * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 38 1.91 agc */ 39 1.90 lukem 40 1.90 lukem #include <sys/cdefs.h> 41 1.141 andvar __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.141 2025/06/11 21:20:37 andvar Exp $"); 42 1.1 gwr 43 1.35 jonathan #include "opt_ddb.h" 44 1.69 lukem #include "opt_kgdb.h" 45 1.118 apb #include "opt_modular.h" 46 1.34 gwr 47 1.1 gwr #include <sys/param.h> 48 1.1 gwr #include <sys/systm.h> 49 1.1 gwr #include <sys/kernel.h> 50 1.1 gwr #include <sys/proc.h> 51 1.1 gwr #include <sys/buf.h> 52 1.1 gwr #include <sys/reboot.h> 53 1.1 gwr #include <sys/conf.h> 54 1.1 gwr #include <sys/file.h> 55 1.37 kleink #include <sys/device.h> 56 1.1 gwr #include <sys/mbuf.h> 57 1.1 gwr #include <sys/msgbuf.h> 58 1.1 gwr #include <sys/ioctl.h> 59 1.1 gwr #include <sys/tty.h> 60 1.1 gwr #include <sys/mount.h> 61 1.1 gwr #include <sys/exec.h> 62 1.119 matt #include <sys/exec_aout.h> /* for MID_* */ 63 1.1 gwr #include <sys/core.h> 64 1.1 gwr #include <sys/kcore.h> 65 1.1 gwr #include <sys/vnode.h> 66 1.1 gwr #include <sys/syscallargs.h> 67 1.87 ragge #include <sys/ksyms.h> 68 1.124 tsutsui #include <sys/module.h> 69 1.135 christos #include <sys/cpu.h> 70 1.8 gwr #ifdef KGDB 71 1.8 gwr #include <sys/kgdb.h> 72 1.8 gwr #endif 73 1.26 hannken 74 1.42 mrg #include <uvm/uvm_extern.h> 75 1.34 gwr 76 1.26 hannken #include <sys/sysctl.h> 77 1.1 gwr 78 1.1 gwr #include <dev/cons.h> 79 1.129 rmind #include <dev/mm.h> 80 1.1 gwr 81 1.1 gwr #include <machine/cpu.h> 82 1.29 gwr #include <machine/dvma.h> 83 1.29 gwr #include <machine/idprom.h> 84 1.29 gwr #include <machine/kcore.h> 85 1.1 gwr #include <machine/reg.h> 86 1.125 tsutsui #include <machine/pcb.h> 87 1.1 gwr #include <machine/psl.h> 88 1.1 gwr #include <machine/pte.h> 89 1.129 rmind #include <machine/mon.h> 90 1.29 gwr 91 1.41 kleink #if defined(DDB) 92 1.1 gwr #include <machine/db_machdep.h> 93 1.33 gwr #include <ddb/db_sym.h> 94 1.32 tv #include <ddb/db_extern.h> 95 1.41 kleink #endif 96 1.1 gwr 97 1.29 gwr #include <sun3/sun3/machdep.h> 98 1.1 gwr 99 1.87 ragge #include "ksyms.h" 100 1.87 ragge 101 1.1 gwr /* Defined in locore.s */ 102 1.1 gwr extern char kernel_text[]; 103 1.1 gwr /* Defined by the linker */ 104 1.1 gwr extern char etext[]; 105 1.56 thorpej 106 1.124 tsutsui /* kernel_arch specific values required by module(9) */ 107 1.124 tsutsui const vaddr_t kernbase = KERNBASE3X; 108 1.124 tsutsui const vaddr_t kern_end = KERN_END3X; 109 1.124 tsutsui 110 1.134 tsutsui /* Our exported CPU info; we can have only one. */ 111 1.56 thorpej struct cpu_info cpu_info_store; 112 1.1 gwr 113 1.70 chs struct vm_map *phys_map = NULL; 114 1.34 gwr 115 1.9 gwr int fputype; 116 1.107 christos void * msgbufaddr; 117 1.1 gwr 118 1.29 gwr /* Virtual page frame for /dev/mem (see mem.c) */ 119 1.73 tsutsui vaddr_t vmmap; 120 1.79 lukem 121 1.29 gwr u_char cpu_machine_id = 0; 122 1.100 tsutsui const char *cpu_string = NULL; 123 1.15 gwr int cpu_has_vme = 0; 124 1.15 gwr int has_iocache = 0; 125 1.15 gwr 126 1.66 chs vaddr_t dumppage; 127 1.66 chs 128 1.97 chs static void identifycpu(void); 129 1.97 chs static void initcpu(void); 130 1.1 gwr 131 1.1 gwr /* 132 1.1 gwr * Console initialization: called early on from main, 133 1.15 gwr * before vm init or cpu_startup. This system is able 134 1.29 gwr * to use the console for output immediately (via PROM) 135 1.29 gwr * but can not use it for input until after this point. 136 1.1 gwr */ 137 1.134 tsutsui void 138 1.97 chs consinit(void) 139 1.1 gwr { 140 1.29 gwr 141 1.29 gwr /* 142 1.29 gwr * Switch from the PROM console (output only) 143 1.29 gwr * to our own console driver. 144 1.29 gwr */ 145 1.29 gwr cninit(); 146 1.1 gwr 147 1.113 ad #if NKSYMS || defined(DDB) || defined(MODULAR) 148 1.32 tv { 149 1.63 chs extern int nsym; 150 1.63 chs extern char *ssym, *esym; 151 1.32 tv 152 1.115 martin ksyms_addsyms_elf(nsym, ssym, esym); 153 1.32 tv } 154 1.72 simonb #endif /* DDB */ 155 1.31 gwr 156 1.31 gwr /* 157 1.31 gwr * Now that the console can do input as well as 158 1.31 gwr * output, consider stopping for a debugger. 159 1.31 gwr */ 160 1.31 gwr if (boothowto & RB_KDB) { 161 1.31 gwr #ifdef KGDB 162 1.31 gwr /* XXX - Ask on console for kgdb_dev? */ 163 1.31 gwr /* Note: this will just return if kgdb_dev==NODEV */ 164 1.31 gwr kgdb_connect(1); 165 1.31 gwr #else /* KGDB */ 166 1.31 gwr /* Either DDB or no debugger (just PROM). */ 167 1.1 gwr Debugger(); 168 1.31 gwr #endif /* KGDB */ 169 1.31 gwr } 170 1.1 gwr } 171 1.1 gwr 172 1.1 gwr /* 173 1.1 gwr * cpu_startup: allocate memory for variable-sized tables, 174 1.95 wiz * initialize CPU, and do autoconfiguration. 175 1.1 gwr * 176 1.1 gwr * This is called early in init_main.c:main(), after the 177 1.1 gwr * kernel memory allocator is ready for use, but before 178 1.1 gwr * the creation of processes 1,2, and mountroot, etc. 179 1.1 gwr */ 180 1.134 tsutsui void 181 1.97 chs cpu_startup(void) 182 1.1 gwr { 183 1.108 tsutsui char *v; 184 1.73 tsutsui vaddr_t minaddr, maxaddr; 185 1.50 lukem char pbuf[9]; 186 1.1 gwr 187 1.1 gwr /* 188 1.1 gwr * Initialize message buffer (for kernel printf). 189 1.1 gwr * This is put in physical page zero so it will 190 1.1 gwr * always be in the same place after a reboot. 191 1.1 gwr * Its mapping was prepared in pmap_bootstrap(). 192 1.1 gwr * Also, offset some to avoid PROM scribbles. 193 1.1 gwr */ 194 1.124 tsutsui v = (char *)KERNBASE3X; 195 1.108 tsutsui msgbufaddr = v + MSGBUFOFF; 196 1.23 gwr initmsgbuf(msgbufaddr, MSGBUFSIZE); 197 1.1 gwr 198 1.1 gwr /* 199 1.1 gwr * Good {morning,afternoon,evening,night}. 200 1.1 gwr */ 201 1.99 lukem printf("%s%s", copyright, version); 202 1.1 gwr identifycpu(); 203 1.1 gwr initfpu(); /* also prints FPU type */ 204 1.1 gwr 205 1.50 lukem format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 206 1.50 lukem printf("total memory = %s\n", pbuf); 207 1.1 gwr 208 1.1 gwr /* 209 1.66 chs * Get scratch page for dumpsys(). 210 1.66 chs */ 211 1.98 yamt dumppage = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED); 212 1.98 yamt if (dumppage == 0) 213 1.66 chs panic("startup: alloc dumppage"); 214 1.66 chs 215 1.94 pk minaddr = 0; 216 1.1 gwr 217 1.1 gwr /* 218 1.84 chs * Allocate a submap for physio 219 1.1 gwr */ 220 1.84 chs phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 221 1.106 thorpej VM_PHYS_SIZE, 0, false, NULL); 222 1.1 gwr 223 1.139 ad format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 224 1.50 lukem printf("avail memory = %s\n", pbuf); 225 1.1 gwr 226 1.1 gwr /* 227 1.1 gwr * Allocate a virtual page (for use by /dev/mem) 228 1.1 gwr * This page is handed to pmap_enter() therefore 229 1.1 gwr * it has to be in the normal kernel VA range. 230 1.1 gwr */ 231 1.98 yamt vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 232 1.98 yamt UVM_KMF_VAONLY | UVM_KMF_WAITVA); 233 1.1 gwr 234 1.1 gwr /* 235 1.1 gwr * Create the DVMA maps. 236 1.1 gwr */ 237 1.1 gwr dvma_init(); 238 1.1 gwr 239 1.1 gwr /* 240 1.1 gwr * Set up CPU-specific registers, cache, etc. 241 1.1 gwr */ 242 1.1 gwr initcpu(); 243 1.1 gwr } 244 1.1 gwr 245 1.1 gwr /* 246 1.1 gwr * Info for CTL_HW 247 1.1 gwr */ 248 1.46 gwr char machine[16] = MACHINE; /* from <machine/param.h> */ 249 1.46 gwr char kernel_arch[16] = "sun3x"; /* XXX needs a sysctl node */ 250 1.15 gwr 251 1.15 gwr /* 252 1.15 gwr * XXX - Should empirically estimate the divisor... 253 1.15 gwr * Note that the value of delay_divisor is roughly 254 1.15 gwr * 2048 / cpuclock (where cpuclock is in MHz). 255 1.15 gwr */ 256 1.16 gwr int delay_divisor = 62; /* assume the fastest (33 MHz) */ 257 1.1 gwr 258 1.134 tsutsui void 259 1.97 chs identifycpu(void) 260 1.1 gwr { 261 1.29 gwr u_char machtype; 262 1.1 gwr 263 1.15 gwr machtype = identity_prom.idp_machtype; 264 1.29 gwr if ((machtype & IDM_ARCH_MASK) != IDM_ARCH_SUN3X) { 265 1.29 gwr printf("Bad IDPROM arch!\n"); 266 1.15 gwr sunmon_abort(); 267 1.15 gwr } 268 1.15 gwr 269 1.29 gwr cpu_machine_id = machtype; 270 1.15 gwr switch (cpu_machine_id) { 271 1.15 gwr 272 1.101 thorpej case ID_SUN3X_80: 273 1.15 gwr cpu_string = "80"; /* Hydra */ 274 1.16 gwr delay_divisor = 102; /* 20 MHz */ 275 1.106 thorpej cpu_has_vme = false; 276 1.15 gwr break; 277 1.15 gwr 278 1.101 thorpej case ID_SUN3X_470: 279 1.15 gwr cpu_string = "470"; /* Pegasus */ 280 1.15 gwr delay_divisor = 62; /* 33 MHz */ 281 1.106 thorpej cpu_has_vme = true; 282 1.15 gwr break; 283 1.15 gwr 284 1.15 gwr default: 285 1.15 gwr printf("unknown sun3x model\n"); 286 1.15 gwr sunmon_abort(); 287 1.15 gwr } 288 1.15 gwr 289 1.15 gwr /* Other stuff? (VAC, mc6888x version, etc.) */ 290 1.46 gwr /* Note: miniroot cares about the kernel_arch part. */ 291 1.135 christos cpu_setmodel("%s %s", kernel_arch, cpu_string); 292 1.1 gwr 293 1.135 christos printf("Model: %s\n", cpu_getmodel()); 294 1.1 gwr } 295 1.1 gwr 296 1.1 gwr /* 297 1.1 gwr * machine dependent system variables. 298 1.1 gwr */ 299 1.93 atatat #if 0 /* XXX - Not yet... */ 300 1.93 atatat static int 301 1.93 atatat sysctl_machdep_root_device(SYSCTLFN_ARGS) 302 1.1 gwr { 303 1.93 atatat struct sysctlnode node = *rnode; 304 1.1 gwr 305 1.93 atatat node.sysctl_data = some permutation on root_device; 306 1.93 atatat node.sysctl_size = strlen(root_device) + 1; 307 1.93 atatat return (sysctl_lookup(SYSCTLFN_CALL(&node))); 308 1.93 atatat } 309 1.1 gwr 310 1.93 atatat static int 311 1.93 atatat sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) 312 1.93 atatat { 313 1.93 atatat struct sysctlnode node = *rnode; 314 1.1 gwr 315 1.93 atatat node.sysctl_data = some permutation on booted_kernel; 316 1.93 atatat node.sysctl_size = strlen(booted_kernel) + 1; 317 1.93 atatat return (sysctl_lookup(SYSCTLFN_CALL(&node))); 318 1.93 atatat } 319 1.1 gwr #endif 320 1.1 gwr 321 1.93 atatat SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 322 1.93 atatat { 323 1.93 atatat 324 1.96 atatat sysctl_createv(clog, 0, NULL, NULL, 325 1.96 atatat CTLFLAG_PERMANENT, 326 1.93 atatat CTLTYPE_NODE, "machdep", NULL, 327 1.93 atatat NULL, 0, NULL, 0, 328 1.93 atatat CTL_MACHDEP, CTL_EOL); 329 1.93 atatat 330 1.96 atatat sysctl_createv(clog, 0, NULL, NULL, 331 1.96 atatat CTLFLAG_PERMANENT, 332 1.93 atatat CTLTYPE_STRUCT, "console_device", NULL, 333 1.93 atatat sysctl_consdev, 0, NULL, sizeof(dev_t), 334 1.93 atatat CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 335 1.93 atatat #if 0 /* XXX - Not yet... */ 336 1.96 atatat sysctl_createv(clog, 0, NULL, NULL, 337 1.96 atatat CTLFLAG_PERMANENT, 338 1.93 atatat CTLTYPE_STRING, "root_device", NULL, 339 1.93 atatat sysctl_machdep_root_device, 0, NULL, 0, 340 1.93 atatat CTL_MACHDEP, CPU_ROOT_DEVICE, CTL_EOL); 341 1.96 atatat sysctl_createv(clog, 0, NULL, NULL, 342 1.96 atatat CTLFLAG_PERMANENT, 343 1.93 atatat CTLTYPE_STRING, "booted_kernel", NULL, 344 1.93 atatat sysctl_machdep_booted_kernel, 0, NULL, 0, 345 1.93 atatat CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); 346 1.93 atatat #endif 347 1.1 gwr } 348 1.1 gwr 349 1.7 gwr /* See: sig_machdep.c */ 350 1.1 gwr 351 1.1 gwr /* 352 1.1 gwr * Do a sync in preparation for a reboot. 353 1.1 gwr * XXX - This could probably be common code. 354 1.1 gwr * XXX - And now, most of it is in vfs_shutdown() 355 1.1 gwr * XXX - Put waittime checks in there too? 356 1.1 gwr */ 357 1.1 gwr int waittime = -1; /* XXX - Who else looks at this? -gwr */ 358 1.1 gwr static void 359 1.97 chs reboot_sync(void) 360 1.1 gwr { 361 1.1 gwr 362 1.1 gwr /* Check waittime here to localize its use to this function. */ 363 1.1 gwr if (waittime >= 0) 364 1.1 gwr return; 365 1.1 gwr waittime = 0; 366 1.1 gwr vfs_shutdown(); 367 1.1 gwr } 368 1.1 gwr 369 1.1 gwr /* 370 1.1 gwr * Common part of the BSD and SunOS reboot system calls. 371 1.1 gwr */ 372 1.134 tsutsui __dead void 373 1.97 chs cpu_reboot(int howto, char *user_boot_string) 374 1.1 gwr { 375 1.2 gwr /* Note: this string MUST be static! */ 376 1.2 gwr static char bootstr[128]; 377 1.2 gwr char *p; 378 1.1 gwr 379 1.1 gwr /* If system is cold, just halt. (early panic?) */ 380 1.1 gwr if (cold) 381 1.1 gwr goto haltsys; 382 1.1 gwr 383 1.24 gwr /* Un-blank the screen if appropriate. */ 384 1.24 gwr cnpollc(1); 385 1.24 gwr 386 1.1 gwr if ((howto & RB_NOSYNC) == 0) { 387 1.1 gwr reboot_sync(); 388 1.1 gwr /* 389 1.1 gwr * If we've been adjusting the clock, the todr 390 1.1 gwr * will be out of synch; adjust it now. 391 1.1 gwr * 392 1.1 gwr * XXX - However, if the kernel has been sitting in ddb, 393 1.1 gwr * the time will be way off, so don't set the HW clock! 394 1.1 gwr * XXX - Should do sanity check against HW clock. -gwr 395 1.1 gwr */ 396 1.1 gwr /* resettodr(); */ 397 1.1 gwr } 398 1.1 gwr 399 1.1 gwr /* Disable interrupts. */ 400 1.1 gwr splhigh(); 401 1.1 gwr 402 1.1 gwr /* Write out a crash dump if asked. */ 403 1.1 gwr if (howto & RB_DUMP) 404 1.1 gwr dumpsys(); 405 1.1 gwr 406 1.1 gwr /* run any shutdown hooks */ 407 1.1 gwr doshutdownhooks(); 408 1.1 gwr 409 1.112 dyoung pmf_system_shutdown(boothowto); 410 1.112 dyoung 411 1.1 gwr if (howto & RB_HALT) { 412 1.1 gwr haltsys: 413 1.63 chs printf("halted.\n"); 414 1.61 tsutsui sunmon_halt(); 415 1.1 gwr } 416 1.1 gwr 417 1.1 gwr /* 418 1.1 gwr * Automatic reboot. 419 1.1 gwr */ 420 1.2 gwr if (user_boot_string) 421 1.2 gwr strncpy(bootstr, user_boot_string, sizeof(bootstr)); 422 1.2 gwr else { 423 1.1 gwr /* 424 1.1 gwr * Build our own boot string with an empty 425 1.1 gwr * boot device/file and (maybe) some flags. 426 1.1 gwr * The PROM will supply the device/file name. 427 1.1 gwr */ 428 1.2 gwr p = bootstr; 429 1.2 gwr *p = '\0'; 430 1.1 gwr if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) { 431 1.1 gwr /* Append the boot flags. */ 432 1.1 gwr *p++ = ' '; 433 1.1 gwr *p++ = '-'; 434 1.1 gwr if (howto & RB_KDB) 435 1.1 gwr *p++ = 'd'; 436 1.1 gwr if (howto & RB_ASKNAME) 437 1.1 gwr *p++ = 'a'; 438 1.1 gwr if (howto & RB_SINGLE) 439 1.1 gwr *p++ = 's'; 440 1.1 gwr *p = '\0'; 441 1.1 gwr } 442 1.1 gwr } 443 1.63 chs printf("rebooting...\n"); 444 1.3 gwr sunmon_reboot(bootstr); 445 1.1 gwr for (;;) ; 446 1.1 gwr /*NOTREACHED*/ 447 1.1 gwr } 448 1.1 gwr 449 1.1 gwr /* 450 1.1 gwr * These variables are needed by /sbin/savecore 451 1.1 gwr */ 452 1.97 chs uint32_t dumpmag = 0x8fca0101; /* magic number */ 453 1.1 gwr int dumpsize = 0; /* pages */ 454 1.1 gwr long dumplo = 0; /* blocks */ 455 1.1 gwr 456 1.71 tsutsui #define DUMP_EXTRA 1 /* CPU-dependent extra pages */ 457 1.71 tsutsui 458 1.1 gwr /* 459 1.11 gwr * This is called by main to set dumplo, dumpsize. 460 1.86 thorpej * Dumps always skip the first PAGE_SIZE of disk space 461 1.1 gwr * in case there might be a disk label stored there. 462 1.1 gwr * If there is extra space, put dump at the end to 463 1.1 gwr * reduce the chance that swapping trashes it. 464 1.1 gwr */ 465 1.134 tsutsui void 466 1.97 chs cpu_dumpconf(void) 467 1.1 gwr { 468 1.71 tsutsui int devblks; /* size of dump device in blocks */ 469 1.71 tsutsui int dumpblks; /* size of dump image in blocks */ 470 1.1 gwr 471 1.1 gwr if (dumpdev == NODEV) 472 1.1 gwr return; 473 1.1 gwr 474 1.131 mrg devblks = bdev_size(dumpdev); 475 1.71 tsutsui if (devblks <= ctod(1)) 476 1.1 gwr return; 477 1.71 tsutsui devblks &= ~(ctod(1) - 1); 478 1.71 tsutsui 479 1.71 tsutsui /* 480 1.71 tsutsui * Note: savecore expects dumpsize to be the 481 1.71 tsutsui * number of pages AFTER the dump header. 482 1.71 tsutsui */ 483 1.71 tsutsui dumpsize = physmem; /* pages */ 484 1.1 gwr 485 1.1 gwr /* Position dump image near end of space, page aligned. */ 486 1.71 tsutsui dumpblks = ctod(physmem + DUMP_EXTRA); 487 1.71 tsutsui dumplo = devblks - dumpblks; 488 1.1 gwr 489 1.1 gwr /* If it does not fit, truncate it by moving dumplo. */ 490 1.1 gwr /* Note: Must force signed comparison. */ 491 1.1 gwr if (dumplo < ((long)ctod(1))) { 492 1.1 gwr dumplo = ctod(1); 493 1.71 tsutsui dumpsize = dtoc(devblks - dumplo) - DUMP_EXTRA; 494 1.1 gwr } 495 1.1 gwr } 496 1.1 gwr 497 1.13 gwr /* Note: gdb looks for "dumppcb" in a kernel crash dump. */ 498 1.1 gwr struct pcb dumppcb; 499 1.1 gwr 500 1.1 gwr /* 501 1.1 gwr * Write a crash dump. The format while in swap is: 502 1.1 gwr * kcore_seg_t cpu_hdr; 503 1.1 gwr * cpu_kcore_hdr_t cpu_data; 504 1.86 thorpej * padding (PAGE_SIZE-sizeof(kcore_seg_t)) 505 1.86 thorpej * pagemap (2*PAGE_SIZE) 506 1.1 gwr * physical memory... 507 1.1 gwr */ 508 1.134 tsutsui void 509 1.97 chs dumpsys(void) 510 1.1 gwr { 511 1.81 gehenna const struct bdevsw *dsw; 512 1.66 chs kcore_seg_t *kseg_p; 513 1.10 gwr cpu_kcore_hdr_t *chdr_p; 514 1.14 thorpej struct sun3x_kcore_hdr *sh; 515 1.14 thorpej phys_ram_seg_t *crs_p; 516 1.1 gwr char *vaddr; 517 1.73 tsutsui paddr_t paddr; 518 1.10 gwr int psize, todo, seg, segsz; 519 1.1 gwr daddr_t blkno; 520 1.1 gwr int error = 0; 521 1.1 gwr 522 1.1 gwr if (dumpdev == NODEV) 523 1.1 gwr return; 524 1.81 gehenna dsw = bdevsw_lookup(dumpdev); 525 1.81 gehenna if (dsw == NULL || dsw->d_psize == NULL) 526 1.81 gehenna return; 527 1.1 gwr 528 1.1 gwr /* 529 1.1 gwr * For dumps during autoconfiguration, 530 1.1 gwr * if dump device has already configured... 531 1.1 gwr */ 532 1.1 gwr if (dumpsize == 0) 533 1.11 gwr cpu_dumpconf(); 534 1.28 mycroft if (dumplo <= 0) { 535 1.117 he printf("\ndump to dev %u,%u not possible\n", 536 1.116 tsutsui major(dumpdev), minor(dumpdev)); 537 1.1 gwr return; 538 1.28 mycroft } 539 1.1 gwr savectx(&dumppcb); 540 1.1 gwr 541 1.131 mrg psize = bdev_size(dumpdev); 542 1.1 gwr if (psize == -1) { 543 1.1 gwr printf("dump area unavailable\n"); 544 1.1 gwr return; 545 1.1 gwr } 546 1.1 gwr 547 1.117 he printf("\ndumping to dev %u,%u offset %ld\n", 548 1.116 tsutsui major(dumpdev), minor(dumpdev), dumplo); 549 1.1 gwr 550 1.1 gwr /* 551 1.71 tsutsui * Prepare the dump header 552 1.1 gwr */ 553 1.71 tsutsui blkno = dumplo; 554 1.71 tsutsui todo = dumpsize; /* pages */ 555 1.71 tsutsui vaddr = (char *)dumppage; 556 1.86 thorpej memset(vaddr, 0, PAGE_SIZE); 557 1.25 gwr 558 1.25 gwr /* Set pointers to all three parts. */ 559 1.71 tsutsui kseg_p = (kcore_seg_t *)vaddr; 560 1.66 chs chdr_p = (cpu_kcore_hdr_t *)(kseg_p + 1); 561 1.14 thorpej sh = &chdr_p->un._sun3x; 562 1.25 gwr 563 1.25 gwr /* Fill in kcore_seg_t part. */ 564 1.10 gwr CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 565 1.71 tsutsui kseg_p->c_size = (ctob(DUMP_EXTRA) - sizeof(*kseg_p)); 566 1.25 gwr 567 1.25 gwr /* Fill in cpu_kcore_hdr_t part. */ 568 1.46 gwr strncpy(chdr_p->name, kernel_arch, sizeof(chdr_p->name)); 569 1.86 thorpej chdr_p->page_size = PAGE_SIZE; 570 1.124 tsutsui chdr_p->kernbase = KERNBASE3X; 571 1.25 gwr 572 1.25 gwr /* Fill in the sun3x_kcore_hdr part. */ 573 1.25 gwr pmap_kcore_hdr(sh); 574 1.10 gwr 575 1.71 tsutsui /* Write out the dump header. */ 576 1.86 thorpej error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE); 577 1.71 tsutsui if (error) 578 1.71 tsutsui goto fail; 579 1.86 thorpej blkno += btodb(PAGE_SIZE); 580 1.71 tsutsui 581 1.10 gwr /* 582 1.10 gwr * Now dump physical memory. Note that physical memory 583 1.141 andvar * might NOT be contiguous, so do it by segments. 584 1.10 gwr */ 585 1.10 gwr 586 1.66 chs vaddr = (char *)vmmap; /* Borrow /dev/mem VA */ 587 1.1 gwr 588 1.14 thorpej for (seg = 0; seg < SUN3X_NPHYS_RAM_SEGS; seg++) { 589 1.14 thorpej crs_p = &sh->ram_segs[seg]; 590 1.10 gwr paddr = crs_p->start; 591 1.10 gwr segsz = crs_p->size; 592 1.1 gwr 593 1.10 gwr while (todo && (segsz > 0)) { 594 1.1 gwr 595 1.10 gwr /* Print pages left after every 16. */ 596 1.10 gwr if ((todo & 0xf) == 0) 597 1.114 ad printf_nolog("\r%4d", todo); 598 1.10 gwr 599 1.10 gwr /* Make a temporary mapping for the page. */ 600 1.120 he pmap_kenter_pa(vmmap, paddr | PMAP_NC, VM_PROT_READ, 0); 601 1.75 chris pmap_update(pmap_kernel()); 602 1.86 thorpej error = (*dsw->d_dump)(dumpdev, blkno, vaddr, 603 1.86 thorpej PAGE_SIZE); 604 1.86 thorpej pmap_kremove(vmmap, PAGE_SIZE); 605 1.75 chris pmap_update(pmap_kernel()); 606 1.10 gwr if (error) 607 1.10 gwr goto fail; 608 1.86 thorpej paddr += PAGE_SIZE; 609 1.86 thorpej segsz -= PAGE_SIZE; 610 1.86 thorpej blkno += btodb(PAGE_SIZE); 611 1.10 gwr todo--; 612 1.10 gwr } 613 1.10 gwr } 614 1.1 gwr printf("\rdump succeeded\n"); 615 1.1 gwr return; 616 1.1 gwr fail: 617 1.1 gwr printf(" dump error=%d\n", error); 618 1.1 gwr } 619 1.1 gwr 620 1.134 tsutsui static void 621 1.97 chs initcpu(void) 622 1.1 gwr { 623 1.1 gwr /* XXX: Enable RAM parity/ECC checking? */ 624 1.1 gwr /* XXX: parityenable(); */ 625 1.1 gwr 626 1.1 gwr #ifdef HAVECACHE 627 1.1 gwr cache_enable(); 628 1.1 gwr #endif 629 1.1 gwr } 630 1.1 gwr 631 1.8 gwr /* straptrap() in trap.c */ 632 1.1 gwr 633 1.1 gwr /* from hp300: badaddr() */ 634 1.15 gwr /* peek_byte(), peek_word() moved to bus_subr.c */ 635 1.1 gwr 636 1.1 gwr /* XXX: parityenable() ? */ 637 1.7 gwr /* regdump() moved to regdump.c */ 638 1.1 gwr 639 1.1 gwr /* 640 1.1 gwr * cpu_exec_aout_makecmds(): 641 1.95 wiz * CPU-dependent a.out format hook for execve(). 642 1.1 gwr * 643 1.1 gwr * Determine if the given exec package refers to something which we 644 1.1 gwr * understand and, if so, set up the vmcmds for it. 645 1.1 gwr */ 646 1.134 tsutsui int 647 1.102 christos cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 648 1.1 gwr { 649 1.27 tv return ENOEXEC; 650 1.1 gwr } 651 1.124 tsutsui 652 1.129 rmind int 653 1.129 rmind mm_md_physacc(paddr_t pa, vm_prot_t prot) 654 1.129 rmind { 655 1.129 rmind 656 1.129 rmind return pmap_pa_exists(pa) ? 0 : EFAULT; 657 1.129 rmind } 658 1.129 rmind 659 1.129 rmind bool 660 1.129 rmind mm_md_direct_mapped_phys(paddr_t paddr, vaddr_t *vaddr) 661 1.129 rmind { 662 1.129 rmind extern paddr_t avail_start; 663 1.129 rmind 664 1.134 tsutsui if (paddr >= avail_start) 665 1.129 rmind return false; 666 1.130 tsutsui *vaddr = KERNBASE3X + paddr; 667 1.129 rmind return true; 668 1.129 rmind } 669 1.129 rmind 670 1.129 rmind /* 671 1.136 msaitoh * Allow access to the PROM mapping similar to uvm_kernacc(). 672 1.129 rmind */ 673 1.129 rmind int 674 1.129 rmind mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) 675 1.129 rmind { 676 1.129 rmind 677 1.129 rmind if ((vaddr_t)ptr < SUN3X_PROM_BASE || (vaddr_t)ptr > SUN3X_MONEND) { 678 1.129 rmind *handled = false; 679 1.129 rmind return 0; 680 1.129 rmind } 681 1.129 rmind 682 1.129 rmind *handled = true; 683 1.129 rmind /* Read in the PROM itself is OK. */ 684 1.129 rmind if ((prot & VM_PROT_WRITE) == 0) 685 1.129 rmind return 0; 686 1.129 rmind 687 1.129 rmind /* PROM data page is OK for read/write. */ 688 1.129 rmind if ((vaddr_t)ptr >= SUN3X_MONDATA && 689 1.129 rmind (vaddr_t)ptr < SUN3X_MONDATA + PAGE_SIZE) 690 1.129 rmind return 0; 691 1.129 rmind return EFAULT; 692 1.129 rmind } 693 1.129 rmind 694 1.124 tsutsui #ifdef MODULAR 695 1.124 tsutsui /* 696 1.124 tsutsui * Push any modules loaded by the bootloader etc. 697 1.124 tsutsui */ 698 1.124 tsutsui void 699 1.124 tsutsui module_init_md(void) 700 1.124 tsutsui { 701 1.124 tsutsui } 702 1.124 tsutsui #endif 703