1 /* $NetBSD: machdep.c,v 1.25 2002/09/25 22:21:11 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 40 41 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.25 2002/09/25 22:21:11 thorpej Exp $"); 42 43 #include "opt_ddb.h" 44 #include "opt_kgdb.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/proc.h> 50 #include <sys/buf.h> 51 #include <sys/reboot.h> 52 #include <sys/conf.h> 53 #include <sys/file.h> 54 #include <sys/device.h> 55 #include <sys/malloc.h> 56 #include <sys/mbuf.h> 57 #include <sys/msgbuf.h> 58 #include <sys/ioctl.h> 59 #include <sys/tty.h> 60 #include <sys/mount.h> 61 #include <sys/user.h> 62 #include <sys/exec.h> 63 #include <sys/core.h> 64 #include <sys/kcore.h> 65 #include <sys/vnode.h> 66 #include <sys/syscallargs.h> 67 #ifdef KGDB 68 #include <sys/kgdb.h> 69 #endif 70 #include <sys/boot_flag.h> 71 72 #include <uvm/uvm_extern.h> 73 74 #include <sys/sysctl.h> 75 76 #include <machine/cpu.h> 77 #include <machine/reg.h> 78 #include <machine/psl.h> 79 #include <machine/pte.h> 80 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 81 82 #include <dev/cons.h> 83 84 #if defined(DDB) 85 #include <machine/db_machdep.h> 86 #include <ddb/db_sym.h> 87 #include <ddb/db_extern.h> 88 #endif 89 90 /* 91 * Info for CTL_HW 92 */ 93 char machine[] = MACHINE; 94 char cpu_model[60]; 95 96 /* Our exported CPU info; we can have only one. */ 97 struct cpu_info cpu_info_store; 98 99 extern char kernel_text[]; 100 extern char etext[]; 101 102 struct vm_map *exec_map = NULL; 103 struct vm_map *mb_map = NULL; 104 struct vm_map *phys_map = NULL; 105 106 caddr_t msgbufaddr; 107 int maxmem; /* max memory per process */ 108 int physmem; /* set by locore */ 109 /* 110 * safepri is a safe priority for sleep to set for a spin-wait 111 * during autoconfiguration or after a panic. 112 */ 113 int safepri = PSL_LOWIPL; 114 115 void luna68k_init __P((void)); 116 void identifycpu __P((void)); 117 void dumpsys __P((void)); 118 119 void straytrap __P((int, u_short)); 120 void nmihand __P((struct frame)); 121 122 int cpu_dumpsize __P((void)); 123 int cpu_dump __P((int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t *)); 124 void cpu_init_kcore_hdr __P((void)); 125 126 /* 127 * Machine-independent crash dump header info. 128 */ 129 cpu_kcore_hdr_t cpu_kcore_hdr; 130 131 int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */ 132 int sysconsole; /* console: 0 for ttya, 1 for video */ 133 134 extern struct consdev syscons; 135 extern void omfb_cnattach __P((void)); 136 extern void ws_cnattach __P((void)); 137 extern void syscnattach __P((int)); 138 139 /* 140 * On the 68020/68030, the value of delay_divisor is roughly 141 * 2048 / cpuspeed (where cpuspeed is in MHz). 142 * 143 * On the 68040/68060(?), the value of delay_divisor is roughly 144 * 759 / cpuspeed (where cpuspeed is in MHz). 145 * XXX -- is the above formula correct? 146 */ 147 int cpuspeed = 25; /* only used for printing later */ 148 int delay_divisor = 300; /* for delay() loop count */ 149 150 /* 151 * Early initialization, before main() is called. 152 */ 153 void 154 luna68k_init() 155 { 156 volatile unsigned char *pio0 = (void *)0x49000000; 157 int sw1, i; 158 char *cp; 159 extern char bootarg[64]; 160 161 extern paddr_t avail_start, avail_end; 162 163 /* 164 * Tell the VM system about available physical memory. The 165 * luna68k only has one segment. 166 */ 167 uvm_page_physload(atop(avail_start), atop(avail_end), 168 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 169 170 /* 171 * Initialize error message buffer (at end of core). 172 * avail_end was pre-decremented in pmap_bootstrap to compensate. 173 */ 174 for (i = 0; i < btoc(MSGBUFSIZE); i++) 175 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * NBPG, 176 avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE, 177 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 178 pmap_update(pmap_kernel()); 179 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 180 181 182 pio0[3] = 0xb6; 183 pio0[2] = 1 << 6; /* enable parity check */ 184 pio0[3] = 0xb6; 185 sw1 = pio0[0]; /* dipssw1 value */ 186 sw1 ^= 0xff; 187 sysconsole = !(sw1 & 0x2); /* console selection */ 188 189 boothowto = 0; 190 i = 0; 191 /* 192 * 'bootarg' has; 193 * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>" 194 * where <addr> is MAC address of which network loader used (not 195 * necessarily same as one at 0x4101.FFE0), <host> and <name> 196 * are the values of HOST and SERVER environment variables, 197 * 198 * NetBSD/luna68k cares only the first argment; any of "sda". 199 */ 200 for (cp = bootarg; *cp != ' '; cp++) { 201 BOOT_FLAG(*cp, boothowto); 202 if (i++ >= sizeof(bootarg)) 203 break; 204 } 205 #if 0 /* overload 1:sw1, which now means 'go ROM monitor' after poweron */ 206 if (boothowto == 0) 207 boothowto = (sw1 & 0x1) ? RB_SINGLE : 0; 208 #endif 209 } 210 211 /* 212 * Console initialization: called early on from main, 213 */ 214 void 215 consinit() 216 { 217 if (sysconsole == 0) 218 syscnattach(0); 219 else { 220 omfb_cnattach(); 221 ws_cnattach(); 222 } 223 224 #ifdef DDB 225 { 226 extern int end; 227 extern int *esym; 228 229 ddb_init(*(int *)&end, ((int *)&end) + 1, esym); 230 } 231 if (boothowto & RB_KDB) 232 cpu_Debugger(); 233 #endif 234 } 235 236 /* 237 * cpu_startup: allocate memory for variable-sized tables. 238 */ 239 void 240 cpu_startup() 241 { 242 caddr_t v; 243 u_int i, base, residual; 244 vaddr_t minaddr, maxaddr; 245 vsize_t size; 246 char pbuf[9]; 247 extern void greeting __P((void)); 248 249 /* 250 * Initialize the kernel crash dump header. 251 */ 252 cpu_init_kcore_hdr(); 253 254 /* 255 * Good {morning,afternoon,evening,night}. 256 */ 257 printf(version); 258 identifycpu(); 259 260 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 261 printf("total memory = %s\n", pbuf); 262 263 /* 264 * Find out how much space we need, allocate it, 265 * and then give everything true virtual addresses. 266 */ 267 size = (int)allocsys(NULL, NULL); 268 if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(size))) == 0) 269 panic("startup: no room for tables"); 270 if (allocsys(v, NULL) - v != size) 271 panic("startup: table size inconsistency"); 272 273 /* 274 * Now allocate buffers proper. They are different than the above 275 * in that they usually occupy more virtual memory than physical. 276 */ 277 size = MAXBSIZE * nbuf; 278 if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), 279 NULL, UVM_UNKNOWN_OFFSET, 0, 280 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 281 UVM_ADV_NORMAL, 0)) != 0) 282 panic("startup: cannot allocate VM for buffers"); 283 minaddr = (vaddr_t)buffers; 284 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { 285 /* don't want to alloc more physical mem than needed */ 286 bufpages = btoc(MAXBSIZE) * nbuf; 287 } 288 base = bufpages / nbuf; 289 residual = bufpages % nbuf; 290 for (i = 0; i < nbuf; i++) { 291 vsize_t curbufsize; 292 vaddr_t curbuf; 293 struct vm_page *pg; 294 295 /* 296 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 297 * that MAXBSIZE space, we allocate and map (base+1) pages 298 * for the first "residual" buffers, and then we allocate 299 * "base" pages for the rest. 300 */ 301 curbuf = (vsize_t) buffers + (i * MAXBSIZE); 302 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 303 304 while (curbufsize) { 305 pg = uvm_pagealloc(NULL, 0, NULL, 0); 306 if (pg == NULL) 307 panic("cpu_startup: not enough memory for " 308 "buffer cache"); 309 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 310 VM_PROT_READ|VM_PROT_WRITE); 311 curbuf += PAGE_SIZE; 312 curbufsize -= PAGE_SIZE; 313 } 314 } 315 pmap_update(pmap_kernel()); 316 317 /* 318 * Allocate a submap for exec arguments. This map effectively 319 * limits the number of processes exec'ing at any time. 320 */ 321 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 322 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 323 324 /* 325 * Allocate a submap for physio 326 */ 327 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 328 VM_PHYS_SIZE, 0, FALSE, NULL); 329 330 /* 331 * Finally, allocate mbuf cluster submap. 332 */ 333 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 334 nmbclusters * mclbytes, VM_MAP_INTRSAFE, 335 FALSE, NULL); 336 337 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 338 printf("avail memory = %s\n", pbuf); 339 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 340 printf("using %u buffers containing %s of memory\n", nbuf, pbuf); 341 342 /* 343 * Tell the VM system that the area before the text segment 344 * is invalid. 345 * 346 * XXX Should just change KERNBASE and VM_MIN_KERNEL_ADDRESS, 347 * XXX but not right now. 348 */ 349 if (uvm_map_protect(kernel_map, 0, round_page((vaddr_t)&kernel_text), 350 UVM_PROT_NONE, TRUE) != 0) 351 panic("can't mark pre-text pages off-limits"); 352 353 /* 354 * Tell the VM system that writing to kernel text isn't allowed. 355 * If we don't, we might end up COW'ing the text segment! 356 */ 357 if (uvm_map_protect(kernel_map, trunc_page((vaddr_t)&kernel_text), 358 trunc_page((vaddr_t)&etext), UVM_PROT_READ|UVM_PROT_EXEC, TRUE) 359 != 0) 360 panic("can't protect kernel text"); 361 362 /* 363 * Set up buffers, so they can be used to read disk labels. 364 */ 365 bufinit(); 366 367 /* 368 * Say "Hi" to the world 369 */ 370 greeting(); 371 } 372 373 /* 374 * Set registers on exec. 375 */ 376 void 377 setregs(p, pack, stack) 378 register struct proc *p; 379 struct exec_package *pack; 380 u_long stack; 381 { 382 struct frame *frame = (struct frame *)p->p_md.md_regs; 383 extern int fputype; 384 385 frame->f_sr = PSL_USERSET; 386 frame->f_pc = pack->ep_entry & ~1; 387 frame->f_regs[D0] = 0; 388 frame->f_regs[D1] = 0; 389 frame->f_regs[D2] = 0; 390 frame->f_regs[D3] = 0; 391 frame->f_regs[D4] = 0; 392 frame->f_regs[D5] = 0; 393 frame->f_regs[D6] = 0; 394 frame->f_regs[D7] = 0; 395 frame->f_regs[A0] = 0; 396 frame->f_regs[A1] = 0; 397 frame->f_regs[A2] = (int)p->p_psstr; 398 frame->f_regs[A3] = 0; 399 frame->f_regs[A4] = 0; 400 frame->f_regs[A5] = 0; 401 frame->f_regs[A6] = 0; 402 frame->f_regs[SP] = stack; 403 404 /* restore a null state frame */ 405 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; 406 if (fputype) 407 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); 408 } 409 410 void 411 identifycpu() 412 { 413 extern int cputype; 414 char *cpu; 415 416 bzero(cpu_model, sizeof(cpu_model)); 417 switch (cputype) { 418 case CPU_68030: 419 cpu = "MC68030 CPU+MMU, MC68882 FPU"; 420 machtype = LUNA_I; 421 cpuspeed = 20; delay_divisor = 102; /* 20MHz 68030 */ 422 hz = 60; 423 break; 424 #if defined(M68040) 425 case CPU_68040: 426 cpu = "MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches"; 427 machtype = LUNA_II; 428 cpuspeed = 25; delay_divisor = 300; /* 25MHz 68040 */ 429 break; 430 #endif 431 default: 432 panic("unknown CPU type"); 433 } 434 strcpy(cpu_model, cpu); 435 printf("%s\n", cpu_model); 436 } 437 438 /* 439 * machine dependent system variables. 440 */ 441 int 442 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 443 int *name; 444 u_int namelen; 445 void *oldp; 446 size_t *oldlenp; 447 void *newp; 448 size_t newlen; 449 struct proc *p; 450 { 451 dev_t consdev; 452 453 /* all sysctl names at this level are terminal */ 454 if (namelen != 1) 455 return (ENOTDIR); /* overloaded */ 456 457 switch (name[0]) { 458 case CPU_CONSDEV: 459 if (cn_tab != NULL) 460 consdev = cn_tab->cn_dev; 461 else 462 consdev = NODEV; 463 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 464 sizeof consdev)); 465 default: 466 return (EOPNOTSUPP); 467 } 468 /* NOTREACHED */ 469 } 470 471 int waittime = -1; 472 473 void 474 cpu_reboot(howto, bootstr) 475 volatile int howto; /* XXX to shutup GCC XXX */ 476 char *bootstr; 477 { 478 extern void doboot __P((void)); 479 480 /* take a snap shot before clobbering any registers */ 481 if (curproc && curproc->p_addr) 482 savectx(&curproc->p_addr->u_pcb); 483 484 /* If system is hold, just halt. */ 485 if (cold) { 486 howto |= RB_HALT; 487 goto haltsys; 488 } 489 490 boothowto = howto; 491 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 492 waittime = 0; 493 vfs_shutdown(); 494 /* 495 * If we've been adjusting the clock, the todr 496 * will be out of synch; adjust it now. 497 */ 498 resettodr(); 499 } 500 501 /* Disable interrupts. */ 502 splhigh(); 503 504 /* If rebooting and a dump is requested, do it. */ 505 if (howto & RB_DUMP) 506 dumpsys(); 507 508 haltsys: 509 /* Run any shutdown hooks. */ 510 doshutdownhooks(); 511 512 /* Finally, halt/reboot the system. */ 513 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 514 u_int8_t *pio = (void *)0x4d000000; 515 516 printf("power is going down.\n"); 517 DELAY(100000); 518 pio[3] = 0x94; 519 pio[2] = 0 << 4; 520 for (;;) /* NOP */; 521 } 522 if (howto & RB_HALT) { 523 printf("System halted. Hit any key to reboot.\n\n"); 524 (void)cngetc(); 525 } 526 527 printf("rebooting...\n"); 528 DELAY(100000); 529 doboot(); 530 /*NOTREACHED*/ 531 while (1) ; 532 } 533 534 /* 535 * Initialize the kernel crash dump header. 536 */ 537 void 538 cpu_init_kcore_hdr() 539 { 540 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 541 struct m68k_kcore_hdr *m = &h->un._m68k; 542 extern char end[]; 543 544 bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr)); 545 546 /* 547 * Initialize the `dispatcher' portion of the header. 548 */ 549 strcpy(h->name, machine); 550 h->page_size = NBPG; 551 h->kernbase = KERNBASE; 552 553 /* 554 * Fill in information about our MMU configuration. 555 */ 556 m->mmutype = mmutype; 557 m->sg_v = SG_V; 558 m->sg_frame = SG_FRAME; 559 m->sg_ishift = SG_ISHIFT; 560 m->sg_pmask = SG_PMASK; 561 m->sg40_shift1 = SG4_SHIFT1; 562 m->sg40_mask2 = SG4_MASK2; 563 m->sg40_shift2 = SG4_SHIFT2; 564 m->sg40_mask3 = SG4_MASK3; 565 m->sg40_shift3 = SG4_SHIFT3; 566 m->sg40_addr1 = SG4_ADDR1; 567 m->sg40_addr2 = SG4_ADDR2; 568 m->pg_v = PG_V; 569 m->pg_frame = PG_FRAME; 570 571 /* 572 * Initialize pointer to kernel segment table. 573 */ 574 m->sysseg_pa = (u_int32_t)(pmap_kernel()->pm_stpa); 575 576 /* 577 * Initialize relocation value such that: 578 * 579 * pa = (va - KERNBASE) + reloc 580 * 581 * Since we're linked and loaded at the same place, 582 * and the kernel is mapped va == pa, this is 0. 583 */ 584 m->reloc = 0; 585 586 /* 587 * Define the end of the relocatable range. 588 */ 589 m->relocend = (u_int32_t)end; 590 591 /* 592 * The luna68k has one contiguous memory segment. 593 */ 594 m->ram_segs[0].start = 0 /* lowram */; 595 m->ram_segs[0].size = ctob(physmem); 596 } 597 598 /* 599 * Compute the size of the machine-dependent crash dump header. 600 * Returns size in disk blocks. 601 */ 602 int 603 cpu_dumpsize() 604 { 605 int size; 606 607 size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); 608 return (btodb(roundup(size, dbtob(1)))); 609 } 610 611 /* 612 * Called by dumpsys() to dump the machine-dependent header. 613 */ 614 int 615 cpu_dump(dump, blknop) 616 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 617 daddr_t *blknop; 618 { 619 int buf[dbtob(1) / sizeof(int)]; 620 cpu_kcore_hdr_t *chdr; 621 kcore_seg_t *kseg; 622 int error; 623 624 kseg = (kcore_seg_t *)buf; 625 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 626 sizeof(int)]; 627 628 /* Create the segment header. */ 629 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 630 kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t)); 631 632 bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t)); 633 error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf)); 634 *blknop += btodb(sizeof(buf)); 635 return (error); 636 } 637 638 /* 639 * These variables are needed by /sbin/savecore 640 */ 641 u_int32_t dumpmag = 0x8fca0101; /* magic number */ 642 int dumpsize = 0; /* pages */ 643 long dumplo = 0; /* blocks */ 644 645 /* 646 * This is called by main to set dumplo and dumpsize. 647 * Dumps always skip the first NBPG of disk space 648 * in case there might be a disk label stored there. 649 * If there is extra space, put dump at the end to 650 * reduce the chance that swapping trashes it. 651 */ 652 void 653 cpu_dumpconf() 654 { 655 const struct bdevsw *bdev; 656 int chdrsize; /* size of dump header */ 657 int nblks; /* size of dump area */ 658 659 if (dumpdev == NODEV) 660 return; 661 bdev = bdevsw_lookup(dumpdev); 662 if (bdev == NULL) 663 panic("dumpconf: bad dumpdev=0x%x", dumpdev); 664 if (bdev->d_psize == NULL) 665 return; 666 nblks = (*bdev->d_psize)(dumpdev); 667 chdrsize = cpu_dumpsize(); 668 669 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); 670 671 /* 672 * Check do see if we will fit. Note we always skip the 673 * first NBPG in case there is a disk label there. 674 */ 675 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 676 dumpsize = 0; 677 dumplo = -1; 678 return; 679 } 680 681 /* 682 * Put dump at the end of the partition. 683 */ 684 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 685 } 686 687 /* 688 * Dump physical memory onto the dump device. Called by cpu_reboot(). 689 */ 690 void 691 dumpsys() 692 { 693 const struct bdevsw *bdev; 694 daddr_t blkno; /* current block to write */ 695 /* dump routine */ 696 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 697 int pg; /* page being dumped */ 698 paddr_t maddr; /* PA being dumped */ 699 int error; /* error code from (*dump)() */ 700 701 /* XXX initialized here because of gcc lossage */ 702 maddr = 0 /* lowram */; 703 pg = 0; 704 705 /* Make sure dump device is valid. */ 706 if (dumpdev == NODEV) 707 return; 708 bdev = bdevsw_lookup(dumpdev); 709 if (bdev == NULL) 710 return; 711 if (dumpsize == 0) { 712 cpu_dumpconf(); 713 if (dumpsize == 0) 714 return; 715 } 716 if (dumplo <= 0) { 717 printf("\ndump to dev %u,%u not possible\n", major(dumpdev), 718 minor(dumpdev)); 719 return; 720 } 721 dump = bdev->d_dump; 722 blkno = dumplo; 723 724 printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), 725 minor(dumpdev), dumplo); 726 727 printf("dump "); 728 729 /* Write the dump header. */ 730 error = cpu_dump(dump, &blkno); 731 if (error) 732 goto bad; 733 734 for (pg = 0; pg < dumpsize; pg++) { 735 #define NPGMB (1024*1024/NBPG) 736 /* print out how many MBs we have dumped */ 737 if (pg && (pg % NPGMB) == 0) 738 printf("%d ", pg / NPGMB); 739 #undef NPGMB 740 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 741 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 742 743 pmap_update(pmap_kernel()); 744 error = (*dump)(dumpdev, blkno, vmmap, NBPG); 745 bad: 746 switch (error) { 747 case 0: 748 maddr += NBPG; 749 blkno += btodb(NBPG); 750 break; 751 752 case ENXIO: 753 printf("device bad\n"); 754 return; 755 756 case EFAULT: 757 printf("device not ready\n"); 758 return; 759 760 case EINVAL: 761 printf("area improper\n"); 762 return; 763 764 case EIO: 765 printf("i/o error\n"); 766 return; 767 768 case EINTR: 769 printf("aborted from console\n"); 770 return; 771 772 default: 773 printf("error %d\n", error); 774 return; 775 } 776 } 777 printf("succeeded\n"); 778 } 779 780 void 781 straytrap(pc, evec) 782 int pc; 783 u_short evec; 784 { 785 printf("unexpected trap (vector offset %x) from %x\n", 786 evec & 0xFFF, pc); 787 } 788 789 int *nofault; 790 791 int 792 badaddr(addr, nbytes) 793 register caddr_t addr; 794 int nbytes; 795 { 796 register int i; 797 label_t faultbuf; 798 799 #ifdef lint 800 i = *addr; if (i) return (0); 801 #endif 802 803 nofault = (int *) &faultbuf; 804 if (setjmp((label_t *)nofault)) { 805 nofault = (int *) 0; 806 return(1); 807 } 808 809 switch (nbytes) { 810 case 1: 811 i = *(volatile char *)addr; 812 break; 813 814 case 2: 815 i = *(volatile short *)addr; 816 break; 817 818 case 4: 819 i = *(volatile int *)addr; 820 break; 821 822 default: 823 panic("badaddr: bad request"); 824 } 825 nofault = (int *) 0; 826 return (0); 827 } 828 829 void luna68k_abort __P((char *)); 830 831 static int innmihand; /* simple mutex */ 832 833 /* 834 * Level 7 interrupts are caused by e.g. the ABORT switch. 835 * 836 * If we have DDB, then break into DDB on ABORT. In a production 837 * environment, bumping the ABORT switch would be bad, so we enable 838 * panic'ing on ABORT with the kernel option "PANICBUTTON". 839 */ 840 void 841 nmihand(frame) 842 struct frame frame; 843 { 844 /* Prevent unwanted recursion */ 845 if (innmihand) 846 return; 847 innmihand = 1; 848 849 luna68k_abort("ABORT SWITCH"); 850 } 851 852 /* 853 * Common code for handling ABORT signals from buttons, switches, 854 * serial lines, etc. 855 */ 856 void 857 luna68k_abort(cp) 858 char *cp; 859 { 860 #ifdef DDB 861 printf("%s\n", cp); 862 cpu_Debugger(); 863 #else 864 #ifdef PANICBUTTON 865 panic(cp); 866 #else 867 printf("%s ignored\n", cp); 868 #endif /* PANICBUTTON */ 869 #endif /* DDB */ 870 } 871 872 /* 873 * cpu_exec_aout_makecmds(): 874 * cpu-dependent a.out format hook for execve(). 875 * 876 * Determine of the given exec package refers to something which we 877 * understand and, if so, set up the vmcmds for it. 878 */ 879 int 880 cpu_exec_aout_makecmds(p, epp) 881 struct proc *p; 882 struct exec_package *epp; 883 { 884 int error = ENOEXEC; 885 #ifdef COMPAT_SUNOS 886 extern sunos_exec_aout_makecmds 887 __P((struct proc *, struct exec_package *)); 888 if ((error = sunos_exec_aout_makecmds(p, epp)) == 0) 889 return 0; 890 #endif 891 return error; 892 } 893 894 /* 895 * Return the best possible estimate of the time in the timeval 896 * to which tvp points. Unfortunately, we can't read the hardware registers. 897 * We guarantee that the time will be greater than the value obtained by a 898 * previous call. 899 */ 900 void 901 microtime(tvp) 902 register struct timeval *tvp; 903 { 904 int s = splclock(); 905 static struct timeval lasttime; 906 907 *tvp = time; 908 #ifdef notdef 909 tvp->tv_usec += clkread(); 910 while (tvp->tv_usec >= 1000000) { 911 tvp->tv_sec++; 912 tvp->tv_usec -= 1000000; 913 } 914 #endif 915 if (tvp->tv_sec == lasttime.tv_sec && 916 tvp->tv_usec <= lasttime.tv_usec && 917 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 918 tvp->tv_sec++; 919 tvp->tv_usec -= 1000000; 920 } 921 lasttime = *tvp; 922 splx(s); 923 } 924 925 #if 1 926 927 struct consdev *cn_tab = &syscons; 928 929 #else 930 931 /* 932 * romcons is useful until m68k TC register is initialized. 933 */ 934 int romcngetc __P((dev_t)); 935 void romcnputc __P((dev_t, int)); 936 937 struct consdev romcons = { 938 NULL, 939 NULL, 940 romcngetc, 941 romcnputc, 942 nullcnpollc, 943 makedev(7, 0), /* XXX */ 944 CN_DEAD, 945 }; 946 struct consdev *cn_tab = &romcons; 947 948 #define __ ((int **)0x41000000) 949 #define GETC() (*(int (*)())__[6])() 950 #define PUTC(x) (*(void (*)())__[7])(x) 951 952 #define ROMPUTC(x) \ 953 ({ \ 954 register _r; \ 955 asm volatile (" \ 956 movc %%vbr,%0 ; \ 957 movel %0,%%sp@- ; \ 958 clrl %0 ; \ 959 movc %0,%%vbr" \ 960 : "=r" (_r)); \ 961 PUTC(x); \ 962 asm volatile (" \ 963 movel %%sp@+,%0 ; \ 964 movc %0,%%vbr" \ 965 : "=r" (_r)); \ 966 }) 967 968 #define ROMGETC() \ 969 ({ \ 970 register _r, _c; \ 971 asm volatile (" \ 972 movc %%vbr,%0 ; \ 973 movel %0,%%sp@- ; \ 974 clrl %0 ; \ 975 movc %0,%%vbr" \ 976 : "=r" (_r)); \ 977 _c = GETC(); \ 978 asm volatile (" \ 979 movel %%sp@+,%0 ; \ 980 movc %0,%%vbr" \ 981 : "=r" (_r)); \ 982 _c; \ 983 }) 984 985 void 986 romcnputc(dev, c) 987 dev_t dev; 988 int c; 989 { 990 int s; 991 992 s = splhigh(); 993 ROMPUTC(c); 994 splx(s); 995 } 996 997 int 998 romcngetc(dev) 999 dev_t dev; 1000 { 1001 int s, c; 1002 1003 do { 1004 s = splhigh(); 1005 c = ROMGETC(); 1006 splx(s); 1007 } while (c == -1); 1008 return c; 1009 } 1010 #endif 1011