xref: /original-bsd/sys/vax/vax/trap.c (revision 9d81f6f7)
1 /*
2  * Copyright (c) 1982, 1986, 1990 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.10 (Berkeley) 06/25/90
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 "user.h"
16 #include "assym.s"
17 #include "proc.h"
18 #include "seg.h"
19 #include "trap.h"
20 #include "acct.h"
21 #include "kernel.h"
22 #ifdef KTRACE
23 #include "ktrace.h"
24 #endif
25 
26 #include "mtpr.h"
27 
28 #define	USER	040		/* user-mode flag added to type */
29 
30 struct	sysent	sysent[];
31 int	nsysent;
32 
33 char	*trap_type[] = {
34 	"Reserved addressing mode",
35 	"Privileged instruction",
36 	"Reserved operand",
37 	"Breakpoint",
38 	"Xfc trap",
39 	"Syscall trap",
40 	"Arithmetic fault",
41 	"Ast trap",
42 	"Segmentation fault",
43 	"Protection fault",
44 	"Trace trap",
45 	"Compatibility mode trap",
46 	"Page fault",
47 	"Page table fault",
48 	"Kernel debugger trap",
49 };
50 int	TRAP_TYPES = (sizeof trap_type / sizeof trap_type[0]);
51 
52 /*
53  * Called from the trap handler when a processor trap occurs.
54  */
55 /*ARGSUSED*/
56 trap(sp, type, code, pc, psl)
57 	int sp, type;
58 	unsigned code;
59 	int pc, psl;
60 {
61 	register int *locr0 = ((int *)&psl)-PS;
62 	register int i;
63 	unsigned ucode = code;
64 	register struct proc *p;
65 	struct timeval syst;
66 
67 	syst = u.u_ru.ru_stime;
68 	if (USERMODE(locr0[PS])) {
69 		type |= USER;
70 		u.u_ar0 = locr0;
71 	}
72 	switch (type) {
73 
74 	default:
75 #ifdef KADB
76 		if (kdb_trap(&psl))
77 			return;
78 #endif
79 		printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
80 		type &= ~USER;
81 		if ((unsigned)type < TRAP_TYPES)
82 			panic(trap_type[type]);
83 		panic("trap");
84 
85 	case T_PROTFLT+USER:	/* protection fault */
86 		i = SIGBUS;
87 		break;
88 
89 	case T_PRIVINFLT+USER:	/* privileged instruction fault */
90 	case T_RESADFLT+USER:	/* reserved addressing fault */
91 	case T_RESOPFLT+USER:	/* reserved operand fault */
92 		ucode = type &~ USER;
93 		i = SIGILL;
94 		break;
95 
96 	case T_ASTFLT+USER:
97 		astoff();
98 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
99 			addupc(pc, &u.u_prof, 1);
100 			u.u_procp->p_flag &= ~SOWEUPC;
101 		}
102 		goto out;
103 
104 	case T_ARITHTRAP+USER:
105 		i = SIGFPE;
106 		break;
107 
108 	/*
109 	 * If the user SP is above the stack segment,
110 	 * grow the stack automatically.
111 	 */
112 	case T_SEGFLT+USER:
113 		if (grow((unsigned)locr0[SP]) || grow(code))
114 			goto out;
115 		i = SIGSEGV;
116 		break;
117 
118 	case T_TABLEFLT:	/* allow page table faults in kernel mode */
119 	case T_TABLEFLT+USER:   /* page table fault */
120 		panic("ptable fault");
121 
122 	case T_PAGEFLT:		/* allow page faults in kernel mode */
123 	case T_PAGEFLT+USER:	/* page fault */
124 		pagein(code, 0);
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 		i = SIGILL;
142 		break;
143 	}
144 	trapsignal(i, ucode);
145 out:
146 	p = u.u_procp;
147 	if (i = CURSIG(p))
148 		psig(i);
149 	p->p_pri = p->p_usrpri;
150 	if (runrun) {
151 		/*
152 		 * Since we are u.u_procp, clock will normally just change
153 		 * our priority without moving us from one queue to another
154 		 * (since the running process is not on a queue.)
155 		 * If that happened after we setrq ourselves but before we
156 		 * swtch()'ed, we might not be on the queue indicated by
157 		 * our priority.
158 		 */
159 		(void) splclock();
160 		setrq(p);
161 		u.u_ru.ru_nivcsw++;
162 		swtch();
163 		if (i = CURSIG(p))
164 			psig(i);
165 	}
166 	if (u.u_prof.pr_scale) {
167 		int ticks;
168 		struct timeval *tv = &u.u_ru.ru_stime;
169 
170 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
171 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
172 		if (ticks)
173 			addupc(locr0[PC], &u.u_prof, ticks);
174 	}
175 	curpri = p->p_pri;
176 }
177 
178 /*
179  * Called from the trap handler when a system call occurs
180  */
181 /*ARGSUSED*/
182 syscall(sp, type, code, pc, psl)
183 	unsigned code;
184 {
185 	register int *locr0 = ((int *)&psl)-PS;
186 	register caddr_t params;		/* known to be r10 below */
187 	register int i;				/* known to be r9 below */
188 	register struct sysent *callp;
189 	register struct proc *p = u.u_procp;
190 	int error, opc;
191 	struct args {
192 		int i[8];
193 	} args;
194 	int rval[2];
195 	struct timeval syst;
196 
197 	syst = u.u_ru.ru_stime;
198 	if (!USERMODE(locr0[PS]))
199 		panic("syscall");
200 	u.u_ar0 = locr0;
201 	params = (caddr_t)locr0[AP] + NBPW;
202 	opc = pc - 2;
203 	if (code > 63)
204 		opc -= 2;
205 	if (code == 0) {			/* indir */
206 		code = fuword(params);
207 		params += NBPW;
208 	}
209 	if (code >= nsysent)
210 		callp = &sysent[0];		/* indir (illegal) */
211 	else
212 		callp = &sysent[code];
213 	if ((i = callp->sy_narg * sizeof (int)) &&
214 	    (error = copyin(params, (caddr_t)&args, (u_int)i)) != 0) {
215 		locr0[R0] = error;
216 		locr0[PS] |= PSL_C;	/* carry bit */
217 #ifdef KTRACE
218 		if (KTRPOINT(p, KTR_SYSCALL))
219 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
220 #endif
221 		goto done;
222 	}
223 #ifdef KTRACE
224 	if (KTRPOINT(p, KTR_SYSCALL))
225 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
226 #endif
227 	rval[0] = 0;
228 	rval[1] = locr0[R1];
229 	error = (*callp->sy_call)(u.u_procp, &args, rval);
230 	if (error == ERESTART)
231 		pc = opc;
232 	else if (error != EJUSTRETURN) {
233 		if (error) {
234 			locr0[R0] = error;
235 			locr0[PS] |= PSL_C;	/* carry bit */
236 		} else {
237 			locr0[R0] = rval[0];
238 			locr0[R1] = rval[1];
239 			locr0[PS] &= ~PSL_C;
240 		}
241 	}
242 	/* else if (error == EJUSTRETURN) */
243 		/* nothing to do */
244 done:
245 	/*
246 	 * Reinitialize proc pointer `p' as it may be different
247 	 * if this is a child returning from fork syscall.
248 	 */
249 	p = u.u_procp;
250 	if (i = CURSIG(p))
251 		psig(i);
252 	p->p_pri = p->p_usrpri;
253 	if (runrun) {
254 		/*
255 		 * Since we are u.u_procp, clock will normally just change
256 		 * our priority without moving us from one queue to another
257 		 * (since the running process is not on a queue.)
258 		 * If that happened after we setrq ourselves but before we
259 		 * swtch()'ed, we might not be on the queue indicated by
260 		 * our priority.
261 		 */
262 		(void) splclock();
263 		setrq(p);
264 		u.u_ru.ru_nivcsw++;
265 		swtch();
266 		if (i = CURSIG(p))
267 			psig(i);
268 	}
269 	if (u.u_prof.pr_scale) {
270 		int ticks;
271 		struct timeval *tv = &u.u_ru.ru_stime;
272 
273 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
274 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
275 		if (ticks)
276 			addupc(locr0[PC], &u.u_prof, ticks);
277 	}
278 	curpri = p->p_pri;
279 #ifdef KTRACE
280 	if (KTRPOINT(p, KTR_SYSRET))
281 		ktrsysret(p->p_tracep, code, error, rval[0]);
282 #endif
283 }
284