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