|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 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.3 (Berkeley) 5/19/88
7: */
8:
9: #include "psl.h"
10: #include "reg.h"
11: #include "pte.h"
12:
13: #include "param.h"
14: #include "systm.h"
15: #include "dir.h"
16: #include "user.h"
17: #include "assym.s"
18: #include "proc.h"
19: #include "seg.h"
20: #include "trap.h"
21: #include "acct.h"
22: #include "kernel.h"
23: #ifdef SYSCALLTRACE
24: #include "../sys/syscalls.c"
25: #endif
26:
27: #include "mtpr.h"
28:
29: #define USER 040 /* user-mode flag added to type */
30:
31: struct sysent sysent[];
32: int nsysent;
33:
34: char *trap_type[] = {
35: "Reserved addressing mode",
36: "Privileged instruction",
37: "Reserved operand",
38: "Breakpoint",
39: "Xfc trap",
40: "Syscall trap",
41: "Arithmetic fault",
42: "Ast trap",
43: "Segmentation fault",
44: "Protection fault",
45: "Trace trap",
46: "Compatibility mode trap",
47: "Page fault",
48: "Page table fault",
49: "Kernel debugger trap",
50: };
51: int TRAP_TYPES = (sizeof trap_type / sizeof trap_type[0]);
52:
53: /*
54: * Called from the trap handler when a processor trap occurs.
55: */
56: /*ARGSUSED*/
57: trap(sp, type, code, pc, psl)
58: int sp, type;
59: unsigned code;
60: int pc, psl;
61: {
62: register int *locr0 = ((int *)&psl)-PS;
63: register int i;
64: register struct proc *p;
65: struct timeval syst;
66:
67: syst = u.u_ru.ru_stime;
68: if (USERMODE(locr0[PS])) {
69: type |= USER;
70: u.u_ar0 = locr0;
71: }
72: switch (type) {
73:
74: default:
75: #ifdef KADB
76: if (kdb_trap(&psl))
77: return;
78: #endif
79: printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
80: type &= ~USER;
81: if ((unsigned)type < TRAP_TYPES)
82: panic(trap_type[type]);
83: panic("trap");
84:
85: case T_PROTFLT+USER: /* protection fault */
86: i = SIGBUS;
87: break;
88:
89: case T_PRIVINFLT+USER: /* privileged instruction fault */
90: case T_RESADFLT+USER: /* reserved addressing fault */
91: case T_RESOPFLT+USER: /* resereved operand fault */
92: u.u_code = type &~ USER;
93: i = SIGILL;
94: break;
95:
96: case T_ASTFLT+USER:
97: astoff();
98: if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
99: addupc(pc, &u.u_prof, 1);
100: u.u_procp->p_flag &= ~SOWEUPC;
101: }
102: goto out;
103:
104: case T_ARITHTRAP+USER:
105: u.u_code = code;
106: i = SIGFPE;
107: break;
108:
109: /*
110: * If the user SP is above the stack segment,
111: * grow the stack automatically.
112: */
113: case T_SEGFLT+USER:
114: if (grow((unsigned)locr0[SP]) || grow(code))
115: goto out;
116: i = SIGSEGV;
117: break;
118:
119: case T_TABLEFLT: /* allow page table faults in kernel mode */
120: case T_TABLEFLT+USER: /* page table fault */
121: panic("ptable fault");
122:
123: case T_PAGEFLT: /* allow page faults in kernel mode */
124: case T_PAGEFLT+USER: /* page fault */
125: i = u.u_error;
126: pagein(code, 0);
127: u.u_error = i;
128: if (type == T_PAGEFLT)
129: return;
130: goto out;
131:
132: case T_BPTFLT+USER: /* bpt instruction fault */
133: case T_TRCTRAP+USER: /* trace trap */
134: locr0[PS] &= ~PSL_T;
135: i = SIGTRAP;
136: break;
137:
138: case T_XFCFLT+USER: /* xfc instruction fault */
139: i = SIGEMT;
140: break;
141:
142: case T_COMPATFLT+USER: /* compatibility mode fault */
143: u.u_acflag |= ACOMPAT;
144: u.u_code = code;
145: i = SIGILL;
146: break;
147: }
148: psignal(u.u_procp, i);
149: out:
150: p = u.u_procp;
151: if (p->p_cursig || ISSIG(p))
152: psig();
153: p->p_pri = p->p_usrpri;
154: if (runrun) {
155: /*
156: * Since we are u.u_procp, clock will normally just change
157: * our priority without moving us from one queue to another
158: * (since the running process is not on a queue.)
159: * If that happened after we setrq ourselves but before we
160: * swtch()'ed, we might not be on the queue indicated by
161: * our priority.
162: */
163: (void) splclock();
164: setrq(p);
165: u.u_ru.ru_nivcsw++;
166: swtch();
167: }
168: if (u.u_prof.pr_scale) {
169: int ticks;
170: struct timeval *tv = &u.u_ru.ru_stime;
171:
172: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
173: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
174: if (ticks)
175: addupc(locr0[PC], &u.u_prof, ticks);
176: }
177: curpri = p->p_pri;
178: }
179:
180: #ifdef SYSCALLTRACE
181: int syscalltrace = 0;
182: #endif
183: /*
184: * Called from the trap handler when a system call occurs
185: */
186: /*ARGSUSED*/
187: syscall(sp, type, code, pc, psl)
188: unsigned code;
189: {
190: register int *locr0 = ((int *)&psl)-PS;
191: register caddr_t params; /* known to be r10 below */
192: register int i; /* known to be r9 below */
193: register struct sysent *callp;
194: register struct proc *p;
195: int opc;
196: struct timeval syst;
197:
198: syst = u.u_ru.ru_stime;
199: if (!USERMODE(locr0[PS]))
200: panic("syscall");
201: u.u_ar0 = locr0;
202: if (code == 139) { /* XXX 4.2 COMPATIBILITY */
203: osigcleanup(); /* XXX 4.2 COMPATIBILITY */
204: goto done; /* XXX 4.2 COMPATIBILITY */
205: } /* XXX 4.2 COMPATIBILITY */
206: params = (caddr_t)locr0[AP] + NBPW;
207: u.u_error = 0;
208: opc = pc - 2;
209: if (code > 63)
210: opc -= 2;
211: if (code >= nsysent)
212: callp = &sysent[0]; /* indir (illegal) */
213: else {
214: callp = &sysent[code];
215: if (callp == sysent) { /* indir */
216: i = fuword(params);
217: params += NBPW;
218: if ((unsigned)i >= nsysent)
219: callp = &sysent[0];
220: else
221: callp = &sysent[i];
222: }
223: }
224: if ((i = callp->sy_narg * sizeof (int)) &&
225: (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
226: locr0[R0] = u.u_error;
227: locr0[PS] |= PSL_C; /* carry bit */
228: goto done;
229: }
230: u.u_r.r_val1 = 0;
231: u.u_r.r_val2 = locr0[R1];
232: if (setjmp(&u.u_qsave)) {
233: if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
234: u.u_error = EINTR;
235: } else {
236: u.u_eosys = NORMALRETURN;
237: #ifdef SYSCALLTRACE
238: if (syscalltrace) {
239: register int i;
240: char *cp;
241:
242: if (code >= nsysent)
243: printf("0x%x", code);
244: else
245: printf("%s", syscallnames[code]);
246: cp = "(";
247: for (i= 0; i < callp->sy_narg; i++) {
248: printf("%s%x", cp, u.u_arg[i]);
249: cp = ", ";
250: }
251: if (i)
252: putchar(')', 0);
253: putchar('\n', 0);
254: }
255: #endif
256: (*(callp->sy_call))();
257: }
258: if (u.u_eosys == NORMALRETURN) {
259: if (u.u_error) {
260: locr0[R0] = u.u_error;
261: locr0[PS] |= PSL_C; /* carry bit */
262: } else {
263: locr0[R0] = u.u_r.r_val1;
264: locr0[R1] = u.u_r.r_val2;
265: locr0[PS] &= ~PSL_C;
266: }
267: } else if (u.u_eosys == RESTARTSYS)
268: pc = opc;
269: /* else if (u.u_eosys == JUSTRETURN) */
270: /* nothing to do */
271: done:
272: p = u.u_procp;
273: if (p->p_cursig || ISSIG(p))
274: psig();
275: p->p_pri = p->p_usrpri;
276: if (runrun) {
277: /*
278: * Since we are u.u_procp, clock will normally just change
279: * our priority without moving us from one queue to another
280: * (since the running process is not on a queue.)
281: * If that happened after we setrq ourselves but before we
282: * swtch()'ed, we might not be on the queue indicated by
283: * our priority.
284: */
285: (void) splclock();
286: setrq(p);
287: u.u_ru.ru_nivcsw++;
288: swtch();
289: }
290: if (u.u_prof.pr_scale) {
291: int ticks;
292: struct timeval *tv = &u.u_ru.ru_stime;
293:
294: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
295: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
296: if (ticks)
297: addupc(locr0[PC], &u.u_prof, ticks);
298: }
299: curpri = p->p_pri;
300: }
301:
302: /*
303: * nonexistent system call-- signal process (may want to handle it)
304: * flag error if process won't see signal immediately
305: * Q: should we do that all the time ??
306: */
307: nosys()
308: {
309: if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
310: u.u_error = EINVAL;
311: psignal(u.u_procp, SIGSYS);
312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.