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