xref: /original-bsd/sys/vax/vax/trap.c (revision b3b53e97)
1 /*	trap.c	4.12	82/03/31	*/
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 "../h/trap.h"
12 #include "../h/psl.h"
13 #include "../h/pte.h"
14 #include "../h/inline.h"
15 #include "../h/mtpr.h"
16 
17 #define	USER	040		/* user-mode flag added to type */
18 
19 struct	sysent	sysent[128];
20 
21 /*
22  * Called from the trap handler when a processor trap occurs.
23  */
24 /*ARGSUSED*/
25 trap(sp, type, code, pc, psl)
26 unsigned code;
27 {
28 	register int *locr0 = ((int *)&psl)-PS;
29 	register int i;
30 	register struct proc *p;
31 	time_t syst;
32 
33 	syst = u.u_vm.vm_stime;
34 	if (USERMODE(locr0[PS])) {
35 		type |= USER;
36 		u.u_ar0 = locr0;
37 	}
38 	switch (type) {
39 
40 	default:
41 		printf("trap type %d, code = %x, pc = %x\n", type, code, pc);
42 		panic("trap");
43 
44 	case PROTFLT + USER:	/* protection fault */
45 		i = SIGBUS;
46 		break;
47 
48 	case PRIVINFLT + USER:	/* privileged instruction fault */
49 	case RESADFLT + USER:	/* reserved addressing fault */
50 	case RESOPFLT + USER:	/* resereved operand fault */
51 		u.u_code = type &~ USER;
52 		i = SIGILL;
53 		break;
54 
55 	case ASTFLT + USER:	/* Allow process switch */
56 		astoff();
57 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
58 			addupc(pc, &u.u_prof, 1);
59 			u.u_procp->p_flag &= ~SOWEUPC;
60 		}
61 		goto out;
62 
63 	case ARITHTRAP + USER:
64 		u.u_code = code;
65 		i = SIGFPE;
66 		break;
67 
68 	/*
69 	 * If the user SP is above the stack segment,
70 	 * grow the stack automatically.
71 	 */
72 	case SEGFLT + USER:
73 		if (grow((unsigned)locr0[SP]) || grow(code))
74 			goto out;
75 		i = SIGSEGV;
76 		break;
77 
78 	case TABLEFLT:		/* allow page table faults in kernel mode */
79 	case TABLEFLT + USER:   /* page table fault */
80 		panic("ptable fault");
81 
82 	case PAGEFLT:		/* allow page faults in kernel mode */
83 	case PAGEFLT + USER:	/* page fault */
84 		i = u.u_error;
85 		pagein(code);
86 		u.u_error = i;
87 		if (type == PAGEFLT)
88 			return;
89 		goto out;
90 
91 	case BPTFLT + USER:	/* bpt instruction fault */
92 	case TRCTRAP + USER:	/* trace trap */
93 		locr0[PS] &= ~PSL_T;
94 		i = SIGTRAP;
95 		break;
96 
97 	case XFCFLT + USER:	/* xfc instruction fault */
98 		i = SIGEMT;
99 		break;
100 
101 	case COMPATFLT + USER:	/* compatibility mode fault */
102 		u.u_code = code;
103 		i = SIGILL;
104 		break;
105 	}
106 	psignal(u.u_procp, i);
107 out:
108 	p = u.u_procp;
109 	if (p->p_cursig || ISSIG(p))
110 		psig();
111 	p->p_pri = p->p_usrpri;
112 	if (runrun) {
113 		/*
114 		 * Since we are u.u_procp, clock will normally just change
115 		 * our priority without moving us from one queue to another
116 		 * (since the running process is not on a queue.)
117 		 * If that happened after we setrq ourselves but before we
118 		 * swtch()'ed, we might not be on the queue indicated by
119 		 * our priority.
120 		 */
121 		(void) spl6();
122 		setrq(p);
123 		swtch();
124 	}
125 	if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime))
126 		addupc(locr0[PC], &u.u_prof, (int)-syst);
127 	curpri = p->p_pri;
128 }
129 
130 /*
131  * Called from the trap handler when a system call occurs
132  */
133 /*ARGSUSED*/
134 syscall(sp, type, code, pc, psl)
135 unsigned code;
136 {
137 	register int *locr0 = ((int *)&psl)-PS;
138 	register caddr_t params;		/* known to be r10 below */
139 	register int i;				/* known to be r9 below */
140 	register struct sysent *callp;
141 	register struct proc *p;
142 	time_t syst;
143 	int opc;
144 
145 	syst = u.u_vm.vm_stime;
146 	if (!USERMODE(locr0[PS]))
147 		panic("syscall");
148 	u.u_ar0 = locr0;
149 	params = (caddr_t)locr0[AP] + NBPW;
150 	u.u_error = 0;
151 	opc = pc - 2;
152 	if (code > 63)
153 		opc -= 2;
154 	callp = &sysent[code&0177];
155 	if (callp == sysent) {
156 		i = fuword(params);
157 		params += NBPW;
158 		callp = &sysent[i&0177];
159 	}
160 	if (i = callp->sy_narg * sizeof (int)) {
161 		asm("prober $3,r9,(r10)");		/* GROT */
162 		asm("bnequ ok");			/* GROT */
163 		u.u_error = EFAULT;			/* GROT */
164 		goto bad;				/* GROT */
165 asm("ok:");						/* GROT */
166 		asm("movc3 r9,(r10),_u+U_ARG");		/* GROT */
167 	}
168 	u.u_ap = u.u_arg;
169 	u.u_dirp = (caddr_t)u.u_arg[0];
170 	u.u_r.r_val1 = 0;
171 	u.u_r.r_val2 = locr0[R1];
172 	if (setjmp(u.u_qsav)) {
173 		if (u.u_error == 0 && u.u_eosys == JUSTRETURN)
174 			u.u_error = EINTR;
175 	} else {
176 		u.u_eosys = JUSTRETURN;
177 		(*(callp->sy_call))();
178 	}
179 	locr0[PS] &= ~PSL_C;
180 	if (u.u_eosys == RESTARTSYS)
181 		pc = opc;
182 	else if (u.u_eosys == SIMULATERTI)
183 		dorti();
184 	else if (u.u_error) {
185 bad:
186 		locr0[R0] = u.u_error;
187 		locr0[PS] |= PSL_C;	/* carry bit */
188 	} else {
189 		locr0[R0] = u.u_r.r_val1;
190 		locr0[R1] = u.u_r.r_val2;
191 	}
192 	p = u.u_procp;
193 	if (p->p_cursig || ISSIG(p))
194 		psig();
195 	p->p_pri = p->p_usrpri;
196 	if (runrun) {
197 		/*
198 		 * Since we are u.u_procp, clock will normally just change
199 		 * our priority without moving us from one queue to another
200 		 * (since the running process is not on a queue.)
201 		 * If that happened after we setrq ourselves but before we
202 		 * swtch()'ed, we might not be on the queue indicated by
203 		 * our priority.
204 		 */
205 		(void) spl6();
206 		setrq(p);
207 		swtch();
208 	}
209 	if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime))
210 		addupc(locr0[PC], &u.u_prof, (int)-syst);
211 	curpri = p->p_pri;
212 }
213 
214 /*
215  * nonexistent system call-- set fatal error code.
216  */
217 nosys()
218 {
219 
220 	u.u_error = 100;
221 }
222