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