xref: /original-bsd/sys/i386/i386/trap.c (revision 34790d09)
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 #ifdef DEBUG
48 dprintf(DALLTRAPS, "%d. trap",u.u_procp->p_pid);
49 dprintf(DALLTRAPS, "\npc:%x cs:%x ds:%x eflags:%x isp %x\n",
50 		frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags,
51 		frame.tf_isp);
52 dprintf(DALLTRAPS, "edi %x esi %x ebp %x ebx %x esp %x\n",
53 		frame.tf_edi, frame.tf_esi, frame.tf_ebp,
54 		frame.tf_ebx, frame.tf_esp);
55 dprintf(DALLTRAPS, "edx %x ecx %x eax %x\n",
56 		frame.tf_edx, frame.tf_ecx, frame.tf_eax);
57 dprintf(DALLTRAPS|DPAUSE, "ec %x type %x cr0 %x cr2 %x cpl %x \n",
58 		frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl);
59 #endif
60 
61 	locr0[tEFLAGS] &= ~PSL_NT;	/* clear nested trap XXX */
62 if(nofault && frame.tf_trapno != 0xc)
63 	{ locr0[tEIP] = nofault; return;}
64 
65 	syst = u.u_ru.ru_stime;
66 	if (ISPL(locr0[tCS]) == SEL_UPL) {
67 		type |= USER;
68 		u.u_ar0 = locr0;
69 	}
70 	switch (type) {
71 
72 	default:
73 bit_sucker:
74 #ifdef KDB
75 		if (kdb_trap(&psl))
76 			return;
77 #endif
78 		printf("trap type %d, code = %x, pc = %x cs = %x, eflags = %x\n", type, code, pc, frame.tf_cs, frame.tf_eflags);
79 		type &= ~USER;
80 		panic("trap");
81 		/*NOTREACHED*/
82 
83 	case T_SEGNPFLT + USER:
84 	case T_PROTFLT + USER:		/* protection fault */
85 		u.u_code = code + BUS_SEGM_FAULT ;
86 		i = SIGBUS;
87 		break;
88 
89 	case T_PRIVINFLT + USER:	/* privileged instruction fault */
90 	case T_RESADFLT + USER:		/* reserved addressing fault */
91 	case T_RESOPFLT + USER:		/* reserved operand fault */
92 	case T_FPOPFLT + USER:		/* coprocessor operand fault */
93 		u.u_code = type &~ USER;
94 		i = SIGILL;
95 		break;
96 
97 	case T_ASTFLT + USER:		/* Allow process switch */
98 	case T_ASTFLT:
99 		astoff();
100 		if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) {
101 			addupc(pc, &u.u_prof, 1);
102 			u.u_procp->p_flag &= ~SOWEUPC;
103 		}
104 		goto out;
105 
106 	case T_DNA + USER:
107 		u.u_code = FPE_FPU_NP_TRAP;
108 		i = SIGFPE;
109 		break;
110 
111 	case T_BOUND + USER:
112 		u.u_code = FPE_SUBRNG_TRAP;
113 		i = SIGFPE;
114 		break;
115 
116 	case T_OFLOW + USER:
117 		u.u_code = FPE_INTOVF_TRAP;
118 		i = SIGFPE;
119 		break;
120 
121 	case T_DIVIDE + USER:
122 		u.u_code = FPE_INTDIV_TRAP;
123 		i = SIGFPE;
124 		break;
125 
126 	case T_ARITHTRAP + USER:
127 		u.u_code = code;
128 		i = SIGFPE;
129 		break;
130 
131 	/*
132 	 * If the user SP is above the stack segment,
133 	 * grow the stack automatically.
134 	 */
135 	case T_STKFLT + USER:
136 	case T_SEGFLT + USER:
137 		if (grow((unsigned)locr0[tESP]) /*|| grow(code)*/)
138 			goto out;
139 		u.u_code = code;
140 		i = SIGSEGV;
141 		break;
142 
143 	case T_TABLEFLT:		/* allow page table faults in kernel */
144 	case T_TABLEFLT + USER:		/* page table fault */
145 		panic("ptable fault");
146 
147 	case T_PAGEFLT:			/* allow page faults in kernel mode */
148 	case T_PAGEFLT + USER:		/* page fault */
149 			{ register u_int vp;
150 			struct pte *pte;
151 
152 			if(u.u_procp->p_pid == 2) goto bit_sucker;
153 #define PGEX_P	0x01
154 			if (rcr2() >= &Sysbase || code & PGEX_P) {
155 				u.u_code = code + BUS_PAGE_FAULT;
156 				i = SIGBUS;
157 				break;
158 			} else {
159 				vp = btop((int)rcr2());
160 				if (vp >= dptov(u.u_procp, u.u_procp->p_dsize)
161 				&& vp < sptov(u.u_procp, u.u_procp->p_ssize-1)){
162 					if (grow((unsigned)locr0[tESP])
163 					|| grow(rcr2()))
164 						goto out;
165 					else	if (nofault) {
166 						locr0[tEIP] = nofault;
167 						return;
168 					}
169 #ifdef DEBUG
170 pg("didnt ");
171 printf("\npc:%x cs:%x ds:%x eflags:%x isp %x\n",
172 		frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags,
173 		frame.tf_isp);
174 printf("edi %x esi %x ebp %x ebx %x esp %x\n",
175 		frame.tf_edi, frame.tf_esi, frame.tf_ebp,
176 		frame.tf_ebx, frame.tf_esp);
177 printf("edx %x ecx %x eax %x\n",
178 		frame.tf_edx, frame.tf_ecx, frame.tf_eax);
179 printf("ec %x type %x cr0 %x cr2 %x cpl %x \n",
180 		frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl);
181 #endif
182 					i = SIGSEGV;
183 					break;
184 				}
185 				i = u.u_error;
186 				pagein(rcr2(), 0);
187 				u.u_error = i;
188 				if (type == T_PAGEFLT) return;
189 
190 				if(nofault) {
191 					locr0[tEIP] = nofault;
192 					return;
193 				}
194 				goto out;
195 			}
196 		}
197 
198 	case T_TRCTRAP:	 /* trace trap -- someone single stepping lcall's */
199 		locr0[tEFLAGS] &= ~PSL_T;
200 			/* Q: how do we turn it on again? */
201 		return;
202 
203 	case T_BPTFLT + USER:		/* bpt instruction fault */
204 	case T_TRCTRAP + USER:		/* trace trap */
205 		locr0[tEFLAGS] &= ~PSL_T;
206 		i = SIGTRAP;
207 		break;
208 
209 	/*
210 	 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to
211 	 * drop to 0 as clock could go off and we would end up
212 	 * doing an rei to the interrupt stack at ipl 0 (a
213 	 * reserved operand fault).  Instead, we allow psignal
214 	 * to post an ast, then return to user mode where we
215 	 * will reenter the kernel on the kernel's stack and
216 	 * can then service the signal.
217 	 */
218 	case T_KSPNOTVAL:
219 		if (noproc)
220 			panic("ksp not valid");
221 		/* fall thru... */
222 	case T_KSPNOTVAL + USER:
223 		printf("pid %d: ksp not valid\n", u.u_procp->p_pid);
224 		/* must insure valid kernel stack pointer? */
225 		psignal(u.u_procp, SIGKILL);
226 		return;
227 
228 	case T_BUSERR + USER:
229 		u.u_code = code;
230 		psignal(u.u_procp, SIGBUS);
231 		return;
232 	}
233 	psignal(u.u_procp, i);
234 out:
235 	p = u.u_procp;
236 
237 	if (p->p_cursig || ISSIG(p))
238 		psig(1);
239 	p->p_pri = p->p_usrpri;
240 	if (runrun) {
241 		/*
242 		 * Since we are u.u_procp, clock will normally just change
243 		 * our priority without moving us from one queue to another
244 		 * (since the running process is not on a queue.)
245 		 * If that happened after we setrq ourselves but before we
246 		 * swtch()'ed, we might not be on the queue indicated by
247 		 * our priority.
248 		 */
249 		(void) splclock();
250 		setrq(p);
251 		u.u_ru.ru_nivcsw++;
252 		swtch();
253 	}
254 	if (u.u_prof.pr_scale) {
255 		int ticks;
256 		struct timeval *tv = &u.u_ru.ru_stime;
257 
258 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
259 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
260 		if (ticks)
261 			addupc(pc, &u.u_prof, ticks);
262 	}
263 	curpri = p->p_pri;
264 #undef type
265 #undef code
266 #undef pc
267 }
268 
269 /*
270  * Called from locore when a system call occurs
271  */
272 /*ARGSUSED*/
273 syscall(frame)
274 	struct syscframe frame;
275 #define code frame.sf_eax	/* note: written over! */
276 #define pc frame.sf_eip
277 {
278 	register int *locr0 = ((int *)&frame)/*-PS*/;
279 	register caddr_t params;
280 	register int i;
281 	register struct sysent *callp;
282 	register struct proc *p;
283 	struct timeval syst;
284 	int opc;
285 
286 #ifdef lint
287 	r0 = 0; r0 = r0; r1 = 0; r1 = r1;
288 #endif
289 	syst = u.u_ru.ru_stime;
290 	if (ISPL(locr0[sCS]) != SEL_UPL)
291 {
292 printf("\npc:%x cs:%x eflags:%x\n",
293 		frame.sf_eip, frame.sf_cs, frame.sf_eflags);
294 printf("edi %x esi %x ebp %x ebx %x esp %x\n",
295 		frame.sf_edi, frame.sf_esi, frame.sf_ebp,
296 		frame.sf_ebx, frame.sf_esp);
297 printf("edx %x ecx %x eax %x\n", frame.sf_edx, frame.sf_ecx, frame.sf_eax);
298 printf("cr0 %x cr2 %x cpl %x \n", rcr0(), rcr2(), cpl);
299 		panic("syscall");
300 }
301 	u.u_ar0 = locr0;
302 	params = (caddr_t)locr0[sESP] + NBPW ;
303 	u.u_error = 0;
304 	/*
305 	 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
306 	 */
307 	opc = pc - 7;
308 	callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
309 	if (callp == sysent) {
310 		i = fuword(params);
311 		params += NBPW;
312 		callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
313 	}
314 /*dprintf(DALLSYSC,"%d. call %d\n", u.u_procp->p_pid, code);*/
315 	if ((i = callp->sy_narg * sizeof (int)) &&
316 	    (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) {
317 		locr0[sEAX] = u.u_error;
318 		locr0[sEFLAGS] |= PSL_C;	/* carry bit */
319 		goto done;
320 	}
321 	u.u_r.r_val1 = 0;
322 	u.u_r.r_val2 = locr0[sEDX];
323 	if (setjmp(&u.u_qsave)) {
324 		if (u.u_error == 0 && u.u_eosys != RESTARTSYS)
325 			u.u_error = EINTR;
326 	} else {
327 		u.u_eosys = NORMALRETURN;
328 		(*callp->sy_call)();
329 	}
330 	if (u.u_eosys == NORMALRETURN) {
331 		if (u.u_error) {
332 /*dprintf(DSYSFAIL,"%d. fail %d %d\n",u.u_procp->p_pid,  code, u.u_error);*/
333 			locr0[sEAX] = u.u_error;
334 			locr0[sEFLAGS] |= PSL_C;	/* carry bit */
335 		} else {
336 			locr0[sEFLAGS] &= ~PSL_C;	/* clear carry bit */
337 			locr0[sEAX] = u.u_r.r_val1;
338 			locr0[sEDX] = u.u_r.r_val2;
339 		}
340 	} else if (u.u_eosys == RESTARTSYS)
341 		pc = opc;
342 	/* else if (u.u_eosys == JUSTRETURN) */
343 		/* nothing to do */
344 done:
345 	p = u.u_procp;
346 	if (p->p_cursig || ISSIG(p))
347 		psig(0);
348 	p->p_pri = p->p_usrpri;
349 	if (runrun) {
350 		/*
351 		 * Since we are u.u_procp, clock will normally just change
352 		 * our priority without moving us from one queue to another
353 		 * (since the running process is not on a queue.)
354 		 * If that happened after we setrq ourselves but before we
355 		 * swtch()'ed, we might not be on the queue indicated by
356 		 * our priority.
357 		 */
358 		(void) splclock();
359 		setrq(p);
360 		u.u_ru.ru_nivcsw++;
361 		swtch();
362 	}
363 	if (u.u_prof.pr_scale) {
364 		int ticks;
365 		struct timeval *tv = &u.u_ru.ru_stime;
366 
367 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
368 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
369 		if (ticks)
370 			addupc(opc, &u.u_prof, ticks);
371 	}
372 	curpri = p->p_pri;
373 }
374 
375 /*
376  * nonexistent system call-- signal process (may want to handle it)
377  * flag error if process won't see signal immediately
378  * Q: should we do that all the time ??
379  */
380 nosys()
381 {
382 
383 	if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD)
384 		u.u_error = EINVAL;
385 	psignal(u.u_procp, SIGSYS);
386 }
387 
388 /*
389  * Ignored system call
390  */
391 nullsys()
392 {
393 
394 }
395