|
|
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: trap.c 1.28 89/09/25$
26: *
27: * @(#)trap.c 7.7 (Berkeley) 6/25/90
28: */
29:
30: #include "cpu.h"
31: #include "psl.h"
32: #include "reg.h"
33: #include "pte.h"
34: #include "mtpr.h"
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "user.h"
39: #include "proc.h"
40: #include "seg.h"
41: #include "trap.h"
42: #include "acct.h"
43: #include "kernel.h"
44: #include "vm.h"
45: #include "cmap.h"
46: #include "syslog.h"
47: #ifdef KTRACE
48: #include "ktrace.h"
49: #endif
50:
51: #ifdef HPUXCOMPAT
52: #include "../hpux/hpux.h"
53: #endif
54:
55: #define USER 040 /* user-mode flag added to type */
56:
57: struct sysent sysent[];
58: int nsysent;
59:
60: char *trap_type[] = {
61: "Bus error",
62: "Address error",
63: "Illegal instruction",
64: "Zero divide",
65: "CHK instruction",
66: "TRAPV instruction",
67: "Privilege violation",
68: "Trace trap",
69: "MMU fault",
70: "SSIR trap",
71: "Format error",
72: "68881 exception",
73: "Coprocessor violation",
74: "Async system trap"
75: };
76: #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0])
77:
78: #ifdef DEBUG
79: int mmudebug = 0;
80: #endif
81:
82: /*
83: * Called from the trap handler when a processor trap occurs.
84: */
85: /*ARGSUSED*/
86: trap(type, code, v, frame)
87: int type;
88: unsigned code;
89: register unsigned v;
90: struct frame frame;
91: {
92: register int i;
93: unsigned ucode = 0;
94: register struct proc *p = u.u_procp;
95: struct timeval syst;
96: unsigned ncode;
97:
98: cnt.v_trap++;
99: syst = u.u_ru.ru_stime;
100: if (USERMODE(frame.f_sr)) {
101: type |= USER;
102: u.u_ar0 = frame.f_regs;
103: }
104: switch (type) {
105:
106: default:
107: dopanic:
108: #ifdef KGDB
109: if (!panicstr && kgdb_trap(type, code, v, &frame))
110: return;
111: #endif
112: printf("trap type %d, code = %x, v = %x\n", type, code, v);
113: regdump(frame.f_regs, 128);
114: type &= ~USER;
115: if ((unsigned)type < TRAP_TYPES)
116: panic(trap_type[type]);
117: panic("trap");
118:
119: case T_BUSERR: /* kernel bus error */
120: if (!u.u_pcb.pcb_onfault)
121: goto dopanic;
122: /*
123: * If we have arranged to catch this fault in any of the
124: * copy to/from user space routines, set PC to return to
125: * indicated location and set flag informing buserror code
126: * that it may need to clean up stack frame.
127: */
128: copyfault:
129: frame.f_pc = (int) u.u_pcb.pcb_onfault;
130: frame.f_stackadj = -1;
131: return;
132:
133: case T_BUSERR+USER: /* bus error */
134: case T_ADDRERR+USER: /* address error */
135: i = SIGBUS;
136: break;
137:
138: #ifdef FPCOPROC
139: case T_COPERR: /* kernel coprocessor violation */
140: #endif
141: case T_FMTERR: /* kernel format error */
142: /*
143: * The user has most likely trashed the RTE or FP state info
144: * in the stack frame of a signal handler.
145: */
146: type |= USER;
147: printf("pid %d: kernel %s exception\n", u.u_procp->p_pid,
148: type==T_COPERR ? "coprocessor" : "format");
149: u.u_signal[SIGILL] = SIG_DFL;
150: i = sigmask(SIGILL);
151: p->p_sigignore &= ~i;
152: p->p_sigcatch &= ~i;
153: p->p_sigmask &= ~i;
154: i = SIGILL;
155: ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
156: break;
157:
158: #ifdef FPCOPROC
159: case T_COPERR+USER: /* user coprocessor violation */
160: /* What is a proper response here? */
161: ucode = 0;
162: i = SIGFPE;
163: break;
164:
165: case T_FPERR+USER: /* 68881 exceptions */
166: /*
167: * We pass along the 68881 status register which locore stashed
168: * in code for us. Note that there is a possibility that the
169: * bit pattern of this register will conflict with one of the
170: * FPE_* codes defined in signal.h. Fortunately for us, the
171: * only such codes we use are all in the range 1-7 and the low
172: * 3 bits of the status register are defined as 0 so there is
173: * no clash.
174: */
175: ucode = code;
176: i = SIGFPE;
177: break;
178: #endif
179:
180: case T_ILLINST+USER: /* illegal instruction fault */
181: #ifdef HPUXCOMPAT
182: if (u.u_procp->p_flag & SHPUX) {
183: ucode = HPUX_ILL_ILLINST_TRAP;
184: i = SIGILL;
185: break;
186: }
187: /* fall through */
188: #endif
189: case T_PRIVINST+USER: /* privileged instruction fault */
190: #ifdef HPUXCOMPAT
191: if (u.u_procp->p_flag & SHPUX)
192: ucode = HPUX_ILL_PRIV_TRAP;
193: else
194: #endif
195: ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
196: i = SIGILL;
197: break;
198:
199: case T_ZERODIV+USER: /* Divide by zero */
200: #ifdef HPUXCOMPAT
201: if (u.u_procp->p_flag & SHPUX)
202: ucode = HPUX_FPE_INTDIV_TRAP;
203: else
204: #endif
205: ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */
206: i = SIGFPE;
207: break;
208:
209: case T_CHKINST+USER: /* CHK instruction trap */
210: #ifdef HPUXCOMPAT
211: if (u.u_procp->p_flag & SHPUX) {
212: /* handled differently under hp-ux */
213: i = SIGILL;
214: ucode = HPUX_ILL_CHK_TRAP;
215: break;
216: }
217: #endif
218: ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */
219: i = SIGFPE;
220: break;
221:
222: case T_TRAPVINST+USER: /* TRAPV instruction trap */
223: #ifdef HPUXCOMPAT
224: if (u.u_procp->p_flag & SHPUX) {
225: /* handled differently under hp-ux */
226: i = SIGILL;
227: ucode = HPUX_ILL_TRAPV_TRAP;
228: break;
229: }
230: #endif
231: ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */
232: i = SIGFPE;
233: break;
234:
235: /*
236: * XXX: Trace traps are a nightmare.
237: *
238: * HP-UX uses trap #1 for breakpoints,
239: * HPBSD uses trap #2,
240: * SUN 3.x uses trap #15,
241: * KGDB uses trap #15 (for kernel breakpoints).
242: *
243: * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
244: * SUN 3.x traps get passed through as T_TRAP15 and are not really
245: * supported yet. KGDB traps are also passed through as T_TRAP15
246: * and are not used yet.
247: */
248: case T_TRACE: /* kernel trace trap */
249: case T_TRAP15: /* SUN (or KGDB) kernel trace trap */
250: #ifdef KGDB
251: if (kgdb_trap(type, code, v, &frame))
252: return;
253: #endif
254: frame.f_sr &= ~PSL_T;
255: i = SIGTRAP;
256: break;
257:
258: case T_TRACE+USER: /* user trace trap */
259: case T_TRAP15+USER: /* SUN user trace trap */
260: frame.f_sr &= ~PSL_T;
261: i = SIGTRAP;
262: break;
263:
264: case T_ASTFLT: /* system async trap, cannot happen */
265: goto dopanic;
266:
267: case T_ASTFLT+USER: /* user async trap */
268: astoff();
269: /*
270: * We check for software interrupts first. This is because
271: * they are at a higher level than ASTs, and on a VAX would
272: * interrupt the AST. We assume that if we are processing
273: * an AST that we must be at IPL0 so we don't bother to
274: * check. Note that we ensure that we are at least at SIR
275: * IPL while processing the SIR.
276: */
277: spl1();
278: /* fall into... */
279:
280: case T_SSIR: /* software interrupt */
281: case T_SSIR+USER:
282: if (ssir & SIR_NET) {
283: siroff(SIR_NET);
284: cnt.v_soft++;
285: netintr();
286: }
287: if (ssir & SIR_CLOCK) {
288: siroff(SIR_CLOCK);
289: cnt.v_soft++;
290: softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
291: }
292: /*
293: * If this was not an AST trap, we are all done.
294: */
295: if (type != T_ASTFLT+USER) {
296: cnt.v_trap--;
297: return;
298: }
299: spl0();
300: #ifndef PROFTIMER
301: if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) {
302: addupc(frame.f_pc, &u.u_prof, 1);
303: u.u_procp->p_flag &= ~SOWEUPC;
304: }
305: #endif
306: goto out;
307:
308: case T_MMUFLT: /* kernel mode page fault */
309: /*
310: * Could be caused by a page fault in one of the copy to/from
311: * user space routines. If so, we will have a catch address.
312: */
313: if (!u.u_pcb.pcb_onfault)
314: goto dopanic;
315: /* fall into ... */
316:
317: case T_MMUFLT+USER: /* page fault */
318: /*
319: printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n",
320: p->p_pid, code, v, frame.f_pc, frame.f_sr);
321: */
322: if (v >= USRSTACK) {
323: if (type == T_MMUFLT)
324: goto copyfault;
325: i = SIGSEGV;
326: break;
327: }
328: ncode = code >> 16;
329: #if defined(HP330) || defined(HP360) || defined(HP370)
330: /*
331: * Crudely map PMMU faults into HP MMU faults.
332: */
333: if (mmutype != MMU_HP) {
334: int ocode = ncode;
335: ncode = 0;
336: if (ocode & PMMU_WP)
337: ncode |= MMU_WPF;
338: else if (ocode & PMMU_INV) {
339: if ((ocode & PMMU_LVLMASK) == 2)
340: ncode |= MMU_PF;
341: else
342: ncode |= MMU_PTF;
343: }
344: /*
345: * RMW cycle, must load ATC by hand
346: */
347: else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) {
348: #ifdef DEBUG
349: log(LOG_WARNING,
350: "RMW fault at %x: MMUSR %x SSW %x\n",
351: v, ocode, code & 0xFFFF);
352: #endif
353: ploadw((caddr_t)v);
354: return;
355: }
356: /*
357: * Fault with no fault bits, should indicate bad
358: * hardware but we see this on 340s using starbase
359: * sometimes (faults accessing catseye registers)
360: */
361: else {
362: log(LOG_WARNING,
363: "Bad PMMU fault at %x: MMUSR %x SSW %x\n",
364: v, ocode, code & 0xFFFF);
365: return;
366: }
367: #ifdef DEBUG
368: if (mmudebug && mmudebug == p->p_pid)
369: printf("MMU %d: v%x, os%x, ns%x\n",
370: p->p_pid, v, ocode, ncode);
371: #endif
372: }
373: #endif
374: #ifdef DEBUG
375: if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) {
376: printf("T_MMUFLT with no fault bits\n");
377: goto dopanic;
378: }
379: #endif
380: if (ncode & MMU_PTF) {
381: #ifdef DEBUG
382: /*
383: * NOTE: we use a u_int instead of an ste since the
384: * current compiler generates bogus code for some
385: * bitfield operations (i.e. attempts to access last
386: * word of a page as a longword causing fault).
387: */
388: extern struct ste *vtoste();
389: u_int *ste = (u_int *)vtoste(p, v);
390:
391: if (*ste & SG_V) {
392: if (ncode & MMU_WPF) {
393: printf("PTF|WPF...\n");
394: if (type == T_MMUFLT)
395: goto copyfault;
396: i = SIGBUS;
397: break;
398: }
399: printf("MMU_PTF with sg_v, ste@%x = %x\n",
400: ste, *ste);
401: goto dopanic;
402: }
403: #endif
404: #ifdef HPUXCOMPAT
405: if (ISHPMMADDR(v)) {
406: extern struct ste *vtoste();
407: u_int *bste, *nste;
408:
409: bste = (u_int *)vtoste(p, HPMMBASEADDR(v));
410: nste = (u_int *)vtoste(p, v);
411: if ((*bste & SG_V) && *nste == SG_NV) {
412: *nste = *bste;
413: TBIAU();
414: return;
415: }
416: }
417: #endif
418: growit:
419: if (type == T_MMUFLT)
420: goto copyfault;
421: if (grow((unsigned)frame.f_regs[SP]) || grow(v))
422: goto out;
423: i = SIGSEGV;
424: break;
425: }
426: #ifdef HPUXCOMPAT
427: if (ISHPMMADDR(v)) {
428: TBIS(v);
429: v = HPMMBASEADDR(v);
430: }
431: #endif
432: /*
433: * NOTE: WPF without PG_V is possible
434: * (e.g. attempt to write shared text which is paged out)
435: */
436: if (ncode & MMU_WPF) {
437: #ifdef DEBUG
438: extern struct ste *vtoste();
439: u_int *ste = (u_int *)vtoste(p, v);
440:
441: if (!(*ste & SG_V)) {
442: printf("MMU_WPF without sg_v, ste@%x = %x\n",
443: ste, *ste);
444: goto dopanic;
445: }
446: #endif
447: if (type == T_MMUFLT)
448: goto copyfault;
449: i = SIGBUS;
450: break;
451: }
452: if (ncode & MMU_PF) {
453: register u_int vp;
454: #ifdef DEBUG
455: extern struct ste *vtoste();
456: u_int *ste = (u_int *)vtoste(p, v);
457: struct pte *pte;
458:
459: if (!(*ste & SG_V)) {
460: printf("MMU_PF without sg_v, ste@%x = %x\n",
461: ste, *ste);
462: goto dopanic;
463: }
464: #endif
465: vp = btop(v);
466: if (vp >= dptov(p, p->p_dsize) &&
467: vp < sptov(p, p->p_ssize-1))
468: goto growit;
469: #ifdef DEBUG
470: pte = vtopte(p, vp);
471: if (*(u_int *)pte & PG_V) {
472: printf("MMU_PF with pg_v, pte = %x\n",
473: *(u_int *)pte);
474: goto dopanic;
475: }
476: #endif
477: pagein(v, 0);
478: if (type == T_MMUFLT)
479: return;
480: goto out;
481: }
482: #ifdef DEBUG
483: printf("T_MMUFLT: unrecognized scenerio\n");
484: goto dopanic;
485: #endif
486: }
487: trapsignal(i, ucode);
488: if ((type & USER) == 0)
489: return;
490: out:
491: p = u.u_procp;
492: if (i = CURSIG(p))
493: psig(i);
494: p->p_pri = p->p_usrpri;
495: if (runrun) {
496: /*
497: * Since we are u.u_procp, clock will normally just change
498: * our priority without moving us from one queue to another
499: * (since the running process is not on a queue.)
500: * If that happened after we setrq ourselves but before we
501: * swtch()'ed, we might not be on the queue indicated by
502: * our priority.
503: */
504: (void) splclock();
505: setrq(p);
506: u.u_ru.ru_nivcsw++;
507: swtch();
508: if (i = CURSIG(p))
509: psig(i);
510: }
511: if (u.u_prof.pr_scale) {
512: int ticks;
513: struct timeval *tv = &u.u_ru.ru_stime;
514:
515: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
516: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
517: if (ticks) {
518: #ifdef PROFTIMER
519: extern int profscale;
520: addupc(frame.f_pc, &u.u_prof, ticks * profscale);
521: #else
522: addupc(frame.f_pc, &u.u_prof, ticks);
523: #endif
524: }
525: }
526: curpri = p->p_pri;
527: }
528:
529: /*
530: * Called from the trap handler when a system call occurs
531: */
532: /*ARGSUSED*/
533: syscall(code, frame)
534: volatile int code;
535: struct frame frame;
536: {
537: register caddr_t params;
538: register int i;
539: register struct sysent *callp;
540: register struct proc *p = u.u_procp;
541: int error, opc, numsys;
542: struct args {
543: int i[8];
544: } args;
545: int rval[2];
546: struct timeval syst;
547: struct sysent *systab;
548: #ifdef HPUXCOMPAT
549: extern struct sysent hpuxsysent[];
550: extern int hpuxnsysent, notimp();
551: #endif
552:
553: cnt.v_syscall++;
554: syst = u.u_ru.ru_stime;
555: if (!USERMODE(frame.f_sr))
556: panic("syscall");
557: u.u_ar0 = frame.f_regs;
558: opc = frame.f_pc - 2;
559: systab = sysent;
560: numsys = nsysent;
561: #ifdef HPUXCOMPAT
562: if (p->p_flag & SHPUX) {
563: systab = hpuxsysent;
564: numsys = hpuxnsysent;
565: }
566: #endif
567: params = (caddr_t)frame.f_regs[SP] + NBPW;
568: if (code == 0) { /* indir */
569: code = fuword(params);
570: params += NBPW;
571: }
572: if (code >= numsys)
573: callp = &systab[0]; /* indir (illegal) */
574: else
575: callp = &systab[code];
576: if ((i = callp->sy_narg * sizeof (int)) &&
577: (error = copyin(params, (caddr_t)&args, (u_int)i))) {
578: #ifdef HPUXCOMPAT
579: if (p->p_flag & SHPUX)
580: error = bsdtohpuxerrno(error);
581: #endif
582: frame.f_regs[D0] = (u_char) error;
583: frame.f_sr |= PSL_C; /* carry bit */
584: #ifdef KTRACE
585: if (KTRPOINT(p, KTR_SYSCALL))
586: ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
587: #endif
588: goto done;
589: }
590: #ifdef KTRACE
591: if (KTRPOINT(p, KTR_SYSCALL))
592: ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
593: #endif
594: rval[0] = 0;
595: rval[1] = frame.f_regs[D1];
596: #ifdef HPUXCOMPAT
597: /* debug kludge */
598: if (callp->sy_call == notimp)
599: error = notimp(u.u_procp, args.i, rval, code, callp->sy_narg);
600: else
601: #endif
602: error = (*callp->sy_call)(u.u_procp, &args, rval);
603: if (error == ERESTART)
604: frame.f_pc = opc;
605: else if (error != EJUSTRETURN) {
606: if (error) {
607: #ifdef HPUXCOMPAT
608: if (p->p_flag & SHPUX)
609: error = bsdtohpuxerrno(error);
610: #endif
611: frame.f_regs[D0] = (u_char) error;
612: frame.f_sr |= PSL_C; /* carry bit */
613: } else {
614: frame.f_regs[D0] = rval[0];
615: frame.f_regs[D1] = rval[1];
616: frame.f_sr &= ~PSL_C;
617: }
618: }
619: /* else if (error == EJUSTRETURN) */
620: /* nothing to do */
621:
622: done:
623: /*
624: * Reinitialize proc pointer `p' as it may be different
625: * if this is a child returning from fork syscall.
626: */
627: p = u.u_procp;
628: /*
629: * XXX the check for sigreturn ensures that we don't
630: * attempt to set up a call to a signal handler (sendsig) before
631: * we have cleaned up the stack from the last call (sigreturn).
632: * Allowing this seems to lock up the machine in certain scenarios.
633: * What should really be done is to clean up the signal handling
634: * so that this is not a problem.
635: */
636: #include "syscall.h"
637: if (code != SYS_sigreturn && (i = CURSIG(p)))
638: psig(i);
639: p->p_pri = p->p_usrpri;
640: if (runrun) {
641: /*
642: * Since we are u.u_procp, clock will normally just change
643: * our priority without moving us from one queue to another
644: * (since the running process is not on a queue.)
645: * If that happened after we setrq ourselves but before we
646: * swtch()'ed, we might not be on the queue indicated by
647: * our priority.
648: */
649: (void) splclock();
650: setrq(p);
651: u.u_ru.ru_nivcsw++;
652: swtch();
653: if (code != SYS_sigreturn && (i = CURSIG(p)))
654: psig(i);
655: }
656: if (u.u_prof.pr_scale) {
657: int ticks;
658: struct timeval *tv = &u.u_ru.ru_stime;
659:
660: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
661: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
662: if (ticks) {
663: #ifdef PROFTIMER
664: extern int profscale;
665: addupc(frame.f_pc, &u.u_prof, ticks * profscale);
666: #else
667: addupc(frame.f_pc, &u.u_prof, ticks);
668: #endif
669: }
670: }
671: curpri = p->p_pri;
672: #ifdef KTRACE
673: if (KTRPOINT(p, KTR_SYSRET))
674: ktrsysret(p->p_tracep, code, error, rval[0]);
675: #endif
676: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.