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