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