1 /* $NetBSD: machdep.c,v 1.252 2025/12/20 10:51:03 skrll 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.252 2025/12/20 10:51:03 skrll Exp $"); 43 44 #include "opt_ddb.h" 45 #include "opt_compat_netbsd.h" 46 #include "opt_fpu_emulate.h" 47 #include "opt_modular.h" 48 #include "opt_panicbutton.h" 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/callout.h> 53 #include <sys/buf.h> 54 #include <sys/conf.h> 55 #include <sys/exec.h> 56 #include <sys/exec_aout.h> /* for MID_* */ 57 #include <sys/file.h> 58 #include <sys/ioctl.h> 59 #include <sys/kernel.h> 60 #include <sys/device.h> 61 #include <sys/malloc.h> 62 #include <sys/mbuf.h> 63 #include <sys/mount.h> 64 #include <sys/msgbuf.h> 65 #include <sys/proc.h> 66 #include <sys/reboot.h> 67 #include <sys/signalvar.h> 68 #include <sys/syscallargs.h> 69 #include <sys/tty.h> 70 #include <sys/core.h> 71 #include <sys/kcore.h> 72 #include <sys/vnode.h> 73 #include <sys/ksyms.h> 74 #include <sys/module.h> 75 #include <sys/cpu.h> 76 77 #ifdef DDB 78 #include <machine/db_machdep.h> 79 #include <ddb/db_sym.h> 80 #include <ddb/db_extern.h> 81 #endif /* DDB */ 82 #include <sys/exec_elf.h> 83 84 #include <machine/autoconf.h> 85 #include <machine/bootinfo.h> 86 #include <machine/bus.h> 87 #include <machine/cpu.h> 88 #include <machine/hp300spu.h> 89 #include <machine/reg.h> 90 #include <machine/pcb.h> 91 #include <machine/psl.h> 92 #include <machine/pte.h> 93 94 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 95 96 #include <dev/cons.h> 97 #include <dev/mm.h> 98 99 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 100 #include <uvm/uvm_extern.h> 101 102 #include <sys/sysctl.h> 103 104 #include "opt_useleds.h" 105 106 #ifdef USELEDS 107 #include <hp300/hp300/leds.h> 108 #endif 109 110 #include "ksyms.h" 111 112 /* the following is used externally (sysctl_hw) */ 113 char machine[] = MACHINE; /* from <machine/param.h> */ 114 115 /* Our exported CPU info; we can have only one. */ 116 struct cpu_info cpu_info_store; 117 118 struct vm_map *phys_map = NULL; 119 120 extern paddr_t avail_start, avail_end; 121 122 /* 123 * bootinfo base (physical and virtual). The bootinfo is placed, by 124 * the boot loader, into the first page of kernel text, which is zero 125 * filled (see locore.s) and not mapped at 0. It is remapped to a 126 * different address in pmap_bootstrap(). 127 */ 128 paddr_t bootinfo_pa; 129 vaddr_t bootinfo_va; 130 131 int maxmem; /* max memory per process */ 132 133 extern u_int lowram; 134 extern short exframesize[]; 135 136 /* prototypes for local functions */ 137 static void parityenable(void); 138 static int parityerror(struct frame *); 139 static int parityerrorfind(void); 140 static void identifycpu(void); 141 static void initcpu(void); 142 143 static int cpu_dumpsize(void); 144 static int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 145 static void cpu_init_kcore_hdr(void); 146 147 /* functions called from locore.s */ 148 void dumpsys(void); 149 void machine_init(paddr_t); 150 void straytrap(int, u_short); 151 void nmihand(struct frame); 152 153 /* 154 * Machine-dependent crash dump header info. 155 */ 156 static cpu_kcore_hdr_t cpu_kcore_hdr; 157 158 /* 159 * Note that the value of delay_divisor is roughly 160 * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020 161 * and 68030 systems. See clock.c for the delay 162 * calibration algorithm. 163 */ 164 int cpuspeed; /* relative CPU speed; XXX skewed on 68040 */ 165 int delay_divisor; /* delay constant */ 166 167 #ifdef __HAVE_NEW_PMAP_68K 168 /* 169 * machine_bootmap[] is checked in pmap_bootstrap1() of the new m68k pmap 170 * and it allocates kernel address space for intio devices. 171 */ 172 #define PMBM_INTIO 0 173 #define PMBM_EXTIO 1 174 #define PMBM_BOOTINFO 2 175 #define PMBM_MAXADDR 3 176 const struct pmap_bootmap machine_bootmap[] = { 177 { .pmbm_vaddr_ptr = (vaddr_t *)&intiobase, 178 .pmbm_paddr = INTIOBASE, 179 .pmbm_size = INTIOSIZE, 180 .pmbm_flags = PMBM_F_CI }, 181 182 { .pmbm_vaddr_ptr = (vaddr_t *)&extiobase, 183 .pmbm_paddr = 0, /* VAONLY, so no PA mappings */ 184 .pmbm_size = ctob(EIOMAPSIZE), 185 .pmbm_flags = PMBM_F_VAONLY | PMBM_F_CI }, 186 187 { .pmbm_vaddr_ptr = &bootinfo_va, 188 .pmbm_paddr = 0, /* VAONLY, so no PA mappings */ 189 .pmbm_size = ctob(1), 190 .pmbm_flags = PMBM_F_VAONLY }, 191 192 /* Last page of RAM is mapped VA==PA for the MMU trampoline. */ 193 { .pmbm_vaddr = MAXADDR, 194 .pmbm_paddr = MAXADDR, 195 .pmbm_size = PAGE_SIZE, 196 .pmbm_flags = PMBM_F_FIXEDVA | PMBM_F_CI }, 197 198 { .pmbm_vaddr = -1 }, 199 }; 200 201 /* 202 * The new 68k pmap utilizes the MAXADDR page as the NULL segment table 203 * to save a page, so we have to preserve PROM workarea for the next reboot. 204 * This preservation area is much less than a page size, so the trade-off 205 * seems worth it. 206 */ 207 #define BOOTWORKSTART 0xfffffdc0U /* from hp300/stand/common/srt0.S */ 208 #define BOOTWORKSIZE (0U - BOOTWORKSTART) 209 static char bootwork_savearea[BOOTWORKSIZE]; 210 #endif /* __HAVE_NEW_PMAP_68K */ 211 212 /* 213 * Early initialization, before main() is called. 214 */ 215 void 216 machine_init(paddr_t nextpa) 217 { 218 struct btinfo_magic *bt_mag; 219 int i; 220 221 #ifdef CACHE_HAVE_VAC 222 /* 223 * Determine VA aliasing distance if any 224 */ 225 switch (machineid) { 226 case HP_320: 227 pmap_init_vac(16 * 1024); 228 break; 229 case HP_350: 230 pmap_init_vac(32 * 1024); 231 break; 232 default: 233 break; 234 } 235 #endif 236 237 #ifdef __HAVE_NEW_PMAP_68K 238 /* 239 * We've used NULL_SEGTAB_PA in <machine/pmap.h> to use the 240 * reserved last-page-of-RAM as the NULL segment table. But, 241 * we copied code into that page (the MMU trampoline) and it 242 * also contains the PROM's work area. Preserve the PROM work 243 * area and zero it out now. 244 */ 245 memcpy(bootwork_savearea, (void *)BOOTWORKSTART, BOOTWORKSIZE); 246 memset((void *)MAXADDR, 0, PAGE_SIZE); 247 #endif 248 249 /* 250 * Tell the VM system about available physical memory. The 251 * hp300 only has one segment. 252 */ 253 avail_start = nextpa; 254 avail_end = m68k_ptob(maxmem) - \ 255 (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1)); 256 257 uvm_page_physload(atop(avail_start), atop(avail_end), 258 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 259 260 /* Calibrate the delay loop. */ 261 hp300_calibrate_delay(); 262 263 /* 264 * Initialize error message buffer (at end of core). 265 * avail_end was pre-decremented in pmap_bootstrap to compensate. 266 */ 267 for (i = 0; i < btoc(MSGBUFSIZE); i++) 268 pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 269 avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); 270 pmap_update(pmap_kernel()); 271 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 272 273 /* 274 * Map in the bootinfo page, and make sure the bootinfo 275 * exists by searching for the MAGIC record. If it's not 276 * there, disable bootinfo. 277 */ 278 #ifndef __HAVE_NEW_PMAP_68K 279 bootinfo_va = virtual_avail; 280 virtual_avail += PAGE_SIZE; 281 #endif 282 pmap_enter(pmap_kernel(), bootinfo_va, bootinfo_pa, 283 VM_PROT_READ|VM_PROT_WRITE, 284 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 285 pmap_update(pmap_kernel()); 286 bt_mag = lookup_bootinfo(BTINFO_MAGIC); 287 if (bt_mag == NULL || 288 bt_mag->magic1 != BOOTINFO_MAGIC1 || 289 bt_mag->magic2 != BOOTINFO_MAGIC2) { 290 pmap_remove(pmap_kernel(), bootinfo_va, 291 bootinfo_va + PAGE_SIZE); 292 pmap_update(pmap_kernel()); 293 #ifndef __HAVE_NEW_PMAP_68K 294 virtual_avail -= PAGE_SIZE; 295 #endif 296 bootinfo_va = 0; 297 } 298 } 299 300 /* 301 * Console initialization: called early on from main, 302 * before vm init or startup. Do enough configuration 303 * to choose and initialize a console. 304 */ 305 void 306 consinit(void) 307 { 308 309 /* 310 * Initialize the external I/O extent map. 311 */ 312 iomap_init(); 313 314 /* 315 * Initialize the console before we print anything out. 316 */ 317 318 hp300_cninit(); 319 320 /* 321 * Issue a warning if the boot loader didn't provide bootinfo. 322 */ 323 if (bootinfo_va != 0) 324 printf("bootinfo found at 0x%08lx\n", bootinfo_pa); 325 else 326 printf("WARNING: boot loader did not provide bootinfo\n"); 327 328 #if NKSYMS || defined(DDB) || defined(MODULAR) 329 { 330 extern int end; 331 extern int *esym; 332 333 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 334 (void *)&end, esym); 335 } 336 #endif 337 #ifdef DDB 338 if (boothowto & RB_KDB) 339 Debugger(); 340 #endif 341 } 342 343 /* 344 * cpu_startup: allocate memory for variable-sized tables, 345 * initialize CPU 346 */ 347 void 348 cpu_startup(void) 349 { 350 vaddr_t minaddr, maxaddr; 351 char pbuf[9]; 352 #if defined(DEBUG) && !defined(__HAVE_NEW_PMAP_68K) 353 extern int pmapdebug; 354 int opmapdebug = pmapdebug; 355 356 pmapdebug = 0; 357 #endif 358 359 hp300_cninit_deferred(); 360 361 if (fputype != FPU_NONE) 362 m68k_make_fpu_idle_frame(); 363 364 /* 365 * Initialize the kernel crash dump header. 366 */ 367 cpu_init_kcore_hdr(); 368 369 /* 370 * Good {morning,afternoon,evening,night}. 371 */ 372 printf("%s%s", copyright, version); 373 identifycpu(); 374 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 375 printf("total memory = %s\n", pbuf); 376 377 minaddr = 0; 378 379 /* 380 * Allocate a submap for physio 381 */ 382 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 383 VM_PHYS_SIZE, 0, false, NULL); 384 385 #if defined(DEBUG) && !defined(__HAVE_NEW_PMAP_68K) 386 pmapdebug = opmapdebug; 387 #endif 388 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 389 printf("avail memory = %s\n", pbuf); 390 391 /* 392 * Set up CPU-specific registers, cache, etc. 393 */ 394 initcpu(); 395 } 396 397 struct hp300_model { 398 int id; 399 int mmuid; 400 const char *name; 401 const char *speed; 402 }; 403 404 static const struct hp300_model hp300_models[] = { 405 { HP_320, -1, "320", "16.67" }, 406 { HP_330, -1, "318/319/330", "16.67" }, 407 { HP_340, -1, "340", "16.67" }, 408 { HP_345, -1, "345", "50" }, 409 { HP_350, -1, "350", "25" }, 410 { HP_360, -1, "360", "25" }, 411 { HP_362, -1, "362", "25" }, 412 { HP_370, -1, "370", "33.33" }, 413 { HP_375, -1, "375", "50" }, 414 { HP_380, -1, "380", "25" }, 415 { HP_382, -1, "382", "25" }, 416 { HP_385, -1, "385", "33" }, 417 { HP_400, -1, "400", "50" }, 418 { HP_425, MMUID_425_T, "425t", "25" }, 419 { HP_425, MMUID_425_S, "425s", "25" }, 420 { HP_425, MMUID_425_E, "425e", "25" }, 421 { HP_425, -1, "425", "25" }, 422 { HP_433, MMUID_433_T, "433t", "33" }, 423 { HP_433, MMUID_433_S, "433s", "33" }, 424 { HP_433, -1, "433", "33" }, 425 { 0, -1, NULL, NULL }, 426 }; 427 428 static void 429 identifycpu(void) 430 { 431 const char *t, *cpu, *s, *mmu; 432 int i; 433 char fpu[64], cache[64]; 434 435 /* 436 * Find the model number. 437 */ 438 for (t = s = NULL, i = 0; hp300_models[i].name != NULL; i++) { 439 if (hp300_models[i].id == machineid) { 440 if (hp300_models[i].mmuid != -1 && 441 hp300_models[i].mmuid != mmuid) 442 continue; 443 t = hp300_models[i].name; 444 s = hp300_models[i].speed; 445 break; 446 } 447 } 448 if (t == NULL) { 449 printf("\nunknown machineid %d\n", machineid); 450 goto lose; 451 } 452 453 /* 454 * ...and the CPU type. 455 */ 456 switch (cputype) { 457 case CPU_68040: 458 cpu = "MC68040"; 459 break; 460 case CPU_68030: 461 cpu = "MC68030"; 462 break; 463 case CPU_68020: 464 cpu = "MC68020"; 465 break; 466 default: 467 printf("\nunknown cputype %d\n", cputype); 468 goto lose; 469 } 470 471 472 /* 473 * ...and the MMU type. 474 */ 475 switch (mmutype) { 476 case MMU_68040: 477 case MMU_68030: 478 mmu = "+MMU"; 479 break; 480 case MMU_68851: 481 mmu = ", MC68851 MMU"; 482 break; 483 case MMU_HP: 484 mmu = ", HP MMU"; 485 break; 486 default: 487 printf("%s\nunknown MMU type %d\n", cpu, mmutype); 488 panic("startup"); 489 } 490 491 /* 492 * ...and the FPU type. 493 */ 494 fpu[0] = '\0'; 495 switch (fputype) { 496 case FPU_68040: 497 strlcpy(fpu, "+FPU", sizeof(fpu)); 498 break; 499 case FPU_68882: 500 snprintf(fpu, sizeof(fpu), ", %sMHz MC68882 FPU", s); 501 break; 502 case FPU_68881: 503 snprintf(fpu, sizeof(fpu), ", %sMHz MC68881 FPU", 504 machineid == HP_350 ? "20" : "16.67"); 505 break; 506 case FPU_NONE: 507 #ifdef FPU_EMULATE 508 strlcpy(fpu, ", emulated FPU", sizeof(fpu)); 509 #else 510 strlcpy(fpu, ", no FPU", sizeof(fpu)); 511 #endif 512 break; 513 default: 514 strlcpy(fpu, ", unknown FPU", sizeof(fpu)); 515 } 516 517 /* 518 * ...and finally, the cache type. 519 */ 520 cache[0] = '\0'; 521 if (cputype == CPU_68040) 522 snprintf(cache, sizeof(cache), 523 ", 4k on-chip physical I/D caches"); 524 else { 525 switch (ectype) { 526 case EC_VIRT: 527 snprintf(cache, sizeof(cache), 528 ", %dK virtual-address cache", 529 machineid == HP_320 ? 16 : 32); 530 break; 531 case EC_PHYS: 532 snprintf(cache, sizeof(cache), 533 ", %dK physical-address cache", 534 machineid == HP_370 ? 64 : 32); 535 break; 536 } 537 } 538 539 cpu_setmodel("HP 9000/%s (%sMHz %s CPU%s%s%s)", t, s, cpu, 540 mmu, fpu, cache); 541 printf("%s\n", cpu_getmodel()); 542 #ifdef DIAGNOSTIC 543 printf("cpu: delay divisor %d", delay_divisor); 544 if (mmuid) 545 printf(", mmuid %d", mmuid); 546 printf("\n"); 547 #endif 548 549 /* 550 * Now that we have told the user what they have, 551 * let them know if that machine type isn't configured. 552 */ 553 switch (machineid) { 554 case -1: /* keep compilers happy */ 555 #if !defined(HP320) 556 case HP_320: 557 #endif 558 #if !defined(HP330) 559 case HP_330: 560 #endif 561 #if !defined(HP340) 562 case HP_340: 563 #endif 564 #if !defined(HP345) 565 case HP_345: 566 #endif 567 #if !defined(HP350) 568 case HP_350: 569 #endif 570 #if !defined(HP360) 571 case HP_360: 572 #endif 573 #if !defined(HP362) 574 case HP_362: 575 #endif 576 #if !defined(HP370) 577 case HP_370: 578 #endif 579 #if !defined(HP375) 580 case HP_375: 581 #endif 582 #if !defined(HP380) 583 case HP_380: 584 #endif 585 #if !defined(HP382) 586 case HP_382: 587 #endif 588 #if !defined(HP385) 589 case HP_385: 590 #endif 591 #if !defined(HP400) 592 case HP_400: 593 #endif 594 #if !defined(HP425) 595 case HP_425: 596 #endif 597 #if !defined(HP433) 598 case HP_433: 599 #endif 600 panic("SPU type not configured"); 601 default: 602 break; 603 } 604 605 return; 606 lose: 607 panic("startup"); 608 } 609 610 /* 611 * machine dependent system variables. 612 */ 613 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 614 { 615 static bool broken_rmc; 616 617 broken_rmc = (cputype == M68020); 618 619 sysctl_createv(clog, 0, NULL, NULL, 620 CTLFLAG_PERMANENT, 621 CTLTYPE_NODE, "machdep", NULL, 622 NULL, 0, NULL, 0, 623 CTL_MACHDEP, CTL_EOL); 624 625 sysctl_createv(clog, 0, NULL, NULL, 626 CTLFLAG_PERMANENT, 627 CTLTYPE_STRUCT, "console_device", NULL, 628 sysctl_consdev, 0, NULL, sizeof(dev_t), 629 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 630 631 sysctl_createv(clog, 0, NULL, NULL, 632 CTLFLAG_PERMANENT, 633 CTLTYPE_BOOL, "broken_rmc", NULL, 634 NULL, 0, &broken_rmc, 0, 635 CTL_MACHDEP, CPU_BROKEN_RMC, CTL_EOL); 636 } 637 638 int waittime = -1; 639 640 void 641 cpu_reboot(int howto, char *bootstr) 642 { 643 struct pcb *pcb = lwp_getpcb(curlwp); 644 645 /* take a snap shot before clobbering any registers */ 646 if (pcb != NULL) 647 savectx(pcb); 648 649 /* If system is cold, just halt. */ 650 if (cold) { 651 howto |= RB_HALT; 652 goto haltsys; 653 } 654 655 boothowto = howto; 656 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 657 waittime = 0; 658 vfs_shutdown(); 659 } 660 661 /* Disable interrupts. */ 662 splhigh(); 663 664 /* If rebooting and a dump is requested do it. */ 665 if (howto & RB_DUMP) 666 dumpsys(); 667 668 haltsys: 669 /* Run any shutdown hooks. */ 670 doshutdownhooks(); 671 672 pmf_system_shutdown(boothowto); 673 674 #if defined(PANICWAIT) && !defined(DDB) 675 if ((howto & RB_HALT) == 0 && panicstr) { 676 printf("hit any key to reboot...\n"); 677 cnpollc(true); 678 (void)cngetc(); 679 cnpollc(false); 680 printf("\n"); 681 } 682 #endif 683 684 /* Finally, halt/reboot the system. */ 685 if (howto & RB_HALT) { 686 printf("System halted. Hit any key to reboot.\n\n"); 687 cnpollc(true); 688 (void)cngetc(); 689 cnpollc(false); 690 } 691 692 printf("rebooting...\n"); 693 DELAY(1000000); 694 695 #ifdef __HAVE_NEW_PMAP_68K 696 /* Restore the PROM work area first. */ 697 memcpy((void *)BOOTWORKSTART, bootwork_savearea, BOOTWORKSIZE); 698 #endif 699 doboot(); 700 /* NOTREACHED */ 701 } 702 703 /* 704 * Initialize the kernel crash dump header. 705 */ 706 static void 707 cpu_init_kcore_hdr(void) 708 { 709 phys_ram_seg_t *ram_segs = pmap_init_kcore_hdr(&cpu_kcore_hdr); 710 711 /* hp300 has one contiguous memory segment. */ 712 ram_segs[0].start = lowram; 713 ram_segs[0].size = ctob(physmem); 714 } 715 716 /* 717 * Compute the size of the machine-dependent crash dump header. 718 * Returns size in disk blocks. 719 */ 720 721 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 722 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 723 724 static int 725 cpu_dumpsize(void) 726 { 727 728 return btodb(MDHDRSIZE); 729 } 730 731 /* 732 * Called by dumpsys() to dump the machine-dependent header. 733 */ 734 static int 735 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 736 { 737 int buf[MDHDRSIZE / sizeof(int)]; 738 cpu_kcore_hdr_t *chdr; 739 kcore_seg_t *kseg; 740 int error; 741 742 kseg = (kcore_seg_t *)buf; 743 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 744 sizeof(int)]; 745 746 /* Create the segment header. */ 747 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 748 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 749 750 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 751 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 752 *blknop += btodb(sizeof(buf)); 753 return error; 754 } 755 756 /* 757 * These variables are needed by /sbin/savecore 758 */ 759 uint32_t dumpmag = 0x8fca0101; /* magic number */ 760 int dumpsize = 0; /* pages */ 761 long dumplo = 0; /* blocks */ 762 763 /* 764 * This is called by main to set dumplo and dumpsize. 765 * Dumps always skip the first PAGE_SIZE of disk space 766 * in case there might be a disk label stored there. 767 * If there is extra space, put dump at the end to 768 * reduce the chance that swapping trashes it. 769 */ 770 void 771 cpu_dumpconf(void) 772 { 773 int chdrsize; /* size of dump header */ 774 int nblks; /* size of dump area */ 775 776 if (dumpdev == NODEV) 777 return; 778 nblks = bdev_size(dumpdev); 779 chdrsize = cpu_dumpsize(); 780 781 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); 782 783 /* 784 * Check do see if we will fit. Note we always skip the 785 * first PAGE_SIZE in case there is a disk label there. 786 */ 787 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 788 dumpsize = 0; 789 dumplo = -1; 790 return; 791 } 792 793 /* 794 * Put dump at the end of the partition. 795 */ 796 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 797 } 798 799 /* 800 * Dump physical memory onto the dump device. Called by cpu_reboot(). 801 */ 802 void 803 dumpsys(void) 804 { 805 const struct bdevsw *bdev; 806 daddr_t blkno; /* current block to write */ 807 /* dump routine */ 808 int (*dump)(dev_t, daddr_t, void *, size_t); 809 int pg; /* page being dumped */ 810 paddr_t maddr; /* PA being dumped */ 811 int error; /* error code from (*dump)() */ 812 813 /* XXX initialized here because of gcc lossage */ 814 maddr = lowram; 815 pg = 0; 816 817 /* Make sure dump device is valid. */ 818 if (dumpdev == NODEV) 819 return; 820 bdev = bdevsw_lookup(dumpdev); 821 if (bdev == NULL) 822 return; 823 if (dumpsize == 0) { 824 cpu_dumpconf(); 825 if (dumpsize == 0) 826 return; 827 } 828 if (dumplo <= 0) { 829 printf("\ndump to dev %u,%u not possible\n", 830 major(dumpdev), minor(dumpdev)); 831 return; 832 } 833 dump = bdev->d_dump; 834 blkno = dumplo; 835 836 printf("\ndumping to dev %u,%u offset %ld\n", 837 major(dumpdev), minor(dumpdev), dumplo); 838 839 printf("dump "); 840 841 /* Write the dump header. */ 842 error = cpu_dump(dump, &blkno); 843 if (error) 844 goto bad; 845 846 for (pg = 0; pg < dumpsize; pg++) { 847 #define NPGMB (1024*1024/PAGE_SIZE) 848 /* print out how many MBs we have dumped */ 849 if (pg && (pg % NPGMB) == 0) 850 printf("%d ", pg / NPGMB); 851 #undef NPGMB 852 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 853 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 854 855 pmap_update(pmap_kernel()); 856 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 857 bad: 858 switch (error) { 859 case 0: 860 maddr += PAGE_SIZE; 861 blkno += btodb(PAGE_SIZE); 862 break; 863 864 case ENXIO: 865 printf("device bad\n"); 866 return; 867 868 case EFAULT: 869 printf("device not ready\n"); 870 return; 871 872 case EINVAL: 873 printf("area improper\n"); 874 return; 875 876 case EIO: 877 printf("i/o error\n"); 878 return; 879 880 case EINTR: 881 printf("aborted from console\n"); 882 return; 883 884 default: 885 printf("error %d\n", error); 886 return; 887 } 888 } 889 printf("succeeded\n"); 890 } 891 892 static void 893 initcpu(void) 894 { 895 896 parityenable(); 897 #ifdef USELEDS 898 ledinit(); 899 #endif 900 } 901 902 void 903 straytrap(int pc, u_short evec) 904 { 905 printf("unexpected trap (vector offset %x) from %x\n", 906 evec & 0xFFF, pc); 907 } 908 909 /* XXX should change the interface, and make one badaddr() function */ 910 911 int *nofault; 912 913 int 914 badaddr(void *addr) 915 { 916 int i; 917 label_t faultbuf; 918 919 nofault = (int *)&faultbuf; 920 if (setjmp((label_t *)nofault)) { 921 nofault = (int *)0; 922 return 1; 923 } 924 i = *(volatile short *)addr; 925 __USE(i); 926 nofault = (int *)0; 927 return 0; 928 } 929 930 int 931 badbaddr(void *addr) 932 { 933 int i; 934 label_t faultbuf; 935 936 nofault = (int *)&faultbuf; 937 if (setjmp((label_t *)nofault)) { 938 nofault = (int *)0; 939 return 1; 940 } 941 i = *(volatile char *)addr; 942 __USE(i); 943 nofault = (int *) 0; 944 return 0; 945 } 946 947 /* 948 * lookup_bootinfo: 949 * 950 * Look up information in bootinfo from boot loader. 951 */ 952 void * 953 lookup_bootinfo(int type) 954 { 955 struct btinfo_common *bt; 956 char *help = (char *)bootinfo_va; 957 958 /* Check for a bootinfo record first. */ 959 if (help == NULL) 960 return NULL; 961 962 do { 963 bt = (struct btinfo_common *)help; 964 if (bt->type == type) 965 return help; 966 help += bt->next; 967 } while (bt->next != 0 && 968 (size_t)help < (size_t)bootinfo_va + BOOTINFO_SIZE); 969 970 return NULL; 971 } 972 973 #if defined(PANICBUTTON) && !defined(DDB) 974 /* 975 * Declare these so they can be patched. 976 */ 977 int panicbutton = 1; /* non-zero if panic buttons are enabled */ 978 int candbdiv = 2; /* give em half a second (hz / candbdiv) */ 979 980 static void candbtimer(void *); 981 982 int crashandburn; 983 984 callout_t candbtimer_ch; 985 986 void 987 candbtimer(void *arg) 988 { 989 990 crashandburn = 0; 991 } 992 #endif /* PANICBUTTON & !DDB */ 993 994 static int innmihand; /* simple mutex */ 995 996 /* 997 * Level 7 interrupts can be caused by HIL keyboards (in cooked mode only, 998 * but we run them in raw mode) or parity errors. 999 */ 1000 void 1001 nmihand(struct frame frame) 1002 { 1003 1004 /* Prevent unwanted recursion. */ 1005 if (innmihand) 1006 return; 1007 innmihand = 1; 1008 1009 if (parityerror(&frame)) 1010 return; 1011 /* panic?? */ 1012 printf("unexpected level 7 interrupt ignored\n"); 1013 1014 innmihand = 0; 1015 } 1016 1017 /* 1018 * Parity error section. Contains magic. 1019 */ 1020 #define PARREG ((volatile short *)IIOV(0x5B0000)) 1021 static int gotparmem = 0; 1022 #ifdef DEBUG 1023 int ignorekperr = 0; /* ignore kernel parity errors */ 1024 #endif 1025 1026 /* 1027 * Enable parity detection 1028 */ 1029 static void 1030 parityenable(void) 1031 { 1032 label_t faultbuf; 1033 1034 nofault = (int *)&faultbuf; 1035 if (setjmp((label_t *)nofault)) { 1036 nofault = (int *)0; 1037 printf("Parity detection disabled\n"); 1038 return; 1039 } 1040 *PARREG = 1; 1041 nofault = (int *)0; 1042 gotparmem = 1; 1043 } 1044 1045 /* 1046 * Determine if level 7 interrupt was caused by a parity error 1047 * and deal with it if it was. Returns 1 if it was a parity error. 1048 */ 1049 static int 1050 parityerror(struct frame *fp) 1051 { 1052 if (!gotparmem) 1053 return 0; 1054 *PARREG = 0; 1055 DELAY(10); 1056 *PARREG = 1; 1057 if (panicstr) { 1058 printf("parity error after panic ignored\n"); 1059 return 1; 1060 } 1061 if (!parityerrorfind()) 1062 printf("WARNING: transient parity error ignored\n"); 1063 else if (USERMODE(fp->f_sr)) { 1064 printf("pid %d: parity error\n", curproc->p_pid); 1065 uprintf("sorry, pid %d killed due to memory parity error\n", 1066 curproc->p_pid); 1067 psignal(curproc, SIGKILL); 1068 #ifdef DEBUG 1069 } else if (ignorekperr) { 1070 printf("WARNING: kernel parity error ignored\n"); 1071 #endif 1072 } else { 1073 regdump((struct trapframe *)fp, 128); 1074 panic("kernel parity error"); 1075 } 1076 return 1; 1077 } 1078 1079 /* 1080 * Yuk! There has got to be a better way to do this! 1081 * Searching all of memory with interrupts blocked can lead to disaster. 1082 */ 1083 static int 1084 parityerrorfind(void) 1085 { 1086 static label_t parcatch; 1087 static int looking = 0; 1088 volatile int pg, o, s; 1089 volatile int *ip; 1090 int i; 1091 int found; 1092 1093 /* 1094 * If looking is true we are searching for a known parity error 1095 * and it has just occurred. All we do is return to the higher 1096 * level invocation. 1097 */ 1098 if (looking) 1099 longjmp(&parcatch); 1100 s = splhigh(); 1101 /* 1102 * If setjmp returns true, the parity error we were searching 1103 * for has just occurred (longjmp above) at the current pg+o 1104 */ 1105 if (setjmp(&parcatch)) { 1106 printf("Parity error at 0x%x\n", ctob(pg)|o); 1107 found = 1; 1108 goto done; 1109 } 1110 /* 1111 * If we get here, a parity error has occurred for the first time 1112 * and we need to find it. We turn off any external caches and 1113 * loop thru memory, testing every longword til a fault occurs and 1114 * we regain control at setjmp above. Note that because of the 1115 * setjmp, pg and o need to be volatile or their values will be lost. 1116 */ 1117 looking = 1; 1118 ecacheoff(); 1119 for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) { 1120 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, ctob(pg), 1121 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 1122 pmap_update(pmap_kernel()); 1123 ip = (int *)vmmap; 1124 for (o = 0; o < PAGE_SIZE; o += sizeof(int)) 1125 i = *ip++; 1126 } 1127 __USE(i); 1128 /* 1129 * Getting here implies no fault was found. Should never happen. 1130 */ 1131 printf("Couldn't locate parity error\n"); 1132 found = 0; 1133 done: 1134 looking = 0; 1135 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, (vaddr_t)&vmmap[PAGE_SIZE]); 1136 pmap_update(pmap_kernel()); 1137 ecacheon(); 1138 splx(s); 1139 return found; 1140 } 1141 1142 /* 1143 * cpu_exec_aout_makecmds(): 1144 * CPU-dependent a.out format hook for execve(). 1145 * 1146 * Determine of the given exec package refers to something which we 1147 * understand and, if so, set up the vmcmds for it. 1148 * 1149 * XXX what are the special cases for the hp300? 1150 * XXX why is this COMPAT_NOMID? was something generating 1151 * hp300 binaries with an a_mid of 0? i thought that was only 1152 * done on little-endian machines... -- cgd 1153 */ 1154 int 1155 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 1156 { 1157 #if defined(COMPAT_NOMID) || defined(COMPAT_44) 1158 u_long midmag, magic; 1159 u_short mid; 1160 int error; 1161 struct exec *execp = epp->ep_hdr; 1162 1163 midmag = ntohl(execp->a_midmag); 1164 mid = (midmag >> 16) & 0xffff; 1165 magic = midmag & 0xffff; 1166 1167 midmag = mid << 16 | magic; 1168 1169 switch (midmag) { 1170 #ifdef COMPAT_NOMID 1171 case (MID_ZERO << 16) | ZMAGIC: 1172 error = exec_aout_prep_oldzmagic(l, epp); 1173 return error; 1174 #endif 1175 #ifdef COMPAT_44 1176 case (MID_HP300 << 16) | ZMAGIC: 1177 error = exec_aout_prep_oldzmagic(l, epp); 1178 return error; 1179 #endif 1180 } 1181 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */ 1182 1183 return ENOEXEC; 1184 } 1185 1186 int 1187 mm_md_physacc(paddr_t pa, vm_prot_t prot) 1188 { 1189 1190 /* 1191 * On the hp300, physical RAM is always located at the end of 1192 * the physical address space, i.e. from 0xffffffff to lowram. 1193 */ 1194 return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0; 1195 } 1196 1197 int 1198 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) 1199 { 1200 1201 /* 1202 * Do not allow reading intio or dio device space. This could lead 1203 * to corruption of device registers. 1204 */ 1205 *handled = false; 1206 return (ISIIOVA(ptr) || ((uint8_t *)ptr >= extiobase && 1207 (uint8_t *)ptr < extiobase + (EIOMAPSIZE * PAGE_SIZE))) 1208 ? EFAULT : 0; 1209 } 1210 1211 #ifdef MODULAR 1212 /* 1213 * Push any modules loaded by the bootloader etc. 1214 */ 1215 void 1216 module_init_md(void) 1217 { 1218 } 1219 #endif 1220