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