xref: /freebsd/sys/kern/subr_trap.c (revision a316b26e50bbed7cf655fbba726ab87d8ab7599d)
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.42 1994/12/24 07:22:58 bde 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 	"reserved addressing fault",		/*  0 T_RESADFLT */
77 	"privileged instruction fault",		/*  1 T_PRIVINFLT */
78 	"reserved operand fault",		/*  2 T_RESOPFLT */
79 	"breakpoint instruction fault",		/*  3 T_BPTFLT */
80 	"",					/*  4 unused */
81 	"system call trap",			/*  5 T_SYSCALL */
82 	"arithmetic trap",			/*  6 T_ARITHTRAP */
83 	"system forced exception",		/*  7 T_ASTFLT */
84 	"segmentation (limit) fault",		/*  8 T_SEGFLT */
85 	"general protection fault",		/*  9 T_PROTFLT */
86 	"trace trap",				/* 10 T_TRCTRAP */
87 	"",					/* 11 unused */
88 	"page fault",				/* 12 T_PAGEFLT */
89 	"page table fault",			/* 13 T_TABLEFLT */
90 	"alignment fault",			/* 14 T_ALIGNFLT */
91 	"kernel stack pointer not valid",	/* 15 T_KSPNOTVAL */
92 	"bus error",				/* 16 T_BUSERR */
93 	"kernel debugger fault",		/* 17 T_KDBTRAP */
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 	if (p->p_stats->p_prof.pr_scale) {
135 		u_quad_t ticks = p->p_sticks - oticks;
136 
137 		if (ticks) {
138 #ifdef PROFTIMER
139 			extern int profscale;
140 			addupc(frame->tf_eip, &p->p_stats->p_prof,
141 			    ticks * profscale);
142 #else
143 			addupc(frame->tf_eip, &p->p_stats->p_prof, ticks);
144 #endif
145 		}
146 	}
147 	curpriority = p->p_priority;
148 }
149 
150 /*
151  * trap(frame):
152  *	Exception, fault, and trap interface to the FreeBSD kernel.
153  * This common code is called from assembly language IDT gate entry
154  * routines that prepare a suitable stack frame, and restore this
155  * frame after the exception has been processed.
156  */
157 
158 /*ARGSUSED*/
159 void
160 trap(frame)
161 	struct trapframe frame;
162 {
163 	struct proc *p = curproc;
164 	u_quad_t sticks = 0;
165 	int i = 0, ucode = 0, type, code;
166 #ifdef DIAGNOSTIC
167 	u_long eva;
168 #endif
169 
170 	frame.tf_eflags &= ~PSL_NT;	/* clear nested trap XXX */
171 	type = frame.tf_trapno;
172 	code = frame.tf_err;
173 
174 	if (ISPL(frame.tf_cs) == SEL_UPL) {
175 		/* user trap */
176 
177 		sticks = p->p_sticks;
178 		p->p_md.md_regs = (int *)&frame;
179 
180 		switch (type) {
181 		case T_RESADFLT:	/* reserved addressing fault */
182 		case T_PRIVINFLT:	/* privileged instruction fault */
183 		case T_RESOPFLT:	/* reserved operand 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) && p->p_stats->p_prof.pr_scale) {
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 			ucode = code + BUS_SEGM_FAULT ;
212 			i = SIGBUS;
213 			break;
214 
215 		case T_PAGEFLT:		/* page fault */
216 			i = trap_pfault(&frame, TRUE);
217 			if (i == -1)
218 				return;
219 			if (i == 0)
220 				goto out;
221 
222 			ucode = T_PAGEFLT;
223 			break;
224 
225 		case T_DIVIDE:		/* integer divide fault */
226 			ucode = FPE_INTDIV_TRAP;
227 			i = SIGFPE;
228 			break;
229 
230 #if NISA > 0
231 		case T_NMI:
232 #ifdef DDB
233 			/* NMI can be hooked up to a pushbutton for debugging */
234 			printf ("NMI ... going to debugger\n");
235 			if (kdb_trap (type, 0, &frame))
236 				return;
237 #endif
238 			/* machine/parity/power fail/"kitchen sink" faults */
239 			if (isa_nmi(code) == 0) return;
240 			panic("NMI indicates hardware failure");
241 #endif
242 
243 		case T_OFLOW:		/* integer overflow fault */
244 			ucode = FPE_INTOVF_TRAP;
245 			i = SIGFPE;
246 			break;
247 
248 		case T_BOUND:		/* bounds check fault */
249 			ucode = FPE_SUBRNG_TRAP;
250 			i = SIGFPE;
251 			break;
252 
253 		case T_DNA:
254 #if NNPX > 0
255 			/* if a transparent fault (due to context switch "late") */
256 			if (npxdna())
257 				return;
258 #endif	/* NNPX > 0 */
259 
260 #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE)
261 			i = math_emulate(&frame);
262 			if (i == 0) {
263 				if (!(frame.tf_eflags & PSL_T))
264 					return;
265 				frame.tf_eflags &= ~PSL_T;
266 				i = SIGTRAP;
267 			}
268 			/* else ucode = emulator_only_knows() XXX */
269 #else	/* MATH_EMULATE || GPL_MATH_EMULATE */
270 			i = SIGFPE;
271 			ucode = FPE_FPU_NP_TRAP;
272 #endif	/* MATH_EMULATE || GPL_MATH_EMULATE */
273 			break;
274 
275 		case T_FPOPFLT:		/* FPU operand fetch fault */
276 			ucode = T_FPOPFLT;
277 			i = SIGILL;
278 			break;
279 
280 		default:
281 			trap_fatal(&frame);
282 			return;
283 		}
284 	} else {
285 		/* kernel trap */
286 
287 		switch (type) {
288 		case T_PAGEFLT:			/* page fault */
289 			(void) trap_pfault(&frame, FALSE);
290 			return;
291 
292 		case T_PROTFLT:		/* general protection fault */
293 		case T_SEGNPFLT:	/* segment not present fault */
294 			if (curpcb && curpcb->pcb_onfault) {
295 				frame.tf_eip = (int)curpcb->pcb_onfault;
296 				return;
297 			}
298 			break;
299 
300 #ifdef DDB
301 		case T_BPTFLT:
302 		case T_TRCTRAP:
303 			if (kdb_trap (type, 0, &frame))
304 				return;
305 			break;
306 #else
307 		case T_TRCTRAP:	 /* trace trap -- someone single stepping lcall's */
308 			/* Q: how do we turn it on again? */
309 			frame.tf_eflags &= ~PSL_T;
310 			return;
311 #endif
312 
313 #if NISA > 0
314 		case T_NMI:
315 #ifdef DDB
316 			/* NMI can be hooked up to a pushbutton for debugging */
317 			printf ("NMI ... going to debugger\n");
318 			if (kdb_trap (type, 0, &frame))
319 				return;
320 #endif
321 			/* machine/parity/power fail/"kitchen sink" faults */
322 			if (isa_nmi(code) == 0) return;
323 			/* FALL THROUGH */
324 #endif
325 		}
326 
327 		trap_fatal(&frame);
328 		return;
329 	}
330 
331 	trapsignal(p, i, ucode);
332 
333 #ifdef DIAGNOSTIC
334 	eva = rcr2();
335 	if (type <= MAX_TRAP_MSG) {
336 		uprintf("fatal process exception: %s",
337 			trap_msg[type]);
338 		if ((type == T_PAGEFLT) || (type == T_PROTFLT))
339 			uprintf(", fault VA = 0x%x", eva);
340 		uprintf("\n");
341 	}
342 #endif
343 
344 out:
345 	userret(p, &frame, sticks);
346 }
347 
348 int
349 trap_pfault(frame, usermode)
350 	struct trapframe *frame;
351 	int usermode;
352 {
353 	vm_offset_t va;
354 	struct vmspace *vm = NULL;
355 	vm_map_t map = 0;
356 	int rv = 0;
357 	vm_prot_t ftype;
358 	extern vm_map_t kernel_map;
359 	int eva;
360 	struct proc *p = curproc;
361 
362 	eva = rcr2();
363 	va = trunc_page((vm_offset_t)eva);
364 
365 	if (va >= KERNBASE) {
366 		/*
367 		 * Don't allow user-mode faults in kernel address space.
368 		 */
369 		if (usermode)
370 			goto nogo;
371 
372 		map = kernel_map;
373 	} else {
374 		/*
375 		 * This is a fault on non-kernel virtual memory.
376 		 * vm is initialized above to NULL. If curproc is NULL
377 		 * or curproc->p_vmspace is NULL the fault is fatal.
378 		 */
379 		if (p != NULL)
380 			vm = p->p_vmspace;
381 
382 		if (vm == NULL)
383 			goto nogo;
384 
385 		map = &vm->vm_map;
386 	}
387 
388 	if (frame->tf_err & PGEX_W)
389 		ftype = VM_PROT_READ | VM_PROT_WRITE;
390 	else
391 		ftype = VM_PROT_READ;
392 
393 	if (map != kernel_map) {
394 		vm_offset_t v = (vm_offset_t) vtopte(va);
395 		vm_page_t ptepg;
396 
397 		/*
398 		 * Keep swapout from messing with us during this
399 		 *	critical time.
400 		 */
401 		++p->p_lock;
402 
403 		/*
404 		 * Grow the stack if necessary
405 		 */
406 		if ((caddr_t)va > vm->vm_maxsaddr
407 		    && (caddr_t)va < (caddr_t)USRSTACK) {
408 			if (!grow(p, va)) {
409 				rv = KERN_FAILURE;
410 				--p->p_lock;
411 				goto nogo;
412 			}
413 		}
414 
415 		/*
416 		 * Check if page table is mapped, if not,
417 		 *	fault it first
418 		 */
419 
420 		/* Fault the pte only if needed: */
421 		*(volatile char *)v += 0;
422 
423 		ptepg = (vm_page_t) pmap_pte_vm_page(vm_map_pmap(map), v);
424 		vm_page_hold(ptepg);
425 
426 		/* Fault in the user page: */
427 		rv = vm_fault(map, va, ftype, FALSE);
428 
429 		vm_page_unhold(ptepg);
430 
431 		/*
432 		 * page table pages don't need to be kept if they
433 		 * are not held
434 		 */
435 		if( ptepg->hold_count == 0 && ptepg->wire_count == 0) {
436 			pmap_page_protect( VM_PAGE_TO_PHYS(ptepg),
437 				VM_PROT_NONE);
438 			vm_page_free(ptepg);
439 		}
440 
441 		--p->p_lock;
442 	} else {
443 		/*
444 		 * Since we know that kernel virtual address addresses
445 		 * always have pte pages mapped, we just have to fault
446 		 * the page.
447 		 */
448 		rv = vm_fault(map, va, ftype, FALSE);
449 	}
450 
451 	if (rv == KERN_SUCCESS)
452 		return (0);
453 nogo:
454 	if (!usermode) {
455 		if (curpcb && curpcb->pcb_onfault) {
456 			frame->tf_eip = (int)curpcb->pcb_onfault;
457 			return (0);
458 		}
459 		trap_fatal(frame);
460 		return (-1);
461 	}
462 
463 	/* kludge to pass faulting virtual address to sendsig */
464 	frame->tf_err = eva;
465 
466 	return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
467 }
468 
469 void
470 trap_fatal(frame)
471 	struct trapframe *frame;
472 {
473 	int code, type, eva;
474 	struct soft_segment_descriptor softseg;
475 
476 	code = frame->tf_err;
477 	type = frame->tf_trapno;
478 	eva = rcr2();
479 	sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
480 
481 	if (type <= MAX_TRAP_MSG)
482 		printf("\n\nFatal trap %d: %s while in %s mode\n",
483 			type, trap_msg[type],
484 			ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
485 	if (type == T_PAGEFLT) {
486 		printf("fault virtual address	= 0x%x\n", eva);
487 		printf("fault code		= %s %s, %s\n",
488 			code & PGEX_U ? "user" : "supervisor",
489 			code & PGEX_W ? "write" : "read",
490 			code & PGEX_P ? "protection violation" : "page not present");
491 	}
492 	printf("instruction pointer	= 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip);
493 	printf("code segment		= base 0x%x, limit 0x%x, type 0x%x\n",
494 	    softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
495 	printf("			= DPL %d, pres %d, def32 %d, gran %d\n",
496 	    softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran);
497 	printf("processor eflags	= ");
498 	if (frame->tf_eflags & PSL_T)
499 		printf("trace/trap, ");
500 	if (frame->tf_eflags & PSL_I)
501 		printf("interrupt enabled, ");
502 	if (frame->tf_eflags & PSL_NT)
503 		printf("nested task, ");
504 	if (frame->tf_eflags & PSL_RF)
505 		printf("resume, ");
506 	if (frame->tf_eflags & PSL_VM)
507 		printf("vm86, ");
508 	printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12);
509 	printf("current process		= ");
510 	if (curproc) {
511 		printf("%lu (%s)\n",
512 		    (u_long)curproc->p_pid, curproc->p_comm ?
513 		    curproc->p_comm : "");
514 	} else {
515 		printf("Idle\n");
516 	}
517 	printf("interrupt mask		= ");
518 	if ((cpl & net_imask) == net_imask)
519 		printf("net ");
520 	if ((cpl & tty_imask) == tty_imask)
521 		printf("tty ");
522 	if ((cpl & bio_imask) == bio_imask)
523 		printf("bio ");
524 	if (cpl == 0)
525 		printf("none");
526 	printf("\n");
527 
528 #ifdef KDB
529 	if (kdb_trap(&psl))
530 		return;
531 #endif
532 #ifdef DDB
533 	if (kdb_trap (type, 0, frame))
534 		return;
535 #endif
536 	if (type <= MAX_TRAP_MSG)
537 		panic(trap_msg[type]);
538 	else
539 		panic("unknown/reserved trap");
540 }
541 
542 /*
543  * Compensate for 386 brain damage (missing URKR).
544  * This is a little simpler than the pagefault handler in trap() because
545  * it the page tables have already been faulted in and high addresses
546  * are thrown out early for other reasons.
547  */
548 int trapwrite(addr)
549 	unsigned addr;
550 {
551 	struct proc *p;
552 	vm_offset_t va, v;
553 	struct vmspace *vm;
554 	int rv;
555 
556 	va = trunc_page((vm_offset_t)addr);
557 	/*
558 	 * XXX - MAX is END.  Changed > to >= for temp. fix.
559 	 */
560 	if (va >= VM_MAXUSER_ADDRESS)
561 		return (1);
562 
563 	p = curproc;
564 	vm = p->p_vmspace;
565 
566 	++p->p_lock;
567 
568 	if ((caddr_t)va >= vm->vm_maxsaddr
569 	    && (caddr_t)va < (caddr_t)USRSTACK) {
570 		if (!grow(p, va)) {
571 			--p->p_lock;
572 			return (1);
573 		}
574 	}
575 
576 	v = trunc_page(vtopte(va));
577 
578 	/*
579 	 * wire the pte page
580 	 */
581 	if (va < USRSTACK) {
582 		vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE);
583 	}
584 
585 	/*
586 	 * fault the data page
587 	 */
588 	rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE);
589 
590 	/*
591 	 * unwire the pte page
592 	 */
593 	if (va < USRSTACK) {
594 		vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE);
595 	}
596 
597 	--p->p_lock;
598 
599 	if (rv != KERN_SUCCESS)
600 		return 1;
601 
602 	return (0);
603 }
604 
605 /*
606  * syscall(frame):
607  *	System call request from POSIX system call gate interface to kernel.
608  * Like trap(), argument is call by reference.
609  */
610 /*ARGSUSED*/
611 void
612 syscall(frame)
613 	struct trapframe frame;
614 {
615 	caddr_t params;
616 	int i;
617 	struct sysent *callp;
618 	struct proc *p = curproc;
619 	u_quad_t sticks;
620 	int error, opc;
621 	int args[8], rval[2];
622 	u_int code;
623 
624 	sticks = p->p_sticks;
625 	if (ISPL(frame.tf_cs) != SEL_UPL)
626 		panic("syscall");
627 
628 	code = frame.tf_eax;
629 	p->p_md.md_regs = (int *)&frame;
630 	params = (caddr_t)frame.tf_esp + sizeof (int) ;
631 
632 	/*
633 	 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
634 	 */
635 	opc = frame.tf_eip - 7;
636 	/*
637 	 * Need to check if this is a 32 bit or 64 bit syscall.
638 	 */
639 	if (code == SYS_syscall) {
640 		/*
641 		 * Code is first argument, followed by actual args.
642 		 */
643 		code = fuword(params);
644 		params += sizeof (int);
645 	} else if (code == SYS___syscall) {
646 		/*
647 		 * Like syscall, but code is a quad, so as to maintain
648 		 * quad alignment for the rest of the arguments.
649 		 */
650 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
651 		params += sizeof(quad_t);
652 	}
653 
654  	if (p->p_sysent->sv_mask)
655  		code = code & p->p_sysent->sv_mask;
656 
657  	if (code >= p->p_sysent->sv_size)
658  		callp = &p->p_sysent->sv_table[0];
659   	else
660  		callp = &p->p_sysent->sv_table[code];
661 
662 	if ((i = callp->sy_narg * sizeof (int)) &&
663 	    (error = copyin(params, (caddr_t)args, (u_int)i))) {
664 #ifdef KTRACE
665 		if (KTRPOINT(p, KTR_SYSCALL))
666 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
667 #endif
668 		goto bad;
669 	}
670 #ifdef KTRACE
671 	if (KTRPOINT(p, KTR_SYSCALL))
672 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
673 #endif
674 	rval[0] = 0;
675 	rval[1] = frame.tf_edx;
676 
677 	error = (*callp->sy_call)(p, args, rval);
678 
679 	switch (error) {
680 
681 	case 0:
682 		/*
683 		 * Reinitialize proc pointer `p' as it may be different
684 		 * if this is a child returning from fork syscall.
685 		 */
686 		p = curproc;
687 		frame.tf_eax = rval[0];
688 		frame.tf_edx = rval[1];
689 		frame.tf_eflags &= ~PSL_C;	/* carry bit */
690 		break;
691 
692 	case ERESTART:
693 		frame.tf_eip = opc;
694 		break;
695 
696 	case EJUSTRETURN:
697 		break;
698 
699 	default:
700 	bad:
701  		if (p->p_sysent->sv_errsize)
702  			if (error >= p->p_sysent->sv_errsize)
703   				error = -1;	/* XXX */
704    			else
705   				error = p->p_sysent->sv_errtbl[error];
706 		frame.tf_eax = error;
707 		frame.tf_eflags |= PSL_C;	/* carry bit */
708 		break;
709 	}
710 
711 	userret(p, &frame, sticks);
712 
713 #ifdef KTRACE
714 	if (KTRPOINT(p, KTR_SYSRET))
715 		ktrsysret(p->p_tracep, code, error, rval[0]);
716 #endif
717 }
718