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