xref: /freebsd/sys/kern/subr_trap.c (revision 17ee9d00bc1ae1e598c38f25826f861e4bc6c3ce)
1 /*-
2  * Copyright (C) 1994, David Greenman
3  * Copyright (c) 1990, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the University of Utah, and William Jolitz.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	from: @(#)trap.c	7.4 (Berkeley) 5/13/91
38  *	$Id: trap.c,v 1.47 1995/02/10 06:43:47 davidg Exp $
39  */
40 
41 /*
42  * 386 Trap and System call handling
43  */
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/proc.h>
48 #include <sys/user.h>
49 #include <sys/acct.h>
50 #include <sys/kernel.h>
51 #include <sys/syscall.h>
52 #include <sys/sysent.h>
53 #ifdef KTRACE
54 #include <sys/ktrace.h>
55 #endif
56 
57 #include <vm/vm_param.h>
58 #include <vm/pmap.h>
59 #include <vm/vm_map.h>
60 #include <vm/vm_page.h>
61 
62 #include <machine/cpu.h>
63 #include <machine/psl.h>
64 #include <machine/reg.h>
65 #include <machine/trap.h>
66 #include <machine/../isa/isa_device.h>
67 
68 #include "isa.h"
69 #include "npx.h"
70 
71 int	trap_pfault	__P((struct trapframe *, int));
72 void	trap_fatal	__P((struct trapframe *));
73 
74 #define MAX_TRAP_MSG		27
75 char *trap_msg[] = {
76 	"",					/*  0 unused */
77 	"privileged instruction fault",		/*  1 T_PRIVINFLT */
78 	"",					/*  2 unused */
79 	"breakpoint instruction fault",		/*  3 T_BPTFLT */
80 	"",					/*  4 unused */
81 	"",					/*  5 unused */
82 	"arithmetic trap",			/*  6 T_ARITHTRAP */
83 	"system forced exception",		/*  7 T_ASTFLT */
84 	"",					/*  8 unused */
85 	"general protection fault",		/*  9 T_PROTFLT */
86 	"trace trap",				/* 10 T_TRCTRAP */
87 	"",					/* 11 unused */
88 	"page fault",				/* 12 T_PAGEFLT */
89 	"",					/* 13 unused */
90 	"alignment fault",			/* 14 T_ALIGNFLT */
91 	"",					/* 15 unused */
92 	"",					/* 16 unused */
93 	"",					/* 17 unused */
94 	"integer divide fault",			/* 18 T_DIVIDE */
95 	"non-maskable interrupt trap",		/* 19 T_NMI */
96 	"overflow trap",			/* 20 T_OFLOW */
97 	"FPU bounds check fault",		/* 21 T_BOUND */
98 	"FPU device not available",		/* 22 T_DNA */
99 	"double fault",				/* 23 T_DOUBLEFLT */
100 	"FPU operand fetch fault",		/* 24 T_FPOPFLT */
101 	"invalid TSS fault",			/* 25 T_TSSFLT */
102 	"segment not present fault",		/* 26 T_SEGNPFLT */
103 	"stack fault",				/* 27 T_STKFLT */
104 };
105 
106 static inline void
107 userret(p, frame, oticks)
108 	struct proc *p;
109 	struct trapframe *frame;
110 	u_quad_t oticks;
111 {
112 	int sig, s;
113 
114 	while ((sig = CURSIG(p)) != 0)
115 		postsig(sig);
116 	p->p_priority = p->p_usrpri;
117 	if (want_resched) {
118 		/*
119 		 * Since we are curproc, clock will normally just change
120 		 * our priority without moving us from one queue to another
121 		 * (since the running process is not on a queue.)
122 		 * If that happened after we setrunqueue ourselves but before we
123 		 * mi_switch()'ed, we might not be on the queue indicated by
124 		 * our priority.
125 		 */
126 		s = splclock();
127 		setrunqueue(p);
128 		p->p_stats->p_ru.ru_nivcsw++;
129 		mi_switch();
130 		splx(s);
131 		while ((sig = CURSIG(p)) != 0)
132 			postsig(sig);
133 	}
134 	/*
135 	 * Charge system time if profiling.
136 	 */
137 	if (p->p_flag & P_PROFIL) {
138 		u_quad_t ticks = p->p_sticks - oticks;
139 
140 		if (ticks) {
141 #ifdef PROFTIMER
142 			extern int profscale;
143 			addupc(frame->tf_eip, &p->p_stats->p_prof,
144 			    ticks * profscale);
145 #else
146 			addupc(frame->tf_eip, &p->p_stats->p_prof, ticks);
147 #endif
148 		}
149 	}
150 	curpriority = p->p_priority;
151 }
152 
153 /*
154  * trap(frame):
155  *	Exception, fault, and trap interface to the FreeBSD kernel.
156  * This common code is called from assembly language IDT gate entry
157  * routines that prepare a suitable stack frame, and restore this
158  * frame after the exception has been processed.
159  */
160 
161 /*ARGSUSED*/
162 void
163 trap(frame)
164 	struct trapframe frame;
165 {
166 	struct proc *p = curproc;
167 	u_quad_t sticks = 0;
168 	int i = 0, ucode = 0, type, code;
169 #ifdef DIAGNOSTIC
170 	u_long eva;
171 #endif
172 
173 	type = frame.tf_trapno;
174 	code = frame.tf_err;
175 
176 	if (ISPL(frame.tf_cs) == SEL_UPL) {
177 		/* user trap */
178 
179 		sticks = p->p_sticks;
180 		p->p_md.md_regs = (int *)&frame;
181 
182 		switch (type) {
183 		case T_PRIVINFLT:	/* privileged instruction fault */
184 			ucode = type;
185 			i = SIGILL;
186 			break;
187 
188 		case T_BPTFLT:		/* bpt instruction fault */
189 		case T_TRCTRAP:		/* trace trap */
190 			frame.tf_eflags &= ~PSL_T;
191 			i = SIGTRAP;
192 			break;
193 
194 		case T_ARITHTRAP:	/* arithmetic trap */
195 			ucode = code;
196 			i = SIGFPE;
197 			break;
198 
199 		case T_ASTFLT:		/* Allow process switch */
200 			astoff();
201 			cnt.v_soft++;
202 			if (p->p_flag & P_OWEUPC) {
203 				addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
204 				p->p_flag &= ~P_OWEUPC;
205 			}
206 			goto out;
207 
208 		case T_PROTFLT:		/* general protection fault */
209 		case T_SEGNPFLT:	/* segment not present fault */
210 		case T_STKFLT:		/* stack fault */
211 		case T_TSSFLT:		/* invalid TSS fault */
212 		case T_DOUBLEFLT:	/* double fault */
213 		default:
214 			ucode = code + BUS_SEGM_FAULT ;
215 			i = SIGBUS;
216 			break;
217 
218 		case T_PAGEFLT:		/* page fault */
219 			i = trap_pfault(&frame, TRUE);
220 			if (i == -1)
221 				return;
222 			if (i == 0)
223 				goto out;
224 
225 			ucode = T_PAGEFLT;
226 			break;
227 
228 		case T_DIVIDE:		/* integer divide fault */
229 			ucode = FPE_INTDIV_TRAP;
230 			i = SIGFPE;
231 			break;
232 
233 #if NISA > 0
234 		case T_NMI:
235 #ifdef DDB
236 			/* NMI can be hooked up to a pushbutton for debugging */
237 			printf ("NMI ... going to debugger\n");
238 			if (kdb_trap (type, 0, &frame))
239 				return;
240 #endif
241 			/* machine/parity/power fail/"kitchen sink" faults */
242 			if (isa_nmi(code) == 0) return;
243 			panic("NMI indicates hardware failure");
244 #endif
245 
246 		case T_OFLOW:		/* integer overflow fault */
247 			ucode = FPE_INTOVF_TRAP;
248 			i = SIGFPE;
249 			break;
250 
251 		case T_BOUND:		/* bounds check fault */
252 			ucode = FPE_SUBRNG_TRAP;
253 			i = SIGFPE;
254 			break;
255 
256 		case T_DNA:
257 #if NNPX > 0
258 			/* if a transparent fault (due to context switch "late") */
259 			if (npxdna())
260 				return;
261 #endif	/* NNPX > 0 */
262 
263 #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE)
264 			i = math_emulate(&frame);
265 			if (i == 0) {
266 				if (!(frame.tf_eflags & PSL_T))
267 					return;
268 				frame.tf_eflags &= ~PSL_T;
269 				i = SIGTRAP;
270 			}
271 			/* else ucode = emulator_only_knows() XXX */
272 #else	/* MATH_EMULATE || GPL_MATH_EMULATE */
273 			i = SIGFPE;
274 			ucode = FPE_FPU_NP_TRAP;
275 #endif	/* MATH_EMULATE || GPL_MATH_EMULATE */
276 			break;
277 
278 		case T_FPOPFLT:		/* FPU operand fetch fault */
279 			ucode = T_FPOPFLT;
280 			i = SIGILL;
281 			break;
282 		}
283 	} else {
284 		/* kernel trap */
285 
286 		switch (type) {
287 		case T_PAGEFLT:			/* page fault */
288 			(void) trap_pfault(&frame, FALSE);
289 			return;
290 
291 		case T_PROTFLT:		/* general protection fault */
292 		case T_SEGNPFLT:	/* segment not present fault */
293 			/*
294 			 * Invalid segment selectors and out of bounds
295 			 * %eip's and %esp's can be set up in user mode.
296 			 * This causes a fault in kernel mode when the
297 			 * kernel tries to return to user mode.  We want
298 			 * to get this fault so that we can fix the
299 			 * problem here and not have to check all the
300 			 * selectors and pointers when the user changes
301 			 * them.
302 			 */
303 #define	MAYBE_DORETI_FAULT(where, whereto)				\
304 	do {								\
305 		extern void where(void) __asm(__STRING(where));		\
306 		extern void whereto(void) __asm(__STRING(whereto));	\
307 		if (frame.tf_eip == (int)where) {			\
308 			frame.tf_eip = (int)whereto;			\
309 			return;						\
310 		}							\
311 	} while (0)
312 
313 			if (intr_nesting_level == 0) {
314 				MAYBE_DORETI_FAULT(doreti_iret,
315 						   doreti_iret_fault);
316 				MAYBE_DORETI_FAULT(doreti_popl_ds,
317 						   doreti_popl_ds_fault);
318 				MAYBE_DORETI_FAULT(doreti_popl_es,
319 						   doreti_popl_es_fault);
320 			}
321 			if (curpcb && curpcb->pcb_onfault) {
322 				frame.tf_eip = (int)curpcb->pcb_onfault;
323 				return;
324 			}
325 			break;
326 
327 		case T_TSSFLT:
328 			/*
329 			 * PSL_NT can be set in user mode and isn't cleared
330 			 * automatically when the kernel is entered.  This
331 			 * causes a TSS fault when the kernel attempts to
332 			 * `iret' because the TSS link is uninitialized.  We
333 			 * want to get this fault so that we can fix the
334 			 * problem here and not every time the kernel is
335 			 * entered.
336 			 */
337 			if (frame.tf_eflags & PSL_NT) {
338 				frame.tf_eflags &= ~PSL_NT;
339 				return;
340 			}
341 			break;
342 
343 #ifdef DDB
344 		case T_BPTFLT:
345 		case T_TRCTRAP:
346 			if (kdb_trap (type, 0, &frame))
347 				return;
348 			break;
349 #else
350 		case T_TRCTRAP:	 /* trace trap -- someone single stepping lcall's */
351 			/* Q: how do we turn it on again? */
352 			frame.tf_eflags &= ~PSL_T;
353 			return;
354 #endif
355 
356 #if NISA > 0
357 		case T_NMI:
358 #ifdef DDB
359 			/* NMI can be hooked up to a pushbutton for debugging */
360 			printf ("NMI ... going to debugger\n");
361 			if (kdb_trap (type, 0, &frame))
362 				return;
363 #endif
364 			/* machine/parity/power fail/"kitchen sink" faults */
365 			if (isa_nmi(code) == 0) return;
366 			/* FALL THROUGH */
367 #endif
368 		}
369 
370 		trap_fatal(&frame);
371 		return;
372 	}
373 
374 	trapsignal(p, i, ucode);
375 
376 #ifdef DIAGNOSTIC
377 	eva = rcr2();
378 	if (type <= MAX_TRAP_MSG) {
379 		uprintf("fatal process exception: %s",
380 			trap_msg[type]);
381 		if ((type == T_PAGEFLT) || (type == T_PROTFLT))
382 			uprintf(", fault VA = 0x%x", eva);
383 		uprintf("\n");
384 	}
385 #endif
386 
387 out:
388 	userret(p, &frame, sticks);
389 }
390 
391 int
392 trap_pfault(frame, usermode)
393 	struct trapframe *frame;
394 	int usermode;
395 {
396 	vm_offset_t va;
397 	struct vmspace *vm = NULL;
398 	vm_map_t map = 0;
399 	int rv = 0;
400 	vm_prot_t ftype;
401 	extern vm_map_t kernel_map;
402 	int eva;
403 	struct proc *p = curproc;
404 
405 	eva = rcr2();
406 	va = trunc_page((vm_offset_t)eva);
407 
408 	if (va >= KERNBASE) {
409 		/*
410 		 * Don't allow user-mode faults in kernel address space.
411 		 */
412 		if (usermode)
413 			goto nogo;
414 
415 		map = kernel_map;
416 	} else {
417 		/*
418 		 * This is a fault on non-kernel virtual memory.
419 		 * vm is initialized above to NULL. If curproc is NULL
420 		 * or curproc->p_vmspace is NULL the fault is fatal.
421 		 */
422 		if (p != NULL)
423 			vm = p->p_vmspace;
424 
425 		if (vm == NULL)
426 			goto nogo;
427 
428 		map = &vm->vm_map;
429 	}
430 
431 	if (frame->tf_err & PGEX_W)
432 		ftype = VM_PROT_READ | VM_PROT_WRITE;
433 	else
434 		ftype = VM_PROT_READ;
435 
436 	if (map != kernel_map) {
437 		vm_offset_t v = (vm_offset_t) vtopte(va);
438 		vm_page_t ptepg;
439 
440 		/*
441 		 * Keep swapout from messing with us during this
442 		 *	critical time.
443 		 */
444 		++p->p_lock;
445 
446 		/*
447 		 * Grow the stack if necessary
448 		 */
449 		if ((caddr_t)va > vm->vm_maxsaddr
450 		    && (caddr_t)va < (caddr_t)USRSTACK) {
451 			if (!grow(p, va)) {
452 				rv = KERN_FAILURE;
453 				--p->p_lock;
454 				goto nogo;
455 			}
456 		}
457 
458 		/*
459 		 * Check if page table is mapped, if not,
460 		 *	fault it first
461 		 */
462 
463 		/* Fault the pte only if needed: */
464 		*(volatile char *)v += 0;
465 
466 		pmap_use_pt( vm_map_pmap(map), va);
467 
468 		/* Fault in the user page: */
469 		rv = vm_fault(map, va, ftype, FALSE);
470 
471 		pmap_unuse_pt( vm_map_pmap(map), va);
472 
473 		--p->p_lock;
474 	} else {
475 		/*
476 		 * Since we know that kernel virtual address addresses
477 		 * always have pte pages mapped, we just have to fault
478 		 * the page.
479 		 */
480 		rv = vm_fault(map, va, ftype, FALSE);
481 	}
482 
483 	if (rv == KERN_SUCCESS)
484 		return (0);
485 nogo:
486 	if (!usermode) {
487 		if (curpcb && curpcb->pcb_onfault) {
488 			frame->tf_eip = (int)curpcb->pcb_onfault;
489 			return (0);
490 		}
491 		trap_fatal(frame);
492 		return (-1);
493 	}
494 
495 	/* kludge to pass faulting virtual address to sendsig */
496 	frame->tf_err = eva;
497 
498 	return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
499 }
500 
501 void
502 trap_fatal(frame)
503 	struct trapframe *frame;
504 {
505 	int code, type, eva;
506 	struct soft_segment_descriptor softseg;
507 
508 	code = frame->tf_err;
509 	type = frame->tf_trapno;
510 	eva = rcr2();
511 	sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
512 
513 	if (type <= MAX_TRAP_MSG)
514 		printf("\n\nFatal trap %d: %s while in %s mode\n",
515 			type, trap_msg[type],
516 			ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
517 	if (type == T_PAGEFLT) {
518 		printf("fault virtual address	= 0x%x\n", eva);
519 		printf("fault code		= %s %s, %s\n",
520 			code & PGEX_U ? "user" : "supervisor",
521 			code & PGEX_W ? "write" : "read",
522 			code & PGEX_P ? "protection violation" : "page not present");
523 	}
524 	printf("instruction pointer	= 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip);
525 	printf("code segment		= base 0x%x, limit 0x%x, type 0x%x\n",
526 	    softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
527 	printf("			= DPL %d, pres %d, def32 %d, gran %d\n",
528 	    softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran);
529 	printf("processor eflags	= ");
530 	if (frame->tf_eflags & PSL_T)
531 		printf("trace/trap, ");
532 	if (frame->tf_eflags & PSL_I)
533 		printf("interrupt enabled, ");
534 	if (frame->tf_eflags & PSL_NT)
535 		printf("nested task, ");
536 	if (frame->tf_eflags & PSL_RF)
537 		printf("resume, ");
538 	if (frame->tf_eflags & PSL_VM)
539 		printf("vm86, ");
540 	printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12);
541 	printf("current process		= ");
542 	if (curproc) {
543 		printf("%lu (%s)\n",
544 		    (u_long)curproc->p_pid, curproc->p_comm ?
545 		    curproc->p_comm : "");
546 	} else {
547 		printf("Idle\n");
548 	}
549 	printf("interrupt mask		= ");
550 	if ((cpl & net_imask) == net_imask)
551 		printf("net ");
552 	if ((cpl & tty_imask) == tty_imask)
553 		printf("tty ");
554 	if ((cpl & bio_imask) == bio_imask)
555 		printf("bio ");
556 	if (cpl == 0)
557 		printf("none");
558 	printf("\n");
559 
560 #ifdef KDB
561 	if (kdb_trap(&psl))
562 		return;
563 #endif
564 #ifdef DDB
565 	if (kdb_trap (type, 0, frame))
566 		return;
567 #endif
568 	if (type <= MAX_TRAP_MSG)
569 		panic(trap_msg[type]);
570 	else
571 		panic("unknown/reserved trap");
572 }
573 
574 /*
575  * Compensate for 386 brain damage (missing URKR).
576  * This is a little simpler than the pagefault handler in trap() because
577  * it the page tables have already been faulted in and high addresses
578  * are thrown out early for other reasons.
579  */
580 int trapwrite(addr)
581 	unsigned addr;
582 {
583 	struct proc *p;
584 	vm_offset_t va, v;
585 	struct vmspace *vm;
586 	int rv;
587 
588 	va = trunc_page((vm_offset_t)addr);
589 	/*
590 	 * XXX - MAX is END.  Changed > to >= for temp. fix.
591 	 */
592 	if (va >= VM_MAXUSER_ADDRESS)
593 		return (1);
594 
595 	p = curproc;
596 	vm = p->p_vmspace;
597 
598 	++p->p_lock;
599 
600 	if ((caddr_t)va >= vm->vm_maxsaddr
601 	    && (caddr_t)va < (caddr_t)USRSTACK) {
602 		if (!grow(p, va)) {
603 			--p->p_lock;
604 			return (1);
605 		}
606 	}
607 
608 	v = trunc_page(vtopte(va));
609 
610 	/*
611 	 * wire the pte page
612 	 */
613 	if (va < USRSTACK) {
614 		vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE);
615 	}
616 
617 	/*
618 	 * fault the data page
619 	 */
620 	rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE);
621 
622 	/*
623 	 * unwire the pte page
624 	 */
625 	if (va < USRSTACK) {
626 		vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE);
627 	}
628 
629 	--p->p_lock;
630 
631 	if (rv != KERN_SUCCESS)
632 		return 1;
633 
634 	return (0);
635 }
636 
637 /*
638  * syscall(frame):
639  *	System call request from POSIX system call gate interface to kernel.
640  * Like trap(), argument is call by reference.
641  */
642 /*ARGSUSED*/
643 void
644 syscall(frame)
645 	struct trapframe frame;
646 {
647 	caddr_t params;
648 	int i;
649 	struct sysent *callp;
650 	struct proc *p = curproc;
651 	u_quad_t sticks;
652 	int error, opc;
653 	int args[8], rval[2];
654 	u_int code;
655 
656 	sticks = p->p_sticks;
657 	if (ISPL(frame.tf_cs) != SEL_UPL)
658 		panic("syscall");
659 
660 	code = frame.tf_eax;
661 	p->p_md.md_regs = (int *)&frame;
662 	params = (caddr_t)frame.tf_esp + sizeof (int) ;
663 
664 	/*
665 	 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
666 	 */
667 	opc = frame.tf_eip - 7;
668 	/*
669 	 * Need to check if this is a 32 bit or 64 bit syscall.
670 	 */
671 	if (code == SYS_syscall) {
672 		/*
673 		 * Code is first argument, followed by actual args.
674 		 */
675 		code = fuword(params);
676 		params += sizeof (int);
677 	} else if (code == SYS___syscall) {
678 		/*
679 		 * Like syscall, but code is a quad, so as to maintain
680 		 * quad alignment for the rest of the arguments.
681 		 */
682 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
683 		params += sizeof(quad_t);
684 	}
685 
686  	if (p->p_sysent->sv_mask)
687  		code = code & p->p_sysent->sv_mask;
688 
689  	if (code >= p->p_sysent->sv_size)
690  		callp = &p->p_sysent->sv_table[0];
691   	else
692  		callp = &p->p_sysent->sv_table[code];
693 
694 	if ((i = callp->sy_narg * sizeof (int)) &&
695 	    (error = copyin(params, (caddr_t)args, (u_int)i))) {
696 #ifdef KTRACE
697 		if (KTRPOINT(p, KTR_SYSCALL))
698 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
699 #endif
700 		goto bad;
701 	}
702 #ifdef KTRACE
703 	if (KTRPOINT(p, KTR_SYSCALL))
704 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
705 #endif
706 	rval[0] = 0;
707 	rval[1] = frame.tf_edx;
708 
709 	error = (*callp->sy_call)(p, args, rval);
710 
711 	switch (error) {
712 
713 	case 0:
714 		/*
715 		 * Reinitialize proc pointer `p' as it may be different
716 		 * if this is a child returning from fork syscall.
717 		 */
718 		p = curproc;
719 		frame.tf_eax = rval[0];
720 		frame.tf_edx = rval[1];
721 		frame.tf_eflags &= ~PSL_C;	/* carry bit */
722 		break;
723 
724 	case ERESTART:
725 		frame.tf_eip = opc;
726 		break;
727 
728 	case EJUSTRETURN:
729 		break;
730 
731 	default:
732 	bad:
733  		if (p->p_sysent->sv_errsize)
734  			if (error >= p->p_sysent->sv_errsize)
735   				error = -1;	/* XXX */
736    			else
737   				error = p->p_sysent->sv_errtbl[error];
738 		frame.tf_eax = error;
739 		frame.tf_eflags |= PSL_C;	/* carry bit */
740 		break;
741 	}
742 
743 	userret(p, &frame, sticks);
744 
745 #ifdef KTRACE
746 	if (KTRPOINT(p, KTR_SYSRET))
747 		ktrsysret(p->p_tracep, code, error, rval[0]);
748 #endif
749 }
750 
751 #ifdef COMPAT_LINUX
752 /*
753  * linux_syscall(frame):
754  */
755 /*ARGSUSED*/
756 void
757 linux_syscall(frame)
758 	struct trapframe frame;
759 {
760 	caddr_t params;
761 	int i;
762 	struct proc *p = curproc;
763 	struct sysent *callp;
764 	u_quad_t sticks;
765 	int error, opc;
766 	int rval[2];
767 	int code;
768 	struct linux_syscall_args {
769 		int ebx;
770 		int ecx;
771 		int edx;
772 		int esi;
773 		int edi;
774 		int ebp;
775 		int eax;
776 	} args;
777 
778 	args.ebx = frame.tf_ebx;
779 	args.ecx = frame.tf_ecx;
780 	args.edx = frame.tf_edx;
781 	args.esi = frame.tf_esi;
782 	args.edi = frame.tf_edi;
783 	args.ebp = frame.tf_ebp;
784 	args.eax = frame.tf_eax;
785 
786 	sticks = p->p_sticks;
787 	if (ISPL(frame.tf_cs) != SEL_UPL)
788 		panic("linux syscall");
789 
790 	code = frame.tf_eax;
791 	p->p_md.md_regs = (int *)&frame;
792 	params = (caddr_t)frame.tf_esp + sizeof (int) ;
793 
794 	/*
795 	 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
796 	 * THIS IS WRONG FOR LINUX  XXX SOS
797 	 * SIZE OF INT 0x80 (2??) NEEDED HERE !!!
798 	 */
799 	opc = frame.tf_eip - 2; /* was 7 */
800 	if (code == 0) {
801 		code = fuword(params);
802 		params += sizeof (int);
803 	}
804 	if (p->p_sysent->sv_mask)
805 		code = code & p->p_sysent->sv_mask;
806 
807 	if (code < 0 || code >= p->p_sysent->sv_size)
808 		callp = &p->p_sysent->sv_table[0];
809 	else
810 		callp = &p->p_sysent->sv_table[code];
811 
812 #ifdef KTRACE
813 	if (KTRPOINT(p, KTR_SYSCALL))
814 		ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
815 #endif
816 
817 #ifdef KTRACE
818 	if (KTRPOINT(p, KTR_SYSCALL))
819 		ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
820 #endif
821 	rval[0] = 0;
822 	rval[1] = frame.tf_edx;
823 
824 	error = (*callp->sy_call)(p, &args, rval);
825 
826 	switch (error) {
827 
828 	case 0:
829 		/*
830 		 * Reinitialize proc pointer `p' as it may be different
831 		 * if this is a child returning from fork syscall.
832 		 */
833 		p = curproc;
834 		frame.tf_eax = rval[0];
835 		frame.tf_eflags &= ~PSL_C;	/* carry bit */
836 		break;
837 
838 	case ERESTART:
839 		frame.tf_eip = opc;
840 		break;
841 
842 	case EJUSTRETURN:
843 		break;
844 
845 	default:
846 	bad:
847  		if (p->p_sysent->sv_errsize)
848  			if (error >= p->p_sysent->sv_errsize)
849   				error = -1;	/* XXX */
850    			else
851   				error = p->p_sysent->sv_errtbl[error];
852 		frame.tf_eax = -error;
853 		frame.tf_eflags |= PSL_C;	/* carry bit */
854 		break;
855 	}
856 
857 	userret(p, &frame, sticks);
858 
859 #ifdef KTRACE
860 	if (KTRPOINT(p, KTR_SYSRET))
861 		ktrsysret(p->p_tracep, code, error, rval[0]);
862 #endif
863 }
864 #endif /* COMPAT_LINUX */
865