1 /* $NetBSD: machdep.c,v 1.255 2024/03/05 14:15:28 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 6 * 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.63 91/04/24$ 37 * 38 * @(#)machdep.c 7.16 (Berkeley) 6/3/91 39 */ 40 41 #include "opt_ddb.h" 42 #include "opt_compat_netbsd.h" 43 #include "opt_fpu_emulate.h" 44 #include "opt_lev6_defer.h" 45 #include "opt_m060sp.h" 46 #include "opt_modular.h" 47 #include "opt_panicbutton.h" 48 #include "opt_m68k_arch.h" 49 50 #include "empm.h" 51 52 #include <sys/cdefs.h> 53 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255 2024/03/05 14:15:28 thorpej Exp $"); 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/callout.h> 58 #include <sys/signalvar.h> 59 #include <sys/kernel.h> 60 #include <sys/proc.h> 61 #include <sys/buf.h> 62 #include <sys/reboot.h> 63 #include <sys/conf.h> 64 #include <sys/file.h> 65 #include <sys/mbuf.h> 66 #include <sys/msgbuf.h> 67 #include <sys/vnode.h> 68 #include <sys/device.h> 69 #include <sys/queue.h> 70 #include <sys/mount.h> 71 #include <sys/core.h> 72 #include <sys/kcore.h> 73 #include <sys/ksyms.h> 74 #include <sys/module.h> 75 #include <sys/cpu.h> 76 #include <sys/exec.h> 77 78 #if defined(DDB) && defined(__ELF__) 79 #include <sys/exec_elf.h> 80 #endif 81 82 #include <sys/exec_aout.h> 83 84 #undef PS /* XXX netccitt/pk.h conflict with machine/reg.h? */ 85 86 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 87 #include <uvm/uvm_extern.h> 88 89 #include <sys/sysctl.h> 90 91 #include <machine/db_machdep.h> 92 #include <ddb/db_sym.h> 93 #include <ddb/db_extern.h> 94 95 #include <machine/reg.h> 96 #include <machine/pcb.h> 97 #include <machine/psl.h> 98 #include <machine/pte.h> 99 #include <machine/kcore.h> 100 #include <dev/cons.h> 101 #include <dev/mm.h> 102 #include <amiga/amiga/isr.h> 103 #include <amiga/amiga/custom.h> 104 #ifdef DRACO 105 #include <amiga/amiga/drcustom.h> 106 #include <m68k/include/asm_single.h> 107 #endif 108 #include <amiga/amiga/cia.h> 109 #include <amiga/amiga/cc.h> 110 #include <amiga/amiga/memlist.h> 111 #include <amiga/amiga/device.h> 112 #if NEMPM > 0 113 #include <amiga/pci/empmvar.h> 114 #endif /* NEMPM > 0 */ 115 116 #include "fd.h" 117 #include "ser.h" 118 #include "ksyms.h" 119 120 /* prototypes */ 121 void identifycpu(void); 122 vm_offset_t reserve_dumppages(vm_offset_t); 123 void dumpsys(void); 124 void initcpu(void); 125 void straytrap(int, u_short); 126 void intrhand(int); 127 #if NSER > 0 128 void ser_outintr(void); 129 #endif 130 #if NFD > 0 131 void fdintr(int); 132 #endif 133 134 volatile unsigned int intr_depth = 0; 135 136 struct vm_map *phys_map = NULL; 137 138 void * msgbufaddr; 139 paddr_t msgbufpa; 140 141 int machineid; 142 int maxmem; /* max memory per process */ 143 144 extern int freebufspace; 145 extern u_int lowram; 146 147 /* used in init_main.c */ 148 const char *cpu_type = "m68k"; 149 /* the following is used externally (sysctl_hw) */ 150 char machine[] = MACHINE; /* from <machine/param.h> */ 151 152 /* Our exported CPU info; we can have only one. */ 153 struct cpu_info cpu_info_store; 154 155 /* 156 * current open serial device speed; used by some SCSI drivers to reduce 157 * DMA transfer lengths. 158 */ 159 int ser_open_speed; 160 161 #ifdef DRACO 162 vaddr_t DRCCADDR; 163 164 volatile u_int8_t *draco_intena, *draco_intpen, *draco_intfrc; 165 volatile u_int8_t *draco_misc; 166 volatile struct drioct *draco_ioct; 167 #endif 168 169 /* 170 * Console initialization: called early on from main, 171 * before vm init or startup. Do enough configuration 172 * to choose and initialize a console. 173 */ 174 void 175 consinit(void) 176 { 177 /* initialize custom chip interface */ 178 #ifdef DRACO 179 if (is_draco()) { 180 /* XXX to be done */ 181 } else 182 #endif 183 custom_chips_init(); 184 185 /* preconfigure graphics cards */ 186 config_console(); 187 188 /* 189 * Initialize the console before we print anything out. 190 */ 191 cninit(); 192 193 #if NKSYMS || defined(DDB) || defined(MODULAR) 194 { 195 extern int end[]; 196 extern int *esym; 197 198 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 199 (void *)&end, esym); 200 } 201 #endif 202 #ifdef DDB 203 if (boothowto & RB_KDB) 204 Debugger(); 205 #endif 206 } 207 208 /* 209 * cpu_startup: allocate memory for variable-sized tables, 210 * initialize CPU, and do autoconfiguration. 211 */ 212 void 213 cpu_startup(void) 214 { 215 u_int i; 216 #ifdef DEBUG 217 extern int pmapdebug; 218 int opmapdebug = pmapdebug; 219 #endif 220 vaddr_t minaddr, maxaddr; 221 222 /* 223 * Initialize error message buffer (at end of core). 224 */ 225 #ifdef DEBUG 226 pmapdebug = 0; 227 #endif 228 /* 229 * pmap_bootstrap has positioned this at the end of kernel 230 * memory segment - map and initialize it now. 231 */ 232 233 for (i = 0; i < btoc(MSGBUFSIZE); i++) 234 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE, 235 msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 236 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 237 pmap_update(pmap_kernel()); 238 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 239 240 minaddr = 0; 241 242 /* 243 * Allocate a submap for physio 244 */ 245 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 246 VM_PHYS_SIZE, 0, false, NULL); 247 248 /* 249 * Good {morning,afternoon,evening,night}. 250 */ 251 banner(); 252 253 /* 254 * Get MMU/FPU type from bootstrap 255 */ 256 identifycpu(); 257 258 #ifdef DEBUG 259 pmapdebug = opmapdebug; 260 #endif 261 262 /* 263 * display memory configuration passed from loadbsd 264 */ 265 if (memlist->m_nseg > 0 && memlist->m_nseg < 16) 266 for (i = 0; i < memlist->m_nseg; i++) 267 printf("memory segment %d at %08x size %08x\n", i, 268 memlist->m_seg[i].ms_start, 269 memlist->m_seg[i].ms_size); 270 271 #ifdef DEBUG_KERNEL_START 272 printf("calling initcpu...\n"); 273 #endif 274 /* 275 * Set up CPU-specific registers, cache, etc. 276 */ 277 initcpu(); 278 279 #ifdef DEBUG_KERNEL_START 280 printf("survived initcpu...\n"); 281 #endif 282 } 283 284 /* 285 * Info for CTL_HW 286 */ 287 #if defined(M68060) 288 int m68060_pcr_init = 0x21; /* make this patchable */ 289 #endif 290 291 292 void 293 identifycpu(void) 294 { 295 /* there's alot of XXX in here... */ 296 const char *mach, *mmu, *fpu; 297 298 #ifdef M68060 299 char cpubuf[16]; 300 u_int32_t pcr; 301 #endif 302 303 #ifdef DRACO 304 char machbuf[16]; 305 306 if (is_draco()) { 307 snprintf(machbuf, sizeof(machbuf), "DraCo rev.%d", is_draco()); 308 mach = machbuf; 309 } else 310 #endif 311 if (is_a4000()) 312 mach = "Amiga 4000"; 313 else if (is_a3000()) 314 mach = "Amiga 3000"; 315 else if (is_a1200()) 316 mach = "Amiga 1200"; 317 else if (is_a600()) 318 mach = "Amiga 600"; 319 else 320 mach = "Amiga 500/2000"; 321 322 fpu = NULL; 323 #ifdef M68060 324 if (machineid & AMIGA_68060) { 325 __asm(".word 0x4e7a,0x0808; movl %%d0,%0" : "=d"(pcr) : : "d0"); 326 snprintf(cpubuf, sizeof(cpubuf), "68%s060 rev.%d", 327 pcr & 0x10000 ? "LC/EC" : "", (pcr>>8)&0xff); 328 cpu_type = cpubuf; 329 mmu = "/MMU"; 330 if (pcr & 2) { 331 fpu = "/FPU disabled"; 332 fputype = FPU_NONE; 333 } else if (m68060_pcr_init & 2){ 334 fpu = "/FPU will be disabled"; 335 fputype = FPU_NONE; 336 } else if (machineid & AMIGA_FPU40) { 337 fpu = "/FPU"; 338 fputype = FPU_68040; /* XXX */ 339 } 340 } else 341 #endif 342 if (machineid & AMIGA_68040) { 343 cpu_type = "m68040"; 344 mmu = "/MMU"; 345 fpu = "/FPU"; 346 fputype = FPU_68040; /* XXX */ 347 } else if (machineid & AMIGA_68030) { 348 cpu_type = "m68030"; /* XXX */ 349 mmu = "/MMU"; 350 } else { 351 cpu_type = "m68020"; 352 mmu = " m68851 MMU"; 353 } 354 if (fpu == NULL) { 355 if (machineid & AMIGA_68882) { 356 fpu = " m68882 FPU"; 357 fputype = FPU_68882; 358 } else if (machineid & AMIGA_68881) { 359 fpu = " m68881 FPU"; 360 fputype = FPU_68881; 361 } else { 362 fpu = " no FPU"; 363 fputype = FPU_NONE; 364 } 365 } 366 cpu_setmodel("%s (%s CPU%s%s)", mach, cpu_type, mmu, fpu); 367 printf("%s\n", cpu_getmodel()); 368 } 369 370 /* 371 * machine dependent system variables. 372 */ 373 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 374 { 375 376 sysctl_createv(clog, 0, NULL, NULL, 377 CTLFLAG_PERMANENT, 378 CTLTYPE_NODE, "machdep", NULL, 379 NULL, 0, NULL, 0, 380 CTL_MACHDEP, CTL_EOL); 381 382 sysctl_createv(clog, 0, NULL, NULL, 383 CTLFLAG_PERMANENT, 384 CTLTYPE_STRUCT, "console_device", NULL, 385 sysctl_consdev, 0, NULL, sizeof(dev_t), 386 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 387 } 388 389 static int waittime = -1; 390 391 void 392 bootsync(void) 393 { 394 if (waittime < 0) { 395 waittime = 0; 396 vfs_shutdown(); 397 } 398 } 399 400 401 void 402 cpu_reboot(register int howto, char *bootstr) 403 { 404 struct pcb *pcb = lwp_getpcb(curlwp); 405 #if NEMPM > 0 406 device_t empmdev; 407 #endif /* NEMPM > 0 */ 408 409 /* take a snap shot before clobbering any registers */ 410 if (pcb != NULL) 411 savectx(pcb); 412 413 boothowto = howto; 414 if ((howto & RB_NOSYNC) == 0) 415 bootsync(); 416 417 /* Disable interrupts. */ 418 spl7(); 419 420 /* If rebooting and a dump is requested do it. */ 421 if (howto & RB_DUMP) 422 dumpsys(); 423 424 #if NEMPM > 0 425 if (howto & RB_POWERDOWN) { 426 empmdev = device_find_by_xname("empm0"); 427 if (empmdev != NULL) { 428 empm_power_off(device_private(empmdev)); 429 } 430 } 431 #endif /* NEMPM > 0 */ 432 433 if (howto & RB_HALT) { 434 printf("\n"); 435 printf("The operating system has halted.\n"); 436 printf("Please press any key to reboot.\n\n"); 437 cnpollc(1); 438 cngetc(); 439 cnpollc(0); 440 } 441 442 printf("rebooting...\n"); 443 DELAY(1000000); 444 doboot(); 445 /*NOTREACHED*/ 446 } 447 448 449 u_int32_t dumpmag = 0x8fca0101; /* magic number for savecore */ 450 int dumpsize = 0; /* also for savecore */ 451 long dumplo = 0; 452 cpu_kcore_hdr_t cpu_kcore_hdr; 453 454 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 455 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 456 457 void 458 cpu_dumpconf(void) 459 { 460 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 461 struct m68k_kcore_hdr *m = &h->un._m68k; 462 int nblks; 463 int i; 464 extern int end[]; 465 466 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 467 468 /* 469 * Intitialize the `dispatcher' portion of the header. 470 */ 471 strcpy(h->name, machine); 472 h->page_size = PAGE_SIZE; 473 h->kernbase = KERNBASE; 474 475 /* 476 * Fill in information about our MMU configuration. 477 */ 478 m->mmutype = mmutype; 479 m->sg_v = SG_V; 480 m->sg_frame = SG_FRAME; 481 m->sg_ishift = SG_ISHIFT; 482 m->sg_pmask = SG_PMASK; 483 m->sg40_shift1 = SG4_SHIFT1; 484 m->sg40_mask2 = SG4_MASK2; 485 m->sg40_shift2 = SG4_SHIFT2; 486 m->sg40_mask3 = SG4_MASK3; 487 m->sg40_shift3 = SG4_SHIFT3; 488 m->sg40_addr1 = SG4_ADDR1; 489 m->sg40_addr2 = SG4_ADDR2; 490 m->pg_v = PG_V; 491 m->pg_frame = PG_FRAME; 492 493 /* 494 * Initialize the pointer to the kernel segment table. 495 */ 496 m->sysseg_pa = (paddr_t)pmap_kernel()->pm_stpa; 497 498 /* 499 * Initialize relocation value such that: 500 * 501 * pa = (va - KERNBASE) + reloc 502 */ 503 m->reloc = lowram; 504 505 /* 506 * Define the end of the relocatable range. 507 */ 508 m->relocend = (u_int32_t)&end; 509 510 /* XXX new corefile format, single segment + chipmem */ 511 dumpsize = physmem; 512 m->ram_segs[0].start = lowram; 513 m->ram_segs[0].size = ctob(physmem); 514 for (i = 0; i < memlist->m_nseg; i++) { 515 if ((memlist->m_seg[i].ms_attrib & MEMF_CHIP) == 0) 516 continue; 517 dumpsize += btoc(memlist->m_seg[i].ms_size); 518 m->ram_segs[1].start = 0; 519 m->ram_segs[1].size = memlist->m_seg[i].ms_size; 520 break; 521 } 522 if (bdevsw_lookup(dumpdev) == NULL) { 523 dumpdev = NODEV; 524 return; 525 } 526 nblks = bdev_size(dumpdev); 527 if (nblks > 0) { 528 if (dumpsize > btoc(dbtob(nblks - dumplo))) 529 dumpsize = btoc(dbtob(nblks - dumplo)); 530 else if (dumplo == 0) 531 dumplo = nblks - btodb(ctob(dumpsize)); 532 } 533 dumplo -= ctod(btoc(MDHDRSIZE)); 534 /* 535 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?) 536 * in case the dump device includes a disk label. 537 */ 538 if (dumplo < btodb(PAGE_SIZE)) 539 dumplo = btodb(PAGE_SIZE); 540 } 541 542 /* 543 * Doadump comes here after turning off memory management and 544 * getting on the dump stack, either when called above, or by 545 * the auto-restart code. 546 */ 547 #define BYTES_PER_DUMP MAXPHYS /* Must be a multiple of pagesize XXX small */ 548 static vm_offset_t dumpspace; 549 550 vm_offset_t 551 reserve_dumppages(vm_offset_t p) 552 { 553 dumpspace = p; 554 return (p + BYTES_PER_DUMP); 555 } 556 557 void 558 dumpsys(void) 559 { 560 unsigned bytes, i, n, seg; 561 int maddr, psize; 562 daddr_t blkno; 563 int (*dump)(dev_t, daddr_t, void *, size_t); 564 int error = 0; 565 kcore_seg_t *kseg_p; 566 cpu_kcore_hdr_t *chdr_p; 567 char dump_hdr[MDHDRSIZE]; 568 const struct bdevsw *bdev; 569 570 if (dumpdev == NODEV) 571 return; 572 bdev = bdevsw_lookup(dumpdev); 573 if (bdev == NULL || bdev->d_psize == NULL) 574 return; 575 /* 576 * For dumps during autoconfiguration, 577 * if dump device has already configured... 578 */ 579 if (dumpsize == 0) 580 cpu_dumpconf(); 581 if (dumplo <= 0) { 582 printf("\ndump to dev %u,%u not possible\n", major(dumpdev), 583 minor(dumpdev)); 584 return; 585 } 586 printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), 587 minor(dumpdev), dumplo); 588 589 psize = bdev_size(dumpdev); 590 printf("dump "); 591 if (psize == -1) { 592 printf("area unavailable.\n"); 593 return; 594 } 595 kseg_p = (kcore_seg_t *)dump_hdr; 596 chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))]; 597 memset(dump_hdr, 0, sizeof(dump_hdr)); 598 599 /* 600 * Generate a segment header 601 */ 602 CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 603 kseg_p->c_size = MDHDRSIZE - ALIGN(sizeof(*kseg_p)); 604 605 /* 606 * Add the md header 607 */ 608 609 *chdr_p = cpu_kcore_hdr; 610 611 bytes = ctob(dumpsize); 612 maddr = cpu_kcore_hdr.un._m68k.ram_segs[0].start; 613 seg = 0; 614 blkno = dumplo; 615 dump = bdev->d_dump; 616 error = (*dump) (dumpdev, blkno, (void *)dump_hdr, sizeof(dump_hdr)); 617 blkno += btodb(sizeof(dump_hdr)); 618 for (i = 0; i < bytes && error == 0; i += n) { 619 /* Print out how many MBs we have to go. */ 620 n = bytes - i; 621 if (n && (n % (1024 * 1024)) == 0) 622 printf_nolog("%d ", n / (1024 * 1024)); 623 624 /* Limit size for next transfer. */ 625 if (n > BYTES_PER_DUMP) 626 n = BYTES_PER_DUMP; 627 628 if (maddr == 0) { /* XXX kvtop chokes on this */ 629 maddr += PAGE_SIZE; 630 n -= PAGE_SIZE; 631 i += PAGE_SIZE; 632 ++blkno; /* XXX skip physical page 0 */ 633 } 634 (void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ); 635 error = (*dump) (dumpdev, blkno, (void *) dumpspace, n); 636 if (error) 637 break; 638 maddr += n; 639 blkno += btodb(n); /* XXX? */ 640 if (maddr >= (cpu_kcore_hdr.un._m68k.ram_segs[seg].start + 641 cpu_kcore_hdr.un._m68k.ram_segs[seg].size)) { 642 ++seg; 643 maddr = cpu_kcore_hdr.un._m68k.ram_segs[seg].start; 644 if (cpu_kcore_hdr.un._m68k.ram_segs[seg].size == 0) 645 break; 646 } 647 } 648 649 switch (error) { 650 651 case ENXIO: 652 printf("device bad\n"); 653 break; 654 655 case EFAULT: 656 printf("device not ready\n"); 657 break; 658 659 case EINVAL: 660 printf("area improper\n"); 661 break; 662 663 case EIO: 664 printf("i/o error\n"); 665 break; 666 667 default: 668 printf("succeeded\n"); 669 break; 670 } 671 printf("\n\n"); 672 delay(5000000); /* 5 seconds */ 673 } 674 675 void 676 initcpu(void) 677 { 678 /* XXX should init '40 vecs here, too */ 679 #if defined(M68060) || defined(M68040) || defined(DRACO) || defined(FPU_EMULATE) 680 typedef void trapfun(void); 681 extern trapfun *vectab[256]; 682 #endif 683 684 #if defined(M68060) || defined(M68040) 685 extern trapfun addrerr4060; 686 #endif 687 688 #ifdef M68060 689 extern trapfun buserr60; 690 #if defined(M060SP) 691 /*extern u_int8_t I_CALL_TOP[];*/ 692 extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60; 693 extern u_int8_t FP_CALL_TOP[]; 694 #else 695 extern trapfun illinst; 696 #endif 697 extern trapfun fpfault; 698 #endif 699 700 #ifdef M68040 701 extern trapfun buserr40; 702 #endif 703 704 #ifdef DRACO 705 extern trapfun DraCoIntr, DraCoLev1intr, DraCoLev2intr; 706 u_char dracorev; 707 #endif 708 709 #ifdef FPU_EMULATE 710 extern trapfun fpemuli; 711 #endif 712 713 #ifdef M68060 714 if (machineid & AMIGA_68060) { 715 if (machineid & AMIGA_FPU40 && m68060_pcr_init & 2) { 716 /* 717 * in this case, we're about to switch the FPU off; 718 * do a FNOP to avoid stray FP traps later 719 * 720 * But we can't use fnop directly anymore as of 721 * gcc-6 because it passes -mno-float to the assembler 722 * because of -msoft-float and the assembler refuses 723 * to assemble the instruction; adding -Wa,-mfloat 724 * does not work either because the assembler then 725 * complains about feature being turned off and on 726 * so we just put in the opcode directly. 727 */ 728 #if 0 729 __asm("fnop"); 730 #else 731 __asm(".word 0xf280,0x0000"); 732 #endif 733 /* ... and mark FPU as absent for identifyfpu() */ 734 machineid &= ~(AMIGA_FPU40|AMIGA_68882|AMIGA_68881); 735 } 736 __asm volatile ("movl %0,%%d0; .word 0x4e7b,0x0808" : : 737 "d"(m68060_pcr_init):"d0" ); 738 739 /* bus/addrerr vectors */ 740 vectab[2] = buserr60; 741 vectab[3] = addrerr4060; 742 #if defined(M060SP) 743 744 /* integer support */ 745 vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/; 746 747 /* floating point support */ 748 /* 749 * XXX maybe we really should run-time check for the 750 * stack frame format here: 751 */ 752 vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/; 753 754 vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/; 755 vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/; 756 757 vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00]; 758 vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08]; 759 vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10]; 760 vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18]; 761 vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20]; 762 vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28]; 763 764 #else 765 vectab[61] = illinst; 766 #endif 767 vectab[48] = fpfault; 768 } 769 #endif 770 771 /* 772 * Vector initialization for special motherboards 773 */ 774 #ifdef M68040 775 #ifdef M68060 776 else 777 #endif 778 if (machineid & AMIGA_68040) { 779 /* addrerr vector */ 780 vectab[2] = buserr40; 781 vectab[3] = addrerr4060; 782 } 783 #endif 784 785 #ifdef FPU_EMULATE 786 if (!(machineid & (AMIGA_68881|AMIGA_68882|AMIGA_FPU40))) { 787 vectab[11] = fpemuli; 788 printf("FPU software emulation initialized.\n"); 789 } 790 #endif 791 792 /* 793 * Vector initialization for special motherboards 794 */ 795 796 #ifdef DRACO 797 dracorev = is_draco(); 798 if (dracorev) { 799 if (dracorev >= 4) { 800 vectab[24+1] = DraCoLev1intr; 801 vectab[24+2] = DraCoIntr; 802 } else { 803 vectab[24+1] = DraCoIntr; 804 vectab[24+2] = DraCoLev2intr; 805 } 806 vectab[24+3] = DraCoIntr; 807 vectab[24+4] = DraCoIntr; 808 vectab[24+5] = DraCoIntr; 809 vectab[24+6] = DraCoIntr; 810 } 811 #endif 812 } 813 814 void 815 straytrap(int pc, u_short evec) 816 { 817 printf("unexpected trap format %x (vector offset %x) from %x\n", 818 evec>>12, evec & 0xFFF, pc); 819 /*XXX*/ panic("straytrap"); 820 } 821 822 int *nofault; 823 824 int 825 badaddr(register void *addr) 826 { 827 int i; 828 label_t faultbuf; 829 830 nofault = (int *) &faultbuf; 831 if (setjmp((label_t *)nofault)) { 832 nofault = NULL; 833 return 1; 834 } 835 i = *(volatile short *)addr; 836 __USE(i); 837 nofault = NULL; 838 return 0; 839 } 840 841 int 842 badbaddr(register void *addr) 843 { 844 int i; 845 label_t faultbuf; 846 847 nofault = (int *) &faultbuf; 848 if (setjmp((label_t *)nofault)) { 849 nofault = NULL; 850 return 1; 851 } 852 i = *(volatile char *)addr; 853 __USE(i); 854 nofault = NULL; 855 return 0; 856 } 857 858 struct isr *isr_ports; 859 #ifdef DRACO 860 struct isr *isr_slot3; 861 struct isr *isr_supio; 862 #endif 863 struct isr *isr_exter; 864 865 void 866 add_isr(struct isr *isr) 867 { 868 struct isr **p, *q; 869 870 #ifdef DRACO 871 switch (isr->isr_ipl) { 872 case 2: 873 p = &isr_ports; 874 break; 875 case 3: 876 p = &isr_slot3; 877 break; 878 case 5: 879 p = &isr_supio; 880 break; 881 default: /* was case 6:; make gcc -Wall quiet */ 882 p = &isr_exter; 883 break; 884 } 885 #else 886 p = isr->isr_ipl == 2 ? &isr_ports : &isr_exter; 887 #endif 888 while ((q = *p) != NULL) 889 p = &q->isr_forw; 890 isr->isr_forw = NULL; 891 *p = isr; 892 /* enable interrupt */ 893 #ifdef DRACO 894 if (is_draco()) 895 switch(isr->isr_ipl) { 896 case 6: 897 single_inst_bset_b(*draco_intena, DRIRQ_INT6); 898 break; 899 case 2: 900 single_inst_bset_b(*draco_intena, DRIRQ_INT2); 901 break; 902 default: 903 break; 904 } 905 else 906 #endif 907 custom.intena = isr->isr_ipl == 2 ? 908 INTF_SETCLR | INTF_PORTS : 909 INTF_SETCLR | INTF_EXTER; 910 } 911 912 void 913 remove_isr(struct isr *isr) 914 { 915 struct isr **p, *q; 916 917 #ifdef DRACO 918 switch (isr->isr_ipl) { 919 case 2: 920 p = &isr_ports; 921 break; 922 case 3: 923 p = &isr_slot3; 924 break; 925 case 5: 926 p = &isr_supio; 927 break; 928 default: /* XXX to make gcc -Wall quiet, was 6: */ 929 p = &isr_exter; 930 break; 931 } 932 #else 933 p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports; 934 #endif 935 936 while ((q = *p) != NULL && q != isr) 937 p = &q->isr_forw; 938 if (q) 939 *p = q->isr_forw; 940 else 941 panic("remove_isr: handler not registered"); 942 /* disable interrupt if no more handlers */ 943 #ifdef DRACO 944 switch (isr->isr_ipl) { 945 case 2: 946 p = &isr_ports; 947 break; 948 case 3: 949 p = &isr_slot3; 950 break; 951 case 5: 952 p = &isr_supio; 953 break; 954 case 6: 955 p = &isr_exter; 956 break; 957 } 958 #else 959 p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports; 960 #endif 961 if (*p == NULL) { 962 #ifdef DRACO 963 if (is_draco()) { 964 switch(isr->isr_ipl) { 965 case 2: 966 single_inst_bclr_b(*draco_intena, 967 DRIRQ_INT2); 968 break; 969 case 6: 970 single_inst_bclr_b(*draco_intena, 971 DRIRQ_INT6); 972 break; 973 default: 974 break; 975 } 976 } else 977 #endif 978 custom.intena = isr->isr_ipl == 6 ? 979 INTF_EXTER : INTF_PORTS; 980 } 981 } 982 983 void 984 intrhand(int sr) 985 { 986 register unsigned int ipl; 987 register unsigned short ireq; 988 register struct isr **p, *q; 989 990 ipl = (sr >> 8) & 7; 991 #ifdef REALLYDEBUG 992 printf("intrhand: got int. %d\n", ipl); 993 #endif 994 #ifdef DRACO 995 if (is_draco()) 996 ireq = ((ipl == 1) && (*draco_intfrc & DRIRQ_SOFT) ? 997 INTF_SOFTINT : 0); 998 else 999 #endif 1000 ireq = custom.intreqr; 1001 1002 switch (ipl) { 1003 case 1: 1004 #ifdef DRACO 1005 if (is_draco() && (draco_ioct->io_status & DRSTAT_KBDRECV)) 1006 drkbdintr(); 1007 #endif 1008 if (ireq & INTF_TBE) { 1009 #if NSER > 0 1010 ser_outintr(); 1011 #else 1012 custom.intreq = INTF_TBE; 1013 #endif 1014 } 1015 1016 if (ireq & INTF_DSKBLK) { 1017 #if NFD > 0 1018 fdintr(0); 1019 #endif 1020 custom.intreq = INTF_DSKBLK; 1021 } 1022 if (ireq & INTF_SOFTINT) { 1023 /* sicallback handling removed */ 1024 #ifdef DEBUG 1025 printf("intrhand: SOFTINT ignored\n"); 1026 #endif 1027 custom.intreq = INTF_SOFTINT; 1028 } 1029 break; 1030 1031 case 2: 1032 p = &isr_ports; 1033 while ((q = *p) != NULL) { 1034 if ((q->isr_intr)(q->isr_arg)) 1035 break; 1036 p = &q->isr_forw; 1037 } 1038 if (q == NULL) 1039 ciaa_intr (); 1040 #ifdef DRACO 1041 if (is_draco()) 1042 single_inst_bclr_b(*draco_intpen, DRIRQ_INT2); 1043 else 1044 #endif 1045 custom.intreq = INTF_PORTS; 1046 1047 break; 1048 1049 #ifdef DRACO 1050 /* only handled here for DraCo */ 1051 case 6: 1052 p = &isr_exter; 1053 while ((q = *p) != NULL) { 1054 if ((q->isr_intr)(q->isr_arg)) 1055 break; 1056 p = &q->isr_forw; 1057 } 1058 single_inst_bclr_b(*draco_intpen, DRIRQ_INT6); 1059 break; 1060 #endif 1061 1062 case 3: 1063 /* VBL */ 1064 if (ireq & INTF_BLIT) 1065 blitter_handler(); 1066 if (ireq & INTF_COPER) 1067 copper_handler(); 1068 if (ireq & INTF_VERTB) 1069 vbl_handler(); 1070 break; 1071 #ifdef DRACO 1072 case 5: 1073 p = &isr_supio; 1074 while ((q = *p) != NULL) { 1075 if ((q->isr_intr)(q->isr_arg)) 1076 break; 1077 p = &q->isr_forw; 1078 } 1079 break; 1080 #endif 1081 #if 0 1082 /* now dealt with in locore.s for speed reasons */ 1083 case 5: 1084 /* check RS232 RBF */ 1085 serintr (0); 1086 1087 custom.intreq = INTF_DSKSYNC; 1088 break; 1089 #endif 1090 1091 case 4: 1092 #ifdef DRACO 1093 #include "drsc.h" 1094 if (is_draco()) 1095 #if NDRSC > 0 1096 drsc_handler(); 1097 #else 1098 single_inst_bclr_b(*draco_intpen, DRIRQ_SCSI); 1099 #endif 1100 else 1101 #endif 1102 audio_handler(); 1103 break; 1104 default: 1105 printf("intrhand: unexpected sr 0x%x, intreq = 0x%x\n", 1106 sr, ireq); 1107 break; 1108 } 1109 #ifdef REALLYDEBUG 1110 printf("intrhand: leaving.\n"); 1111 #endif 1112 } 1113 1114 bool 1115 cpu_intr_p(void) 1116 { 1117 1118 return intr_depth != 0; 1119 } 1120 1121 #if defined(DEBUG) && !defined(PANICBUTTON) 1122 #define PANICBUTTON 1123 #endif 1124 1125 #ifdef PANICBUTTON 1126 int panicbutton = 1; /* non-zero if panic buttons are enabled */ 1127 int crashandburn = 0; 1128 int candbdelay = 50; /* give em half a second */ 1129 void candbtimer(void); 1130 callout_t candbtimer_ch; 1131 1132 void 1133 candbtimer(void) 1134 { 1135 crashandburn = 0; 1136 } 1137 #endif 1138 1139 #if 0 1140 /* 1141 * Level 7 interrupts can be caused by the keyboard or parity errors. 1142 */ 1143 nmihand(struct frame frame) 1144 { 1145 if (kbdnmi()) { 1146 #ifdef PANICBUTTON 1147 static int innmihand = 0; 1148 1149 /* 1150 * Attempt to reduce the window of vulnerability for recursive 1151 * NMIs (e.g. someone holding down the keyboard reset button). 1152 */ 1153 if (innmihand == 0) { 1154 innmihand = 1; 1155 printf("Got a keyboard NMI\n"); 1156 innmihand = 0; 1157 } 1158 if (panicbutton) { 1159 if (crashandburn) { 1160 crashandburn = 0; 1161 panic(panicstr ? 1162 "forced crash, nosync" : "forced crash"); 1163 } 1164 crashandburn++; 1165 callout_reset(&candbtimer_ch, candbdelay, 1166 candbtimer, NULL); 1167 } 1168 #endif 1169 return; 1170 } 1171 if (parityerror(&frame)) 1172 return; 1173 /* panic?? */ 1174 printf("unexpected level 7 interrupt ignored\n"); 1175 } 1176 #endif 1177 1178 /* 1179 * should only get here, if no standard executable. This can currently 1180 * only mean, we're reading an old ZMAGIC file without MID, but since Amiga 1181 * ZMAGIC always worked the `right' way (;-)) just ignore the missing 1182 * MID and proceed to new zmagic code ;-) 1183 */ 1184 int 1185 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 1186 { 1187 #ifdef COMPAT_NOMID 1188 struct exec *execp = epp->ep_hdr; 1189 1190 if (!((execp->a_midmag >> 16) & 0x0fff) 1191 && execp->a_midmag == ZMAGIC) 1192 return(exec_aout_prep_zmagic(l, epp)); 1193 #endif 1194 return ENOEXEC; 1195 } 1196 1197 #ifdef MODULAR 1198 /* 1199 * Push any modules loaded by the bootloader etc. 1200 */ 1201 void 1202 module_init_md(void) 1203 { 1204 } 1205 1206 int _spllkm6(void); 1207 int _spllkm7(void); 1208 1209 #ifdef LEV6_DEFER 1210 int _spllkm6(void) { 1211 return spl4(); 1212 }; 1213 1214 int _spllkm7(void) { 1215 return spl4(); 1216 }; 1217 1218 #else 1219 1220 int _spllkm6(void) { 1221 return spl6(); 1222 }; 1223 1224 int _spllkm7(void) { 1225 return spl7(); 1226 }; 1227 1228 #endif 1229 1230 #endif 1231 1232 int ipl2spl_table[_NIPL] = { 1233 [IPL_NONE] = PSL_IPL0|PSL_S, 1234 [IPL_SOFTCLOCK] = PSL_IPL1|PSL_S, 1235 [IPL_VM] = PSL_IPL4|PSL_S, 1236 #if defined(LEV6_DEFER) 1237 [IPL_SCHED] = PSL_IPL4|PSL_S, 1238 [IPL_HIGH] = PSL_IPL4|PSL_S, 1239 #else /* defined(LEV6_DEFER) */ 1240 [IPL_SCHED] = PSL_IPL6|PSL_S, 1241 [IPL_HIGH] = PSL_IPL7|PSL_S, 1242 #endif /* defined(LEV6_DEFER) */ 1243 }; 1244 1245 int 1246 mm_md_physacc(paddr_t pa, vm_prot_t prot) 1247 { 1248 1249 return (pa >= 0xfffffffc || pa < lowram) ? EFAULT : 0; 1250 } 1251