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