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