1 /* $NetBSD: machdep.c,v 1.56 2011/01/17 14:53:42 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 36 * 37 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 38 */ 39 /* 40 * Copyright (c) 1988 University of Utah. 41 * 42 * This code is derived from software contributed to Berkeley by 43 * the Systems Programming Group of the University of Utah Computer 44 * Science Department. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 75 * 76 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 77 */ 78 79 #include <sys/cdefs.h> 80 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.56 2011/01/17 14:53:42 tsutsui Exp $"); 81 82 #include "opt_bufcache.h" 83 #include "opt_ddb.h" 84 #include "opt_kgdb.h" 85 #include "opt_compat_netbsd.h" 86 #include "opt_sysv.h" 87 #include "opt_panicbutton.h" 88 #include "opt_modular.h" 89 90 #include <sys/param.h> 91 #include <sys/systm.h> 92 #include <sys/buf.h> 93 #include <sys/callout.h> 94 #include <sys/conf.h> 95 #include <sys/exec.h> 96 #include <sys/exec_aout.h> /* for MID_* */ 97 #include <sys/file.h> 98 #include <sys/ioctl.h> 99 #include <sys/kernel.h> 100 #include <sys/malloc.h> 101 #include <sys/mbuf.h> 102 #include <sys/mount.h> 103 #include <sys/msgbuf.h> 104 #include <sys/proc.h> 105 #include <sys/reboot.h> 106 #include <sys/signalvar.h> 107 #include <sys/syscallargs.h> 108 #include <sys/tty.h> 109 #include <sys/vnode.h> 110 #include <sys/ksyms.h> 111 #include <sys/module.h> 112 #ifdef SYSVMSG 113 #include <sys/msg.h> 114 #endif 115 #ifdef SYSVSEM 116 #include <sys/sem.h> 117 #endif 118 #ifdef SYSVSHM 119 #include <sys/shm.h> 120 #endif 121 #include <sys/kgdb.h> 122 123 #include <machine/db_machdep.h> 124 #include <ddb/db_sym.h> 125 #include <ddb/db_extern.h> 126 127 #include <machine/autoconf.h> 128 #include <machine/cpu.h> 129 #include <machine/reg.h> 130 #include <machine/pcb.h> 131 #include <machine/psl.h> 132 #include <machine/pte.h> 133 134 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 135 136 #include <uvm/uvm_extern.h> 137 138 #include <sys/sysctl.h> 139 #include <sys/device.h> 140 #include <dev/cons.h> 141 #include <dev/ic/z8530reg.h> 142 #include <machine/z8530var.h> 143 #include <cesfic/dev/zsvar.h> 144 145 #include "ksyms.h" 146 147 /* the following is used externally (sysctl_hw) */ 148 char machine[] = MACHINE; /* CPU "architecture" */ 149 150 /* Our exported CPU info; we can have only one. */ 151 struct cpu_info cpu_info_store; 152 153 struct vm_map *phys_map = NULL; 154 155 /* 156 * Declare these as initialized data so we can patch them. 157 */ 158 /*int maxmem;*/ /* max memory per process */ 159 int physmem = MAXMEM; /* max supported memory, changes to actual */ 160 /* 161 * safepri is a safe priority for sleep to set for a spin-wait 162 * during autoconfiguration or after a panic. 163 */ 164 int safepri = PSL_LOWIPL; 165 166 extern u_int lowram; 167 168 void fic_init(void); 169 170 /* prototypes for local functions */ 171 void identifycpu(void); 172 void dumpmem(int *, int, int); 173 char *hexstr(int, int); 174 175 /* functions called from locore.s */ 176 void dumpsys(void); 177 void straytrap(int, u_short); 178 void nmihand(struct frame); 179 180 int delay_divisor; /* delay constant */ 181 182 extern void sicinit(void*); 183 184 void fic_init(void) 185 { 186 int i; 187 188 extern paddr_t avail_start, avail_end; 189 190 boothowto = RB_SINGLE; /* XXX for now */ 191 boothowto |= RB_KDB; /* XXX for now */ 192 193 delay_divisor = 30; /* XXX */ 194 195 /* 196 * Tell the VM system about available physical memory. The 197 * fic uses one segment. 198 */ 199 uvm_page_physload(atop(avail_start), atop(avail_end), 200 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 201 202 /* 203 * map and init interrupt controller 204 */ 205 physaccess((void*)virtual_avail, (void*)0x44000000, 206 PAGE_SIZE, PG_RW|PG_CI); 207 sicinit((void*)virtual_avail); 208 virtual_avail += PAGE_SIZE; 209 210 /* 211 * Initialize error message buffer (at end of core). 212 * avail_end was pre-decremented in pmap_bootstrap to compensate. 213 */ 214 for (i = 0; i < btoc(MSGBUFSIZE); i++) 215 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE, 216 avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 217 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 218 pmap_update(pmap_kernel()); 219 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 220 } 221 222 int 223 zs_check_kgdb(struct zs_chanstate *cs, int dev) 224 { 225 226 if((boothowto & RB_KDB) && (dev == makedev(10, 0))) 227 return (1); 228 return (0); 229 } 230 231 void zs_kgdb_cnputc(dev_t, int); 232 void zs_kgdb_cnputc(dev, c) 233 dev_t dev; 234 int c; 235 { 236 zscnputc(dev, c); 237 } 238 int zs_kgdb_cngetc(dev_t); 239 int zs_kgdb_cngetc(dev) 240 dev_t dev; 241 { 242 return (zscngetc(dev)); 243 } 244 245 /* 246 * Console initialization: called early on from main, 247 * before vm init or startup. Do enough configuration 248 * to choose and initialize a console. 249 */ 250 extern void sic_enable_int(int, int, int, int, int); 251 void 252 consinit(void) 253 { 254 255 /* 256 * Initialize the console before we print anything out. 257 */ 258 physaccess((void*)virtual_avail, 259 (void*)0x58000000, PAGE_SIZE, PG_RW|PG_CI); 260 zs_cnattach((void*)virtual_avail); 261 virtual_avail += PAGE_SIZE; 262 263 #ifdef KGDB 264 kgdb_dev = 1; 265 kgdb_attach((void*)zscngetc, (void*)zscnputc, (void *)0); 266 267 if (boothowto & RB_KDB) { 268 kgdb_connect(1); 269 zscons.cn_putc = zs_kgdb_cnputc; 270 zscons.cn_getc = zs_kgdb_cngetc; 271 } 272 #endif 273 #ifdef DDB 274 if (boothowto & RB_KDB) 275 Debugger(); 276 #endif 277 sic_enable_int(39, 2, 1, 7, 0); /* NMI */ 278 } 279 280 /* 281 * cpu_startup: allocate memory for variable-sized tables, 282 * initialize CPU, and do autoconfiguration. 283 */ 284 void 285 cpu_startup(void) 286 { 287 vaddr_t minaddr, maxaddr; 288 #ifdef DEBUG 289 extern int pmapdebug; 290 int opmapdebug = pmapdebug; 291 292 pmapdebug = 0; 293 #endif 294 295 if (fputype != FPU_NONE) 296 m68k_make_fpu_idle_frame(); 297 298 /* 299 * Good {morning,afternoon,evening,night}. 300 */ 301 printf("%s%s", copyright, version); 302 identifycpu(); 303 printf("real mem = %d\n", ctob(physmem)); 304 305 minaddr = 0; 306 307 /* 308 * Allocate a submap for physio 309 */ 310 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 311 VM_PHYS_SIZE, 0, false, NULL); 312 313 #ifdef DEBUG 314 pmapdebug = opmapdebug; 315 #endif 316 printf("avail mem = %ld\n", ptoa(uvmexp.free)); 317 } 318 319 /* 320 * Set registers on exec. 321 * XXX Should clear registers except sp, pc, 322 * but would break init; should be fixed soon. 323 */ 324 void 325 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 326 { 327 struct frame *frame = (struct frame *)l->l_md.md_regs; 328 struct pcb *pcb = lwp_getpcb(l); 329 330 frame->f_sr = PSL_USERSET; 331 frame->f_pc = pack->ep_entry & ~1; 332 frame->f_regs[D0] = 0; 333 frame->f_regs[D1] = 0; 334 frame->f_regs[D2] = 0; 335 frame->f_regs[D3] = 0; 336 frame->f_regs[D4] = 0; 337 frame->f_regs[D5] = 0; 338 frame->f_regs[D6] = 0; 339 frame->f_regs[D7] = 0; 340 frame->f_regs[A0] = 0; 341 frame->f_regs[A1] = 0; 342 frame->f_regs[A2] = (int)l->l_proc->p_psstr; 343 frame->f_regs[A3] = 0; 344 frame->f_regs[A4] = 0; 345 frame->f_regs[A5] = 0; 346 frame->f_regs[A6] = 0; 347 frame->f_regs[SP] = stack; 348 349 /* restore a null state frame */ 350 pcb->pcb_fpregs.fpf_null = 0; 351 if (fputype) 352 m68881_restore(&pcb->pcb_fpregs); 353 } 354 355 /* 356 * Info for CTL_HW 357 */ 358 char cpu_model[] = "FIC8234"; 359 360 void 361 identifycpu(void) 362 { 363 printf("%s\n", cpu_model); 364 printf("delay constant: %d\n", delay_divisor); 365 } 366 367 /* 368 * machine dependent system variables. 369 */ 370 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 371 { 372 373 sysctl_createv(clog, 0, NULL, NULL, 374 CTLFLAG_PERMANENT, 375 CTLTYPE_NODE, "machdep", NULL, 376 NULL, 0, NULL, 0, 377 CTL_MACHDEP, CTL_EOL); 378 379 sysctl_createv(clog, 0, NULL, NULL, 380 CTLFLAG_PERMANENT, 381 CTLTYPE_STRUCT, "console_device", NULL, 382 sysctl_consdev, 0, NULL, sizeof(dev_t), 383 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 384 } 385 386 int waittime = -1; 387 388 void 389 cpu_reboot(int howto, char *bootstr) 390 { 391 struct pcb *pcb = lwp_getpcb(curlwp); 392 393 /* take a snap shot before clobbering any registers */ 394 if (pcb != NULL) 395 savectx(pcb); 396 397 /* If system is cold, just halt. */ 398 if (cold) { 399 howto |= RB_HALT; 400 goto haltsys; 401 } 402 403 boothowto = howto; 404 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 405 waittime = 0; 406 vfs_shutdown(); 407 /* 408 * If we've been adjusting the clock, the todr 409 * will be out of synch; adjust it now. 410 */ 411 resettodr(); 412 } 413 414 /* Disable interrupts. */ 415 splhigh(); 416 417 /* If rebooting and a dump is requested do it. */ 418 if (howto & RB_DUMP) 419 dumpsys(); 420 421 haltsys: 422 /* Run any shutdown hooks. */ 423 doshutdownhooks(); 424 425 pmf_system_shutdown(boothowto); 426 427 #if defined(PANICWAIT) && !defined(DDB) 428 if ((howto & RB_HALT) == 0 && panicstr) { 429 printf("hit any key to reboot...\n"); 430 (void)cngetc(); 431 printf("\n"); 432 } 433 #endif 434 435 /* Finally, halt/reboot the system. */ 436 if (howto & RB_HALT) { 437 printf("System halted. Hit any key to reboot.\n\n"); 438 (void)cngetc(); 439 } 440 441 printf("rebooting...\n"); 442 DELAY(1000000); 443 doboot(); 444 /*NOTREACHED*/ 445 } 446 447 /* 448 * These variables are needed by /sbin/savecore 449 */ 450 u_int32_t dumpmag = 0x8fca0101; /* magic number */ 451 int dumpsize = 0; /* pages */ 452 long dumplo = 0; /* blocks */ 453 454 /* 455 * This is called by main to set dumplo and dumpsize. 456 * Dumps always skip the first CLBYTES of disk space 457 * in case there might be a disk label stored there. 458 * If there is extra space, put dump at the end to 459 * reduce the chance that swapping trashes it. 460 */ 461 void 462 cpu_dumpconf(void) 463 { 464 const struct bdevsw *bdev; 465 int nblks; /* size of dump area */ 466 467 if (dumpdev == NODEV) 468 return; 469 bdev = bdevsw_lookup(dumpdev); 470 if (bdev == NULL) { 471 dumpdev = NODEV; 472 return; 473 } 474 if (bdev->d_psize == NULL) 475 return; 476 nblks = (*bdev->d_psize)(dumpdev); 477 if (nblks <= ctod(1)) 478 return; 479 480 /* 481 * XXX include the final RAM page which is not included in physmem. 482 */ 483 dumpsize = physmem + 1; 484 485 /* Always skip the first CLBYTES, in case there is a label there. */ 486 if (dumplo < ctod(1)) 487 dumplo = ctod(1); 488 489 /* Put dump at end of partition, and make it fit. */ 490 if (dumpsize > dtoc(nblks - dumplo)) 491 dumpsize = dtoc(nblks - dumplo); 492 if (dumplo < nblks - ctod(dumpsize)) 493 dumplo = nblks - ctod(dumpsize); 494 } 495 496 /* 497 * Dump physical memory onto the dump device. Called by doadump() 498 * in locore.s or by cpu_reboot() here in machdep.c 499 */ 500 void 501 dumpsys(void) 502 { 503 const struct bdevsw *bdev; 504 daddr_t blkno; /* current block to write */ 505 /* dump routine */ 506 int (*dump)(dev_t, daddr_t, void *, size_t); 507 int pg; /* page being dumped */ 508 vm_offset_t maddr; /* PA being dumped */ 509 int error; /* error code from (*dump)() */ 510 511 /* Don't put dump messages in msgbuf. */ 512 msgbufmapped = 0; 513 514 /* Make sure dump device is valid. */ 515 if (dumpdev == NODEV) 516 return; 517 bdev = bdevsw_lookup(dumpdev); 518 if (bdev == NULL) 519 return; 520 if (dumpsize == 0) { 521 cpu_dumpconf(); 522 if (dumpsize == 0) 523 return; 524 } 525 if (dumplo < 0) 526 return; 527 dump = bdev->d_dump; 528 blkno = dumplo; 529 530 printf("\ndumping to dev %"PRIx64", offset %ld\n", dumpdev, dumplo); 531 532 printf("dump "); 533 maddr = lowram; 534 for (pg = 0; pg < dumpsize; pg++) { 535 #define NPGMB (1024*1024/PAGE_SIZE) 536 /* print out how many MBs we have dumped */ 537 if (pg && (pg % NPGMB) == 0) 538 printf("%d ", pg / NPGMB); 539 #undef NPGMB 540 pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, maddr, 541 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 542 pmap_update(pmap_kernel()); 543 544 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 545 switch (error) { 546 case 0: 547 maddr += PAGE_SIZE; 548 blkno += btodb(PAGE_SIZE); 549 break; 550 551 case ENXIO: 552 printf("device bad\n"); 553 return; 554 555 case EFAULT: 556 printf("device not ready\n"); 557 return; 558 559 case EINVAL: 560 printf("area improper\n"); 561 return; 562 563 case EIO: 564 printf("i/o error\n"); 565 return; 566 567 case EINTR: 568 printf("aborted from console\n"); 569 return; 570 571 default: 572 printf("error %d\n", error); 573 return; 574 } 575 } 576 printf("succeeded\n"); 577 } 578 579 void 580 straytrap(int pc, u_short evec) 581 { 582 printf("unexpected trap (vector offset %x) from %x\n", 583 evec & 0xFFF, pc); 584 } 585 586 /* XXX should change the interface, and make one badaddr() function */ 587 588 int *nofault; 589 590 int 591 badaddr(void *addr) 592 { 593 int i; 594 label_t faultbuf; 595 596 nofault = (int *) &faultbuf; 597 if (setjmp((label_t *)nofault)) { 598 nofault = (int *) 0; 599 return (1); 600 } 601 i = *(volatile short *)addr; 602 nofault = (int *) 0; 603 return (0); 604 } 605 606 int 607 badbaddr(void *addr) 608 { 609 int i; 610 label_t faultbuf; 611 612 nofault = (int *) &faultbuf; 613 if (setjmp((label_t *)nofault)) { 614 nofault = (int *) 0; 615 return (1); 616 } 617 i = *(volatile char *)addr; 618 nofault = (int *) 0; 619 return (0); 620 } 621 622 #ifdef PANICBUTTON 623 /* 624 * Declare these so they can be patched. 625 */ 626 int panicbutton = 1; /* non-zero if panic buttons are enabled */ 627 int candbdiv = 2; /* give em half a second (hz / candbdiv) */ 628 629 void candbtimer(void *); 630 631 int crashandburn; 632 633 void 634 candbtimer(void *arg) 635 { 636 637 crashandburn = 0; 638 } 639 #endif /* PANICBUTTON */ 640 641 static int innmihand; /* simple mutex */ 642 643 /* 644 * Level 7 interrupts can be caused by the keyboard or parity errors. 645 */ 646 void 647 nmihand(struct frame frame) 648 { 649 650 /* Prevent unwanted recursion. */ 651 if (innmihand) 652 return; 653 innmihand = 1; 654 655 printf("NMI\n"); 656 #if defined(DDB) || defined(KGDB) 657 Debugger(); 658 #endif 659 660 innmihand = 0; 661 } 662 663 664 /* 665 * cpu_exec_aout_makecmds(): 666 * CPU-dependent a.out format hook for execve(). 667 * 668 * Determine of the given exec package refers to something which we 669 * understand and, if so, set up the vmcmds for it. 670 * 671 * XXX what are the special cases for the hp300? 672 * XXX why is this COMPAT_NOMID? was something generating 673 * hp300 binaries with an a_mid of 0? i thought that was only 674 * done on little-endian machines... -- cgd 675 */ 676 int 677 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 678 { 679 #if defined(COMPAT_NOMID) || defined(COMPAT_44) 680 u_long midmag, magic; 681 u_short mid; 682 int error; 683 struct exec *execp = epp->ep_hdr; 684 685 midmag = ntohl(execp->a_midmag); 686 mid = (midmag >> 16) & 0xffff; 687 magic = midmag & 0xffff; 688 689 midmag = mid << 16 | magic; 690 691 switch (midmag) { 692 #ifdef COMPAT_NOMID 693 case (MID_ZERO << 16) | ZMAGIC: 694 error = exec_aout_prep_oldzmagic(l, epp); 695 return (error); 696 #endif 697 #ifdef COMPAT_44 698 case (MID_HP300 << 16) | ZMAGIC: 699 error = exec_aout_prep_oldzmagic(l, epp); 700 return (error); 701 #endif 702 } 703 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */ 704 705 return ENOEXEC; 706 } 707 708 #ifdef MODULAR 709 /* 710 * Push any modules loaded by the bootloader etc. 711 */ 712 void 713 module_init_md(void) 714 { 715 } 716 #endif 717