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