|
|
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.