xref: /netbsd/sys/arch/vax/vax/syscall.c (revision 6550d01e)
1 /*	$NetBSD: syscall.c,v 1.18 2010/12/20 00:25:45 matt Exp $     */
2 
3 /*
4  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *     This product includes software developed at Ludd, University of Lule}.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33  /* All bugs are subject to removal without further notice */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.18 2010/12/20 00:25:45 matt Exp $");
37 
38 #include "opt_multiprocessor.h"
39 #include "opt_sa.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/cpu.h>
44 #include <sys/ktrace.h>
45 #include <sys/proc.h>
46 #include <sys/sa.h>
47 #include <sys/savar.h>
48 #include <sys/syscall.h>
49 #include <sys/syscallvar.h>
50 
51 #include <machine/userret.h>
52 
53 #ifdef TRAPDEBUG
54 int startsysc = 0;
55 #define TDB(a) if (startsysc) printf a
56 #else
57 #define TDB(a)
58 #endif
59 
60 void syscall(struct trapframe *);
61 
62 void
63 syscall_intern(struct proc *p)
64 {
65 	p->p_trace_enabled = trace_is_enabled(p);
66 	p->p_md.md_syscall = syscall;
67 }
68 
69 void
70 syscall(struct trapframe *frame)
71 {
72 	int error;
73 	int rval[2];
74 	int args[2+SYS_MAXSYSARGS]; /* add two for SYS___syscall + padding */
75 	struct trapframe * const exptr = frame;
76 	struct lwp * const l = curlwp;
77 	struct proc * const p = l->l_proc;
78 	struct pcb *pcb = lwp_getpcb(l);
79 	const struct emul * const emul = p->p_emul;
80 	const struct sysent *callp = emul->e_sysent;
81 	const u_quad_t oticks = p->p_sticks;
82 
83 	TDB(("trap syscall %s pc %lx, psl %lx, sp %lx, pid %d, frame %p\n",
84 	    syscallnames[frame->code], frame->pc, frame->psl,frame->sp,
85 	    p->p_pid,frame));
86 
87 	curcpu()->ci_data.cpu_nsyscall++;
88 
89  	LWP_CACHE_CREDS(l, p);
90 
91 	pcb->framep = frame;
92 
93 	if ((unsigned long) frame->code >= emul->e_nsysent)
94 		callp += emul->e_nosys;
95 	else
96 		callp += frame->code;
97 
98 	rval[0] = 0;
99 	rval[1] = frame->r1;
100 
101 	if (callp->sy_narg) {
102 		error = copyin((char*)frame->ap + 4, args, callp->sy_argsize);
103 		if (error)
104 			goto bad;
105 	}
106 
107 #ifdef KERN_SA
108 	if (__predict_false((l->l_savp)
109             && (l->l_savp->savp_pflags & SAVP_FLAG_DELIVERING)))
110 		l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING;
111 #endif
112 
113 	/*
114 	 * Only trace if tracing is enabled and the syscall isn't indirect
115 	 * (SYS_syscall or SYS___syscall)
116 	 */
117 	if (__predict_true(!p->p_trace_enabled)
118 	    || __predict_false(callp->sy_flags & SYCALL_INDIRECT)
119 	    || (error = trace_enter(frame->code, args, callp->sy_narg)) == 0) {
120 		error = sy_call(callp, curlwp, args, rval);
121 	}
122 
123 	KASSERT(exptr == pcb->framep);
124 	TDB(("return %s pc %lx, psl %lx, sp %lx, pid %d, err %d r0 %d, r1 %d, "
125 	    "frame %p\n", syscallnames[exptr->code], exptr->pc, exptr->psl,
126 	    exptr->sp, p->p_pid, error, rval[0], rval[1], exptr));
127 bad:
128 	switch (error) {
129 	case 0:
130 		exptr->r1 = rval[1];
131 		exptr->r0 = rval[0];
132 		exptr->psl &= ~PSL_C;
133 		break;
134 
135 	case EJUSTRETURN:
136 		break;
137 
138 	case ERESTART:
139 		/* assumes CHMK $n was used */
140 		exptr->pc -= (exptr->code > 63 ? 4 : 2);
141 		break;
142 
143 	default:
144 		exptr->r0 = error;
145 		exptr->psl |= PSL_C;
146 		break;
147 	}
148 
149 	if (__predict_false(p->p_trace_enabled)
150 	    && __predict_true(!(callp->sy_flags & SYCALL_INDIRECT)))
151 		trace_exit(frame->code, rval, error);
152 
153 	userret(l, frame, oticks);
154 }
155 
156 void
157 child_return(void *arg)
158 {
159 	struct lwp *l = arg;
160 	struct pcb *pcb = lwp_getpcb(l);
161 
162 	userret(l, pcb->framep, 0);
163 	ktrsysret(SYS_fork, 0, 0);
164 }
165