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