1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department and Ralph Campbell. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: machdep.c 1.63 91/04/24$ 13 * 14 * @(#)machdep.c 7.1 (Berkeley) 01/07/92 15 */ 16 17 #include "param.h" 18 #include "systm.h" 19 #include "signalvar.h" 20 #include "kernel.h" 21 #include "map.h" 22 #include "proc.h" 23 #include "buf.h" 24 #include "reboot.h" 25 #include "conf.h" 26 #include "file.h" 27 #include "clist.h" 28 #include "callout.h" 29 #include "malloc.h" 30 #include "mbuf.h" 31 #include "msgbuf.h" 32 #include "user.h" 33 #ifdef SYSVSHM 34 #include "shm.h" 35 #endif 36 37 #include "vm/vm.h" 38 #include "vm/vm_kern.h" 39 #include "vm/vm_page.h" 40 41 #include "../include/cpu.h" 42 #include "../include/reg.h" 43 #include "../include/psl.h" 44 #include "../include/machMon.h" 45 #include "clockreg.h" 46 #include "pte.h" 47 48 #define MAXMEM 24*1024*CLSIZE /* XXX - from cmap.h */ 49 50 vm_map_t buffer_map; 51 52 /* 53 * Declare these as initialized data so we can patch them. 54 */ 55 int nswbuf = 0; 56 #ifdef NBUF 57 int nbuf = NBUF; 58 #else 59 int nbuf = 0; 60 #endif 61 #ifdef BUFPAGES 62 int bufpages = BUFPAGES; 63 #else 64 int bufpages = 0; 65 #endif 66 int msgbufmapped; /* set when safe to use msgbuf */ 67 int maxmem; /* max memory per process */ 68 int physmem = MAXMEM; /* max supported memory, changes to actual */ 69 /* 70 * safepri is a safe priority for sleep to set for a spin-wait 71 * during autoconfiguration or after a panic. 72 */ 73 int safepri = PSL_LOWIPL; 74 75 struct user *proc0paddr; 76 struct proc nullproc; /* for use by swtch_exit() */ 77 78 /* 79 * Do all the stuff that locore normally does before calling main(). 80 * Process arguments passed to us by the prom monitor. 81 * Return the first page address following the system. 82 */ 83 mach_init(argc, argv) 84 int argc; 85 char *argv[]; 86 { 87 register char *cp; 88 register int i; 89 register unsigned firstaddr; 90 register caddr_t v; 91 extern char edata[], end[]; 92 extern char MachUTLBMiss[], MachUTLBMissEnd[]; 93 extern char MachException[], MachExceptionEnd[]; 94 #ifdef ATTR 95 extern char *pmap_attributes; 96 #endif 97 98 /* clear BSS segment, pages for u, and proc[0] page table */ 99 v = (caddr_t)pmax_round_page(end) + 2 * UPAGES * NBPG; 100 bzero(edata, v - edata); 101 102 /* look at argv[0] and compute bootdev */ 103 makebootdev(argv[0]); 104 105 /* 106 * Look at arguments passed to us and compute boothowto. 107 */ 108 #ifdef GENERIC 109 boothowto = RB_SINGLE | RB_ASKNAME; 110 #else 111 boothowto = RB_SINGLE | RB_DFLTROOT; 112 #endif 113 if (argc > 1) { 114 for (i = 1; i < argc; i++) { 115 for (cp = argv[i]; *cp; cp++) { 116 switch (*cp) { 117 case '-': 118 continue; 119 120 case '0': /* XXX */ 121 case '1': /* XXX */ 122 case '2': /* XXX */ 123 case '3': /* XXX */ 124 case '4': /* XXX */ 125 case '5': /* XXX */ 126 case '6': /* XXX */ 127 { 128 extern int sii_debug; 129 130 sii_debug = *cp - '0'; 131 break; 132 } 133 134 case 'a': /* autoboot */ 135 boothowto &= ~RB_SINGLE; 136 break; 137 138 case 'n': /* ask for names */ 139 boothowto |= RB_ASKNAME; 140 boothowto &= ~RB_DFLTROOT; 141 break; 142 143 case 'N': /* don't ask for names */ 144 boothowto &= ~RB_ASKNAME; 145 boothowto |= RB_DFLTROOT; 146 } 147 } 148 } 149 } 150 151 /* 152 * Init mapping for u page(s) for proc[0], pm_tlbpid 1. 153 */ 154 firstaddr = pmax_round_page(end); 155 curproc->p_addr = proc0paddr = (struct user *)firstaddr; 156 curproc->p_regs = proc0paddr->u_pcb.pcb_regs; 157 for (i = 0; i < UPAGES; i++) { 158 MachTLBWriteIndexed(i, 159 (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT), 160 curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M); 161 firstaddr += NBPG; 162 } 163 MachSetPID(1); 164 165 /* 166 * init nullproc for swtch_exit(). 167 * init mapping for u page(s), pm_tlbpid 0 168 * This could be used for an idle process. 169 */ 170 nullproc.p_regs = ((struct user *)firstaddr)->u_pcb.pcb_regs; 171 for (i = 0; i < UPAGES; i++) { 172 nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M; 173 firstaddr += NBPG; 174 } 175 176 /* 177 * Copy down exception vector code. 178 */ 179 if (MachUTLBMissEnd - MachUTLBMiss > 0x80) 180 panic("startup: UTLB code too large"); 181 bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC, 182 MachUTLBMissEnd - MachUTLBMiss); 183 bcopy(MachException, (char *)MACH_GEN_EXC_VEC, 184 MachExceptionEnd - MachException); 185 186 /* 187 * Clear out the I and D caches. 188 */ 189 MachConfigCache(); 190 MachFlushCache(); 191 192 /* 193 * Find out how much memory is available. 194 */ 195 physmem = btoc(v - KERNBASE); 196 cp = (char *)(MACH_UNCACHED_MEMORY_ADDR + (physmem << PGSHIFT)); 197 while (cp < (char *)MACH_UNCACHED_FRAME_BUFFER_ADDR) { 198 if (badaddr(cp, 4)) 199 break; 200 cp += NBPG; 201 physmem++; 202 } 203 maxmem = physmem + btoc(KERNBASE); 204 205 /* 206 * Initialize error message buffer (at end of core). 207 */ 208 maxmem -= btoc(sizeof (struct msgbuf)); 209 msgbufp = (struct msgbuf *)(maxmem << PGSHIFT); 210 msgbufmapped = 1; 211 212 /* 213 * Allocate space for system data structures. 214 * The first available real memory address is in "firstaddr". 215 * The first available kernel virtual address is in "v". 216 * As pages of kernel virtual memory are allocated, "v" is incremented. 217 * As pages of memory are allocated and cleared, 218 * "firstaddr" is incremented. 219 */ 220 /* 221 * These data structures are allocated here instead of cpu_startup() 222 * because physical memory is directly addressable. We don't have 223 * to map these into virtual address space. 224 */ 225 firstaddr = (unsigned)v; 226 227 #define valloc(name, type, num) \ 228 (name) = (type *)v; v = (caddr_t)((name)+(num)) 229 #define valloclim(name, type, num, lim) \ 230 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 231 valloc(cfree, struct cblock, nclist); 232 valloc(callout, struct callout, ncallout); 233 valloc(swapmap, struct map, nswapmap = maxproc * 2); 234 #ifdef SYSVSHM 235 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 236 #endif 237 #ifdef ATTR 238 /* this is allocated here just to save a few bytes */ 239 valloc(pmap_attributes, char, physmem); 240 #endif 241 242 /* 243 * Determine how many buffers to allocate. 244 * We allocate more buffer space than the BSD standard of 245 * using 10% of memory for the first 2 Meg, 5% of remaining. 246 * We just allocate a flat 10%. Insure a minimum of 16 buffers. 247 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 248 */ 249 if (bufpages == 0) 250 bufpages = physmem / 10 / CLSIZE; 251 if (nbuf == 0) { 252 nbuf = bufpages; 253 if (nbuf < 16) 254 nbuf = 16; 255 } 256 if (nswbuf == 0) { 257 nswbuf = (nbuf / 2) &~ 1; /* force even */ 258 if (nswbuf > 256) 259 nswbuf = 256; /* sanity */ 260 } 261 valloc(swbuf, struct buf, nswbuf); 262 valloc(buf, struct buf, nbuf); 263 264 /* 265 * Clear allocated memory. 266 */ 267 v = (caddr_t)pmax_round_page(v); 268 bzero((caddr_t)firstaddr, (unsigned)v - firstaddr); 269 270 /* 271 * Initialize the virtual memory system. 272 */ 273 pmap_bootstrap((vm_offset_t)v); 274 } 275 276 /* 277 * Console initialization: called early on from main, 278 * before vm init or startup. Do enough configuration 279 * to choose and initialize a console. 280 */ 281 consinit() 282 { 283 284 #include "pm.h" 285 #if NPM > 0 286 /* 287 * Initialize the console before we print anything out. 288 */ 289 pminit(); 290 #endif 291 } 292 293 /* 294 * cpu_startup: allocate memory for variable-sized tables, 295 * initialize cpu, and do autoconfiguration. 296 */ 297 cpu_startup() 298 { 299 register unsigned i; 300 register caddr_t v, firstaddr; 301 int base, residual; 302 extern long Usrptsize; 303 extern struct map *useriomap; 304 #ifdef DEBUG 305 extern int pmapdebug; 306 int opmapdebug = pmapdebug; 307 #endif 308 vm_offset_t minaddr, maxaddr; 309 vm_size_t size; 310 311 #ifdef DEBUG 312 pmapdebug = 0; 313 #endif 314 315 /* 316 * Good {morning,afternoon,evening,night}. 317 */ 318 printf(version); 319 printf("real mem = %d\n", ctob(physmem)); 320 321 /* 322 * Allocate virtual address space for file I/O buffers. 323 * Note they are different than the array of headers, 'buf', 324 * and usually occupy more virtual memory than physical. 325 */ 326 size = MAXBSIZE * nbuf; 327 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers, 328 &maxaddr, size, FALSE); 329 minaddr = (vm_offset_t)buffers; 330 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 331 &minaddr, size, FALSE) != KERN_SUCCESS) 332 panic("startup: cannot allocate buffers"); 333 base = bufpages / nbuf; 334 residual = bufpages % nbuf; 335 for (i = 0; i < nbuf; i++) { 336 vm_size_t curbufsize; 337 vm_offset_t curbuf; 338 339 /* 340 * First <residual> buffers get (base+1) physical pages 341 * allocated for them. The rest get (base) physical pages. 342 * 343 * The rest of each buffer occupies virtual space, 344 * but has no physical memory allocated for it. 345 */ 346 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 347 curbufsize = CLBYTES * (i < residual ? base+1 : base); 348 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 349 vm_map_simplify(buffer_map, curbuf); 350 } 351 /* 352 * Allocate a submap for exec arguments. This map effectively 353 * limits the number of processes exec'ing at any time. 354 */ 355 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 356 16*NCARGS, TRUE); 357 /* 358 * Allocate a submap for physio 359 */ 360 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 361 VM_PHYS_SIZE, TRUE); 362 363 /* 364 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 365 * we use the more space efficient malloc in place of kmem_alloc. 366 */ 367 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 368 M_MBUF, M_NOWAIT); 369 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 370 mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr, 371 VM_MBUF_SIZE, FALSE); 372 /* 373 * Initialize callouts 374 */ 375 callfree = callout; 376 for (i = 1; i < ncallout; i++) 377 callout[i-1].c_next = &callout[i]; 378 379 #ifdef DEBUG 380 pmapdebug = opmapdebug; 381 #endif 382 printf("avail mem = %d\n", ptoa(cnt.v_free_count)); 383 printf("using %d buffers containing %d bytes of memory\n", 384 nbuf, bufpages * CLBYTES); 385 /* 386 * Set up CPU-specific registers, cache, etc. 387 */ 388 initcpu(); 389 390 /* 391 * Set up buffers, so they can be used to read disk labels. 392 */ 393 bufinit(); 394 395 /* 396 * Configure the system. 397 */ 398 configure(); 399 } 400 401 /* 402 * Set registers on exec. 403 * Clear all registers except sp, pc. 404 */ 405 setregs(p, entry, retval) 406 register struct proc *p; 407 u_long entry; 408 int retval[2]; 409 { 410 int sp = p->p_regs[SP]; 411 412 bzero((caddr_t)p->p_regs, (FSR + 1) * sizeof(int)); 413 p->p_regs[SP] = sp; 414 p->p_regs[PC] = entry; 415 p->p_regs[PS] = PSL_USERSET; 416 p->p_md.md_flags & ~MDP_FPUSED; 417 } 418 419 /* 420 * WARNING: code in locore.s assumes the layout shown for sf_signum 421 * thru sf_handler so... don't screw with them! 422 */ 423 struct sigframe { 424 int sf_signum; /* signo for handler */ 425 int sf_code; /* additional info for handler */ 426 struct sigcontext *sf_scp; /* context ptr for handler */ 427 sig_t sf_handler; /* handler addr for u_sigc */ 428 }; 429 430 #ifdef DEBUG 431 int sigdebug = 0; 432 int sigpid = 0; 433 #define SDB_FOLLOW 0x01 434 #define SDB_KSTACK 0x02 435 #define SDB_FPSTATE 0x04 436 #endif 437 438 /* 439 * Send an interrupt to process. 440 */ 441 void 442 sendsig(catcher, sig, mask, code) 443 sig_t catcher; 444 int sig, mask; 445 unsigned code; 446 { 447 register struct proc *p = curproc; 448 register struct sigframe *fp; 449 register struct sigacts *ps = p->p_sigacts; 450 register struct sigcontext *scp; 451 register int *regs; 452 int oonstack, fsize; 453 struct sigcontext ksc; 454 455 regs = p->p_regs; 456 oonstack = ps->ps_onstack; 457 /* 458 * Allocate and validate space for the signal handler 459 * context. Note that if the stack is in data space, the 460 * call to grow() is a nop, and the copyout() 461 * will fail if the process has not already allocated 462 * the space with a `brk'. 463 */ 464 if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) { 465 scp = (struct sigcontext *)ps->ps_sigsp - 1; 466 ps->ps_onstack = 1; 467 } else 468 scp = (struct sigcontext *)regs[SP] - 1; 469 fp = (struct sigframe *)scp - 1; 470 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 471 (void)grow(p, (unsigned)fp); 472 /* 473 * Build the signal context to be used by sigreturn. 474 */ 475 ksc.sc_onstack = oonstack; 476 ksc.sc_mask = mask; 477 ksc.sc_pc = regs[PC]; 478 ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ 479 bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1], 480 sizeof(ksc.sc_regs) - sizeof(int)); 481 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 482 if (ksc.sc_fpused) { 483 extern struct proc *machFPCurProcPtr; 484 485 /* if FPU has current state, save it first */ 486 if (p == machFPCurProcPtr) { 487 MachSaveCurFPState(p); 488 machFPCurProcPtr = (struct proc *)0; 489 } 490 bcopy((caddr_t)&p->p_regs[F0], (caddr_t)ksc.sc_fpregs, 491 sizeof(ksc.sc_fpregs)); 492 } 493 if (copyout((caddr_t)&ksc, (caddr_t)scp, sizeof(ksc))) { 494 /* 495 * Process has trashed its stack; give it an illegal 496 * instruction to halt it in its tracks. 497 */ 498 SIGACTION(p, SIGILL) = SIG_DFL; 499 sig = sigmask(SIGILL); 500 p->p_sigignore &= ~sig; 501 p->p_sigcatch &= ~sig; 502 p->p_sigmask &= ~sig; 503 psignal(p, SIGILL); 504 return; 505 } 506 /* 507 * Build the argument list for the signal handler. 508 */ 509 regs[A0] = sig; 510 regs[A1] = code; 511 regs[A2] = (int)scp; 512 regs[A3] = (int)catcher; 513 514 regs[PC] = (int)catcher; 515 regs[SP] = (int)fp; 516 regs[RA] = KERNBASE; /* this causes a trap which we interpret as 517 * meaning "do a sigreturn". */ 518 #ifdef DEBUG 519 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 520 printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", 521 p->p_pid, sig, &oonstack, fp, fp->sf_scp); 522 #endif 523 } 524 525 /* 526 * System call to cleanup state after a signal 527 * has been taken. Reset signal mask and 528 * stack state from context left by sendsig (above). 529 * Return to previous pc and psl as specified by 530 * context left by sendsig. Check carefully to 531 * make sure that the user has not modified the 532 * psl to gain improper priviledges or to cause 533 * a machine fault. 534 */ 535 /* ARGSUSED */ 536 sigreturn(p, uap, retval) 537 struct proc *p; 538 struct args { 539 struct sigcontext *sigcntxp; 540 } *uap; 541 int *retval; 542 { 543 register struct sigcontext *scp; 544 register int *regs; 545 struct sigcontext ksc; 546 int error; 547 548 register struct frame *frame; 549 register int rf; 550 struct sigcontext tsigc; 551 int flags; 552 553 scp = uap->sigcntxp; 554 #ifdef DEBUG 555 if (sigdebug & SDB_FOLLOW) 556 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 557 #endif 558 regs = p->p_regs; 559 /* 560 * Test and fetch the context structure. 561 * We grab it all at once for speed. 562 */ 563 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); 564 if (error != 0 || ksc.sc_regs[ZERO] != 0xACEDBADE || 565 (unsigned)ksc.sc_regs[SP] < (unsigned)regs[SP]) { 566 #ifdef DEBUG 567 if (!(sigdebug & SDB_FOLLOW)) 568 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 569 printf(" old sp %x ra %x pc %x\n", 570 regs[SP], regs[RA], regs[PC]); 571 printf(" new sp %x ra %x pc %x err %d z %x\n", 572 ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], 573 error, ksc.sc_regs[ZERO]); 574 #endif 575 if (regs[PC] == KERNBASE) { 576 int sig; 577 578 /* 579 * Process has trashed its stack; give it an illegal 580 * instruction to halt it in its tracks. 581 */ 582 SIGACTION(p, SIGILL) = SIG_DFL; 583 sig = sigmask(SIGILL); 584 p->p_sigignore &= ~sig; 585 p->p_sigcatch &= ~sig; 586 p->p_sigmask &= ~sig; 587 psignal(p, SIGILL); 588 } 589 return (EINVAL); 590 } 591 /* 592 * Restore the user supplied information 593 */ 594 p->p_sigacts->ps_onstack = scp->sc_onstack & 01; 595 p->p_sigmask = scp->sc_mask &~ sigcantmask; 596 regs[PC] = ksc.sc_pc; 597 bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)®s[1], 598 sizeof(ksc.sc_regs) - sizeof(int)); 599 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 600 if (ksc.sc_fpused) 601 bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_regs[F0], 602 sizeof(ksc.sc_fpregs)); 603 return (EJUSTRETURN); 604 } 605 606 int waittime = -1; 607 608 boot(howto) 609 register int howto; 610 { 611 612 trapDump("boot"); /* XXX */ 613 /* take a snap shot before clobbering any registers */ 614 if (curproc) 615 savectx(curproc->p_addr, 0); 616 617 howto |= RB_HALT; /* XXX */ 618 boothowto = howto; 619 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 620 register struct buf *bp; 621 int iter, nbusy; 622 623 waittime = 0; 624 (void) spl0(); 625 printf("syncing disks... "); 626 /* 627 * Release vnodes held by texts before sync. 628 */ 629 if (panicstr == 0) 630 vnode_pager_umount(NULL); 631 #ifdef notdef 632 #include "fd.h" 633 #if NFD > 0 634 fdshutdown(); 635 #endif 636 #endif 637 sync(&proc0, (void *)NULL, (int *)NULL); 638 639 for (iter = 0; iter < 20; iter++) { 640 nbusy = 0; 641 for (bp = &buf[nbuf]; --bp >= buf; ) 642 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 643 nbusy++; 644 if (nbusy == 0) 645 break; 646 printf("%d ", nbusy); 647 DELAY(40000 * iter); 648 } 649 if (nbusy) 650 printf("giving up\n"); 651 else 652 printf("done\n"); 653 /* 654 * If we've been adjusting the clock, the todr 655 * will be out of synch; adjust it now. 656 */ 657 resettodr(); 658 } 659 (void) splhigh(); /* extreme priority */ 660 if (howto & RB_HALT) { 661 #ifdef DEBUG 662 void (*f)() = (void (*)())MACH_MON_RESTART; 663 #else 664 void (*f)() = (void (*)())MACH_MON_REINIT; 665 #endif 666 667 (*f)(); /* jump back to prom monitor */ 668 } else { 669 void (*f)() = (void (*)())MACH_MON_AUTOBOOT; 670 671 if (howto & RB_DUMP) 672 dumpsys(); 673 (*f)(); /* jump back to prom monitor and do 'auto' cmd */ 674 /*NOTREACHED*/ 675 } 676 /*NOTREACHED*/ 677 } 678 679 int dumpmag = 0x8fca0101; /* magic number for savecore */ 680 int dumpsize = 0; /* also for savecore */ 681 long dumplo = 0; 682 683 dumpconf() 684 { 685 int nblks; 686 687 dumpsize = physmem; 688 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 689 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 690 if (dumpsize > btoc(dbtob(nblks - dumplo))) 691 dumpsize = btoc(dbtob(nblks - dumplo)); 692 else if (dumplo == 0) 693 dumplo = nblks - btodb(ctob(physmem)); 694 } 695 /* 696 * Don't dump on the first CLBYTES (why CLBYTES?) 697 * in case the dump device includes a disk label. 698 */ 699 if (dumplo < btodb(CLBYTES)) 700 dumplo = btodb(CLBYTES); 701 } 702 703 /* 704 * Doadump comes here after turning off memory management and 705 * getting on the dump stack, either when called above, or by 706 * the auto-restart code. 707 */ 708 dumpsys() 709 { 710 int error; 711 712 msgbufmapped = 0; 713 if (dumpdev == NODEV) 714 return; 715 /* 716 * For dumps during autoconfiguration, 717 * if dump device has already configured... 718 */ 719 if (dumpsize == 0) 720 dumpconf(); 721 if (dumplo < 0) 722 return; 723 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 724 printf("dump "); 725 switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 726 727 case ENXIO: 728 printf("device bad\n"); 729 break; 730 731 case EFAULT: 732 printf("device not ready\n"); 733 break; 734 735 case EINVAL: 736 printf("area improper\n"); 737 break; 738 739 case EIO: 740 printf("i/o error\n"); 741 break; 742 743 default: 744 printf("error %d\n", error); 745 break; 746 747 case 0: 748 printf("succeeded\n"); 749 } 750 } 751 752 /* 753 * Return the best possible estimate of the time in the timeval 754 * to which tvp points. Unfortunately, we can't read the hardware registers. 755 * We guarantee that the time will be greater than the value obtained by a 756 * previous call. 757 */ 758 microtime(tvp) 759 register struct timeval *tvp; 760 { 761 int s = splclock(); 762 static struct timeval lasttime; 763 764 *tvp = time; 765 #ifdef notdef 766 tvp->tv_usec += clkread(); 767 while (tvp->tv_usec > 1000000) { 768 tvp->tv_sec++; 769 tvp->tv_usec -= 1000000; 770 } 771 #endif 772 if (tvp->tv_sec == lasttime.tv_sec && 773 tvp->tv_usec <= lasttime.tv_usec && 774 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 775 tvp->tv_sec++; 776 tvp->tv_usec -= 1000000; 777 } 778 lasttime = *tvp; 779 splx(s); 780 } 781 782 initcpu() 783 { 784 register volatile struct chiptime *c; 785 int i; 786 787 /* disable clock interrupts (until startrtclock()) */ 788 c = (volatile struct chiptime *)MACH_CLOCK_ADDR; 789 c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT; 790 i = c->regc; 791 spl0(); /* safe to turn interrupts on now */ 792 return (i); 793 } 794