1 /* $NetBSD: machdep.c,v 1.18 1997/06/12 15:46:50 mrg 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. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah Hdr: machdep.c 1.74 92/12/20 41 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/map.h> 48 #include <sys/proc.h> 49 #include <sys/buf.h> 50 #include <sys/reboot.h> 51 #include <sys/conf.h> 52 #include <sys/file.h> 53 #include <sys/clist.h> 54 #include <sys/callout.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/sysctl.h> 67 #include <sys/syscallargs.h> 68 #ifdef SYSVMSG 69 #include <sys/msg.h> 70 #endif 71 #ifdef SYSVSEM 72 #include <sys/sem.h> 73 #endif 74 #ifdef SYSVSHM 75 #include <sys/shm.h> 76 #endif 77 #ifdef KGDB 78 #include <sys/kgdb.h> 79 #endif 80 81 #include <vm/vm.h> 82 #include <vm/vm_map.h> 83 #include <vm/vm_kern.h> 84 #include <vm/vm_page.h> 85 86 #include <dev/cons.h> 87 88 #include <machine/cpu.h> 89 #include <machine/reg.h> 90 #include <machine/psl.h> 91 #include <machine/pte.h> 92 #include <machine/dvma.h> 93 #include <machine/kcore.h> 94 #include <machine/db_machdep.h> 95 #include <machine/idprom.h> 96 #include <machine/machdep.h> 97 98 extern char version[]; 99 100 /* Defined in locore.s */ 101 extern char kernel_text[]; 102 /* Defined by the linker */ 103 extern char etext[]; 104 105 int physmem; 106 int fputype; 107 int msgbufmapped; 108 struct msgbuf *msgbufp; 109 110 vm_offset_t vmmap; 111 112 /* 113 * safepri is a safe priority for sleep to set for a spin-wait 114 * during autoconfiguration or after a panic. 115 */ 116 int safepri = PSL_LOWIPL; 117 118 /* 119 * Declare these as initialized data so we can patch them. 120 */ 121 int nswbuf = 0; 122 #ifdef NBUF 123 int nbuf = NBUF; 124 #else 125 int nbuf = 0; 126 #endif 127 #ifdef BUFPAGES 128 int bufpages = BUFPAGES; 129 #else 130 int bufpages = 0; 131 #endif 132 133 unsigned char cpu_machine_id = 0; 134 char *cpu_string = NULL; 135 int cpu_has_vme = 0; 136 int has_iocache = 0; 137 138 static void identifycpu __P((void)); 139 static void initcpu __P((void)); 140 141 /* 142 * Console initialization: called early on from main, 143 * before vm init or cpu_startup. This system is able 144 * to setup the console much earlier than here (thanks 145 * to some help from the PROM monitor) so all that is 146 * left to do here is the debugger stuff. 147 */ 148 void 149 consinit() 150 { 151 152 #ifdef KGDB 153 /* XXX - Ask on console for kgdb_dev? */ 154 /* Note: this will just return if kgdb_dev<0 */ 155 if (boothowto & RB_KDB) 156 kgdb_connect(1); 157 #endif 158 #ifdef DDB 159 /* Now that we have a console, we can stop in DDB. */ 160 db_machine_init(); 161 ddb_init(); 162 if (boothowto & RB_KDB) 163 Debugger(); 164 #endif DDB 165 } 166 167 /* 168 * allocsys() - Private routine used by cpu_startup() below. 169 * 170 * Allocate space for system data structures. We are given 171 * a starting virtual address and we return a final virtual 172 * address; along the way we set each data structure pointer. 173 * 174 * We call allocsys() with 0 to find out how much space we want, 175 * allocate that much and fill it with zeroes, and then call 176 * allocsys() again with the correct base virtual address. 177 */ 178 #define valloc(name, type, num) \ 179 v = (caddr_t)(((name) = (type *)v) + (num)) 180 static caddr_t allocsys __P((caddr_t)); 181 static caddr_t 182 allocsys(v) 183 register caddr_t v; 184 { 185 186 #ifdef REAL_CLISTS 187 valloc(cfree, struct cblock, nclist); 188 #endif 189 valloc(callout, struct callout, ncallout); 190 #ifdef SYSVSHM 191 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 192 #endif 193 #ifdef SYSVSEM 194 valloc(sema, struct semid_ds, seminfo.semmni); 195 valloc(sem, struct sem, seminfo.semmns); 196 /* This is pretty disgusting! */ 197 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 198 #endif 199 #ifdef SYSVMSG 200 valloc(msgpool, char, msginfo.msgmax); 201 valloc(msgmaps, struct msgmap, msginfo.msgseg); 202 valloc(msghdrs, struct msg, msginfo.msgtql); 203 valloc(msqids, struct msqid_ds, msginfo.msgmni); 204 #endif 205 206 /* 207 * Determine how many buffers to allocate. We allocate 208 * the BSD standard of use 10% of memory for the first 2 Meg, 209 * 5% of remaining. Insure a minimum of 16 buffers. 210 * Allocate 1/2 as many swap buffer headers as file i/o buffers. 211 */ 212 if (bufpages == 0) { 213 /* We always have more than 2MB of memory. */ 214 bufpages = ((btoc(2 * 1024 * 1024) + physmem) / 215 (20 * CLSIZE)); 216 } 217 if (nbuf == 0) { 218 nbuf = bufpages; 219 if (nbuf < 16) 220 nbuf = 16; 221 } 222 if (nswbuf == 0) { 223 nswbuf = (nbuf / 2) &~ 1; /* force even */ 224 if (nswbuf > 256) 225 nswbuf = 256; /* sanity */ 226 } 227 valloc(swbuf, struct buf, nswbuf); 228 valloc(buf, struct buf, nbuf); 229 return v; 230 } 231 #undef valloc 232 233 /* 234 * cpu_startup: allocate memory for variable-sized tables, 235 * initialize cpu, and do autoconfiguration. 236 * 237 * This is called early in init_main.c:main(), after the 238 * kernel memory allocator is ready for use, but before 239 * the creation of processes 1,2, and mountroot, etc. 240 */ 241 void 242 cpu_startup() 243 { 244 caddr_t v; 245 int sz, i; 246 vm_size_t size; 247 int base, residual; 248 vm_offset_t minaddr, maxaddr; 249 250 /* 251 * Initialize message buffer (for kernel printf). 252 * This is put in physical page zero so it will 253 * always be in the same place after a reboot. 254 * Its mapping was prepared in pmap_bootstrap(). 255 * Also, offset some to avoid PROM scribbles. 256 */ 257 v = (caddr_t) KERNBASE; 258 msgbufp = (struct msgbuf *)(v + 0x1000); 259 msgbufmapped = 1; 260 261 /* 262 * Good {morning,afternoon,evening,night}. 263 */ 264 printf(version); 265 identifycpu(); 266 initfpu(); /* also prints FPU type */ 267 268 printf("real mem = %d\n", ctob(physmem)); 269 270 /* 271 * Find out how much space we need, allocate it, 272 * and then give everything true virtual addresses. 273 */ 274 sz = (int)allocsys((caddr_t)0); 275 if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0) 276 panic("startup: no room for tables"); 277 if (allocsys(v) - v != sz) 278 panic("startup: table size inconsistency"); 279 280 /* 281 * Now allocate buffers proper. They are different than the above 282 * in that they usually occupy more virtual memory than physical. 283 */ 284 size = MAXBSIZE * nbuf; 285 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 286 &maxaddr, size, TRUE); 287 minaddr = (vm_offset_t)buffers; 288 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 289 &minaddr, size, FALSE) != KERN_SUCCESS) 290 panic("startup: cannot allocate buffers"); 291 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { 292 /* don't want to alloc more physical mem than needed */ 293 bufpages = btoc(MAXBSIZE) * nbuf; 294 } 295 base = bufpages / nbuf; 296 residual = bufpages % nbuf; 297 for (i = 0; i < nbuf; i++) { 298 vm_size_t curbufsize; 299 vm_offset_t curbuf; 300 301 /* 302 * First <residual> buffers get (base+1) physical pages 303 * allocated for them. The rest get (base) physical pages. 304 * 305 * The rest of each buffer occupies virtual space, 306 * but has no physical memory allocated for it. 307 */ 308 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 309 curbufsize = CLBYTES * (i < residual ? base+1 : base); 310 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 311 vm_map_simplify(buffer_map, curbuf); 312 } 313 314 /* 315 * Allocate a submap for exec arguments. This map effectively 316 * limits the number of processes exec'ing at any time. 317 */ 318 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 319 16*NCARGS, TRUE); 320 321 /* 322 * We don't use a submap for physio, and use a separate map 323 * for DVMA allocations. Our vmapbuf just maps pages into 324 * the kernel map (any kernel mapping is OK) and then the 325 * device drivers clone the kernel mappings into DVMA space. 326 */ 327 328 /* 329 * Finally, allocate mbuf cluster submap. 330 */ 331 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 332 VM_MBUF_SIZE, FALSE); 333 334 /* 335 * Initialize callouts 336 */ 337 callfree = callout; 338 for (i = 1; i < ncallout; i++) 339 callout[i-1].c_next = &callout[i]; 340 callout[i-1].c_next = NULL; 341 342 printf("avail mem = %d\n", (int) ptoa(cnt.v_free_count)); 343 printf("using %d buffers containing %d bytes of memory\n", 344 nbuf, bufpages * CLBYTES); 345 346 /* 347 * Tell the VM system that writing to kernel text isn't allowed. 348 * If we don't, we might end up COW'ing the text segment! 349 */ 350 if (vm_map_protect(kernel_map, (vm_offset_t) kernel_text, 351 trunc_page((vm_offset_t) etext), 352 VM_PROT_READ|VM_PROT_EXECUTE, TRUE) 353 != KERN_SUCCESS) 354 panic("can't protect kernel text"); 355 356 /* 357 * Allocate a virtual page (for use by /dev/mem) 358 * This page is handed to pmap_enter() therefore 359 * it has to be in the normal kernel VA range. 360 */ 361 vmmap = kmem_alloc_wait(kernel_map, NBPG); 362 363 /* 364 * Create the DVMA maps. 365 */ 366 dvma_init(); 367 368 /* 369 * Set up CPU-specific registers, cache, etc. 370 */ 371 initcpu(); 372 373 /* 374 * Set up buffers, so they can be used to read disk labels. 375 */ 376 bufinit(); 377 378 /* 379 * Configure the system. 380 */ 381 configure(); 382 } 383 384 /* 385 * Set registers on exec. 386 * XXX Should clear registers except sp, pc, 387 * but would break init; should be fixed soon. 388 */ 389 void 390 setregs(p, pack, stack, retval) 391 register struct proc *p; 392 struct exec_package *pack; 393 u_long stack; 394 register_t *retval; 395 { 396 struct trapframe *tf = (struct trapframe *)p->p_md.md_regs; 397 398 tf->tf_pc = pack->ep_entry & ~1; 399 tf->tf_regs[SP] = stack; 400 tf->tf_regs[A2] = (int)PS_STRINGS; 401 402 /* restore a null state frame */ 403 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; 404 if (fputype) { 405 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); 406 } 407 p->p_md.md_flags = 0; 408 /* XXX - HPUX sigcode hack would go here... */ 409 } 410 411 /* 412 * Info for CTL_HW 413 */ 414 char machine[] = MACHINE; /* from <machine/param.h> */ 415 char cpu_model[120]; 416 417 /* 418 * XXX - Should empirically estimate the divisor... 419 * Note that the value of delay_divisor is roughly 420 * 2048 / cpuclock (where cpuclock is in MHz). 421 */ 422 int delay_divisor = 62; /* assume the fastest (33 MHz) */ 423 424 void 425 identifycpu() 426 { 427 unsigned char machtype; 428 429 /* Find the IDPROM and copy it to memory. */ 430 /* Note: this needs to use peek_byte(). */ 431 idprom_init(); 432 433 machtype = identity_prom.idp_machtype; 434 if ((machtype & CPU_ARCH_MASK) != SUN3X_ARCH) { 435 printf("not a sun3x?\n"); 436 sunmon_abort(); 437 } 438 439 cpu_machine_id = machtype & SUN3X_IMPL_MASK; 440 switch (cpu_machine_id) { 441 442 case SUN3X_MACH_80: 443 cpu_string = "80"; /* Hydra */ 444 delay_divisor = 102; /* 20 MHz */ 445 cpu_has_vme = FALSE; 446 break; 447 448 case SUN3X_MACH_470: 449 cpu_string = "470"; /* Pegasus */ 450 delay_divisor = 62; /* 33 MHz */ 451 cpu_has_vme = TRUE; 452 break; 453 454 default: 455 printf("unknown sun3x model\n"); 456 sunmon_abort(); 457 } 458 459 /* Other stuff? (VAC, mc6888x version, etc.) */ 460 sprintf(cpu_model, "Sun 3/%s", cpu_string); 461 462 printf("Model: %s (hostid %x)\n", cpu_model, (int) hostid); 463 } 464 465 /* 466 * machine dependent system variables. 467 */ 468 int 469 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 470 int *name; 471 u_int namelen; 472 void *oldp; 473 size_t *oldlenp; 474 void *newp; 475 size_t newlen; 476 struct proc *p; 477 { 478 int error; 479 dev_t consdev; 480 481 /* all sysctl names at this level are terminal */ 482 if (namelen != 1) 483 return (ENOTDIR); /* overloaded */ 484 485 switch (name[0]) { 486 case CPU_CONSDEV: 487 if (cn_tab != NULL) 488 consdev = cn_tab->cn_dev; 489 else 490 consdev = NODEV; 491 error = sysctl_rdstruct(oldp, oldlenp, newp, 492 &consdev, sizeof consdev); 493 break; 494 495 #if 0 /* XXX - Not yet... */ 496 case CPU_ROOT_DEVICE: 497 error = sysctl_rdstring(oldp, oldlenp, newp, root_device); 498 break; 499 500 case CPU_BOOTED_KERNEL: 501 error = sysctl_rdstring(oldp, oldlenp, newp, booted_kernel); 502 break; 503 #endif 504 505 default: 506 error = EOPNOTSUPP; 507 } 508 return (error); 509 } 510 511 /* See: sig_machdep.c */ 512 513 /* 514 * Do a sync in preparation for a reboot. 515 * XXX - This could probably be common code. 516 * XXX - And now, most of it is in vfs_shutdown() 517 * XXX - Put waittime checks in there too? 518 */ 519 int waittime = -1; /* XXX - Who else looks at this? -gwr */ 520 static void 521 reboot_sync __P((void)) 522 { 523 524 /* Check waittime here to localize its use to this function. */ 525 if (waittime >= 0) 526 return; 527 waittime = 0; 528 vfs_shutdown(); 529 } 530 531 /* 532 * Common part of the BSD and SunOS reboot system calls. 533 */ 534 __dead void 535 cpu_reboot(howto, user_boot_string) 536 int howto; 537 char *user_boot_string; 538 { 539 /* Note: this string MUST be static! */ 540 static char bootstr[128]; 541 char *p; 542 543 /* If system is cold, just halt. (early panic?) */ 544 if (cold) 545 goto haltsys; 546 547 if ((howto & RB_NOSYNC) == 0) { 548 reboot_sync(); 549 /* 550 * If we've been adjusting the clock, the todr 551 * will be out of synch; adjust it now. 552 * 553 * XXX - However, if the kernel has been sitting in ddb, 554 * the time will be way off, so don't set the HW clock! 555 * XXX - Should do sanity check against HW clock. -gwr 556 */ 557 /* resettodr(); */ 558 } 559 560 /* Disable interrupts. */ 561 splhigh(); 562 563 /* Write out a crash dump if asked. */ 564 if (howto & RB_DUMP) 565 dumpsys(); 566 567 /* run any shutdown hooks */ 568 doshutdownhooks(); 569 570 if (howto & RB_HALT) { 571 haltsys: 572 printf("Kernel halted.\n"); 573 #if 0 574 /* 575 * This calls the PROM monitor "exit_to_mon" function 576 * which appears to have problems... SunOS uses the 577 * "abort" function when you halt (bug work-around?) 578 * so we might as well do the same. 579 */ 580 sunmon_halt(); /* provokes PROM monitor bug */ 581 #else 582 sunmon_abort(); 583 #endif 584 } 585 586 /* 587 * Automatic reboot. 588 */ 589 if (user_boot_string) 590 strncpy(bootstr, user_boot_string, sizeof(bootstr)); 591 else { 592 /* 593 * Build our own boot string with an empty 594 * boot device/file and (maybe) some flags. 595 * The PROM will supply the device/file name. 596 */ 597 p = bootstr; 598 *p = '\0'; 599 if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) { 600 /* Append the boot flags. */ 601 *p++ = ' '; 602 *p++ = '-'; 603 if (howto & RB_KDB) 604 *p++ = 'd'; 605 if (howto & RB_ASKNAME) 606 *p++ = 'a'; 607 if (howto & RB_SINGLE) 608 *p++ = 's'; 609 *p = '\0'; 610 } 611 } 612 printf("Kernel rebooting...\n"); 613 sunmon_reboot(bootstr); 614 for (;;) ; 615 /*NOTREACHED*/ 616 } 617 618 /* 619 * These variables are needed by /sbin/savecore 620 */ 621 u_long dumpmag = 0x8fca0101; /* magic number */ 622 int dumpsize = 0; /* pages */ 623 long dumplo = 0; /* blocks */ 624 625 /* 626 * This is called by main to set dumplo, dumpsize. 627 * Dumps always skip the first CLBYTES of disk space 628 * in case there might be a disk label stored there. 629 * If there is extra space, put dump at the end to 630 * reduce the chance that swapping trashes it. 631 */ 632 void 633 cpu_dumpconf() 634 { 635 int nblks; /* size of dump area */ 636 int maj; 637 int (*getsize)__P((dev_t)); 638 639 if (dumpdev == NODEV) 640 return; 641 642 maj = major(dumpdev); 643 if (maj < 0 || maj >= nblkdev) 644 panic("dumpconf: bad dumpdev=0x%x", dumpdev); 645 getsize = bdevsw[maj].d_psize; 646 if (getsize == NULL) 647 return; 648 nblks = (*getsize)(dumpdev); 649 if (nblks <= ctod(1)) 650 return; 651 652 /* Position dump image near end of space, page aligned. */ 653 dumpsize = physmem; /* pages */ 654 dumplo = nblks - ctod(dumpsize); 655 dumplo &= ~(ctod(1)-1); 656 657 /* If it does not fit, truncate it by moving dumplo. */ 658 /* Note: Must force signed comparison. */ 659 if (dumplo < ((long)ctod(1))) { 660 dumplo = ctod(1); 661 dumpsize = dtoc(nblks - dumplo); 662 } 663 } 664 665 /* Note: gdb looks for "dumppcb" in a kernel crash dump. */ 666 struct pcb dumppcb; 667 668 /* 669 * Write a crash dump. The format while in swap is: 670 * kcore_seg_t cpu_hdr; 671 * cpu_kcore_hdr_t cpu_data; 672 * padding (NBPG-sizeof(kcore_seg_t)) 673 * pagemap (2*NBPG) 674 * physical memory... 675 */ 676 void 677 dumpsys() 678 { 679 struct bdevsw *dsw; 680 kcore_seg_t *kseg_p; 681 cpu_kcore_hdr_t *chdr_p; 682 struct sun3x_kcore_hdr *sh; 683 phys_ram_seg_t *crs_p; 684 char *vaddr; 685 vm_offset_t paddr; 686 int psize, todo, seg, segsz; 687 daddr_t blkno; 688 int error = 0; 689 690 msgbufmapped = 0; 691 if (dumpdev == NODEV) 692 return; 693 694 /* 695 * For dumps during autoconfiguration, 696 * if dump device has already configured... 697 */ 698 if (dumpsize == 0) 699 cpu_dumpconf(); 700 if (dumplo <= 0) 701 return; 702 savectx(&dumppcb); 703 704 dsw = &bdevsw[major(dumpdev)]; 705 psize = (*(dsw->d_psize))(dumpdev); 706 if (psize == -1) { 707 printf("dump area unavailable\n"); 708 return; 709 } 710 711 printf("\ndumping to dev %x, offset %d\n", 712 (int) dumpdev, (int) dumplo); 713 714 /* 715 * We put the dump header is in physical page zero, 716 * so there is no extra work here to write it out. 717 */ 718 kseg_p = (kcore_seg_t *)KERNBASE; 719 chdr_p = (cpu_kcore_hdr_t *) (kseg_p + 1); 720 sh = &chdr_p->un._sun3x; 721 CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 722 kseg_p->c_size = sizeof(*chdr_p); 723 pmap_set_kcore_hdr(chdr_p); 724 725 /* 726 * Now dump physical memory. Note that physical memory 727 * might NOT be congiguous, so do it by segments. 728 */ 729 730 blkno = dumplo; 731 todo = dumpsize; /* pages */ 732 vaddr = (char*)vmmap; /* Borrow /dev/mem VA */ 733 734 for (seg = 0; seg < SUN3X_NPHYS_RAM_SEGS; seg++) { 735 crs_p = &sh->ram_segs[seg]; 736 paddr = crs_p->start; 737 segsz = crs_p->size; 738 /* 739 * Our header lives in the first little bit of 740 * physical memory (not written separately), so 741 * we have to adjust the first ram segment size 742 * and start address to reflect the stolen RAM. 743 * (Nothing interesing in that RAM anyway 8^). 744 */ 745 if (seg == 0) { 746 int adj = sizeof(*kseg_p) + sizeof(*chdr_p); 747 crs_p->start += adj; 748 crs_p->size -= adj; 749 } 750 751 while (todo && (segsz > 0)) { 752 753 /* Print pages left after every 16. */ 754 if ((todo & 0xf) == 0) 755 printf("\r%4d", todo); 756 757 /* Make a temporary mapping for the page. */ 758 pmap_enter(pmap_kernel(), vmmap, paddr | PMAP_NC, 759 VM_PROT_READ, FALSE); 760 error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG); 761 pmap_remove(pmap_kernel(), vmmap, vmmap + NBPG); 762 if (error) 763 goto fail; 764 paddr += NBPG; 765 segsz -= NBPG; 766 blkno += btodb(NBPG); 767 todo--; 768 } 769 } 770 printf("\rdump succeeded\n"); 771 return; 772 fail: 773 printf(" dump error=%d\n", error); 774 } 775 776 static void 777 initcpu() 778 { 779 /* XXX: Enable RAM parity/ECC checking? */ 780 /* XXX: parityenable(); */ 781 782 #ifdef HAVECACHE 783 cache_enable(); 784 #endif 785 } 786 787 /* straptrap() in trap.c */ 788 789 /* from hp300: badaddr() */ 790 /* peek_byte(), peek_word() moved to bus_subr.c */ 791 792 /* XXX: parityenable() ? */ 793 /* regdump() moved to regdump.c */ 794 795 /* 796 * cpu_exec_aout_makecmds(): 797 * cpu-dependent a.out format hook for execve(). 798 * 799 * Determine if the given exec package refers to something which we 800 * understand and, if so, set up the vmcmds for it. 801 */ 802 int 803 cpu_exec_aout_makecmds(p, epp) 804 struct proc *p; 805 struct exec_package *epp; 806 { 807 int error = ENOEXEC; 808 809 #ifdef COMPAT_SUNOS 810 extern sunos_exec_aout_makecmds 811 __P((struct proc *, struct exec_package *)); 812 if ((error = sunos_exec_aout_makecmds(p, epp)) == 0) 813 return 0; 814 #endif 815 return error; 816 } 817