1 /* $NetBSD: syscall.c,v 1.27 2023/10/05 19:41:06 ad 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* All bugs are subject to removal without further notice */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.27 2023/10/05 19:41:06 ad Exp $");
32
33 #include "opt_multiprocessor.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/cpu.h>
38 #include <sys/ktrace.h>
39 #include <sys/proc.h>
40 #include <sys/syscall.h>
41 #include <sys/syscallvar.h>
42
43 #include <machine/userret.h>
44
45 #ifdef TRAPDEBUG
46 int startsysc = 0;
47 #define TDB(a) if (startsysc) printf a
48 #else
49 #define TDB(a)
50 #endif
51
52 void syscall(struct trapframe *);
53
54 void
syscall_intern(struct proc * p)55 syscall_intern(struct proc *p)
56 {
57 p->p_trace_enabled = trace_is_enabled(p);
58 p->p_md.md_syscall = syscall;
59 }
60
61 void
syscall(struct trapframe * tf)62 syscall(struct trapframe *tf)
63 {
64 int error;
65 int rval[2];
66 int args[2+SYS_MAXSYSARGS]; /* add two for SYS___syscall + padding */
67 struct lwp * const l = curlwp;
68 struct proc * const p = l->l_proc;
69 const struct emul * const emul = p->p_emul;
70 const struct sysent *callp = emul->e_sysent;
71 const u_quad_t oticks = p->p_sticks;
72
73 TDB(("trap syscall %s pc %lx, psl %lx, sp %lx, pid %d, frame %p\n",
74 syscallnames[tf->tf_code], tf->tf_pc, tf->tf_psl,tf->tf_sp,
75 p->p_pid,tf));
76
77 curcpu()->ci_data.cpu_nsyscall++;
78
79 l->l_md.md_utf = tf;
80
81 if ((unsigned long) tf->tf_code >= emul->e_nsysent)
82 callp += emul->e_nosys;
83 else
84 callp += tf->tf_code;
85
86 rval[0] = 0;
87 rval[1] = tf->tf_r1;
88
89 if (callp->sy_narg) {
90 error = copyin((char*)tf->tf_ap + 4, args, callp->sy_argsize);
91 if (error)
92 goto bad;
93 }
94
95 /*
96 * Only trace if tracing is enabled and the syscall isn't indirect
97 * (SYS_syscall or SYS___syscall)
98 */
99 error = sy_invoke(callp, curlwp, args, rval, tf->tf_code);
100
101 TDB(("return %s pc %lx, psl %lx, sp %lx, pid %d, err %d r0 %d, r1 %d, "
102 "tf %p\n", syscallnames[tf->tf_code], tf->tf_pc, tf->tf_psl,
103 tf->tf_sp, p->p_pid, error, rval[0], rval[1], tf));
104 bad:
105 switch (error) {
106 case 0:
107 tf->tf_r1 = rval[1];
108 tf->tf_r0 = rval[0];
109 tf->tf_psl &= ~PSL_C;
110 break;
111
112 case EJUSTRETURN:
113 break;
114
115 case ERESTART:
116 /* assumes CHMK $n was used */
117 tf->tf_pc -= (tf->tf_code > 63 ? 4 : 2);
118 break;
119
120 default:
121 tf->tf_r0 = error;
122 tf->tf_psl |= PSL_C;
123 break;
124 }
125
126 userret(l, tf, oticks);
127 }
128
129 void
md_child_return(struct lwp * l)130 md_child_return(struct lwp *l)
131 {
132
133 userret(l, l->l_md.md_utf, 0);
134 }
135
136 /*
137 * Process the tail end of a posix_spawn() for the child.
138 */
139 void
cpu_spawn_return(struct lwp * l)140 cpu_spawn_return(struct lwp *l)
141 {
142
143 userret(l, l->l_md.md_utf, 0);
144 }
145