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.14 (Berkeley) 09/23/93
7 */
8
9 #include "sys/param.h"
10 #include "sys/systm.h"
11 #include "sys/user.h"
12 #include "sys/proc.h"
13 #include "sys/seg.h"
14 #include "sys/acct.h"
15 #include "sys/kernel.h"
16
17 #include "../include/psl.h"
18 #include "../include/reg.h"
19 #include "../include/pte.h"
20 #include "../include/mtpr.h"
21 #ifdef KTRACE
22 #include "sys/ktrace.h"
23 #endif
24
25 #include "../include/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*/
trap(sp,type,hfs,accmst,acclst,dbl,code,pc,psl)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 & P_OWEUPC) && u.u_prof.pr_scale) {
107 addupc(pc, &u.u_prof, 1);
108 u.u_procp->p_flag &= ~P_OWEUPC;
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 postsig(i);
176 p->p_priority = 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 put ourselves on the run queue
183 * but before we Xswitch()'ed, we might not be on the queue
184 * indicated by our priority.
185 */
186 (void) splclock();
187 setrunqueue(p);
188 u.u_ru.ru_nivcsw++;
189 Xswitch();
190 if (i = CURSIG(p))
191 postsig(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 curpriority = p->p_priority;
203 }
204
205 /*
206 * Called from locore when a system call occurs
207 */
208 /*ARGSUSED*/
syscall(sp,type,hfs,accmst,acclst,dbl,code,pc,psl)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 postsig(i);
295 p->p_priority = 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 put ourselves on the run queue
302 * but before we Xswitch()'ed, we might not be on the queue
303 * indicated by our priority.
304 */
305 (void) splclock();
306 setrunqueue(p);
307 u.u_ru.ru_nivcsw++;
308 Xswitch();
309 if (i = CURSIG(p))
310 postsig(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 curpriority = p->p_priority;
322 #ifdef KTRACE
323 if (KTRPOINT(p, KTR_SYSRET))
324 ktrsysret(p->p_tracep, code, error, rval[0]);
325 #endif
326 }
327