1 /* $NetBSD: machdep.c,v 1.165 2024/03/05 14:15:33 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.165 2024/03/05 14:15:33 thorpej Exp $"); 43 44 #include "opt_ddb.h" 45 #include "opt_m060sp.h" 46 #include "opt_modular.h" 47 #include "opt_panicbutton.h" 48 #include "opt_m68k_arch.h" 49 #include "opt_mvmeconf.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/signalvar.h> 54 #include <sys/kernel.h> 55 #include <sys/proc.h> 56 #include <sys/buf.h> 57 #include <sys/reboot.h> 58 #include <sys/conf.h> 59 #include <sys/file.h> 60 #include <sys/mbuf.h> 61 #include <sys/msgbuf.h> 62 #include <sys/ioctl.h> 63 #include <sys/tty.h> 64 #include <sys/mount.h> 65 #include <sys/exec.h> 66 #include <sys/exec_aout.h> /* for MID_* */ 67 #include <sys/core.h> 68 #include <sys/kcore.h> 69 #include <sys/vnode.h> 70 #include <sys/syscallargs.h> 71 #include <sys/ksyms.h> 72 #include <sys/module.h> 73 #include <sys/device.h> 74 #include <sys/cpu.h> 75 76 #include "ksyms.h" 77 78 #if NKSYMS || defined(DDB) || defined(MODULAR) 79 #include <sys/exec_elf.h> 80 #endif 81 82 #include <uvm/uvm_extern.h> 83 84 #include <sys/sysctl.h> 85 86 #include <machine/cpu.h> 87 #define _MVME68K_BUS_DMA_PRIVATE 88 #include <machine/bus.h> 89 #undef _MVME68K_BUS_DMA_PRIVATE 90 #include <machine/pcb.h> 91 #include <machine/prom.h> 92 #include <machine/psl.h> 93 #include <machine/pte.h> 94 #include <machine/vmparam.h> 95 #include <m68k/include/cacheops.h> 96 #include <dev/cons.h> 97 #include <dev/mm.h> 98 99 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 100 101 #include <mvme68k/dev/mainbus.h> 102 #include <mvme68k/mvme68k/seglist.h> 103 104 #ifdef DDB 105 #include <machine/db_machdep.h> 106 #include <ddb/db_extern.h> 107 #include <ddb/db_output.h> 108 #endif 109 110 #define MAXMEM 64*1024 /* XXX - from cmap.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 /* 121 * Model information, filled in by the Bug; see locore.s 122 */ 123 struct mvmeprom_brdid boardid; 124 125 paddr_t msgbufpa; /* PA of message buffer */ 126 127 int maxmem; /* max memory per process */ 128 129 /* 130 * The driver for the ethernet chip appropriate to the 131 * platform (lance or i82586) will use this variable 132 * to size the chip's packet buffer. 133 */ 134 #ifndef ETHER_DATA_BUFF_PAGES 135 #define ETHER_DATA_BUFF_PAGES 4 136 #endif 137 u_long ether_data_buff_size = ETHER_DATA_BUFF_PAGES * PAGE_SIZE; 138 uint8_t mvme_ea[6]; 139 140 extern u_int lowram; 141 extern short exframesize[]; 142 143 /* prototypes for local functions */ 144 void identifycpu(void); 145 void initcpu(void); 146 void dumpsys(void); 147 148 int cpu_dumpsize(void); 149 int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 150 void cpu_init_kcore_hdr(void); 151 u_long cpu_dump_mempagecnt(void); 152 int cpu_exec_aout_makecmds(struct lwp *, struct exec_package *); 153 void straytrap(int, u_short); 154 155 /* 156 * Machine-independent crash dump header info. 157 */ 158 cpu_kcore_hdr_t cpu_kcore_hdr; 159 160 /* 161 * Memory segments initialized in locore, which are eventually loaded 162 * as managed VM pages. 163 */ 164 phys_seg_list_t phys_seg_list[VM_PHYSSEG_MAX]; 165 166 /* 167 * Memory segments to dump. This is initialized from the phys_seg_list 168 * before pages are stolen from it for VM system overhead. I.e. this 169 * covers the entire range of physical memory. 170 */ 171 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 172 int mem_cluster_cnt; 173 174 /* 175 * On the 68020/68030 (mvme14x), the value of delay_divisor is roughly 176 * 8192 / cpuspeed (where cpuspeed is in MHz). 177 * 178 * On the other boards (mvme162 and up), the cpuspeed is passed 179 * in from the firmware. 180 */ 181 int cpuspeed; /* only used for printing later */ 182 int delay_divisor = 512; /* assume some reasonable value to start */ 183 184 /* Machine-dependent initialization routines. */ 185 void mvme68k_init(void); 186 187 #ifdef MVME147 188 #include <mvme68k/dev/pccreg.h> 189 void mvme147_init(void); 190 #endif 191 192 #if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 193 #include <dev/mvme/pcctworeg.h> 194 void mvme1xx_init(void); 195 #endif 196 197 /* 198 * Early initialization, right before main is called. 199 */ 200 void 201 mvme68k_init(void) 202 { 203 int i; 204 205 /* 206 * Since mvme68k boards can have anything from 4MB of onboard RAM, we 207 * would rather set the pager_map_size at runtime based on the amount 208 * of onboard RAM. 209 * 210 * Set pager_map_size to half the size of onboard RAM, up to a 211 * maximum of 16MB. 212 * (Note: Just use ps_end here since onboard RAM starts at 0x0) 213 */ 214 pager_map_size = phys_seg_list[0].ps_end / 2; 215 if (pager_map_size > (16 * 1024 * 1024)) 216 pager_map_size = 16 * 1024 * 1024; 217 218 /* 219 * Tell the VM system about available physical memory. 220 */ 221 for (i = 0; i < mem_cluster_cnt; i++) { 222 if (phys_seg_list[i].ps_start == phys_seg_list[i].ps_end) { 223 /* 224 * Segment has been completely gobbled up. 225 */ 226 continue; 227 } 228 /* 229 * Note the index of the mem cluster is the free 230 * list we want to put the memory on (0 == default, 231 * 1 == VME). There can only be two. 232 */ 233 uvm_page_physload(atop(phys_seg_list[i].ps_start), 234 atop(phys_seg_list[i].ps_end), 235 atop(phys_seg_list[i].ps_start), 236 atop(phys_seg_list[i].ps_end), i); 237 } 238 239 switch (machineid) { 240 #ifdef MVME147 241 case MVME_147: 242 mvme147_init(); 243 break; 244 #endif 245 #ifdef MVME167 246 case MVME_167: 247 #endif 248 #ifdef MVME162 249 case MVME_162: 250 #endif 251 #ifdef MVME177 252 case MVME_177: 253 #endif 254 #ifdef MVME172 255 case MVME_172: 256 #endif 257 #if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 258 mvme1xx_init(); 259 break; 260 #endif 261 default: 262 panic("%s: impossible machineid", __func__); 263 } 264 265 /* 266 * Initialize error message buffer (at end of core). 267 */ 268 for (i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) 269 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE, 270 msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 271 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 272 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 273 pmap_update(pmap_kernel()); 274 } 275 276 #ifdef MVME147 277 /* 278 * MVME-147 specific initialization. 279 */ 280 void 281 mvme147_init(void) 282 { 283 bus_space_tag_t bt = &_mainbus_space_tag; 284 bus_space_handle_t bh; 285 286 /* 287 * Set up a temporary mapping to the PCC's registers 288 */ 289 bus_space_map(bt, intiobase_phys + MAINBUS_PCC_OFFSET, PCCREG_SIZE, 0, 290 &bh); 291 292 /* 293 * calibrate delay() using the 6.25 usec counter. 294 * we adjust the delay_divisor until we get the result we want. 295 */ 296 bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERCLEAR); 297 bus_space_write_2(bt, bh, PCCREG_TMR1_PRELOAD, 0); 298 bus_space_write_1(bt, bh, PCCREG_TMR1_INTR_CTRL, 0); 299 300 for (delay_divisor = 512; delay_divisor > 0; delay_divisor--) { 301 bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERSTART); 302 delay(10000); 303 bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERSTOP); 304 305 /* 1600 * 6.25usec == 10000usec */ 306 if (bus_space_read_2(bt, bh, PCCREG_TMR1_COUNT) > 1600) 307 break; /* got it! */ 308 309 bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERCLEAR); 310 /* retry! */ 311 } 312 /* just in case */ 313 if (delay_divisor == 0) { 314 delay_divisor = 1; 315 } 316 317 bus_space_unmap(bt, bh, PCCREG_SIZE); 318 319 /* calculate cpuspeed */ 320 cpuspeed = 8192 / delay_divisor; 321 cpuspeed *= 100; 322 } 323 #endif /* MVME147 */ 324 325 #if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 326 int get_cpuspeed(void); 327 328 /* 329 * MVME-1[67]x specific initialization. 330 */ 331 void 332 mvme1xx_init(void) 333 { 334 bus_space_tag_t bt = &_mainbus_space_tag; 335 bus_space_handle_t bh; 336 337 /* 338 * Set up a temporary mapping to the PCCChip2's registers 339 */ 340 bus_space_map(bt, 341 intiobase_phys + MAINBUS_PCCTWO_OFFSET + PCCTWO_REG_OFF, 342 PCC2REG_SIZE, 0, &bh); 343 344 bus_space_write_1(bt, bh, PCC2REG_TIMER1_ICSR, 0); 345 346 for (delay_divisor = (cputype == CPU_68060) ? 20 : 154; 347 delay_divisor > 0; delay_divisor--) { 348 bus_space_write_4(bt, bh, PCC2REG_TIMER1_COUNTER, 0); 349 bus_space_write_1(bt, bh, PCC2REG_TIMER1_CONTROL, 350 PCCTWO_TT_CTRL_CEN); 351 delay(10000); 352 bus_space_write_1(bt, bh, PCC2REG_TIMER1_CONTROL, 0); 353 if (bus_space_read_4(bt, bh, PCC2REG_TIMER1_COUNTER) > 10000) 354 break; /* got it! */ 355 } 356 357 bus_space_unmap(bt, bh, PCC2REG_SIZE); 358 359 /* calculate cpuspeed */ 360 cpuspeed = get_cpuspeed(); 361 if (cpuspeed < 1250 || cpuspeed > 6000) { 362 printf("%s: Warning! Firmware has " \ 363 "bogus CPU speed: `%s'\n", __func__, boardid.speed); 364 cpuspeed = ((cputype == CPU_68060) ? 1000 : 3072) / 365 delay_divisor; 366 cpuspeed *= 100; 367 printf("%s: Approximating speed using delay_divisor\n", 368 __func__); 369 } 370 } 371 372 /* 373 * Parse the `speed' field of Bug's boardid structure. 374 */ 375 int 376 get_cpuspeed(void) 377 { 378 int rv, i; 379 380 for (i = 0, rv = 0; i < sizeof(boardid.speed); i++) { 381 if (boardid.speed[i] < '0' || boardid.speed[i] > '9') 382 return 0; 383 rv = (rv * 10) + (boardid.speed[i] - '0'); 384 } 385 386 return rv; 387 } 388 #endif 389 390 /* 391 * Console initialization: called early on from main, 392 * before vm init or startup. Do enough configuration 393 * to choose and initialize a console. 394 */ 395 void 396 consinit(void) 397 { 398 399 /* 400 * Initialize the console before we print anything out. 401 */ 402 cninit(); 403 404 #if NKSYMS || defined(DDB) || defined(MODULAR) 405 { 406 extern char end[]; 407 extern int *esym; 408 409 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 410 (void *)&end, esym); 411 } 412 #endif 413 #ifdef DDB 414 if (boothowto & RB_KDB) 415 Debugger(); 416 #endif 417 } 418 419 /* 420 * cpu_startup: allocate memory for variable-sized tables, 421 * initialize CPU, and do autoconfiguration. 422 */ 423 void 424 cpu_startup(void) 425 { 426 u_quad_t vmememsize; 427 vaddr_t minaddr, maxaddr; 428 char pbuf[9]; 429 u_int i; 430 #ifdef DEBUG 431 extern int pmapdebug; 432 int opmapdebug = pmapdebug; 433 434 pmapdebug = 0; 435 #endif 436 437 /* 438 * If we have an FPU, initialise the cached idle frame 439 */ 440 if (fputype != FPU_NONE) 441 m68k_make_fpu_idle_frame(); 442 443 /* 444 * Initialize the kernel crash dump header. 445 */ 446 cpu_init_kcore_hdr(); 447 448 /* 449 * Good {morning,afternoon,evening,night}. 450 */ 451 printf("%s%s", copyright, version); 452 identifycpu(); 453 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 454 printf("total memory = %s", pbuf); 455 456 for (vmememsize = 0, i = 1; i < mem_cluster_cnt; i++) 457 vmememsize += mem_clusters[i].size; 458 if (vmememsize != 0) { 459 format_bytes(pbuf, sizeof(pbuf), mem_clusters[0].size); 460 printf(" (%s on-board", pbuf); 461 format_bytes(pbuf, sizeof(pbuf), vmememsize); 462 printf(", %s VMEbus)", pbuf); 463 } 464 465 printf("\n"); 466 467 minaddr = 0; 468 /* 469 * Allocate a submap for physio 470 */ 471 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 472 VM_PHYS_SIZE, 0, false, NULL); 473 474 #ifdef DEBUG 475 pmapdebug = opmapdebug; 476 #endif 477 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 478 printf("avail memory = %s\n", pbuf); 479 480 /* 481 * Set up CPU-specific registers, cache, etc. 482 */ 483 initcpu(); 484 } 485 486 void 487 identifycpu(void) 488 { 489 char board_str[16]; 490 const char *cpu_str, *mmu_str, *fpu_str, *cache_str; 491 492 /* Fill in the CPU string. */ 493 switch (cputype) { 494 #ifdef M68020 495 case CPU_68020: 496 cpu_str = "MC68020 CPU"; 497 fpu_str = ", MC68881 FPU"; /* XXX */ 498 break; 499 #endif 500 501 #ifdef M68030 502 case CPU_68030: 503 cpu_str = "MC68030 CPU+MMU"; 504 fpu_str = ", MC68882 FPU"; /* XXX */ 505 break; 506 #endif 507 508 #ifdef M68040 509 case CPU_68040: 510 cpu_str = "MC68040 CPU+MMU+FPU"; 511 fpu_str = ""; 512 break; 513 #endif 514 515 #ifdef M68060 516 case CPU_68060: 517 cpu_str = "MC68060 CPU+MMU+FPU"; 518 fpu_str = ""; 519 break; 520 #endif 521 522 default: 523 printf("unknown CPU type"); 524 panic("startup"); 525 } 526 527 /* Fill in the MMU string; only need to handle one case. */ 528 switch (mmutype) { 529 case MMU_68851: 530 mmu_str = ", MC68851 MMU"; 531 break; 532 default: 533 mmu_str = ""; 534 break; 535 } 536 537 /* Fill in board model string. */ 538 switch (machineid) { 539 #if defined(MVME_147) || defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) 540 case MVME_147: 541 case MVME_162: 542 case MVME_167: 543 case MVME_172: 544 case MVME_177: 545 { 546 char *suffix = (char *)&boardid.suffix; 547 int len = snprintf(board_str, sizeof(board_str), "%x", 548 machineid); 549 if (suffix[0] != '\0' && len > 0 && 550 len + 3 < sizeof(board_str)) { 551 board_str[len++] = suffix[0]; 552 if (suffix[1] != '\0') 553 board_str[len++] = suffix[1]; 554 board_str[len] = '\0'; 555 } 556 break; 557 } 558 #endif 559 default: 560 printf("unknown machine type: 0x%x\n", machineid); 561 panic("startup"); 562 } 563 564 switch (cputype) { 565 #if defined(M68040) 566 case CPU_68040: 567 cache_str = ", 4k+4k on-chip physical I/D caches"; 568 break; 569 #endif 570 #if defined(M68060) 571 case CPU_68060: 572 cache_str = ", 8k+8k on-chip physical I/D caches"; 573 break; 574 #endif 575 default: 576 cache_str = ""; 577 break; 578 } 579 580 cpu_setmodel("Motorola MVME-%s: %d.%dMHz %s%s%s%s", 581 board_str, cpuspeed / 100, (cpuspeed % 100) / 10, cpu_str, 582 mmu_str, fpu_str, cache_str); 583 584 cpuspeed /= 100; 585 586 printf("%s\n", cpu_getmodel()); 587 } 588 589 /* 590 * machine dependent system variables. 591 */ 592 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 593 { 594 595 sysctl_createv(clog, 0, NULL, NULL, 596 CTLFLAG_PERMANENT, 597 CTLTYPE_NODE, "machdep", NULL, 598 NULL, 0, NULL, 0, 599 CTL_MACHDEP, CTL_EOL); 600 601 sysctl_createv(clog, 0, NULL, NULL, 602 CTLFLAG_PERMANENT, 603 CTLTYPE_STRUCT, "console_device", NULL, 604 sysctl_consdev, 0, NULL, sizeof(dev_t), 605 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 606 } 607 608 /* See: sig_machdep.c */ 609 610 int waittime = -1; 611 612 void 613 cpu_reboot(int howto, char *bootstr) 614 { 615 struct pcb *pcb = lwp_getpcb(curlwp); 616 617 /* take a snap shot before clobbering any registers */ 618 if (pcb != NULL) 619 savectx(pcb); 620 621 /* Save the RB_SBOOT flag. */ 622 howto |= (boothowto & RB_SBOOT); 623 624 /* If system is hold, just halt. */ 625 if (cold) { 626 howto |= RB_HALT; 627 goto haltsys; 628 } 629 630 boothowto = howto; 631 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 632 waittime = 0; 633 vfs_shutdown(); 634 } 635 636 /* Disable interrupts. */ 637 splhigh(); 638 639 /* If rebooting and a dump is requested, do it. */ 640 if (howto & RB_DUMP) 641 dumpsys(); 642 643 haltsys: 644 /* Run any shutdown hooks. */ 645 doshutdownhooks(); 646 647 pmf_system_shutdown(boothowto); 648 649 #if defined(PANICWAIT) && !defined(DDB) 650 if ((howto & RB_HALT) == 0 && panicstr) { 651 printf("hit any key to reboot...\n"); 652 cnpollc(1); 653 (void)cngetc(); 654 cnpollc(0); 655 printf("\n"); 656 } 657 #endif 658 659 /* Finally, halt/reboot the system. */ 660 if (howto & RB_HALT) { 661 printf("halted\n\n"); 662 doboot(RB_HALT); 663 /* NOTREACHED */ 664 } 665 666 printf("rebooting...\n"); 667 delay(1000000); 668 doboot(RB_AUTOBOOT); 669 /*NOTREACHED*/ 670 } 671 672 /* 673 * Initialize the kernel crash dump header. 674 */ 675 void 676 cpu_init_kcore_hdr(void) 677 { 678 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 679 struct m68k_kcore_hdr *m = &h->un._m68k; 680 int i; 681 extern char end[]; 682 683 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 684 685 /* 686 * Initialize the `dispatcher' portion of the header. 687 */ 688 strcpy(h->name, machine); 689 h->page_size = PAGE_SIZE; 690 h->kernbase = KERNBASE; 691 692 /* 693 * Fill in information about our MMU configuration. 694 */ 695 m->mmutype = mmutype; 696 m->sg_v = SG_V; 697 m->sg_frame = SG_FRAME; 698 m->sg_ishift = SG_ISHIFT; 699 m->sg_pmask = SG_PMASK; 700 m->sg40_shift1 = SG4_SHIFT1; 701 m->sg40_mask2 = SG4_MASK2; 702 m->sg40_shift2 = SG4_SHIFT2; 703 m->sg40_mask3 = SG4_MASK3; 704 m->sg40_shift3 = SG4_SHIFT3; 705 m->sg40_addr1 = SG4_ADDR1; 706 m->sg40_addr2 = SG4_ADDR2; 707 m->pg_v = PG_V; 708 m->pg_frame = PG_FRAME; 709 710 /* 711 * Initialize pointer to kernel segment table. 712 */ 713 m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); 714 715 /* 716 * Initialize relocation value such that: 717 * 718 * pa = (va - KERNBASE) + reloc 719 * 720 * Since we're linked and loaded at the same place, 721 * and the kernel is mapped va == pa, this is 0. 722 */ 723 m->reloc = 0; 724 725 /* 726 * Define the end of the relocatable range. 727 */ 728 m->relocend = (uint32_t)end; 729 730 /* 731 * The mvme68k has one or two memory segments. 732 */ 733 for (i = 0; i < mem_cluster_cnt; i++) { 734 m->ram_segs[i].start = mem_clusters[i].start; 735 m->ram_segs[i].size = mem_clusters[i].size; 736 } 737 } 738 739 /* 740 * Compute the size of the machine-dependent crash dump header. 741 * Returns size in disk blocks. 742 */ 743 744 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 745 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 746 747 int 748 cpu_dumpsize(void) 749 { 750 751 return btodb(MDHDRSIZE); 752 } 753 754 /* 755 * Calculate size of RAM (in pages) to be dumped. 756 */ 757 u_long 758 cpu_dump_mempagecnt(void) 759 { 760 u_long i, n; 761 762 n = 0; 763 for (i = 0; i < mem_cluster_cnt; i++) 764 n += atop(mem_clusters[i].size); 765 return n; 766 } 767 768 /* 769 * Called by dumpsys() to dump the machine-dependent header. 770 */ 771 int 772 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 773 { 774 int buf[MDHDRSIZE / sizeof(int)]; 775 cpu_kcore_hdr_t *chdr; 776 kcore_seg_t *kseg; 777 int error; 778 779 kseg = (kcore_seg_t *)buf; 780 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 781 sizeof(int)]; 782 783 /* Create the segment header. */ 784 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 785 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 786 787 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 788 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 789 *blknop += btodb(sizeof(buf)); 790 return error; 791 } 792 793 /* 794 * These variables are needed by /sbin/savecore 795 */ 796 uint32_t dumpmag = 0x8fca0101; /* magic number */ 797 int dumpsize = 0; /* pages */ 798 long dumplo = 0; /* blocks */ 799 800 /* 801 * This is called by main to set dumplo and dumpsize. 802 * Dumps always skip the first PAGE_SIZE of disk space 803 * in case there might be a disk label stored there. 804 * If there is extra space, put dump at the end to 805 * reduce the chance that swapping trashes it. 806 */ 807 void 808 cpu_dumpconf(void) 809 { 810 int nblks, dumpblks; /* size of dump area */ 811 812 if (dumpdev == NODEV) 813 goto bad; 814 nblks = bdev_size(dumpdev); 815 if (nblks <= ctod(1)) 816 goto bad; 817 818 dumpblks = cpu_dumpsize(); 819 if (dumpblks < 0) 820 goto bad; 821 dumpblks += ctod(cpu_dump_mempagecnt()); 822 823 /* If dump won't fit (incl. room for possible label), punt. */ 824 if (dumpblks > (nblks - ctod(1))) 825 goto bad; 826 827 /* Put dump at end of partition */ 828 dumplo = nblks - dumpblks; 829 830 /* dumpsize is in page units, and doesn't include headers. */ 831 dumpsize = cpu_dump_mempagecnt(); 832 return; 833 834 bad: 835 dumpsize = 0; 836 } 837 838 /* 839 * Dump physical memory onto the dump device. Called by cpu_reboot(). 840 */ 841 void 842 dumpsys(void) 843 { 844 const struct bdevsw *bdev; 845 u_long totalbytesleft, bytes, i, n, memcl; 846 u_long maddr; 847 int psize; 848 daddr_t blkno; 849 int (*dump)(dev_t, daddr_t, void *, size_t); 850 int error; 851 852 /* XXX Should save registers. */ 853 854 if (dumpdev == NODEV) 855 return; 856 bdev = bdevsw_lookup(dumpdev); 857 if (bdev == NULL || bdev->d_psize == NULL) 858 return; 859 860 /* 861 * For dumps during autoconfiguration, 862 * if dump device has already configured... 863 */ 864 if (dumpsize == 0) 865 cpu_dumpconf(); 866 if (dumplo <= 0) { 867 printf("\ndump to dev %u,%u not possible\n", 868 major(dumpdev), minor(dumpdev)); 869 return; 870 } 871 printf("\ndumping to dev %u,%u offset %ld\n", 872 major(dumpdev), minor(dumpdev), dumplo); 873 874 psize = bdev_size(dumpdev); 875 printf("dump "); 876 if (psize == -1) { 877 printf("area unavailable\n"); 878 return; 879 } 880 881 /* XXX should purge all outstanding keystrokes. */ 882 883 dump = bdev->d_dump; 884 blkno = dumplo; 885 886 if ((error = cpu_dump(dump, &blkno)) != 0) 887 goto err; 888 889 totalbytesleft = ptoa(cpu_dump_mempagecnt()); 890 891 for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { 892 maddr = mem_clusters[memcl].start; 893 bytes = mem_clusters[memcl].size; 894 895 for (i = 0; i < bytes; i += n, totalbytesleft -= n) { 896 897 /* Print out how many MBs we have left to go. */ 898 if ((totalbytesleft % (1024*1024)) == 0) 899 printf_nolog("%ld ", 900 totalbytesleft / (1024 * 1024)); 901 902 /* Limit size for next transfer. */ 903 n = bytes - i; 904 if (n > PAGE_SIZE) 905 n = PAGE_SIZE; 906 907 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 908 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 909 pmap_update(pmap_kernel()); 910 911 error = (*dump)(dumpdev, blkno, vmmap, n); 912 if (error) 913 goto err; 914 maddr += n; 915 blkno += btodb(n); 916 } 917 } 918 919 err: 920 switch (error) { 921 922 case ENXIO: 923 printf("device bad\n"); 924 break; 925 926 case EFAULT: 927 printf("device not ready\n"); 928 break; 929 930 case EINVAL: 931 printf("area improper\n"); 932 break; 933 934 case EIO: 935 printf("i/o error\n"); 936 break; 937 938 case EINTR: 939 printf("aborted from console\n"); 940 break; 941 942 case 0: 943 printf("succeeded\n"); 944 break; 945 946 default: 947 printf("error %d\n", error); 948 break; 949 } 950 printf("\n\n"); 951 delay(5000); 952 } 953 954 void 955 initcpu(void) 956 { 957 /* Nothing to do. */ 958 } 959 960 void 961 straytrap(int pc, u_short evec) 962 { 963 964 printf("unexpected trap (vector offset %x) from %x\n", 965 evec & 0xFFF, pc); 966 } 967 968 /* 969 * Level 7 interrupts are caused by e.g. the ABORT switch. 970 * 971 * If we have DDB, then break into DDB on ABORT. In a production 972 * environment, bumping the ABORT switch would be bad, so we enable 973 * panic'ing on ABORT with the kernel option "PANICBUTTON". 974 */ 975 int 976 nmihand(void *arg) 977 { 978 979 mvme68k_abort("ABORT SWITCH"); 980 981 return 1; 982 } 983 984 /* 985 * Common code for handling ABORT signals from buttons, switches, 986 * serial lines, etc. 987 */ 988 void 989 mvme68k_abort(const char *cp) 990 { 991 992 #ifdef DDB 993 db_printf("%s\n", cp); 994 Debugger(); 995 #else 996 #ifdef PANICBUTTON 997 panic(cp); 998 #else 999 printf("%s ignored\n", cp); 1000 #endif /* PANICBUTTON */ 1001 #endif /* DDB */ 1002 } 1003 1004 /* 1005 * cpu_exec_aout_makecmds(): 1006 * CPU-dependent a.out format hook for execve(). 1007 * 1008 * Determine of the given exec package refers to something which we 1009 * understand and, if so, set up the vmcmds for it. 1010 */ 1011 int 1012 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 1013 { 1014 1015 return ENOEXEC; 1016 } 1017 1018 #ifdef MODULAR 1019 /* 1020 * Push any modules loaded by the bootloader etc. 1021 */ 1022 void 1023 module_init_md(void) 1024 { 1025 } 1026 #endif 1027 1028 int 1029 mm_md_physacc(paddr_t pa, vm_prot_t prot) 1030 { 1031 1032 return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0; 1033 } 1034