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