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