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