1/* $NetBSD: machdep.c,v 1.9 2024/03/05 14:15:36 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.9 2024/03/05 14:15:36 thorpej Exp $"); 43 44#include "opt_ddb.h" 45#include "opt_m060sp.h" 46#include "opt_modular.h" 47#include "opt_m68k_arch.h" 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/signalvar.h> 52#include <sys/kernel.h> 53#include <sys/proc.h> 54#include <sys/buf.h> 55#include <sys/reboot.h> 56#include <sys/conf.h> 57#include <sys/file.h> 58#include <sys/mbuf.h> 59#include <sys/msgbuf.h> 60#include <sys/ioctl.h> 61#include <sys/tty.h> 62#include <sys/mount.h> 63#include <sys/exec.h> 64#include <sys/exec_aout.h> /* for MID_* */ 65#include <sys/core.h> 66#include <sys/kcore.h> 67#include <sys/vnode.h> 68#include <sys/syscallargs.h> 69#include <sys/ksyms.h> 70#include <sys/module.h> 71#include <sys/device.h> 72#include <sys/cpu.h> 73#include <sys/boot_flag.h> 74 75#include "ksyms.h" 76 77#if NKSYMS || defined(DDB) || defined(MODULAR) 78#include <sys/exec_elf.h> 79#endif 80 81#include <uvm/uvm_extern.h> 82 83#include <sys/sysctl.h> 84 85#include <machine/bootinfo.h> 86#include <machine/cpu.h> 87#include <machine/bus.h> 88#include <machine/pcb.h> 89#include <machine/psl.h> 90#include <machine/pte.h> 91#include <machine/vmparam.h> 92#include <m68k/include/cacheops.h> 93#include <dev/cons.h> 94#include <dev/mm.h> 95 96#include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 97 98#ifdef DDB 99#include <machine/db_machdep.h> 100#include <ddb/db_extern.h> 101#include <ddb/db_output.h> 102#endif 103 104/* the following is used externally (sysctl_hw) */ 105char machine[] = MACHINE; /* from <machine/param.h> */ 106 107/* Our exported CPU info; we can have only one. */ 108struct cpu_info cpu_info_store; 109 110struct vm_map *phys_map = NULL; 111 112paddr_t msgbufpa; /* PA of message buffer */ 113 114// int maxmem; /* max memory per process */ 115 116extern short exframesize[]; 117 118/* prototypes for local functions */ 119void identifycpu(void); 120void initcpu(void); 121void dumpsys(void); 122 123int cpu_dumpsize(void); 124int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 125void cpu_init_kcore_hdr(void); 126u_long cpu_dump_mempagecnt(void); 127int cpu_exec_aout_makecmds(struct lwp *, struct exec_package *); 128void straytrap(int, u_short); 129 130/* 131 * Machine-independent crash dump header info. 132 */ 133cpu_kcore_hdr_t cpu_kcore_hdr; 134 135/* Machine-dependent initialization routines. */ 136void virt68k_init(void); 137 138/* 139 * Machine-dependent bootinfo "console attach" routine. 140 */ 141void 142bootinfo_md_cnattach(void (*func)(bus_space_tag_t, bus_space_handle_t), 143 paddr_t addr, paddr_t size) 144{ 145 extern struct virt68k_bus_space_tag _mainbus_space_tag; 146 extern paddr_t consdev_addr; 147 bus_space_tag_t bst = &_mainbus_space_tag; 148 bus_space_handle_t bsh; 149 150 if (bus_space_map(bst, addr, size, 0, &bsh) == 0) { 151 func(bst, bsh); 152 } 153 consdev_addr = addr; 154} 155 156/* 157 * Early initialization, right before main is called. 158 */ 159void 160virt68k_init(void) 161{ 162 int i; 163 164 /* 165 * Just use the default pager_map_size for now. We may decide 166 * to make it larger for large memory configs. 167 */ 168 169 /* 170 * Tell the VM system about available physical memory. 171 */ 172 for (i = 0; i < bootinfo_mem_nsegments_avail; i++) { 173 if (bootinfo_mem_segments_avail[i].mem_size < PAGE_SIZE) { 174 /* 175 * Segment has been completely gobbled up. 176 */ 177 continue; 178 } 179 180 paddr_t start = bootinfo_mem_segments_avail[i].mem_addr; 181 psize_t size = bootinfo_mem_segments_avail[i].mem_size; 182 183 printf("Memory segment %d: addr=0x%08lx size=0x%08lx\n", i, 184 start, size); 185 186 KASSERT(atop(start + size) == atop(start) + atop(size)); 187 188 uvm_page_physload(atop(start), 189 atop(start) + atop(size), 190 atop(start), 191 atop(start) + atop(size), 192 VM_FREELIST_DEFAULT); 193 } 194 195 /* 196 * Initialize error message buffer (just before kernel text). 197 */ 198 for (i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) { 199 pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 200 msgbufpa + i * PAGE_SIZE, 201 VM_PROT_READ|VM_PROT_WRITE, 0); 202 } 203 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 204 pmap_update(pmap_kernel()); 205 206 /* Check for RND seed from the loader. */ 207 bootinfo_setup_rndseed(); 208 209 char flags[32]; 210 if (bootinfo_getarg("flags", flags, sizeof(flags))) { 211 for (const char *cp = flags; *cp != '\0'; cp++) { 212 /* Consume 'm' in favor of BI_RAMDISK. */ 213 if (*cp == 'm') { 214 continue; 215 } 216 BOOT_FLAG(*cp, boothowto); 217 } 218 } 219} 220 221/* 222 * Console initialization: called early on from main, 223 * before vm init or startup. Do enough configuration 224 * to choose and initialize a console. 225 */ 226void 227consinit(void) 228{ 229 230 /* 231 * The Goldfish TTY console has already been attached when 232 * the bootinfo was parsed. 233 */ 234 235#ifdef DDB 236 if (boothowto & RB_KDB) 237 Debugger(); 238#endif 239} 240 241/* 242 * cpu_startup: allocate memory for variable-sized tables, 243 * initialize CPU, and do autoconfiguration. 244 */ 245void 246cpu_startup(void) 247{ 248 vaddr_t minaddr, maxaddr; 249 char pbuf[9]; 250#ifdef DEBUG 251 extern int pmapdebug; 252 int opmapdebug = pmapdebug; 253 254 pmapdebug = 0; 255#endif 256 257 /* 258 * If we have an FPU, initialise the cached idle frame 259 */ 260 if (fputype != FPU_NONE) 261 m68k_make_fpu_idle_frame(); 262 263 /* 264 * Initialize the kernel crash dump header. 265 */ 266 cpu_init_kcore_hdr(); 267 268 /* 269 * Good {morning,afternoon,evening,night}. 270 */ 271 printf("%s%s", copyright, version); 272 identifycpu(); 273 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 274 printf("total memory = %s\n", pbuf); 275 276 minaddr = 0; 277 /* 278 * Allocate a submap for physio 279 */ 280 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 281 VM_PHYS_SIZE, 0, false, NULL); 282 283#ifdef DEBUG 284 pmapdebug = opmapdebug; 285#endif 286 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 287 printf("avail memory = %s\n", pbuf); 288 289 if (bootinfo_mem_segments_ignored) { 290 printf("WARNING: ignored %zd bytes of memory in %d segments.\n", 291 bootinfo_mem_segments_ignored_bytes, 292 bootinfo_mem_segments_ignored); 293 } 294 295 /* 296 * Set up CPU-specific registers, cache, etc. 297 */ 298 initcpu(); 299} 300 301static const char * 302mmu_string(void) 303{ 304 switch (mmutype) { 305 case MMU_68851: 306 return ", MC68851 MMU"; 307 break; 308 309 case MMU_68030: 310 case MMU_68040: 311 case MMU_68060: 312 return "+MMU"; 313 314 default: 315 return ""; 316 } 317} 318 319static const char * 320fpu_string(void) 321{ 322 switch (fputype) { 323 case FPU_68881: 324 return ", MC68881 FPU"; 325 326 case FPU_68882: 327 return ", MC68882 FPU"; 328 329 case FPU_68040: 330 case FPU_68060: 331 return "+FPU"; 332 333 default: 334 return ""; 335 } 336} 337 338void 339identifycpu(void) 340{ 341 const char *cpu_str, *mmu_str, *fpu_str, *cache_str; 342 struct bi_record *bi; 343 uint32_t qvers; 344 345 /* Fill in the CPU string. */ 346 switch (cputype) { 347#ifdef M68020 348 case CPU_68020: 349 cpu_str = "MC68020"; 350 break; 351#endif 352 353#ifdef M68030 354 case CPU_68030: 355 cpu_str = "MC68030"; 356 break; 357#endif 358 359#ifdef M68040 360 case CPU_68040: 361 cpu_str = "MC68040"; 362 break; 363#endif 364 365#ifdef M68060 366 case CPU_68060: 367 cpu_str = "MC68060"; 368 break; 369#endif 370 371 default: 372 printf("unknown CPU type"); 373 panic("startup"); 374 } 375 376 mmu_str = mmu_string(); 377 fpu_str = fpu_string(); 378 379 switch (cputype) { 380#if defined(M68040) 381 case CPU_68040: 382 cache_str = ", 4k+4k on-chip physical I/D caches"; 383 break; 384#endif 385#if defined(M68060) 386 case CPU_68060: 387 cache_str = ", 8k+8k on-chip physical I/D caches"; 388 break; 389#endif 390 default: 391 cache_str = ""; 392 break; 393 } 394 395 bi = bootinfo_find(BI_VIRT_QEMU_VERSION); 396 if (bi != NULL) { 397 qvers = bootinfo_get_u32(bi); 398 } else { 399 qvers = 0; 400 } 401 402 cpu_setmodel("Qemu %d.%d.%d: %s%s%s%s", 403 (qvers >> 24) & 0xff, 404 (qvers >> 16) & 0xff, 405 (qvers >> 8) & 0xff, 406 cpu_str, mmu_str, fpu_str, cache_str); 407 408 printf("%s\n", cpu_getmodel()); 409} 410 411/* 412 * machine dependent system variables. 413 */ 414SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 415{ 416 417 sysctl_createv(clog, 0, NULL, NULL, 418 CTLFLAG_PERMANENT, 419 CTLTYPE_NODE, "machdep", NULL, 420 NULL, 0, NULL, 0, 421 CTL_MACHDEP, CTL_EOL); 422 423 sysctl_createv(clog, 0, NULL, NULL, 424 CTLFLAG_PERMANENT, 425 CTLTYPE_STRUCT, "console_device", NULL, 426 sysctl_consdev, 0, NULL, sizeof(dev_t), 427 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 428} 429 430/* See: sig_machdep.c */ 431 432int waittime = -1; 433 434static void (*cpu_reset_func)(void *, int); 435static void *cpu_reset_func_arg; 436 437void 438cpu_set_reset_func(void (*func)(void *, int), void *arg) 439{ 440 if (cpu_reset_func == NULL) { 441 cpu_reset_func = func; 442 cpu_reset_func_arg = arg; 443 } 444} 445 446void 447cpu_reboot(int howto, char *bootstr) 448{ 449 struct pcb *pcb = lwp_getpcb(curlwp); 450 451 /* take a snap shot before clobbering any registers */ 452 if (pcb != NULL) 453 savectx(pcb); 454 455 /* If system is hold, just halt. */ 456 if (cold) { 457 howto |= RB_HALT; 458 goto haltsys; 459 } 460 461 boothowto = howto; 462 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 463 waittime = 0; 464 vfs_shutdown(); 465 } 466 467 /* Disable interrupts. */ 468 splhigh(); 469 470 /* If rebooting and a dump is requested, do it. */ 471 if (howto & RB_DUMP) 472 dumpsys(); 473 474 haltsys: 475 /* Run any shutdown hooks. */ 476 doshutdownhooks(); 477 478 pmf_system_shutdown(boothowto); 479 480#if defined(PANICWAIT) && !defined(DDB) 481 if ((howto & RB_HALT) == 0 && panicstr) { 482 printf("hit any key to reboot...\n"); 483 cnpollc(1); 484 (void)cngetc(); 485 cnpollc(0); 486 printf("\n"); 487 } 488#endif 489 490 if (cpu_reset_func == NULL) { 491 printf("WARNING: No reset handler, holding here.\n\n"); 492 for (;;) { 493 /* spin forever. */ 494 } 495 } 496 497 /* Finally, halt/reboot the system. */ 498 if (howto & RB_HALT) { 499 printf("halted\n\n"); 500 (*cpu_reset_func)(cpu_reset_func_arg, RB_HALT); 501 /* NOTREACHED */ 502 } else { 503 printf("rebooting...\n"); 504 delay(1000000); 505 (*cpu_reset_func)(cpu_reset_func_arg, RB_AUTOBOOT); 506 /* NOTREACHED */ 507 } 508 /* ...but just in case it is... */ 509 printf("WARNING: System reset handler failed, holding here.\n\n"); 510 for (;;) { 511 /* spin forever. */ 512 } 513} 514 515/* 516 * Initialize the kernel crash dump header. 517 */ 518void 519cpu_init_kcore_hdr(void) 520{ 521 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 522 struct m68k_kcore_hdr *m = &h->un._m68k; 523 int i; 524 extern char end[]; 525 526 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 527 528 /* 529 * Initialize the `dispatcher' portion of the header. 530 */ 531 strcpy(h->name, machine); 532 h->page_size = PAGE_SIZE; 533 h->kernbase = KERNBASE; 534 535 /* 536 * Fill in information about our MMU configuration. 537 */ 538 m->mmutype = mmutype; 539 m->sg_v = SG_V; 540 m->sg_frame = SG_FRAME; 541 m->sg_ishift = SG_ISHIFT; 542 m->sg_pmask = SG_PMASK; 543 m->sg40_shift1 = SG4_SHIFT1; 544 m->sg40_mask2 = SG4_MASK2; 545 m->sg40_shift2 = SG4_SHIFT2; 546 m->sg40_mask3 = SG4_MASK3; 547 m->sg40_shift3 = SG4_SHIFT3; 548 m->sg40_addr1 = SG4_ADDR1; 549 m->sg40_addr2 = SG4_ADDR2; 550 m->pg_v = PG_V; 551 m->pg_frame = PG_FRAME; 552 553 /* 554 * Initialize pointer to kernel segment table. 555 */ 556 m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); 557 558 /* 559 * Initialize relocation value such that: 560 * 561 * pa = (va - KERNBASE) + reloc 562 * 563 * Since we're linked and loaded at the same place, 564 * and the kernel is mapped va == pa, this is 0. 565 */ 566 m->reloc = 0; 567 568 /* 569 * Define the end of the relocatable range. 570 */ 571 m->relocend = (uint32_t)end; 572 573 for (i = 0; i < bootinfo_mem_nsegments; i++) { 574 m->ram_segs[i].start = bootinfo_mem_segments[i].mem_addr; 575 m->ram_segs[i].size = bootinfo_mem_segments[i].mem_size; 576 } 577} 578 579/* 580 * Compute the size of the machine-dependent crash dump header. 581 * Returns size in disk blocks. 582 */ 583 584#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 585#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 586 587int 588cpu_dumpsize(void) 589{ 590 591 return btodb(MDHDRSIZE); 592} 593 594/* 595 * Calculate size of RAM (in pages) to be dumped. 596 */ 597u_long 598cpu_dump_mempagecnt(void) 599{ 600 u_long i, n; 601 602 n = 0; 603 for (i = 0; i < bootinfo_mem_nsegments; i++) 604 n += atop(bootinfo_mem_segments[i].mem_size); 605 return n; 606} 607 608/* 609 * Called by dumpsys() to dump the machine-dependent header. 610 */ 611int 612cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 613{ 614 int buf[MDHDRSIZE / sizeof(int)]; 615 cpu_kcore_hdr_t *chdr; 616 kcore_seg_t *kseg; 617 int error; 618 619 kseg = (kcore_seg_t *)buf; 620 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 621 sizeof(int)]; 622 623 /* Create the segment header. */ 624 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 625 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 626 627 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 628 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 629 *blknop += btodb(sizeof(buf)); 630 return error; 631} 632 633/* 634 * These variables are needed by /sbin/savecore 635 */ 636uint32_t dumpmag = 0x8fca0101; /* magic number */ 637int dumpsize = 0; /* pages */ 638long dumplo = 0; /* blocks */ 639 640/* 641 * This is called by main to set dumplo and dumpsize. 642 * Dumps always skip the first PAGE_SIZE of disk space 643 * in case there might be a disk label stored there. 644 * If there is extra space, put dump at the end to 645 * reduce the chance that swapping trashes it. 646 */ 647void 648cpu_dumpconf(void) 649{ 650 int nblks, dumpblks; /* size of dump area */ 651 652 if (dumpdev == NODEV) 653 goto bad; 654 nblks = bdev_size(dumpdev); 655 if (nblks <= ctod(1)) 656 goto bad; 657 658 dumpblks = cpu_dumpsize(); 659 if (dumpblks < 0) 660 goto bad; 661 dumpblks += ctod(cpu_dump_mempagecnt()); 662 663 /* If dump won't fit (incl. room for possible label), punt. */ 664 if (dumpblks > (nblks - ctod(1))) 665 goto bad; 666 667 /* Put dump at end of partition */ 668 dumplo = nblks - dumpblks; 669 670 /* dumpsize is in page units, and doesn't include headers. */ 671 dumpsize = cpu_dump_mempagecnt(); 672 return; 673 674 bad: 675 dumpsize = 0; 676} 677 678/* 679 * Dump physical memory onto the dump device. Called by cpu_reboot(). 680 */ 681void 682dumpsys(void) 683{ 684 const struct bdevsw *bdev; 685 u_long totalbytesleft, bytes, i, n, memcl; 686 u_long maddr; 687 int psize; 688 daddr_t blkno; 689 int (*dump)(dev_t, daddr_t, void *, size_t); 690 int error; 691 692 /* XXX Should save registers. */ 693 694 if (dumpdev == NODEV) 695 return; 696 bdev = bdevsw_lookup(dumpdev); 697 if (bdev == NULL || bdev->d_psize == NULL) 698 return; 699 700 /* 701 * For dumps during autoconfiguration, 702 * if dump device has already configured... 703 */ 704 if (dumpsize == 0) 705 cpu_dumpconf(); 706 if (dumplo <= 0) { 707 printf("\ndump to dev %u,%u not possible\n", 708 major(dumpdev), minor(dumpdev)); 709 return; 710 } 711 printf("\ndumping to dev %u,%u offset %ld\n", 712 major(dumpdev), minor(dumpdev), dumplo); 713 714 psize = bdev_size(dumpdev); 715 printf("dump "); 716 if (psize == -1) { 717 printf("area unavailable\n"); 718 return; 719 } 720 721 /* XXX should purge all outstanding keystrokes. */ 722 723 dump = bdev->d_dump; 724 blkno = dumplo; 725 726 if ((error = cpu_dump(dump, &blkno)) != 0) 727 goto err; 728 729 totalbytesleft = ptoa(cpu_dump_mempagecnt()); 730 731 for (memcl = 0; memcl < bootinfo_mem_nsegments; memcl++) { 732 maddr = bootinfo_mem_segments[memcl].mem_addr; 733 bytes = bootinfo_mem_segments[memcl].mem_size; 734 735 for (i = 0; i < bytes; i += n, totalbytesleft -= n) { 736 737 /* Print out how many MBs we have left to go. */ 738 if ((totalbytesleft % (1024*1024)) == 0) 739 printf_nolog("%ld ", 740 totalbytesleft / (1024 * 1024)); 741 742 /* Limit size for next transfer. */ 743 n = bytes - i; 744 if (n > PAGE_SIZE) 745 n = PAGE_SIZE; 746 747 pmap_kenter_pa((vaddr_t)vmmap, maddr, VM_PROT_READ, 0); 748 pmap_update(pmap_kernel()); 749 750 error = (*dump)(dumpdev, blkno, vmmap, n); 751 if (error) 752 goto err; 753 754 pmap_kremove((vaddr_t)vmmap, PAGE_SIZE); 755 pmap_update(pmap_kernel()); 756 757 maddr += n; 758 blkno += btodb(n); 759 } 760 } 761 762 err: 763 switch (error) { 764 765 case ENXIO: 766 printf("device bad\n"); 767 break; 768 769 case EFAULT: 770 printf("device not ready\n"); 771 break; 772 773 case EINVAL: 774 printf("area improper\n"); 775 break; 776 777 case EIO: 778 printf("i/o error\n"); 779 break; 780 781 case EINTR: 782 printf("aborted from console\n"); 783 break; 784 785 case 0: 786 printf("succeeded\n"); 787 break; 788 789 default: 790 printf("error %d\n", error); 791 break; 792 } 793 printf("\n\n"); 794 delay(5000); 795} 796 797void 798initcpu(void) 799{ 800 /* No work to do. */ 801} 802 803void 804straytrap(int pc, u_short evec) 805{ 806 807 printf("unexpected trap (vector offset %x) from %x\n", 808 evec & 0xFFF, pc); 809} 810 811/* 812 * Level 7 interrupts are caused by e.g. the ABORT switch. 813 * 814 * If we have DDB, then break into DDB on ABORT. In a production 815 * environment, bumping the ABORT switch would be bad, so we enable 816 * panic'ing on ABORT with the kernel option "PANICBUTTON". 817 */ 818int 819nmihand(void *arg) 820{ 821 822 printf("NMI ignored.\n"); 823 824 return 1; 825} 826 827/* 828 * cpu_exec_aout_makecmds(): 829 * CPU-dependent a.out format hook for execve(). 830 * 831 * Determine of the given exec package refers to something which we 832 * understand and, if so, set up the vmcmds for it. 833 */ 834int 835cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 836{ 837 838 return ENOEXEC; 839} 840 841#ifdef MODULAR 842/* 843 * Push any modules loaded by the bootloader etc. 844 */ 845void 846module_init_md(void) 847{ 848} 849#endif 850 851const uint16_t ipl2psl_table[NIPL] = { 852 [IPL_NONE] = PSL_S | PSL_IPL0, 853 [IPL_SOFTCLOCK] = PSL_S | PSL_IPL1, 854 [IPL_SOFTBIO] = PSL_S | PSL_IPL1, 855 [IPL_SOFTNET] = PSL_S | PSL_IPL1, 856 [IPL_SOFTSERIAL] = PSL_S | PSL_IPL1, 857 [IPL_VM] = PSL_S | PSL_IPL5, 858 [IPL_SCHED] = PSL_S | PSL_IPL6, 859 [IPL_HIGH] = PSL_S | PSL_IPL7, 860}; 861 862int 863mm_md_physacc(paddr_t pa, vm_prot_t prot) 864{ 865 psize_t size; 866 int i; 867 868 for (i = 0; i < bootinfo_mem_nsegments; i++) { 869 if (pa < bootinfo_mem_segments[i].mem_addr) { 870 continue; 871 } 872 size = trunc_page(bootinfo_mem_segments[i].mem_size); 873 if (pa >= bootinfo_mem_segments[i].mem_addr + size) { 874 continue; 875 } 876 return 0; 877 } 878 return EFAULT; 879} 880