xref: /original-bsd/sys/vax/vax/trap.c (revision f71cd02e)
1 /*	trap.c	6.5	85/03/12	*/
2 
3 #include "psl.h"
4 #include "reg.h"
5 #include "pte.h"
6 
7 #include "param.h"
8 #include "systm.h"
9 #include "dir.h"
10 #include "user.h"
11 #include "assym.s"
12 #include "proc.h"
13 #include "seg.h"
14 #include "trap.h"
15 #include "acct.h"
16 #include "kernel.h"
17 #ifdef SYSCALLTRACE
18 #include "../sys/syscalls.c"
19 #endif
20 
21 #include "mtpr.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",
30 	"Privileged instruction",
31 	"Reserved operand",
32 	"Breakpoint",
33 	"Xfc trap",
34 	"Syscall trap",
35 	"Arithmetic fault",
36 	"Ast trap",
37 	"Segmentation fault",
38 	"Protection fault",
39 	"Trace trap",
40 	"Compatibility mode trap",
41 #ifdef notdef
42 	"Page fault",
43 	"Page table fault",
44 #endif
45 };
46 #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
47 
48 /*
49  * Called from the trap handler when a processor trap occurs.
50  */
51 /*ARGSUSED*/
52 trap(sp, type, code, pc, psl)
53 	int sp, type;
54 	unsigned code;
55 	int pc, psl;
56 {
57 	register int *locr0 = ((int *)&psl)-PS;
58 	register int i;
59 	register struct proc *p;
60 	struct timeval syst;
61 
62 	syst = u.u_ru.ru_stime;
63 	if (USERMODE(locr0[PS])) {
64 		type |= USER;
65 		u.u_ar0 = locr0;
66 	}
67 	switch (type) {
68 
69 	default:
70 		printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
71 		type &= ~USER;
72 		if ((unsigned)type < TRAP_TYPES)
73 			panic(trap_type[type]);
74 		panic("trap");
75 
76 	case T_PROTFLT+USER:	/* protection fault */
77 		i = SIGBUS;
78 		break;
79 
80 	case T_PRIVINFLT+USER:	/* privileged instruction fault */
81 	case T_RESADFLT+USER:	/* reserved addressing fault */
82 	case T_RESOPFLT+USER:	/* resereved operand fault */
83 		u.u_code = type &~ USER;
84 		i = SIGILL;
85 		break;
86 
87 	case T_ASTFLT+USER:
88 		astoff();
89 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
90 			addupc(pc, &u.u_prof, 1);
91 			u.u_procp->p_flag &= ~SOWEUPC;
92 		}
93 		goto out;
94 
95 	case T_ARITHTRAP+USER:
96 		u.u_code = code;
97 		i = SIGFPE;
98 		break;
99 
100 	/*
101 	 * If the user SP is above the stack segment,
102 	 * grow the stack automatically.
103 	 */
104 	case T_SEGFLT+USER:
105 		if (grow((unsigned)locr0[SP]) || grow(code))
106 			goto out;
107 		i = SIGSEGV;
108 		break;
109 
110 	case T_TABLEFLT:	/* allow page table faults in kernel mode */
111 	case T_TABLEFLT+USER:   /* page table fault */
112 		panic("ptable fault");
113 
114 	case T_PAGEFLT:		/* allow page faults in kernel mode */
115 	case T_PAGEFLT+USER:	/* page fault */
116 		i = u.u_error;
117 		pagein(code, 0);
118 		u.u_error = i;
119 		if (type == T_PAGEFLT)
120 			return;
121 		goto out;
122 
123 	case T_BPTFLT+USER:	/* bpt instruction fault */
124 	case T_TRCTRAP+USER:	/* trace trap */
125 		locr0[PS] &= ~PSL_T;
126 		i = SIGTRAP;
127 		break;
128 
129 	case T_XFCFLT+USER:	/* xfc instruction fault */
130 		i = SIGEMT;
131 		break;
132 
133 	case T_COMPATFLT+USER:	/* compatibility mode fault */
134 		u.u_acflag |= ACOMPAT;
135 		u.u_code = code;
136 		i = SIGILL;
137 		break;
138 	}
139 	psignal(u.u_procp, i);
140 out:
141 	p = u.u_procp;
142 	if (p->p_cursig || ISSIG(p))
143 		psig();
144 	p->p_pri = p->p_usrpri;
145 	if (runrun) {
146 		/*
147 		 * Since we are u.u_procp, clock will normally just change
148 		 * our priority without moving us from one queue to another
149 		 * (since the running process is not on a queue.)
150 		 * If that happened after we setrq ourselves but before we
151 		 * swtch()'ed, we might not be on the queue indicated by
152 		 * our priority.
153 		 */
154 		(void) spl6();
155 		setrq(p);
156 		u.u_ru.ru_nivcsw++;
157 		swtch();
158 	}
159 	if (u.u_prof.pr_scale) {
160 		int ticks;
161 		struct timeval *tv = &u.u_ru.ru_stime;
162 
163 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
164 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
165 		if (ticks)
166 			addupc(locr0[PC], &u.u_prof, ticks);
167 	}
168 	curpri = p->p_pri;
169 }
170 
171 #ifdef SYSCALLTRACE
172 int syscalltrace = 0;
173 #endif
174 /*
175  * Called from the trap handler when a system call occurs
176  */
177 /*ARGSUSED*/
178 syscall(sp, type, code, pc, psl)
179 	unsigned code;
180 {
181 	register int *locr0 = ((int *)&psl)-PS;
182 	register caddr_t params;		/* known to be r10 below */
183 	register int i;				/* known to be r9 below */
184 	register struct sysent *callp;
185 	register struct proc *p;
186 	int opc;
187 	struct timeval syst;
188 
189 	syst = u.u_ru.ru_stime;
190 	if (!USERMODE(locr0[PS]))
191 		panic("syscall");
192 	u.u_ar0 = locr0;
193 	if (code == 139) {			/* XXX 4.2 COMPATIBILITY */
194 		osigcleanup();			/* XXX 4.2 COMPATIBILITY */
195 		goto done;			/* XXX 4.2 COMPATIBILITY */
196 	}					/* XXX 4.2 COMPATIBILITY */
197 	params = (caddr_t)locr0[AP] + NBPW;
198 	u.u_error = 0;
199 	opc = pc - 2;
200 	if (code > 63)
201 		opc -= 2;
202 	callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
203 	if (callp == sysent) {
204 		i = fuword(params);
205 		params += NBPW;
206 		callp = ((unsigned)i >= nsysent) ? &sysent[63] : &sysent[i];
207 	}
208 	if ((i = callp->sy_narg * sizeof (int)) &&
209 	    (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
210 		locr0[R0] = u.u_error;
211 		locr0[PS] |= PSL_C;	/* carry bit */
212 		goto done;
213 	}
214 	u.u_r.r_val1 = 0;
215 	u.u_r.r_val2 = locr0[R1];
216 	if (setjmp(&u.u_qsave)) {
217 		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
218 			u.u_error = EINTR;
219 	} else {
220 		u.u_eosys = NORMALRETURN;
221 #ifdef SYSCALLTRACE
222 		if (syscalltrace) {
223 			register int i;
224 			char *cp;
225 
226 			if (code >= nsysent)
227 				printf("0x%x", code);
228 			else
229 				printf("%s", syscallnames[code]);
230 			cp = "(";
231 			for (i= 0; i < callp->sy_narg; i++) {
232 				printf("%s%x", cp, u.u_arg[i]);
233 				cp = ", ";
234 			}
235 			if (i)
236 				putchar(')', 0);
237 			putchar('\n', 0);
238 		}
239 #endif
240 		(*(callp->sy_call))();
241 	}
242 	if (u.u_eosys == NORMALRETURN) {
243 		if (u.u_error) {
244 			locr0[R0] = u.u_error;
245 			locr0[PS] |= PSL_C;	/* carry bit */
246 		} else {
247 			locr0[R0] = u.u_r.r_val1;
248 			locr0[R1] = u.u_r.r_val2;
249 			locr0[PS] &= ~PSL_C;
250 		}
251 	} else if (u.u_eosys == RESTARTSYS)
252 		pc = opc;
253 	/* else if (u.u_eosys == JUSTRETURN) */
254 		/* nothing to do */
255 done:
256 	p = u.u_procp;
257 	if (p->p_cursig || ISSIG(p))
258 		psig();
259 	p->p_pri = p->p_usrpri;
260 	if (runrun) {
261 		/*
262 		 * Since we are u.u_procp, clock will normally just change
263 		 * our priority without moving us from one queue to another
264 		 * (since the running process is not on a queue.)
265 		 * If that happened after we setrq ourselves but before we
266 		 * swtch()'ed, we might not be on the queue indicated by
267 		 * our priority.
268 		 */
269 		(void) spl6();
270 		setrq(p);
271 		u.u_ru.ru_nivcsw++;
272 		swtch();
273 	}
274 	if (u.u_prof.pr_scale) {
275 		int ticks;
276 		struct timeval *tv = &u.u_ru.ru_stime;
277 
278 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
279 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
280 		if (ticks)
281 			addupc(locr0[PC], &u.u_prof, ticks);
282 	}
283 	curpri = p->p_pri;
284 }
285 
286 /*
287  * nonexistent system call-- signal process (may want to handle it)
288  * flag error if process won't see signal immediately
289  * Q: should we do that all the time ??
290  */
291 nosys()
292 {
293 	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
294 		u.u_error = EINVAL;
295 	psignal(u.u_procp, SIGSYS);
296 }
297