xref: /csrg-svn/sys/tahoe/tahoe/trap.c (revision 25678)
1 /*	trap.c	1.2	86/01/05	*/
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 	case T_KSPNOTVAL:
137 	case T_KSPNOTVAL + USER:
138 		i = SIGKILL;	/* There is nothing to do but to kill the
139 				 * process.. */
140 		printf("KSP NOT VALID.\n");
141 		break;
142 
143 	case T_BUSERR + USER:
144 		i = SIGBUS;
145 		u.u_code = code;
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) spl8();
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 /*
185  * Called from locore when a system call occurs
186  */
187 /*ARGSUSED*/
188 syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl)
189 	unsigned code;
190 {
191 	int r0, r1;			/* must reserve space */
192 	register int *locr0 = ((int *)&psl)-PS;
193 	register caddr_t params;
194 	register int i;
195 	register struct sysent *callp;
196 	register struct proc *p;
197 	struct timeval syst;
198 	int opc;
199 
200 #ifdef lint
201 	r0 = 0; r0 = r0; r1 = 0; r1 = r1;
202 #endif
203 	syst = u.u_ru.ru_stime;
204 	if (!USERMODE(locr0[PS]))
205 		panic("syscall");
206 	u.u_ar0 = locr0;
207 	if (code == 139) {			/* 4.2 COMPATIBILTY XXX */
208 		osigcleanup();			/* 4.2 COMPATIBILTY XXX */
209 		goto done;			/* 4.2 COMPATIBILTY XXX */
210 	}
211 	params = (caddr_t)locr0[FP] + NBPW;
212 	u.u_error = 0;
213 /* BEGIN GROT */
214 	/*
215 	 * Try to reconstruct pc, assuming code
216 	 * is an immediate constant
217 	 */
218 	opc = pc - 2;		/* short literal */
219 	if (code > 0x3f) {
220 		opc--;				/* byte immediate */
221 		if (code > 0x7f) {
222 			opc--;			/* word immediate */
223 			if (code > 0x7fff)
224 				opc -= 2;	/* long immediate */
225 		}
226 	}
227 /* END GROT */
228 	callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
229 	if (callp == sysent) {
230 		i = fuword(params);
231 		params += NBPW;
232 		callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
233 	}
234 	if ((i = callp->sy_narg * sizeof (int)) &&
235 	    (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
236 		locr0[R0] = u.u_error;
237 		locr0[PS] |= PSL_C;	/* carry bit */
238 		goto done;
239 	}
240 	u.u_r.r_val1 = 0;
241 	u.u_r.r_val2 = locr0[R1];
242 	if (setjmp(&u.u_qsave)) {
243 		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
244 			u.u_error = EINTR;
245 	} else {
246 		u.u_eosys = NORMALRETURN;
247 #ifdef SYSCALLTRACE
248 		if (syscalltrace) {
249 			register int i;
250 			char *cp;
251 
252 			if (code >= nsysent)
253 				printf("0x%x", code);
254 			else
255 				printf("%s", syscallnames[code]);
256 			cp = "(";
257 			for (i= 0; i < callp->sy_narg; i++) {
258 				printf("%s%x", cp, u.u_arg[i]);
259 				cp = ", ";
260 			}
261 			if (i)
262 				putchar(')', 0);
263 			putchar('\n', 0);
264 		}
265 #endif
266 		(*callp->sy_call)();
267 	}
268 	if (u.u_eosys == NORMALRETURN) {
269 		if (u.u_error) {
270 			locr0[R0] = u.u_error;
271 			locr0[PS] |= PSL_C;	/* carry bit */
272 		} else {
273 			locr0[PS] &= ~PSL_C;	/* clear carry bit */
274 			locr0[R0] = u.u_r.r_val1;
275 			locr0[R1] = u.u_r.r_val2;
276 		}
277 	} else if (u.u_eosys == RESTARTSYS)
278 		pc = opc;
279 	/* else if (u.u_eosys == JUSTRETURN) */
280 		/* nothing to do */
281 done:
282 	p = u.u_procp;
283 	if (p->p_cursig || ISSIG(p))
284 		psig();
285 	p->p_pri = p->p_usrpri;
286 	if (runrun) {
287 		/*
288 		 * Since we are u.u_procp, clock will normally just change
289 		 * our priority without moving us from one queue to another
290 		 * (since the running process is not on a queue.)
291 		 * If that happened after we setrq ourselves but before we
292 		 * swtch()'ed, we might not be on the queue indicated by
293 		 * our priority.
294 		 */
295 		(void) spl8();
296 		setrq(p);
297 		u.u_ru.ru_nivcsw++;
298 		swtch();
299 	}
300 	if (u.u_prof.pr_scale) {
301 		int ticks;
302 		struct timeval *tv = &u.u_ru.ru_stime;
303 
304 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
305 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
306 		if (ticks)
307 			addupc(locr0[PC], &u.u_prof, ticks);
308 	}
309 	curpri = p->p_pri;
310 }
311 
312 /*
313  * nonexistent system call-- signal process (may want to handle it)
314  * flag error if process won't see signal immediately
315  * Q: should we do that all the time ??
316  */
317 nosys()
318 {
319 
320 	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
321 		u.u_error = EINVAL;
322 	psignal(u.u_procp, SIGSYS);
323 }
324 
325 #ifdef notdef
326 /*
327  * Ignored system call
328  */
329 nullsys()
330 {
331 
332 }
333 #endif
334