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