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