BSD 4_3_Tahoe release
[unix-history] / usr / src / sys / tahoe / trap.c
CommitLineData
430f81c3
MK
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 *
ca67e7b4 6 * @(#)trap.c 7.1 (Berkeley) 5/21/88
430f81c3 7 */
a55e280b
SL
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"
430f81c3
MK
17
18#include "psl.h"
19#include "reg.h"
20#include "pte.h"
21#include "mtpr.h"
22
a55e280b 23#define SYSCALLTRACE
2a120284
SL
24#ifdef SYSCALLTRACE
25#include "../sys/syscalls.c"
26#endif
a55e280b
SL
27
28#include "../tahoe/trap.h"
2a120284
SL
29
30#define USER 040 /* user-mode flag added to type */
31
a55e280b
SL
32struct sysent sysent[];
33int nsysent;
34
35char *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 */
c5747722 53 "Kernel debugger trap", /* T_KDBTRAP */
a55e280b 54};
c5747722 55int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
2a120284
SL
56
57/*
58 * Called from the trap handler when a processor trap occurs.
59 */
a55e280b 60/*ARGSUSED*/
2a120284 61trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
a55e280b 62 unsigned type, code;
2a120284 63{
a55e280b 64 int r0, r1; /* must reserve space */
2a120284
SL
65 register int *locr0 = ((int *)&psl)-PS;
66 register int i;
67 register struct proc *p;
68 struct timeval syst;
2a120284 69
a55e280b
SL
70#ifdef lint
71 r0 = 0; r0 = r0; r1 = 0; r1 = r1;
72#endif
2a120284
SL
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
a55e280b 80 default:
8b58ff19 81#ifdef KADB
c5747722
SL
82 if (kdb_trap(&psl))
83 return;
84#endif
a55e280b
SL
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*/
2a120284 92
a55e280b 93 case T_PROTFLT + USER: /* protection fault */
2a120284
SL
94 i = SIGBUS;
95 break;
96
97 case T_PRIVINFLT + USER: /* privileged instruction fault */
a55e280b
SL
98 case T_RESADFLT + USER: /* reserved addressing fault */
99 case T_RESOPFLT + USER: /* resereved operand fault */
100 case T_ALIGNFLT + USER: /* unaligned data fault */
2a120284
SL
101 u.u_code = type &~ USER;
102 i = SIGILL;
103 break;
104
a55e280b 105 case T_ASTFLT + USER: /* Allow process switch */
2a120284
SL
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
a55e280b
SL
129 case T_TABLEFLT: /* allow page table faults in kernel */
130 case T_TABLEFLT + USER: /* page table fault */
2a120284
SL
131 panic("ptable fault");
132
a55e280b
SL
133 case T_PAGEFLT: /* allow page faults in kernel mode */
134 case T_PAGEFLT + USER: /* page fault */
2a120284 135 i = u.u_error;
a55e280b 136 pagein(code, 0);
2a120284
SL
137 u.u_error = i;
138 if (type == T_PAGEFLT)
139 return;
140 goto out;
141
a55e280b
SL
142 case T_BPTFLT + USER: /* bpt instruction fault */
143 case T_TRCTRAP + USER: /* trace trap */
2a120284
SL
144 locr0[PS] &= ~PSL_T;
145 i = SIGTRAP;
146 break;
a55e280b 147
2f63ec38
SL
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 */
2a120284 157 case T_KSPNOTVAL:
2f63ec38
SL
158 if (noproc)
159 panic("ksp not valid");
160 /* fall thru... */
2a120284 161 case T_KSPNOTVAL + USER:
c05010e2 162 printf("pid %d: ksp not valid\n", u.u_procp->p_pid);
2f63ec38
SL
163 /* must insure valid kernel stack pointer? */
164 psignal(u.u_procp, SIGKILL);
165 return;
2a120284 166
a55e280b 167 case T_BUSERR + USER:
a55e280b 168 u.u_code = code;
2f63ec38
SL
169 psignal(u.u_procp, SIGBUS);
170 return;
2a120284
SL
171 }
172 psignal(u.u_procp, i);
173out:
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 */
b1cd91d1 187 (void) splclock();
2a120284
SL
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
a55e280b 205int syscalltrace = 0;
2a120284
SL
206#endif
207
208/*
a55e280b 209 * Called from locore when a system call occurs
2a120284 210 */
a55e280b 211/*ARGSUSED*/
2a120284 212syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
a55e280b 213 unsigned code;
2a120284 214{
a55e280b 215 int r0, r1; /* must reserve space */
2a120284 216 register int *locr0 = ((int *)&psl)-PS;
a55e280b
SL
217 register caddr_t params;
218 register int i;
2a120284
SL
219 register struct sysent *callp;
220 register struct proc *p;
a55e280b 221 struct timeval syst;
2a120284
SL
222 int opc;
223
a55e280b
SL
224#ifdef lint
225 r0 = 0; r0 = r0; r1 = 0; r1 = r1;
226#endif
2a120284
SL
227 syst = u.u_ru.ru_stime;
228 if (!USERMODE(locr0[PS]))
229 panic("syscall");
230 u.u_ar0 = locr0;
a55e280b
SL
231 if (code == 139) { /* 4.2 COMPATIBILTY XXX */
232 osigcleanup(); /* 4.2 COMPATIBILTY XXX */
233 goto done; /* 4.2 COMPATIBILTY XXX */
2a120284
SL
234 }
235 params = (caddr_t)locr0[FP] + NBPW;
236 u.u_error = 0;
a55e280b
SL
237/* BEGIN GROT */
238 /*
239 * Try to reconstruct pc, assuming code
240 * is an immediate constant
241 */
2a120284
SL
242 opc = pc - 2; /* short literal */
243 if (code > 0x3f) {
a55e280b 244 opc--; /* byte immediate */
2a120284 245 if (code > 0x7f) {
a55e280b 246 opc--; /* word immediate */
2a120284
SL
247 if (code > 0x7fff)
248 opc -= 2; /* long immediate */
249 }
250 }
a55e280b 251/* END GROT */
2a120284
SL
252 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
253 if (callp == sysent) {
254 i = fuword(params);
255 params += NBPW;
a55e280b 256 callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
2a120284 257 }
a55e280b
SL
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;
2a120284 263 }
2a120284 264 u.u_r.r_val1 = 0;
a55e280b 265 u.u_r.r_val2 = locr0[R1];
2a120284 266 if (setjmp(&u.u_qsave)) {
a55e280b 267 if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
2a120284
SL
268 u.u_error = EINTR;
269 } else {
a55e280b 270 u.u_eosys = NORMALRETURN;
2a120284
SL
271#ifdef SYSCALLTRACE
272 if (syscalltrace) {
9d61b7ff 273 register int a;
2a120284
SL
274 char *cp;
275
276 if (code >= nsysent)
277 printf("0x%x", code);
278 else
279 printf("%s", syscallnames[code]);
280 cp = "(";
9d61b7ff
SL
281 for (a = 0; a < callp->sy_narg; a++) {
282 printf("%s%x", cp, u.u_arg[a]);
2a120284
SL
283 cp = ", ";
284 }
9d61b7ff
SL
285 if (a)
286 printf(")");
287 printf("\n");
2a120284
SL
288 }
289#endif
a55e280b 290 (*callp->sy_call)();
2a120284 291 }
a55e280b
SL
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)
2a120284 302 pc = opc;
a55e280b
SL
303 /* else if (u.u_eosys == JUSTRETURN) */
304 /* nothing to do */
2a120284
SL
305done:
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 */
b1cd91d1 319 (void) splclock();
2a120284
SL
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 */
341nosys()
342{
a55e280b 343
2a120284
SL
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
a55e280b 349#ifdef notdef
2a120284
SL
350/*
351 * Ignored system call
352 */
353nullsys()
354{
355
356}
a55e280b 357#endif