1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990 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. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: machdep.c 1.68 92/01/20$ 13 * 14 * @(#)machdep.c 7.28 (Berkeley) 06/05/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 "mount.h" 33 #include "user.h" 34 #include "exec.h" 35 #ifdef SYSVSHM 36 #include "shm.h" 37 #endif 38 #ifdef HPUXCOMPAT 39 #include "hp/hpux/hpux.h" 40 #endif 41 42 #include "../include/cpu.h" 43 #include "../include/reg.h" 44 #include "../include/psl.h" 45 #include "isr.h" 46 #include "pte.h" 47 #include "net/netisr.h" 48 49 #define MAXMEM 64*1024*CLSIZE /* XXX - from cmap.h */ 50 #include "vm/vm_kern.h" 51 52 vm_map_t buffer_map; 53 extern vm_offset_t avail_end; 54 55 /* 56 * Declare these as initialized data so we can patch them. 57 */ 58 int nswbuf = 0; 59 #ifdef NBUF 60 int nbuf = NBUF; 61 #else 62 int nbuf = 0; 63 #endif 64 #ifdef BUFPAGES 65 int bufpages = BUFPAGES; 66 #else 67 int bufpages = 0; 68 #endif 69 int msgbufmapped; /* set when safe to use msgbuf */ 70 int maxmem; /* max memory per process */ 71 int physmem = MAXMEM; /* max supported memory, changes to actual */ 72 /* 73 * safepri is a safe priority for sleep to set for a spin-wait 74 * during autoconfiguration or after a panic. 75 */ 76 int safepri = PSL_LOWIPL; 77 78 extern u_int lowram; 79 80 /* 81 * Console initialization: called early on from main, 82 * before vm init or startup. Do enough configuration 83 * to choose and initialize a console. 84 */ 85 consinit() 86 { 87 88 /* 89 * Set cpuspeed immediately since cninit() called routines 90 * might use delay. 91 */ 92 switch (machineid) { 93 case HP_320: 94 case HP_330: 95 case HP_340: 96 cpuspeed = MHZ_16; 97 break; 98 case HP_350: 99 case HP_360: 100 cpuspeed = MHZ_25; 101 break; 102 case HP_370: 103 cpuspeed = MHZ_33; 104 break; 105 case HP_375: 106 cpuspeed = MHZ_50; 107 break; 108 case HP_380: 109 cpuspeed = MHZ_25 * 2; /* XXX */ 110 break; 111 } 112 /* 113 * Find what hardware is attached to this machine. 114 */ 115 find_devs(); 116 117 /* 118 * Initialize the console before we print anything out. 119 */ 120 cninit(); 121 } 122 123 /* 124 * cpu_startup: allocate memory for variable-sized tables, 125 * initialize cpu, and do autoconfiguration. 126 */ 127 cpu_startup() 128 { 129 register unsigned i; 130 register caddr_t v, firstaddr; 131 int base, residual; 132 vm_offset_t minaddr, maxaddr; 133 vm_size_t size; 134 #ifdef DEBUG 135 extern int pmapdebug; 136 int opmapdebug = pmapdebug; 137 138 pmapdebug = 0; 139 #endif 140 141 /* 142 * Initialize error message buffer (at end of core). 143 * avail_end was pre-decremented in pmap_bootstrap to compensate. 144 */ 145 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 146 pmap_enter(kernel_pmap, (vm_offset_t)msgbufp, 147 avail_end + i * NBPG, VM_PROT_ALL, TRUE); 148 msgbufmapped = 1; 149 150 /* 151 * Good {morning,afternoon,evening,night}. 152 */ 153 printf(version); 154 identifycpu(); 155 printf("real mem = %d\n", ctob(physmem)); 156 157 /* 158 * Allocate space for system data structures. 159 * The first available real memory address is in "firstaddr". 160 * The first available kernel virtual address is in "v". 161 * As pages of kernel virtual memory are allocated, "v" is incremented. 162 * As pages of memory are allocated and cleared, 163 * "firstaddr" is incremented. 164 * An index into the kernel page table corresponding to the 165 * virtual memory address maintained in "v" is kept in "mapaddr". 166 */ 167 /* 168 * Make two passes. The first pass calculates how much memory is 169 * needed and allocates it. The second pass assigns virtual 170 * addresses to the various data structures. 171 */ 172 firstaddr = 0; 173 again: 174 v = (caddr_t)firstaddr; 175 176 #define valloc(name, type, num) \ 177 (name) = (type *)v; v = (caddr_t)((name)+(num)) 178 #define valloclim(name, type, num, lim) \ 179 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 180 valloc(cfree, struct cblock, nclist); 181 valloc(callout, struct callout, ncallout); 182 valloc(swapmap, struct map, nswapmap = maxproc * 2); 183 #ifdef SYSVSHM 184 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 185 #endif 186 187 /* 188 * Determine how many buffers to allocate. 189 * Since HPs tend to be long on memory and short on disk speed, 190 * we allocate more buffer space than the BSD standard of 191 * use 10% of memory for the first 2 Meg, 5% of remaining. 192 * We just allocate a flat 10%. Insure a minimum of 16 buffers. 193 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 194 */ 195 if (bufpages == 0) 196 bufpages = physmem / 10 / CLSIZE; 197 if (nbuf == 0) { 198 nbuf = bufpages; 199 if (nbuf < 16) 200 nbuf = 16; 201 } 202 if (nswbuf == 0) { 203 nswbuf = (nbuf / 2) &~ 1; /* force even */ 204 if (nswbuf > 256) 205 nswbuf = 256; /* sanity */ 206 } 207 valloc(swbuf, struct buf, nswbuf); 208 valloc(buf, struct buf, nbuf); 209 /* 210 * End of first pass, size has been calculated so allocate memory 211 */ 212 if (firstaddr == 0) { 213 size = (vm_size_t)(v - firstaddr); 214 firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size)); 215 if (firstaddr == 0) 216 panic("startup: no room for tables"); 217 goto again; 218 } 219 /* 220 * End of second pass, addresses have been assigned 221 */ 222 if ((vm_size_t)(v - firstaddr) != size) 223 panic("startup: table size inconsistency"); 224 /* 225 * Now allocate buffers proper. They are different than the above 226 * in that they usually occupy more virtual memory than physical. 227 */ 228 size = MAXBSIZE * nbuf; 229 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 230 &maxaddr, size, FALSE); 231 minaddr = (vm_offset_t)buffers; 232 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 233 &minaddr, size, FALSE) != KERN_SUCCESS) 234 panic("startup: cannot allocate buffers"); 235 base = bufpages / nbuf; 236 residual = bufpages % nbuf; 237 for (i = 0; i < nbuf; i++) { 238 vm_size_t curbufsize; 239 vm_offset_t curbuf; 240 241 /* 242 * First <residual> buffers get (base+1) physical pages 243 * allocated for them. The rest get (base) physical pages. 244 * 245 * The rest of each buffer occupies virtual space, 246 * but has no physical memory allocated for it. 247 */ 248 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 249 curbufsize = CLBYTES * (i < residual ? base+1 : base); 250 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 251 vm_map_simplify(buffer_map, curbuf); 252 } 253 /* 254 * Allocate a submap for exec arguments. This map effectively 255 * limits the number of processes exec'ing at any time. 256 */ 257 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 258 16*NCARGS, TRUE); 259 /* 260 * Allocate a submap for physio 261 */ 262 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 263 VM_PHYS_SIZE, TRUE); 264 265 /* 266 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 267 * we use the more space efficient malloc in place of kmem_alloc. 268 */ 269 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 270 M_MBUF, M_NOWAIT); 271 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 272 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 273 VM_MBUF_SIZE, FALSE); 274 /* 275 * Initialize callouts 276 */ 277 callfree = callout; 278 for (i = 1; i < ncallout; i++) 279 callout[i-1].c_next = &callout[i]; 280 callout[i-1].c_next = NULL; 281 282 #ifdef DEBUG 283 pmapdebug = opmapdebug; 284 #endif 285 printf("avail mem = %d\n", ptoa(cnt.v_free_count)); 286 printf("using %d buffers containing %d bytes of memory\n", 287 nbuf, bufpages * CLBYTES); 288 /* 289 * Set up CPU-specific registers, cache, etc. 290 */ 291 initcpu(); 292 293 /* 294 * Set up buffers, so they can be used to read disk labels. 295 */ 296 bufinit(); 297 298 /* 299 * Configure the system. 300 */ 301 configure(); 302 } 303 304 /* 305 * Set registers on exec. 306 * XXX Should clear registers except sp, pc, 307 * but would break init; should be fixed soon. 308 */ 309 setregs(p, entry, retval) 310 register struct proc *p; 311 u_long entry; 312 int retval[2]; 313 { 314 p->p_md.md_regs[PC] = entry & ~1; 315 #ifdef FPCOPROC 316 /* restore a null state frame */ 317 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; 318 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); 319 #endif 320 #ifdef HPUXCOMPAT 321 if (p->p_flag & SHPUX) { 322 323 p->p_md.md_regs[A0] = 0; /* not 68010 (bit 31), no FPA (30) */ 324 retval[0] = 0; /* no float card */ 325 #ifdef FPCOPROC 326 retval[1] = 1; /* yes 68881 */ 327 #else 328 retval[1] = 0; /* no 68881 */ 329 #endif 330 } 331 /* 332 * Ensure we perform the right action on traps type 1 and 2: 333 * If our parent is an HPUX process and we are being traced, turn 334 * on HPUX style interpretation. Else if we were using the HPUX 335 * style interpretation, revert to the BSD interpretation. 336 * 337 * XXX This doesn't have much to do with setting registers but 338 * I didn't want to muck up kern_exec.c with this code, so I 339 * stuck it here. 340 */ 341 if ((p->p_pptr->p_flag & SHPUX) && 342 (p->p_flag & STRC)) { 343 tweaksigcode(1); 344 p->p_addr->u_pcb.pcb_flags |= PCB_HPUXTRACE; 345 } else if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) { 346 tweaksigcode(0); 347 p->p_addr->u_pcb.pcb_flags &= ~PCB_HPUXTRACE; 348 } 349 #endif 350 } 351 352 identifycpu() 353 { 354 355 printf("HP9000/"); 356 switch (machineid) { 357 case HP_320: 358 printf("320 (16.67Mhz"); 359 break; 360 case HP_330: 361 printf("318/319/330 (16.67Mhz"); 362 break; 363 case HP_340: 364 printf("340 (16.67Mhz"); 365 break; 366 case HP_350: 367 printf("350 (25Mhz"); 368 break; 369 case HP_360: 370 printf("360 (25Mhz"); 371 break; 372 case HP_370: 373 printf("370 (33.33Mhz"); 374 break; 375 case HP_375: 376 printf("345/375 (50Mhz"); 377 break; 378 case HP_380: 379 printf("380/425 (25Mhz)"); 380 break; 381 default: 382 printf("\nunknown machine type %d\n", machineid); 383 panic("startup"); 384 } 385 printf(" MC680%s CPU", 386 mmutype == MMU_68040 ? "40" : 387 (mmutype == MMU_68030 ? "30" : "20")); 388 switch (mmutype) { 389 case MMU_68040: 390 case MMU_68030: 391 printf("+MMU"); 392 break; 393 case MMU_68851: 394 printf(", MC68851 MMU"); 395 break; 396 case MMU_HP: 397 printf(", HP MMU"); 398 break; 399 default: 400 printf("\nunknown MMU type %d\n", mmutype); 401 panic("startup"); 402 } 403 if (mmutype == MMU_68040) 404 printf("+FPU, 4k on-chip physical I/D caches"); 405 else if (mmutype == MMU_68030) 406 printf(", %sMhz MC68882 FPU", 407 machineid == HP_340 ? "16.67" : 408 (machineid == HP_360 ? "25" : 409 (machineid == HP_370 ? "33.33" : "50"))); 410 else 411 printf(", %sMhz MC68881 FPU", 412 machineid == HP_350 ? "20" : "16.67"); 413 switch (ectype) { 414 case EC_VIRT: 415 printf(", %dK virtual-address cache", 416 machineid == HP_320 ? 16 : 32); 417 break; 418 case EC_PHYS: 419 printf(", %dK physical-address cache", 420 machineid == HP_370 ? 64 : 32); 421 break; 422 } 423 printf(")\n"); 424 /* 425 * Now that we have told the user what they have, 426 * let them know if that machine type isn't configured. 427 */ 428 switch (machineid) { 429 case -1: /* keep compilers happy */ 430 #if !defined(HP320) && !defined(HP350) 431 case HP_320: 432 case HP_350: 433 #endif 434 #ifndef HP330 435 case HP_330: 436 #endif 437 #if !defined(HP360) && !defined(HP370) 438 case HP_340: 439 case HP_360: 440 case HP_370: 441 #endif 442 #if !defined(HP380) 443 case HP_380: 444 #endif 445 panic("CPU type not configured"); 446 default: 447 break; 448 } 449 } 450 451 #ifdef HPUXCOMPAT 452 tweaksigcode(ishpux) 453 { 454 static short *sigtrap = NULL; 455 extern short sigcode[], esigcode[]; 456 457 /* locate trap instruction in pcb_sigc */ 458 if (sigtrap == NULL) { 459 sigtrap = esigcode; 460 while (--sigtrap >= sigcode) 461 if ((*sigtrap & 0xFFF0) == 0x4E40) 462 break; 463 if (sigtrap < sigcode) 464 panic("bogus sigcode\n"); 465 } 466 *sigtrap = ishpux ? 0x4E42 : 0x4E41; 467 } 468 #endif 469 470 #define SS_RTEFRAME 1 471 #define SS_FPSTATE 2 472 #define SS_USERREGS 4 473 474 struct sigstate { 475 int ss_flags; /* which of the following are valid */ 476 struct frame ss_frame; /* original exception frame */ 477 struct fpframe ss_fpstate; /* 68881/68882 state info */ 478 }; 479 480 /* 481 * WARNING: code in locore.s assumes the layout shown for sf_signum 482 * thru sf_handler so... don't screw with them! 483 */ 484 struct sigframe { 485 int sf_signum; /* signo for handler */ 486 int sf_code; /* additional info for handler */ 487 struct sigcontext *sf_scp; /* context ptr for handler */ 488 sig_t sf_handler; /* handler addr for u_sigc */ 489 struct sigstate sf_state; /* state of the hardware */ 490 struct sigcontext sf_sc; /* actual context */ 491 }; 492 493 #ifdef HPUXCOMPAT 494 struct hpuxsigcontext { 495 int hsc_syscall; 496 char hsc_action; 497 char hsc_pad1; 498 char hsc_pad2; 499 char hsc_onstack; 500 int hsc_mask; 501 int hsc_sp; 502 short hsc_ps; 503 int hsc_pc; 504 /* the rest aren't part of the context but are included for our convenience */ 505 short hsc_pad; 506 u_int hsc_magic; /* XXX sigreturn: cookie */ 507 struct sigcontext *hsc_realsc; /* XXX sigreturn: ptr to BSD context */ 508 }; 509 510 /* 511 * For an HP-UX process, a partial hpuxsigframe follows the normal sigframe. 512 * Tremendous waste of space, but some HP-UX applications (e.g. LCL) need it. 513 */ 514 struct hpuxsigframe { 515 int hsf_signum; 516 int hsf_code; 517 struct sigcontext *hsf_scp; 518 struct hpuxsigcontext hsf_sc; 519 int hsf_regs[15]; 520 }; 521 #endif 522 523 #ifdef DEBUG 524 int sigdebug = 0; 525 int sigpid = 0; 526 #define SDB_FOLLOW 0x01 527 #define SDB_KSTACK 0x02 528 #define SDB_FPSTATE 0x04 529 #endif 530 531 /* 532 * Send an interrupt to process. 533 */ 534 void 535 sendsig(catcher, sig, mask, code) 536 sig_t catcher; 537 int sig, mask; 538 unsigned code; 539 { 540 register struct proc *p = curproc; 541 register struct sigframe *fp, *kfp; 542 register struct frame *frame; 543 register struct sigacts *psp = p->p_sigacts; 544 register short ft; 545 int oonstack, fsize; 546 extern short exframesize[]; 547 extern char sigcode[], esigcode[]; 548 549 frame = (struct frame *)p->p_md.md_regs; 550 ft = frame->f_format; 551 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 552 /* 553 * Allocate and validate space for the signal handler 554 * context. Note that if the stack is in P0 space, the 555 * call to grow() is a nop, and the useracc() check 556 * will fail if the process has not already allocated 557 * the space with a `brk'. 558 */ 559 #ifdef HPUXCOMPAT 560 if (p->p_flag & SHPUX) 561 fsize = sizeof(struct sigframe) + sizeof(struct hpuxsigframe); 562 else 563 #endif 564 fsize = sizeof(struct sigframe); 565 if ((psp->ps_flags & SAS_ALTSTACK) && 566 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 567 (psp->ps_sigonstack & sigmask(sig))) { 568 fp = (struct sigframe *)(psp->ps_sigstk.ss_base + 569 psp->ps_sigstk.ss_size - fsize); 570 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 571 } else 572 fp = (struct sigframe *)(frame->f_regs[SP] - fsize); 573 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 574 (void)grow(p, (unsigned)fp); 575 #ifdef DEBUG 576 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 577 printf("sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n", 578 p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft); 579 #endif 580 if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) { 581 #ifdef DEBUG 582 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 583 printf("sendsig(%d): useracc failed on sig %d\n", 584 p->p_pid, sig); 585 #endif 586 /* 587 * Process has trashed its stack; give it an illegal 588 * instruction to halt it in its tracks. 589 */ 590 SIGACTION(p, SIGILL) = SIG_DFL; 591 sig = sigmask(SIGILL); 592 p->p_sigignore &= ~sig; 593 p->p_sigcatch &= ~sig; 594 p->p_sigmask &= ~sig; 595 psignal(p, SIGILL); 596 return; 597 } 598 kfp = (struct sigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK); 599 /* 600 * Build the argument list for the signal handler. 601 */ 602 kfp->sf_signum = sig; 603 kfp->sf_code = code; 604 kfp->sf_scp = &fp->sf_sc; 605 kfp->sf_handler = catcher; 606 /* 607 * Save necessary hardware state. Currently this includes: 608 * - general registers 609 * - original exception frame (if not a "normal" frame) 610 * - FP coprocessor state 611 */ 612 kfp->sf_state.ss_flags = SS_USERREGS; 613 bcopy((caddr_t)frame->f_regs, 614 (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs); 615 if (ft >= FMT7) { 616 #ifdef DEBUG 617 if (ft != FMT9 && ft != FMTA && ft != FMTB 618 #if defined(HP380) 619 && mmutype != MMU_68040 || mmutype==MMU_68040 && ft != FMT7 620 #endif 621 ) 622 panic("sendsig: bogus frame type"); 623 #endif 624 kfp->sf_state.ss_flags |= SS_RTEFRAME; 625 kfp->sf_state.ss_frame.f_format = frame->f_format; 626 kfp->sf_state.ss_frame.f_vector = frame->f_vector; 627 bcopy((caddr_t)&frame->F_u, 628 (caddr_t)&kfp->sf_state.ss_frame.F_u, exframesize[ft]); 629 /* 630 * Leave an indicator that we need to clean up the kernel 631 * stack. We do this by setting the "pad word" above the 632 * hardware stack frame to the amount the stack must be 633 * adjusted by. 634 * 635 * N.B. we increment rather than just set f_stackadj in 636 * case we are called from syscall when processing a 637 * sigreturn. In that case, f_stackadj may be non-zero. 638 */ 639 frame->f_stackadj += exframesize[ft]; 640 frame->f_format = frame->f_vector = 0; 641 #ifdef DEBUG 642 if (sigdebug & SDB_FOLLOW) 643 printf("sendsig(%d): copy out %d of frame %d\n", 644 p->p_pid, exframesize[ft], ft); 645 #endif 646 } 647 #ifdef FPCOPROC 648 kfp->sf_state.ss_flags |= SS_FPSTATE; 649 m68881_save(&kfp->sf_state.ss_fpstate); 650 #ifdef DEBUG 651 if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate) 652 printf("sendsig(%d): copy out FP state (%x) to %x\n", 653 p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate, 654 &kfp->sf_state.ss_fpstate); 655 #endif 656 #endif 657 /* 658 * Build the signal context to be used by sigreturn. 659 */ 660 kfp->sf_sc.sc_onstack = oonstack; 661 kfp->sf_sc.sc_mask = mask; 662 kfp->sf_sc.sc_sp = frame->f_regs[SP]; 663 kfp->sf_sc.sc_fp = frame->f_regs[A6]; 664 kfp->sf_sc.sc_ap = (int)&fp->sf_state; 665 kfp->sf_sc.sc_pc = frame->f_pc; 666 kfp->sf_sc.sc_ps = frame->f_sr; 667 #ifdef HPUXCOMPAT 668 /* 669 * Create an HP-UX style sigcontext structure and associated goo 670 */ 671 if (p->p_flag & SHPUX) { 672 register struct hpuxsigframe *hkfp; 673 674 hkfp = (struct hpuxsigframe *)&kfp[1]; 675 hkfp->hsf_signum = bsdtohpuxsig(kfp->sf_signum); 676 hkfp->hsf_code = kfp->sf_code; 677 hkfp->hsf_scp = (struct sigcontext *) 678 &((struct hpuxsigframe *)(&fp[1]))->hsf_sc; 679 hkfp->hsf_sc.hsc_syscall = 0; /* XXX */ 680 hkfp->hsf_sc.hsc_action = 0; /* XXX */ 681 hkfp->hsf_sc.hsc_pad1 = hkfp->hsf_sc.hsc_pad2 = 0; 682 hkfp->hsf_sc.hsc_onstack = kfp->sf_sc.sc_onstack; 683 hkfp->hsf_sc.hsc_mask = kfp->sf_sc.sc_mask; 684 hkfp->hsf_sc.hsc_sp = kfp->sf_sc.sc_sp; 685 hkfp->hsf_sc.hsc_ps = kfp->sf_sc.sc_ps; 686 hkfp->hsf_sc.hsc_pc = kfp->sf_sc.sc_pc; 687 hkfp->hsf_sc.hsc_pad = 0; 688 hkfp->hsf_sc.hsc_magic = 0xdeadbeef; 689 hkfp->hsf_sc.hsc_realsc = kfp->sf_scp; 690 bcopy((caddr_t)frame->f_regs, (caddr_t)hkfp->hsf_regs, 691 sizeof (hkfp->hsf_regs)); 692 693 kfp->sf_signum = hkfp->hsf_signum; 694 kfp->sf_scp = hkfp->hsf_scp; 695 } 696 #endif 697 (void) copyout((caddr_t)kfp, (caddr_t)fp, fsize); 698 frame->f_regs[SP] = (int)fp; 699 #ifdef DEBUG 700 if (sigdebug & SDB_FOLLOW) 701 printf("sendsig(%d): sig %d scp %x fp %x sc_sp %x sc_ap %x\n", 702 p->p_pid, sig, kfp->sf_scp, fp, 703 kfp->sf_sc.sc_sp, kfp->sf_sc.sc_ap); 704 #endif 705 /* 706 * Signal trampoline code is at base of user stack. 707 */ 708 frame->f_pc = (int)PS_STRINGS - (esigcode - sigcode); 709 #ifdef DEBUG 710 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 711 printf("sendsig(%d): sig %d returns\n", 712 p->p_pid, sig); 713 #endif 714 free((caddr_t)kfp, M_TEMP); 715 } 716 717 /* 718 * System call to cleanup state after a signal 719 * has been taken. Reset signal mask and 720 * stack state from context left by sendsig (above). 721 * Return to previous pc and psl as specified by 722 * context left by sendsig. Check carefully to 723 * make sure that the user has not modified the 724 * psl to gain improper priviledges or to cause 725 * a machine fault. 726 */ 727 /* ARGSUSED */ 728 sigreturn(p, uap, retval) 729 struct proc *p; 730 struct args { 731 struct sigcontext *sigcntxp; 732 } *uap; 733 int *retval; 734 { 735 register struct sigcontext *scp; 736 register struct frame *frame; 737 register int rf; 738 struct sigcontext tsigc; 739 struct sigstate tstate; 740 int flags; 741 extern short exframesize[]; 742 743 scp = uap->sigcntxp; 744 #ifdef DEBUG 745 if (sigdebug & SDB_FOLLOW) 746 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 747 #endif 748 if ((int)scp & 1) 749 return (EINVAL); 750 #ifdef HPUXCOMPAT 751 /* 752 * Grab context as an HP-UX style context and determine if it 753 * was one that we contructed in sendsig. 754 */ 755 if (p->p_flag & SHPUX) { 756 struct hpuxsigcontext *hscp = (struct hpuxsigcontext *)scp; 757 struct hpuxsigcontext htsigc; 758 759 if (useracc((caddr_t)hscp, sizeof (*hscp), B_WRITE) == 0 || 760 copyin((caddr_t)hscp, (caddr_t)&htsigc, sizeof htsigc)) 761 return (EINVAL); 762 /* 763 * If not generated by sendsig or we cannot restore the 764 * BSD-style sigcontext, just restore what we can -- state 765 * will be lost, but them's the breaks. 766 */ 767 hscp = &htsigc; 768 if (hscp->hsc_magic != 0xdeadbeef || 769 (scp = hscp->hsc_realsc) == 0 || 770 useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 || 771 copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc)) { 772 if (hscp->hsc_onstack & 01) 773 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 774 else 775 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 776 p->p_sigmask = hscp->hsc_mask &~ sigcantmask; 777 frame = (struct frame *) p->p_md.md_regs; 778 frame->f_regs[SP] = hscp->hsc_sp; 779 frame->f_pc = hscp->hsc_pc; 780 frame->f_sr = hscp->hsc_ps &~ PSL_USERCLR; 781 return (EJUSTRETURN); 782 } 783 /* 784 * Otherwise, overlay BSD context with possibly modified 785 * HP-UX values. 786 */ 787 tsigc.sc_onstack = hscp->hsc_onstack; 788 tsigc.sc_mask = hscp->hsc_mask; 789 tsigc.sc_sp = hscp->hsc_sp; 790 tsigc.sc_ps = hscp->hsc_ps; 791 tsigc.sc_pc = hscp->hsc_pc; 792 } else 793 #endif 794 /* 795 * Test and fetch the context structure. 796 * We grab it all at once for speed. 797 */ 798 if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 || 799 copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc)) 800 return (EINVAL); 801 scp = &tsigc; 802 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) 803 return (EINVAL); 804 /* 805 * Restore the user supplied information 806 */ 807 if (scp->sc_onstack & 01) 808 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 809 else 810 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 811 p->p_sigmask = scp->sc_mask &~ sigcantmask; 812 frame = (struct frame *) p->p_md.md_regs; 813 frame->f_regs[SP] = scp->sc_sp; 814 frame->f_regs[A6] = scp->sc_fp; 815 frame->f_pc = scp->sc_pc; 816 frame->f_sr = scp->sc_ps; 817 /* 818 * Grab pointer to hardware state information. 819 * If zero, the user is probably doing a longjmp. 820 */ 821 if ((rf = scp->sc_ap) == 0) 822 return (EJUSTRETURN); 823 /* 824 * See if there is anything to do before we go to the 825 * expense of copying in close to 1/2K of data 826 */ 827 flags = fuword((caddr_t)rf); 828 #ifdef DEBUG 829 if (sigdebug & SDB_FOLLOW) 830 printf("sigreturn(%d): sc_ap %x flags %x\n", 831 p->p_pid, rf, flags); 832 #endif 833 /* 834 * fuword failed (bogus sc_ap value). 835 */ 836 if (flags == -1) 837 return (EINVAL); 838 if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate)) 839 return (EJUSTRETURN); 840 #ifdef DEBUG 841 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 842 printf("sigreturn(%d): ssp %x usp %x scp %x ft %d\n", 843 p->p_pid, &flags, scp->sc_sp, uap->sigcntxp, 844 (flags&SS_RTEFRAME) ? tstate.ss_frame.f_format : -1); 845 #endif 846 /* 847 * Restore most of the users registers except for A6 and SP 848 * which were handled above. 849 */ 850 if (flags & SS_USERREGS) 851 bcopy((caddr_t)tstate.ss_frame.f_regs, 852 (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW); 853 /* 854 * Restore long stack frames. Note that we do not copy 855 * back the saved SR or PC, they were picked up above from 856 * the sigcontext structure. 857 */ 858 if (flags & SS_RTEFRAME) { 859 register int sz; 860 861 /* grab frame type and validate */ 862 sz = tstate.ss_frame.f_format; 863 if (sz > 15 || (sz = exframesize[sz]) < 0) 864 return (EINVAL); 865 frame->f_stackadj -= sz; 866 frame->f_format = tstate.ss_frame.f_format; 867 frame->f_vector = tstate.ss_frame.f_vector; 868 bcopy((caddr_t)&tstate.ss_frame.F_u, (caddr_t)&frame->F_u, sz); 869 #ifdef DEBUG 870 if (sigdebug & SDB_FOLLOW) 871 printf("sigreturn(%d): copy in %d of frame type %d\n", 872 p->p_pid, sz, tstate.ss_frame.f_format); 873 #endif 874 } 875 #ifdef FPCOPROC 876 /* 877 * Finally we restore the original FP context 878 */ 879 if (flags & SS_FPSTATE) 880 m68881_restore(&tstate.ss_fpstate); 881 #ifdef DEBUG 882 if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) 883 printf("sigreturn(%d): copied in FP state (%x) at %x\n", 884 p->p_pid, *(u_int *)&tstate.ss_fpstate, 885 &tstate.ss_fpstate); 886 #endif 887 #endif 888 #ifdef DEBUG 889 if ((sigdebug & SDB_FOLLOW) || 890 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 891 printf("sigreturn(%d): returns\n", p->p_pid); 892 #endif 893 return (EJUSTRETURN); 894 } 895 896 int waittime = -1; 897 898 boot(howto) 899 register int howto; 900 { 901 /* take a snap shot before clobbering any registers */ 902 if (curproc) 903 savectx(curproc->p_addr, 0); 904 905 boothowto = howto; 906 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 907 register struct buf *bp; 908 int iter, nbusy; 909 910 waittime = 0; 911 (void) spl0(); 912 printf("syncing disks... "); 913 /* 914 * Release vnodes held by texts before sync. 915 */ 916 if (panicstr == 0) 917 vnode_pager_umount(NULL); 918 #ifdef notdef 919 #include "fd.h" 920 #if NFD > 0 921 fdshutdown(); 922 #endif 923 #endif 924 sync(&proc0, (void *)NULL, (int *)NULL); 925 926 for (iter = 0; iter < 20; iter++) { 927 nbusy = 0; 928 for (bp = &buf[nbuf]; --bp >= buf; ) 929 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 930 nbusy++; 931 if (nbusy == 0) 932 break; 933 printf("%d ", nbusy); 934 DELAY(40000 * iter); 935 } 936 if (nbusy) 937 printf("giving up\n"); 938 else 939 printf("done\n"); 940 /* 941 * If we've been adjusting the clock, the todr 942 * will be out of synch; adjust it now. 943 */ 944 resettodr(); 945 } 946 splhigh(); /* extreme priority */ 947 if (howto&RB_HALT) { 948 printf("halted\n\n"); 949 asm(" stop #0x2700"); 950 } else { 951 if (howto & RB_DUMP) 952 dumpsys(); 953 doboot(); 954 /*NOTREACHED*/ 955 } 956 /*NOTREACHED*/ 957 } 958 959 int dumpmag = 0x8fca0101; /* magic number for savecore */ 960 int dumpsize = 0; /* also for savecore */ 961 long dumplo = 0; 962 963 dumpconf() 964 { 965 int nblks; 966 967 dumpsize = physmem; 968 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 969 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 970 if (dumpsize > btoc(dbtob(nblks - dumplo))) 971 dumpsize = btoc(dbtob(nblks - dumplo)); 972 else if (dumplo == 0) 973 dumplo = nblks - btodb(ctob(physmem)); 974 } 975 /* 976 * Don't dump on the first CLBYTES (why CLBYTES?) 977 * in case the dump device includes a disk label. 978 */ 979 if (dumplo < btodb(CLBYTES)) 980 dumplo = btodb(CLBYTES); 981 } 982 983 /* 984 * Doadump comes here after turning off memory management and 985 * getting on the dump stack, either when called above, or by 986 * the auto-restart code. 987 */ 988 dumpsys() 989 { 990 991 msgbufmapped = 0; 992 if (dumpdev == NODEV) 993 return; 994 /* 995 * For dumps during autoconfiguration, 996 * if dump device has already configured... 997 */ 998 if (dumpsize == 0) 999 dumpconf(); 1000 if (dumplo < 0) 1001 return; 1002 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 1003 printf("dump "); 1004 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 1005 1006 case ENXIO: 1007 printf("device bad\n"); 1008 break; 1009 1010 case EFAULT: 1011 printf("device not ready\n"); 1012 break; 1013 1014 case EINVAL: 1015 printf("area improper\n"); 1016 break; 1017 1018 case EIO: 1019 printf("i/o error\n"); 1020 break; 1021 1022 default: 1023 printf("succeeded\n"); 1024 break; 1025 } 1026 } 1027 1028 /* 1029 * Return the best possible estimate of the time in the timeval 1030 * to which tvp points. We do this by returning the current time 1031 * plus the amount of time since the last clock interrupt (clock.c:clkread). 1032 * 1033 * Check that this time is no less than any previously-reported time, 1034 * which could happen around the time of a clock adjustment. Just for fun, 1035 * we guarantee that the time will be greater than the value obtained by a 1036 * previous call. 1037 */ 1038 microtime(tvp) 1039 register struct timeval *tvp; 1040 { 1041 int s = splhigh(); 1042 static struct timeval lasttime; 1043 1044 *tvp = time; 1045 tvp->tv_usec += clkread(); 1046 while (tvp->tv_usec > 1000000) { 1047 tvp->tv_sec++; 1048 tvp->tv_usec -= 1000000; 1049 } 1050 if (tvp->tv_sec == lasttime.tv_sec && 1051 tvp->tv_usec <= lasttime.tv_usec && 1052 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 1053 tvp->tv_sec++; 1054 tvp->tv_usec -= 1000000; 1055 } 1056 lasttime = *tvp; 1057 splx(s); 1058 } 1059 1060 initcpu() 1061 { 1062 parityenable(); 1063 } 1064 1065 straytrap(pc, evec) 1066 int pc; 1067 u_short evec; 1068 { 1069 printf("unexpected trap (vector offset %x) from %x\n", 1070 evec & 0xFFF, pc); 1071 } 1072 1073 int *nofault; 1074 1075 badaddr(addr) 1076 register caddr_t addr; 1077 { 1078 register int i; 1079 label_t faultbuf; 1080 1081 #ifdef lint 1082 i = *addr; if (i) return(0); 1083 #endif 1084 nofault = (int *) &faultbuf; 1085 if (setjmp((label_t *)nofault)) { 1086 nofault = (int *) 0; 1087 return(1); 1088 } 1089 i = *(volatile short *)addr; 1090 nofault = (int *) 0; 1091 return(0); 1092 } 1093 1094 badbaddr(addr) 1095 register caddr_t addr; 1096 { 1097 register int i; 1098 label_t faultbuf; 1099 1100 #ifdef lint 1101 i = *addr; if (i) return(0); 1102 #endif 1103 nofault = (int *) &faultbuf; 1104 if (setjmp((label_t *)nofault)) { 1105 nofault = (int *) 0; 1106 return(1); 1107 } 1108 i = *(volatile char *)addr; 1109 nofault = (int *) 0; 1110 return(0); 1111 } 1112 1113 netintr() 1114 { 1115 #ifdef INET 1116 if (netisr & (1 << NETISR_ARP)) { 1117 netisr &= ~(1 << NETISR_ARP); 1118 arpintr(); 1119 } 1120 if (netisr & (1 << NETISR_IP)) { 1121 netisr &= ~(1 << NETISR_IP); 1122 ipintr(); 1123 } 1124 #endif 1125 #ifdef NS 1126 if (netisr & (1 << NETISR_NS)) { 1127 netisr &= ~(1 << NETISR_NS); 1128 nsintr(); 1129 } 1130 #endif 1131 #ifdef ISO 1132 if (netisr & (1 << NETISR_ISO)) { 1133 netisr &= ~(1 << NETISR_ISO); 1134 clnlintr(); 1135 } 1136 #endif 1137 } 1138 1139 intrhand(sr) 1140 int sr; 1141 { 1142 register struct isr *isr; 1143 register int found = 0; 1144 register int ipl; 1145 extern struct isr isrqueue[]; 1146 1147 ipl = (sr >> 8) & 7; 1148 switch (ipl) { 1149 1150 case 3: 1151 case 4: 1152 case 5: 1153 ipl = ISRIPL(ipl); 1154 isr = isrqueue[ipl].isr_forw; 1155 for (; isr != &isrqueue[ipl]; isr = isr->isr_forw) { 1156 if ((isr->isr_intr)(isr->isr_arg)) { 1157 found++; 1158 break; 1159 } 1160 } 1161 if (found == 0) 1162 printf("stray interrupt, sr 0x%x\n", sr); 1163 break; 1164 1165 case 0: 1166 case 1: 1167 case 2: 1168 case 6: 1169 case 7: 1170 printf("intrhand: unexpected sr 0x%x\n", sr); 1171 break; 1172 } 1173 } 1174 1175 #if defined(DEBUG) && !defined(PANICBUTTON) 1176 #define PANICBUTTON 1177 #endif 1178 1179 #ifdef PANICBUTTON 1180 int panicbutton = 1; /* non-zero if panic buttons are enabled */ 1181 int crashandburn = 0; 1182 int candbdelay = 50; /* give em half a second */ 1183 1184 candbtimer() 1185 { 1186 crashandburn = 0; 1187 } 1188 #endif 1189 1190 /* 1191 * Level 7 interrupts can be caused by the keyboard or parity errors. 1192 */ 1193 nmihand(frame) 1194 struct frame frame; 1195 { 1196 if (kbdnmi()) { 1197 #ifdef PANICBUTTON 1198 static int innmihand = 0; 1199 1200 /* 1201 * Attempt to reduce the window of vulnerability for recursive 1202 * NMIs (e.g. someone holding down the keyboard reset button). 1203 */ 1204 if (innmihand == 0) { 1205 innmihand = 1; 1206 printf("Got a keyboard NMI\n"); 1207 innmihand = 0; 1208 } 1209 if (panicbutton) { 1210 if (crashandburn) { 1211 crashandburn = 0; 1212 panic(panicstr ? 1213 "forced crash, nosync" : "forced crash"); 1214 } 1215 crashandburn++; 1216 timeout(candbtimer, (caddr_t)0, candbdelay); 1217 } 1218 #endif 1219 return; 1220 } 1221 if (parityerror(&frame)) 1222 return; 1223 /* panic?? */ 1224 printf("unexpected level 7 interrupt ignored\n"); 1225 } 1226 1227 /* 1228 * Parity error section. Contains magic. 1229 */ 1230 #define PARREG ((volatile short *)IIOV(0x5B0000)) 1231 static int gotparmem = 0; 1232 #ifdef DEBUG 1233 int ignorekperr = 0; /* ignore kernel parity errors */ 1234 #endif 1235 1236 /* 1237 * Enable parity detection 1238 */ 1239 parityenable() 1240 { 1241 label_t faultbuf; 1242 1243 nofault = (int *) &faultbuf; 1244 if (setjmp((label_t *)nofault)) { 1245 nofault = (int *) 0; 1246 #ifdef DEBUG 1247 printf("No parity memory\n"); 1248 #endif 1249 return; 1250 } 1251 *PARREG = 1; 1252 nofault = (int *) 0; 1253 gotparmem = 1; 1254 #ifdef DEBUG 1255 printf("Parity detection enabled\n"); 1256 #endif 1257 } 1258 1259 /* 1260 * Determine if level 7 interrupt was caused by a parity error 1261 * and deal with it if it was. Returns 1 if it was a parity error. 1262 */ 1263 parityerror(fp) 1264 struct frame *fp; 1265 { 1266 if (!gotparmem) 1267 return(0); 1268 *PARREG = 0; 1269 DELAY(10); 1270 *PARREG = 1; 1271 if (panicstr) { 1272 printf("parity error after panic ignored\n"); 1273 return(1); 1274 } 1275 if (!findparerror()) 1276 printf("WARNING: transient parity error ignored\n"); 1277 else if (USERMODE(fp->f_sr)) { 1278 printf("pid %d: parity error\n", curproc->p_pid); 1279 uprintf("sorry, pid %d killed due to memory parity error\n", 1280 curproc->p_pid); 1281 psignal(curproc, SIGKILL); 1282 #ifdef DEBUG 1283 } else if (ignorekperr) { 1284 printf("WARNING: kernel parity error ignored\n"); 1285 #endif 1286 } else { 1287 regdump(fp->f_regs, 128); 1288 panic("kernel parity error"); 1289 } 1290 return(1); 1291 } 1292 1293 /* 1294 * Yuk! There has got to be a better way to do this! 1295 * Searching all of memory with interrupts blocked can lead to disaster. 1296 */ 1297 findparerror() 1298 { 1299 static label_t parcatch; 1300 static int looking = 0; 1301 volatile struct pte opte; 1302 volatile int pg, o, s; 1303 register volatile int *ip; 1304 register int i; 1305 int found; 1306 1307 #ifdef lint 1308 ip = &found; 1309 i = o = pg = 0; if (i) return(0); 1310 #endif 1311 /* 1312 * If looking is true we are searching for a known parity error 1313 * and it has just occured. All we do is return to the higher 1314 * level invocation. 1315 */ 1316 if (looking) 1317 longjmp(&parcatch); 1318 s = splhigh(); 1319 /* 1320 * If setjmp returns true, the parity error we were searching 1321 * for has just occured (longjmp above) at the current pg+o 1322 */ 1323 if (setjmp(&parcatch)) { 1324 printf("Parity error at 0x%x\n", ctob(pg)|o); 1325 found = 1; 1326 goto done; 1327 } 1328 /* 1329 * If we get here, a parity error has occured for the first time 1330 * and we need to find it. We turn off any external caches and 1331 * loop thru memory, testing every longword til a fault occurs and 1332 * we regain control at setjmp above. Note that because of the 1333 * setjmp, pg and o need to be volatile or their values will be lost. 1334 */ 1335 looking = 1; 1336 ecacheoff(); 1337 for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) { 1338 pmap_enter(kernel_pmap, (vm_offset_t)vmmap, ctob(pg), 1339 VM_PROT_READ, TRUE); 1340 for (o = 0; o < NBPG; o += sizeof(int)) 1341 i = *(int *)(&vmmap[o]); 1342 } 1343 /* 1344 * Getting here implies no fault was found. Should never happen. 1345 */ 1346 printf("Couldn't locate parity error\n"); 1347 found = 0; 1348 done: 1349 looking = 0; 1350 pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 1351 (vm_offset_t)&vmmap[NBPG]); 1352 ecacheon(); 1353 splx(s); 1354 return(found); 1355 } 1356 1357 regdump(rp, sbytes) 1358 int *rp; /* must not be register */ 1359 int sbytes; 1360 { 1361 static int doingdump = 0; 1362 register int i; 1363 int s; 1364 extern char *hexstr(); 1365 1366 if (doingdump) 1367 return; 1368 s = splhigh(); 1369 doingdump = 1; 1370 printf("pid = %d, pc = %s, ", curproc->p_pid, hexstr(rp[PC], 8)); 1371 printf("ps = %s, ", hexstr(rp[PS], 4)); 1372 printf("sfc = %s, ", hexstr(getsfc(), 4)); 1373 printf("dfc = %s\n", hexstr(getdfc(), 4)); 1374 printf("Registers:\n "); 1375 for (i = 0; i < 8; i++) 1376 printf(" %d", i); 1377 printf("\ndreg:"); 1378 for (i = 0; i < 8; i++) 1379 printf(" %s", hexstr(rp[i], 8)); 1380 printf("\nareg:"); 1381 for (i = 0; i < 8; i++) 1382 printf(" %s", hexstr(rp[i+8], 8)); 1383 if (sbytes > 0) { 1384 if (rp[PS] & PSL_S) { 1385 printf("\n\nKernel stack (%s):", 1386 hexstr((int)(((int *)&rp)-1), 8)); 1387 dumpmem(((int *)&rp)-1, sbytes, 0); 1388 } else { 1389 printf("\n\nUser stack (%s):", hexstr(rp[SP], 8)); 1390 dumpmem((int *)rp[SP], sbytes, 1); 1391 } 1392 } 1393 doingdump = 0; 1394 splx(s); 1395 } 1396 1397 extern char kstack[]; 1398 #define KSADDR ((int *)&(kstack[(UPAGES-1)*NBPG])) 1399 1400 dumpmem(ptr, sz, ustack) 1401 register int *ptr; 1402 int sz; 1403 { 1404 register int i, val; 1405 extern char *hexstr(); 1406 1407 for (i = 0; i < sz; i++) { 1408 if ((i & 7) == 0) 1409 printf("\n%s: ", hexstr((int)ptr, 6)); 1410 else 1411 printf(" "); 1412 if (ustack == 1) { 1413 if ((val = fuword(ptr++)) == -1) 1414 break; 1415 } else { 1416 if (ustack == 0 && 1417 (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1))) 1418 break; 1419 val = *ptr++; 1420 } 1421 printf("%s", hexstr(val, 8)); 1422 } 1423 printf("\n"); 1424 } 1425 1426 char * 1427 hexstr(val, len) 1428 register int val; 1429 { 1430 static char nbuf[9]; 1431 register int x, i; 1432 1433 if (len > 8) 1434 return(""); 1435 nbuf[len] = '\0'; 1436 for (i = len-1; i >= 0; --i) { 1437 x = val & 0xF; 1438 if (x > 9) 1439 nbuf[i] = x - 10 + 'A'; 1440 else 1441 nbuf[i] = x + '0'; 1442 val >>= 4; 1443 } 1444 return(nbuf); 1445 } 1446