|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)trap.c 7.10 (Berkeley) 6/25/90
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "user.h"
12: #include "proc.h"
13: #include "seg.h"
14: #include "acct.h"
15: #include "kernel.h"
16:
17: #include "psl.h"
18: #include "reg.h"
19: #include "pte.h"
20: #include "mtpr.h"
21: #ifdef KTRACE
22: #include "ktrace.h"
23: #endif
24:
25: #include "../tahoe/trap.h"
26:
27: #define USER 040 /* user-mode flag added to type */
28:
29: struct sysent sysent[];
30: int nsysent;
31:
32: char *trap_type[] = {
33: "Reserved addressing mode", /* T_RESADFLT */
34: "Privileged instruction", /* T_PRIVINFLT */
35: "Reserved operand", /* T_RESOPFLT */
36: "Breakpoint", /* T_BPTFLT */
37: 0,
38: "Kernel call", /* T_SYSCALL */
39: "Arithmetic trap", /* T_ARITHTRAP */
40: "System forced exception", /* T_ASTFLT */
41: "Segmentation fault", /* T_SEGFLT */
42: "Protection fault", /* T_PROTFLT */
43: "Trace trap", /* T_TRCTRAP */
44: 0,
45: "Page fault", /* T_PAGEFLT */
46: "Page table fault", /* T_TABLEFLT */
47: "Alignment fault", /* T_ALIGNFLT */
48: "Kernel stack not valid", /* T_KSPNOTVAL */
49: "Bus error", /* T_BUSERR */
50: "Kernel debugger request", /* T_KDBTRAP */
51: };
52: int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
53:
54: /*
55: * Called from the trap handler when a processor trap occurs.
56: */
57: /*ARGSUSED*/
58: trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
59: unsigned type, code; /* kdb assumes these are *not* registers */
60: {
61: int r0, r1; /* must reserve space */
62: register int *locr0 = ((int *)&psl)-PS;
63: register int i;
64: unsigned ucode = code;
65: register struct proc *p;
66: struct timeval syst;
67:
68: #ifdef lint
69: r0 = 0; r0 = r0; r1 = 0; r1 = r1;
70: #endif
71: syst = u.u_ru.ru_stime;
72: if (USERMODE(locr0[PS])) {
73: type |= USER;
74: u.u_ar0 = locr0;
75: }
76: switch (type) {
77:
78: default:
79: #ifdef KADB
80: if (kdb_trap(&psl))
81: return;
82: #endif
83: printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
84: type &= ~USER;
85: if (type < TRAP_TYPES && trap_type[type])
86: panic(trap_type[type]);
87: else
88: panic("trap");
89: /*NOTREACHED*/
90:
91: case T_PROTFLT + USER: /* protection fault */
92: i = SIGBUS;
93: break;
94:
95: case T_PRIVINFLT + USER: /* privileged instruction fault */
96: case T_RESADFLT + USER: /* reserved addressing fault */
97: case T_RESOPFLT + USER: /* resereved operand fault */
98: case T_ALIGNFLT + USER: /* unaligned data fault */
99: ucode = type &~ USER;
100: i = SIGILL;
101: break;
102:
103: case T_ASTFLT + USER: /* Allow process switch */
104: case T_ASTFLT:
105: astoff();
106: if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
107: addupc(pc, &u.u_prof, 1);
108: u.u_procp->p_flag &= ~SOWEUPC;
109: }
110: goto out;
111:
112: case T_ARITHTRAP + USER:
113: i = SIGFPE;
114: break;
115:
116: /*
117: * If the user SP is above the stack segment,
118: * grow the stack automatically.
119: */
120: case T_SEGFLT + USER:
121: if (grow((unsigned)locr0[SP]) || grow(code))
122: goto out;
123: i = SIGSEGV;
124: break;
125:
126: case T_TABLEFLT: /* allow page table faults in kernel */
127: case T_TABLEFLT + USER: /* page table fault */
128: panic("ptable fault");
129:
130: case T_PAGEFLT: /* allow page faults in kernel mode */
131: case T_PAGEFLT + USER: /* page fault */
132: pagein(code, 0);
133: if (type == T_PAGEFLT)
134: return;
135: goto out;
136:
137: case T_BPTFLT + USER: /* bpt instruction fault */
138: case T_TRCTRAP + USER: /* trace trap */
139: locr0[PS] &= ~PSL_T;
140: i = SIGTRAP;
141: break;
142:
143: #ifdef notdef
144: /* THIS CODE IS BOGUS- delete? (KSP not valid is unrecoverable)
145: And what does KSPNOTVAL in user-mode mean? */
146: /*
147: * For T_KSPNOTVAL and T_BUSERR, can not allow spl to
148: * drop to 0 as clock could go off and we would end up
149: * doing an rei to the interrupt stack at ipl 0 (a
150: * reserved operand fault). Instead, we allow psignal
151: * to post an ast, then return to user mode where we
152: * will reenter the kernel on the kernel's stack and
153: * can then service the signal.
154: */
155: case T_KSPNOTVAL:
156: if (noproc)
157: panic("ksp not valid");
158: /* fall thru... */
159: case T_KSPNOTVAL + USER:
160: printf("pid %d: ksp not valid\n", u.u_procp->p_pid);
161: panic("ksp not valid - 2");
162: /* must insure valid kernel stack pointer? */
163: psignal(u.u_procp, SIGKILL);
164: return;
165: #endif
166:
167: case T_BUSERR + USER:
168: i = SIGBUS;
169: break;
170: }
171: trapsignal(i, ucode);
172: out:
173: p = u.u_procp;
174: if (i = CURSIG(p))
175: psig(i);
176: p->p_pri = p->p_usrpri;
177: if (runrun) {
178: /*
179: * Since we are u.u_procp, clock will normally just change
180: * our priority without moving us from one queue to another
181: * (since the running process is not on a queue.)
182: * If that happened after we setrq ourselves but before we
183: * swtch()'ed, we might not be on the queue indicated by
184: * our priority.
185: */
186: (void) splclock();
187: setrq(p);
188: u.u_ru.ru_nivcsw++;
189: swtch();
190: if (i = CURSIG(p))
191: psig(i);
192: }
193: if (u.u_prof.pr_scale) {
194: int ticks;
195: struct timeval *tv = &u.u_ru.ru_stime;
196:
197: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
198: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
199: if (ticks)
200: addupc(locr0[PC], &u.u_prof, ticks);
201: }
202: curpri = p->p_pri;
203: }
204:
205: /*
206: * Called from locore when a system call occurs
207: */
208: /*ARGSUSED*/
209: syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
210: unsigned code;
211: {
212: int r0, r1; /* must reserve space */
213: register int *locr0 = ((int *)&psl)-PS;
214: register caddr_t params;
215: register int i;
216: register struct sysent *callp;
217: register struct proc *p = u.u_procp;
218: struct timeval syst;
219: int error, opc;
220: struct args {
221: int i[8];
222: } args;
223: int rval[2];
224:
225: #ifdef lint
226: r0 = 0; r0 = r0; r1 = 0; r1 = r1;
227: #endif
228: syst = u.u_ru.ru_stime;
229: if (!USERMODE(locr0[PS]))
230: panic("syscall");
231: u.u_ar0 = locr0;
232: params = (caddr_t)locr0[FP] + NBPW;
233: /* BEGIN GROT */
234: /*
235: * Try to reconstruct pc, assuming code
236: * is an immediate constant
237: */
238: opc = pc - 2; /* short literal */
239: if (code > 0x3f) {
240: opc--; /* byte immediate */
241: if (code > 0x7f) {
242: opc--; /* word immediate */
243: if (code > 0x7fff)
244: opc -= 2; /* long immediate */
245: }
246: }
247: /* END GROT */
248: if (code == 0) { /* indir */
249: code = fuword(params);
250: params += NBPW;
251: }
252: if (code >= nsysent)
253: callp = &sysent[0]; /* indir (illegal) */
254: else
255: callp = &sysent[code];
256: if ((i = callp->sy_narg * sizeof (int)) &&
257: (error = copyin(params, (caddr_t)&args, (u_int)i)) != 0) {
258: locr0[R0] = error;
259: locr0[PS] |= PSL_C; /* carry bit */
260: #ifdef KTRACE
261: if (KTRPOINT(p, KTR_SYSCALL))
262: ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
263: #endif
264: goto done;
265: }
266: #ifdef KTRACE
267: if (KTRPOINT(p, KTR_SYSCALL))
268: ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
269: #endif
270: rval[0] = 0;
271: rval[1] = locr0[R1];
272: error = (*callp->sy_call)(u.u_procp, &args, rval);
273: if (error == ERESTART)
274: pc = opc;
275: else if (error != EJUSTRETURN) {
276: if (error) {
277: locr0[R0] = error;
278: locr0[PS] |= PSL_C; /* carry bit */
279: } else {
280: locr0[PS] &= ~PSL_C; /* clear carry bit */
281: locr0[R0] = rval[0];
282: locr0[R1] = rval[1];
283: }
284: }
285: /* else if (error == EJUSTRETURN) */
286: /* nothing to do */
287: done:
288: /*
289: * Reinitialize proc pointer `p' as it may be different
290: * if this is a child returning from fork syscall.
291: */
292: p = u.u_procp;
293: if (i = CURSIG(p))
294: psig(i);
295: p->p_pri = p->p_usrpri;
296: if (runrun) {
297: /*
298: * Since we are u.u_procp, clock will normally just change
299: * our priority without moving us from one queue to another
300: * (since the running process is not on a queue.)
301: * If that happened after we setrq ourselves but before we
302: * swtch()'ed, we might not be on the queue indicated by
303: * our priority.
304: */
305: (void) splclock();
306: setrq(p);
307: u.u_ru.ru_nivcsw++;
308: swtch();
309: if (i = CURSIG(p))
310: psig(i);
311: }
312: if (u.u_prof.pr_scale) {
313: int ticks;
314: struct timeval *tv = &u.u_ru.ru_stime;
315:
316: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
317: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
318: if (ticks)
319: addupc(locr0[PC], &u.u_prof, ticks);
320: }
321: curpri = p->p_pri;
322: #ifdef KTRACE
323: if (KTRPOINT(p, KTR_SYSRET))
324: ktrsysret(p->p_tracep, code, error, rval[0]);
325: #endif
326: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.