1/*	$NetBSD: netbsd32_lwp.c,v 1.23 2021/01/14 02:51:52 simonb Exp $	*/
2
3/*
4 *  Copyright (c) 2005, 2006, 2007, 2020 The NetBSD Foundation.
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 *  POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: netbsd32_lwp.c,v 1.23 2021/01/14 02:51:52 simonb Exp $");
31
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/dirent.h>
37#include <sys/mount.h>
38#include <sys/proc.h>
39#include <sys/syscallargs.h>
40#include <sys/lwpctl.h>
41
42#include <compat/netbsd32/netbsd32.h>
43#include <compat/netbsd32/netbsd32_syscallargs.h>
44#include <compat/netbsd32/netbsd32_conv.h>
45
46/* Sycalls conversion */
47
48int
49netbsd32__lwp_create(struct lwp *l, const struct netbsd32__lwp_create_args *uap, register_t *retval)
50{
51	/* {
52		syscallarg(const netbsd32_ucontextp) ucp;
53		syscallarg(netbsd32_u_long) flags;
54		syscallarg(netbsd32_lwpidp) new_lwp;
55	} */
56	struct proc *p = l->l_proc;
57	ucontext32_t *newuc = NULL;
58	lwp_t *l2;
59	int error;
60
61	KASSERT(p->p_emul->e_ucsize == sizeof(*newuc));
62
63	newuc = kmem_alloc(sizeof(ucontext_t), KM_SLEEP);
64	error = copyin(SCARG_P32(uap, ucp), newuc, p->p_emul->e_ucsize);
65	if (error)
66		goto fail;
67
68	/* validate the ucontext */
69	if ((newuc->uc_flags & _UC_CPU) == 0) {
70		error = EINVAL;
71		goto fail;
72	}
73	error = cpu_mcontext32_validate(l, &newuc->uc_mcontext);
74	if (error)
75		goto fail;
76
77	const sigset_t *sigmask = newuc->uc_flags & _UC_SIGMASK ?
78	    &newuc->uc_sigmask : &l->l_sigmask;
79
80	error = do_lwp_create(l, newuc, SCARG(uap, flags), &l2, sigmask,
81	    &SS_INIT);
82	if (error != 0)
83		goto fail;
84
85	error = copyout(&l2->l_lid, SCARG_P32(uap, new_lwp),
86	    sizeof(l2->l_lid));
87	if (error == 0) {
88		lwp_start(l2, SCARG(uap, flags));
89		return 0;
90	}
91	lwp_exit(l2);
92 fail:
93	kmem_free(newuc, sizeof(ucontext_t));
94	return error;
95}
96
97int
98netbsd32__lwp_wait(struct lwp *l, const struct netbsd32__lwp_wait_args *uap, register_t *retval)
99{
100	/* {
101		syscallarg(lwpid_t) wait_for;
102		syscallarg(netbsd32_lwpidp) departed;
103	} */
104	struct sys__lwp_wait_args ua;
105
106	NETBSD32TO64_UAP(wait_for);
107	NETBSD32TOP_UAP(departed, lwpid_t);
108	return sys__lwp_wait(l, &ua, retval);
109}
110
111int
112netbsd32__lwp_suspend(struct lwp *l, const struct netbsd32__lwp_suspend_args *uap, register_t *retval)
113{
114	/* {
115		syscallarg(lwpid_t) target;
116	} */
117	struct sys__lwp_suspend_args ua;
118
119	NETBSD32TO64_UAP(target);
120	return sys__lwp_suspend(l, &ua, retval);
121}
122
123int
124netbsd32__lwp_continue(struct lwp *l, const struct netbsd32__lwp_continue_args *uap, register_t *retval)
125{
126	/* {
127		syscallarg(lwpid_t) target;
128	} */
129	struct sys__lwp_continue_args ua;
130
131	NETBSD32TO64_UAP(target);
132	return sys__lwp_continue(l, &ua, retval);
133}
134
135int
136netbsd32__lwp_wakeup(struct lwp *l, const struct netbsd32__lwp_wakeup_args *uap, register_t *retval)
137{
138	/* {
139		syscallarg(lwpid_t) target;
140	} */
141	struct sys__lwp_wakeup_args ua;
142
143	NETBSD32TO64_UAP(target);
144	return sys__lwp_wakeup(l, &ua, retval);
145}
146
147int
148netbsd32__lwp_setprivate(struct lwp *l, const struct netbsd32__lwp_setprivate_args *uap, register_t *retval)
149{
150	/* {
151		syscallarg(netbsd32_voidp) ptr;
152	} */
153	struct sys__lwp_setprivate_args ua;
154
155	NETBSD32TOP_UAP(ptr, void);
156	return sys__lwp_setprivate(l, &ua, retval);
157}
158
159int
160netbsd32____lwp_park60(struct lwp *l,
161    const struct netbsd32____lwp_park60_args *uap, register_t *retval)
162{
163	/* {
164		syscallarg(const netbsd32_clockid_t) clock_id;
165		syscallarg(int) flags;
166		syscallarg(const netbsd32_timespec50p) ts;
167		syscallarg(netbsd32_lwpid_t) unpark;
168		syscallarg(netbsd32_voidp) hint;
169		syscallarg(netbsd32_voidp) unparkhint;
170	} */
171	struct timespec ts, *tsp;
172	struct netbsd32_timespec ts32;
173	int ret;
174	int error;
175
176	if (SCARG_P32(uap, ts) == NULL)
177		tsp = NULL;
178	else {
179		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof ts32);
180		if (error != 0)
181			return error;
182		netbsd32_to_timespec(&ts32, &ts);
183		tsp = &ts;
184	}
185
186	if (SCARG(uap, unpark) != 0) {
187		error = lwp_unpark(&SCARG(uap, unpark), 1);
188		if (error != 0)
189			return error;
190	}
191
192	ret = lwp_park(SCARG(uap, clock_id), SCARG(uap, flags), tsp);
193	if (SCARG_P32(uap, ts) != NULL && (SCARG(uap, flags) & TIMER_ABSTIME) == 0) {
194		netbsd32_from_timespec(&ts, &ts32);
195		(void)copyout(&ts32, SCARG_P32(uap, ts), sizeof(ts32));
196	}
197	return ret;
198}
199
200int
201netbsd32__lwp_kill(struct lwp *l, const struct netbsd32__lwp_kill_args *uap, register_t *retval)
202{
203	/* {
204		syscallarg(lwpid_t) target;
205		syscallarg(int) signo;
206	} */
207	struct sys__lwp_kill_args ua;
208
209	NETBSD32TO64_UAP(target);
210	NETBSD32TO64_UAP(signo);
211	return sys__lwp_kill(l, &ua, retval);
212}
213int
214netbsd32__lwp_detach(struct lwp *l, const struct netbsd32__lwp_detach_args *uap, register_t *retval)
215{
216	/* {
217		syscallarg(lwpid_t) target;
218	} */
219	struct sys__lwp_detach_args ua;
220
221	NETBSD32TO64_UAP(target);
222	return sys__lwp_detach(l, &ua, retval);
223}
224
225int
226netbsd32__lwp_unpark(struct lwp *l, const struct netbsd32__lwp_unpark_args *uap, register_t *retval)
227{
228	/* {
229		syscallarg(lwpid_t) target;
230		syscallarg(netbsd32_voidp) hint;
231	} */
232	struct sys__lwp_unpark_args ua;
233
234	NETBSD32TO64_UAP(target);
235	NETBSD32TOP_UAP(hint, void);
236	return sys__lwp_unpark(l, &ua, retval);
237}
238
239int
240netbsd32__lwp_unpark_all(struct lwp *l, const struct netbsd32__lwp_unpark_all_args *uap, register_t *retval)
241{
242	/* {
243		syscallarg(const netbsd32_lwpidp) targets;
244		syscallarg(netbsd32_size_t) ntargets;
245		syscallarg(netbsd32_voidp) hint;
246	} */
247	struct sys__lwp_unpark_all_args ua;
248
249	NETBSD32TOP_UAP(targets, const lwpid_t);
250	NETBSD32TOX_UAP(ntargets, size_t);
251	NETBSD32TOP_UAP(hint, void);
252	return sys__lwp_unpark_all(l, &ua, retval);
253}
254
255int
256netbsd32__lwp_setname(struct lwp *l, const struct netbsd32__lwp_setname_args *uap, register_t *retval)
257{
258	/* {
259		syscallarg(lwpid_t) target;
260		syscallarg(const netbsd32_charp) name;
261	} */
262	struct sys__lwp_setname_args ua;
263
264	NETBSD32TO64_UAP(target);
265	NETBSD32TOP_UAP(name, char *);
266	return sys__lwp_setname(l, &ua, retval);
267}
268
269int
270netbsd32__lwp_getname(struct lwp *l, const struct netbsd32__lwp_getname_args *uap, register_t *retval)
271{
272	/* {
273		syscallarg(lwpid_t) target;
274		syscallarg(netbsd32_charp) name;
275		syscallarg(netbsd32_size_t) len;
276	} */
277	struct sys__lwp_getname_args ua;
278
279	NETBSD32TO64_UAP(target);
280	NETBSD32TOP_UAP(name, char *);
281	NETBSD32TOX_UAP(len, size_t);
282	return sys__lwp_getname(l, &ua, retval);
283}
284
285int
286netbsd32__lwp_ctl(struct lwp *l, const struct netbsd32__lwp_ctl_args *uap, register_t *retval)
287{
288	/* {
289		syscallarg(int) features;
290		syscallarg(netbsd32_pointer_t) address;
291	} */
292	netbsd32_pointer_t vaddr32;
293	int error, features;
294	vaddr_t vaddr;
295
296	features = SCARG(uap, features);
297	features &= ~(LWPCTL_FEATURE_CURCPU | LWPCTL_FEATURE_PCTR);
298	if (features != 0)
299		return ENODEV;
300	if ((error = lwp_ctl_alloc(&vaddr)) != 0)
301		return error;
302	NETBSD32PTR32(vaddr32, (void *)vaddr);
303	return copyout(&vaddr32, SCARG_P32(uap, address), sizeof(vaddr32));
304}
305