1 /* $NetBSD: syscall.c,v 1.58 2023/10/05 19:41:05 ad Exp $ */
2
3 /*
4 * Copyright (C) 2002 Matt Thomas
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved.
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 TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /* DO NOT INCLUDE opt_compat_XXX.h */
36 /* If needed, they will be included by file that includes this one */
37
38 #include <sys/param.h>
39 #include <sys/cpu.h>
40 #include <sys/ktrace.h>
41 #include <sys/proc.h>
42 #include <sys/reboot.h>
43 #include <sys/systm.h>
44 #include <sys/syscallvar.h>
45
46 #include <uvm/uvm_extern.h>
47
48 #include <powerpc/frame.h>
49 #include <powerpc/pcb.h>
50 #include <powerpc/userret.h>
51
52 #define FIRSTARG 3 /* first argument is in reg 3 */
53 #define NARGREG 8 /* 8 args are in registers */
54 #define MOREARGS(sp) ((void *)((uintptr_t)(sp) + 8)) /* more args go here */
55
56 #ifndef EMULNAME
57 #include <sys/syscall.h>
58
59 #define EMULNAME(x) (x)
60 #define EMULNAMEU(x) (x)
61
62 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.58 2023/10/05 19:41:05 ad Exp $");
63
64 void
md_child_return(struct lwp * l)65 md_child_return(struct lwp *l)
66 {
67 struct trapframe * const tf = l->l_md.md_utf;
68
69 tf->tf_fixreg[FIRSTARG] = 0;
70 tf->tf_fixreg[FIRSTARG + 1] = 1;
71 tf->tf_cr &= ~0x10000000;
72 tf->tf_srr1 &= ~(PSL_FP|PSL_VEC); /* Disable FP & AltiVec, as we can't
73 be them. */
74 }
75 #endif
76
77 #include <powerpc/spr.h>
78
79 static void EMULNAME(syscall)(struct trapframe *);
80
81 void
EMULNAME(syscall)82 EMULNAME(syscall)(struct trapframe *tf)
83 {
84 struct lwp * const l = curlwp;
85 struct proc * const p = l->l_proc;
86 const struct sysent *callp;
87 size_t argsize;
88 register_t code;
89 register_t *params, rval[2];
90 register_t args[10];
91 int error;
92 int n;
93
94 curcpu()->ci_ev_scalls.ev_count++;
95
96 code = tf->tf_fixreg[0];
97 params = tf->tf_fixreg + FIRSTARG;
98 n = NARGREG;
99
100 {
101 switch (code) {
102 case EMULNAMEU(SYS_syscall):
103 /*
104 * code is first argument,
105 * followed by actual args.
106 */
107 code = *params++;
108 n -= 1;
109 break;
110 #if !defined(COMPAT_LINUX)
111 case EMULNAMEU(SYS___syscall):
112 params++;
113 code = *params++;
114 n -= 2;
115 break;
116 #endif
117 default:
118 break;
119 }
120
121 code &= EMULNAMEU(SYS_NSYSENT) - 1;
122 callp = p->p_emul->e_sysent + code;
123 }
124
125 argsize = callp->sy_argsize;
126
127 if (argsize > n * sizeof(register_t)) {
128 memcpy(args, params, n * sizeof(register_t));
129 error = copyin(MOREARGS(tf->tf_fixreg[1]),
130 args + n,
131 argsize - n * sizeof(register_t));
132 if (error)
133 goto bad;
134 params = args;
135 }
136
137 error = sy_invoke(callp, l, params, rval, code);
138
139 if (__predict_true(error == 0)) {
140 tf->tf_fixreg[FIRSTARG] = rval[0];
141 tf->tf_fixreg[FIRSTARG + 1] = rval[1];
142 tf->tf_cr &= ~0x10000000;
143 } else {
144 switch (error) {
145 case ERESTART:
146 /*
147 * Set user's pc back to redo the system call.
148 */
149 tf->tf_srr0 -= 4;
150 break;
151 case EJUSTRETURN:
152 /* nothing to do */
153 break;
154 default:
155 bad:
156 if (p->p_emul->e_errno)
157 error = p->p_emul->e_errno[error];
158 tf->tf_fixreg[FIRSTARG] = error;
159 tf->tf_cr |= 0x10000000;
160 break;
161 }
162 }
163
164 userret(l, tf);
165 }
166
167 void EMULNAME(syscall_intern)(struct proc *);
168
169 void
EMULNAME(syscall_intern)170 EMULNAME(syscall_intern)(struct proc *p)
171 {
172
173 p->p_md.md_syscall = EMULNAME(syscall);
174 }
175