xref: /original-bsd/sys/i386/i386/trap.c (revision dbe44373)
1 /*
2  * 386 Trap and System call handleing
3  */
4 
5 #include "../i386/psl.h"
6 #include "../i386/reg.h"
7 #include "../i386/pte.h"
8 #include "../i386/segments.h"
9 #include "../i386/frame.h"
10 
11 #include "param.h"
12 #include "systm.h"
13 #include "dir.h"
14 #include "user.h"
15 #include "proc.h"
16 #include "seg.h"
17 #include "acct.h"
18 #include "kernel.h"
19 #include "vm.h"
20 #include "cmap.h"
21 
22 #include "../i386/trap.h"
23 
24 #define	USER	040		/* user-mode flag added to type */
25 
26 struct	sysent sysent[];
27 int	nsysent;
28 #include "dbg.h"
29 /*
30  * Called from the trap handler when a processor trap occurs.
31  */
32 unsigned *rcr2(), Sysbase;
33 extern short cpl;
34 /*ARGSUSED*/
35 trap(frame)
36 	struct trapframe frame;
37 #define type frame.tf_trapno
38 #define code frame.tf_err
39 #define pc frame.tf_eip
40 {
41 	register int *locr0 = ((int *)&frame)/*-PS*/;
42 	register int i;
43 	register struct proc *p;
44 	struct timeval syst;
45 	extern int nofault;
46 
47 dprintf(DALLTRAPS, "%d. trap",u.u_procp->p_pid);
48 dprintf(DALLTRAPS, "\npc:%x cs:%x ds:%x eflags:%x isp %x\n",
49 		frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags,
50 		frame.tf_isp);
51 dprintf(DALLTRAPS, "edi %x esi %x ebp %x ebx %x esp %x\n",
52 		frame.tf_edi, frame.tf_esi, frame.tf_ebp,
53 		frame.tf_ebx, frame.tf_esp);
54 dprintf(DALLTRAPS, "edx %x ecx %x eax %x\n",
55 		frame.tf_edx, frame.tf_ecx, frame.tf_eax);
56 dprintf(DALLTRAPS|DPAUSE, "ec %x type %x cr0 %x cr2 %x cpl %x \n",
57 		frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl);
58 
59 	locr0[tEFLAGS] &= ~PSL_NT;	/* clear nested trap */
60 if(nofault && frame.tf_trapno != 0xc)
61 	{ locr0[tEIP] = nofault; return;}
62 
63 	syst = u.u_ru.ru_stime;
64 	if (ISPL(locr0[tCS]) == SEL_UPL) {
65 		type |= USER;
66 		u.u_ar0 = locr0;
67 	}
68 	switch (type) {
69 
70 	default:
71 #ifdef KDB
72 		if (kdb_trap(&psl))
73 			return;
74 #endif
75 		printf("trap type %d, code = %x, pc = %x cs = %x, eflags = %x\n", type, code, pc, frame.tf_cs, frame.tf_eflags);
76 		type &= ~USER;
77 		panic("trap");
78 		/*NOTREACHED*/
79 
80 	case T_PROTFLT + USER:		/* protection fault */
81 		i = SIGBUS;
82 		break;
83 
84 	case T_PRIVINFLT + USER:	/* privileged instruction fault */
85 	case T_RESADFLT + USER:		/* reserved addressing fault */
86 	case T_RESOPFLT + USER:		/* resereved operand fault */
87 		u.u_code = type &~ USER;
88 		i = SIGILL;
89 		break;
90 
91 	case T_ASTFLT + USER:		/* Allow process switch */
92 	case T_ASTFLT:
93 		astoff();
94 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
95 			addupc(pc, &u.u_prof, 1);
96 			u.u_procp->p_flag &= ~SOWEUPC;
97 		}
98 		goto out;
99 
100 	case T_ARITHTRAP + USER:
101 	case T_DIVIDE + USER:
102 		u.u_code = code;
103 		i = SIGFPE;
104 		break;
105 
106 	/*
107 	 * If the user SP is above the stack segment,
108 	 * grow the stack automatically.
109 	 */
110 	case T_STKFLT + USER:
111 	case T_SEGFLT + USER:
112 		if (grow((unsigned)locr0[tESP]) /*|| grow(code)*/)
113 			goto out;
114 xxx:
115 		i = SIGSEGV;
116 		break;
117 
118 	case T_TABLEFLT:		/* allow page table faults in kernel */
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 			{ register u_int vp;
125 			struct pte *pte;
126 
127 			if (rcr2() >= &Sysbase) goto xxx;
128 			vp = btop((int)rcr2());
129 			if (vp >= dptov(u.u_procp, u.u_procp->p_dsize) &&
130 			    vp < sptov(u.u_procp, u.u_procp->p_ssize-1)) {
131 				if (grow((unsigned)locr0[tESP]) || grow(rcr2()))
132 				goto out;
133 				else	{
134 if(nofault) { locr0[tEIP] = nofault; return;}
135 printf("didnt");
136 				i = SIGSEGV;
137 				break;
138 				}
139 			}
140 			i = u.u_error;
141 			pagein(rcr2(), 0);
142 			u.u_error = i;
143 		if (type == T_PAGEFLT)
144 				return;
145 if(nofault) { locr0[tEIP] = nofault; return;}
146 			goto out;
147 	}
148 
149 	case T_BPTFLT + USER:		/* bpt instruction fault */
150 	case T_TRCTRAP + USER:		/* trace trap */
151 		locr0[tEFLAGS] &= ~PSL_T;
152 		i = SIGTRAP;
153 		break;
154 
155 	/*
156 	 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to
157 	 * drop to 0 as clock could go off and we would end up
158 	 * doing an rei to the interrupt stack at ipl 0 (a
159 	 * reserved operand fault).  Instead, we allow psignal
160 	 * to post an ast, then return to user mode where we
161 	 * will reenter the kernel on the kernel's stack and
162 	 * can then service the signal.
163 	 */
164 	case T_KSPNOTVAL:
165 		if (noproc)
166 			panic("ksp not valid");
167 		/* fall thru... */
168 	case T_KSPNOTVAL + USER:
169 		printf("pid %d: ksp not valid\n", u.u_procp->p_pid);
170 		/* must insure valid kernel stack pointer? */
171 		psignal(u.u_procp, SIGKILL);
172 		return;
173 
174 	case T_BUSERR + USER:
175 		u.u_code = code;
176 		psignal(u.u_procp, SIGBUS);
177 		return;
178 	}
179 	psignal(u.u_procp, i);
180 out:
181 	p = u.u_procp;
182 
183 if(p->p_cursig)
184 printf("out cursig %x flg %x sig %x ign %x msk %x\n",
185 	p->p_cursig,
186 	p->p_flag, p->p_sig, p->p_sigignore, p->p_sigmask);
187 
188 	if (p->p_cursig || ISSIG(p))
189 		psig(1);
190 	p->p_pri = p->p_usrpri;
191 	if (runrun) {
192 		/*
193 		 * Since we are u.u_procp, clock will normally just change
194 		 * our priority without moving us from one queue to another
195 		 * (since the running process is not on a queue.)
196 		 * If that happened after we setrq ourselves but before we
197 		 * swtch()'ed, we might not be on the queue indicated by
198 		 * our priority.
199 		 */
200 		(void) splclock();
201 		setrq(p);
202 		u.u_ru.ru_nivcsw++;
203 		swtch();
204 	}
205 	if (u.u_prof.pr_scale) {
206 		int ticks;
207 		struct timeval *tv = &u.u_ru.ru_stime;
208 
209 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
210 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
211 		if (ticks)
212 			addupc(pc, &u.u_prof, ticks);
213 	}
214 	curpri = p->p_pri;
215 #undef type
216 #undef code
217 #undef pc
218 }
219 
220 /*
221  * Called from locore when a system call occurs
222  */
223 int fuckup;
224 /*ARGSUSED*/
225 syscall(frame)
226 	struct syscframe frame;
227 #define code frame.sf_eax	/* note: written over! */
228 #define pc frame.sf_eip
229 {
230 	register int *locr0 = ((int *)&frame)/*-PS*/;
231 	register caddr_t params;
232 	register int i;
233 	register struct sysent *callp;
234 	register struct proc *p;
235 	struct timeval syst;
236 	int opc;
237 
238 #ifdef lint
239 	r0 = 0; r0 = r0; r1 = 0; r1 = r1;
240 #endif
241 	syst = u.u_ru.ru_stime;
242 	if (ISPL(locr0[sCS]) != SEL_UPL)
243 		panic("syscall");
244 	u.u_ar0 = locr0;
245 svfpsp();
246 	params = (caddr_t)locr0[sESP] + NBPW ;
247 	u.u_error = 0;
248 	/*
249 	 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
250 	 */
251 	opc = pc - 7;
252 	callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
253 	if (callp == sysent) {
254 		i = fuword(params);
255 		params += NBPW;
256 		callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
257 	}
258 /*dprintf(DALLSYSC,"%d. call %d\n", u.u_procp->p_pid, code);*/
259 	if ((i = callp->sy_narg * sizeof (int)) &&
260 	    (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
261 		locr0[sEAX] = u.u_error;
262 		locr0[sEFLAGS] |= PSL_C;	/* carry bit */
263 		goto done;
264 	}
265 	u.u_r.r_val1 = 0;
266 	u.u_r.r_val2 = locr0[sEDX];
267 	if (setjmp(&u.u_qsave)) {
268 		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
269 			u.u_error = EINTR;
270 	} else {
271 		u.u_eosys = NORMALRETURN;
272 		(*callp->sy_call)();
273 	}
274 /*rsfpsp();*/
275 	if (u.u_eosys == NORMALRETURN) {
276 		if (u.u_error) {
277 /*dprintf(DSYSFAIL,"%d. fail %d %d\n",u.u_procp->p_pid,  code, u.u_error);*/
278 			locr0[sEAX] = u.u_error;
279 			locr0[sEFLAGS] |= PSL_C;	/* carry bit */
280 		} else {
281 			locr0[sEFLAGS] &= ~PSL_C;	/* clear carry bit */
282 			locr0[sEAX] = u.u_r.r_val1;
283 			locr0[sEDX] = u.u_r.r_val2;
284 		}
285 	} else if (u.u_eosys == RESTARTSYS)
286 		pc = opc;
287 	/* else if (u.u_eosys == JUSTRETURN) */
288 		/* nothing to do */
289 done:
290 	p = u.u_procp;
291 	if (p->p_cursig || ISSIG(p))
292 		psig(0);
293 	p->p_pri = p->p_usrpri;
294 	if (runrun) {
295 		/*
296 		 * Since we are u.u_procp, clock will normally just change
297 		 * our priority without moving us from one queue to another
298 		 * (since the running process is not on a queue.)
299 		 * If that happened after we setrq ourselves but before we
300 		 * swtch()'ed, we might not be on the queue indicated by
301 		 * our priority.
302 		 */
303 		(void) splclock();
304 		setrq(p);
305 		u.u_ru.ru_nivcsw++;
306 		swtch();
307 	}
308 	if (u.u_prof.pr_scale) {
309 		int ticks;
310 		struct timeval *tv = &u.u_ru.ru_stime;
311 
312 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
313 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
314 		if (ticks)
315 			addupc(opc, &u.u_prof, ticks);
316 	}
317 	curpri = p->p_pri;
318 }
319 
320 /*
321  * nonexistent system call-- signal process (may want to handle it)
322  * flag error if process won't see signal immediately
323  * Q: should we do that all the time ??
324  */
325 nosys()
326 {
327 
328 	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
329 		u.u_error = EINVAL;
330 	psignal(u.u_procp, SIGSYS);
331 }
332 
333 #ifdef notdef
334 /*
335  * Ignored system call
336  */
337 nullsys()
338 {
339 
340 }
341 #endif
342