xref: /netbsd-src/sys/rump/kern/lib/libsysproxy/sysproxy.c (revision f89f6560d453f5e37386cc7938c072d2f528b9fa)
1 /*	$NetBSD: sysproxy.c,v 1.2 2015/04/03 16:40:55 pooka Exp $	*/
2 
3 /*
4  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: sysproxy.c,v 1.2 2015/04/03 16:40:55 pooka Exp $");
30 
31 #include <sys/param.h>
32 #include <sys/filedesc.h>
33 #include <sys/kmem.h>
34 #include <sys/syscall.h>
35 #include <sys/syscallvar.h>
36 #include <sys/systm.h>
37 #include <sys/xcall.h>
38 
39 #define _RUMP_SYSPROXY
40 #include <rump/rumpuser.h>
41 
42 #include "rump_private.h"
43 
44 int
45 rump_init_server(const char *url)
46 {
47 
48 	return rumpuser_sp_init(url, ostype, osrelease, MACHINE);
49 }
50 
51 static pid_t
52 hyp_getpid(void)
53 {
54 
55 	return curproc->p_pid;
56 }
57 
58 static int
59 hyp_syscall(int num, void *arg, long *retval)
60 {
61 	register_t regrv[2] = {0, 0};
62 	struct lwp *l;
63 	struct sysent *callp;
64 	int rv;
65 
66 	if (__predict_false(num >= SYS_NSYSENT))
67 		return ENOSYS;
68 
69 	/* XXX: always uses native syscall vector */
70 	callp = rump_sysent + num;
71 	l = curlwp;
72 	rv = sy_invoke(callp, l, (void *)arg, regrv, num);
73 	retval[0] = regrv[0];
74 	retval[1] = regrv[1];
75 
76 	return rv;
77 }
78 
79 static int
80 hyp_rfork(void *priv, int flags, const char *comm)
81 {
82 	struct vmspace *vm;
83 	struct proc *p;
84 	struct lwp *l;
85 	int error;
86 	bool initfds;
87 
88 	/*
89 	 * If we are forking off of pid 1, initialize file descriptors.
90 	 */
91 	l = curlwp;
92 	if (l->l_proc->p_pid == 1) {
93 		KASSERT(flags == RUMP_RFFD_CLEAR);
94 		initfds = true;
95 	} else {
96 		initfds = false;
97 	}
98 
99 	/*
100 	 * Since it's a proxy proc, we need create a vmspace for it.
101 	 */
102 	vm = kmem_zalloc(sizeof(*vm), KM_SLEEP);
103 	uvmspace_init(vm, priv, 0, 0, false);
104 
105 	if ((error = rump_lwproc_rfork_vmspace(vm, flags)) != 0) {
106 		kmem_free(vm, sizeof(*vm));
107 		return error;
108 	}
109 
110 	/*
111 	 * We forked in this routine, so cannot use curlwp (const)
112 	 */
113 	l = rump_lwproc_curlwp();
114 	p = l->l_proc;
115 
116 	if (comm)
117 		strlcpy(p->p_comm, comm, sizeof(p->p_comm));
118 	if (initfds)
119 		rump_consdev_init();
120 
121 	return 0;
122 }
123 
124 /*
125  * Order all lwps in a process to exit.  does *not* wait for them to drain.
126  */
127 static void
128 hyp_lwpexit(void)
129 {
130 	struct proc *p = curproc;
131 	uint64_t where;
132 	struct lwp *l;
133 
134 	mutex_enter(p->p_lock);
135 	/*
136 	 * First pass: mark all lwps in the process with LW_RUMP_QEXIT
137 	 * so that they know they should exit.
138 	 */
139 	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
140 		if (l == curlwp)
141 			continue;
142 		l->l_flag |= LW_RUMP_QEXIT;
143 	}
144 	mutex_exit(p->p_lock);
145 
146 	/*
147 	 * Next, make sure everyone on all CPUs sees our status
148 	 * update.  This keeps threads inside cv_wait() and makes
149 	 * sure we don't access a stale cv pointer later when
150 	 * we wake up the threads.
151 	 */
152 
153 	where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
154 	xc_wait(where);
155 
156 	/*
157 	 * Ok, all lwps are either:
158 	 *  1) not in the cv code
159 	 *  2) sleeping on l->l_private
160 	 *  3) sleeping on p->p_waitcv
161 	 *
162 	 * Either way, l_private is stable until we set PS_RUMP_LWPEXIT
163 	 * in p->p_sflag.
164 	 */
165 
166 	mutex_enter(p->p_lock);
167 	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
168 		if (l->l_private)
169 			cv_broadcast(l->l_private);
170 	}
171 	p->p_sflag |= PS_RUMP_LWPEXIT;
172 	cv_broadcast(&p->p_waitcv);
173 	mutex_exit(p->p_lock);
174 }
175 
176 /*
177  * Notify process that all threads have been drained and exec is complete.
178  */
179 static void
180 hyp_execnotify(const char *comm)
181 {
182 	struct proc *p = curproc;
183 
184 	fd_closeexec();
185 	mutex_enter(p->p_lock);
186 	KASSERT(p->p_nlwps == 1 && p->p_sflag & PS_RUMP_LWPEXIT);
187 	p->p_sflag &= ~PS_RUMP_LWPEXIT;
188 	mutex_exit(p->p_lock);
189 	strlcpy(p->p_comm, comm, sizeof(p->p_comm));
190 }
191 
192 /*
193  * Initialize interface pointers since component is present.
194  */
195 RUMP_COMPONENT(RUMP_COMPONENT_KERN)
196 {
197 
198 	rump_sysproxy_ops.rspo_copyin		= rumpuser_sp_copyin;
199 	rump_sysproxy_ops.rspo_copyinstr	= rumpuser_sp_copyinstr;
200 	rump_sysproxy_ops.rspo_copyout		= rumpuser_sp_copyout;
201 	rump_sysproxy_ops.rspo_copyoutstr	= rumpuser_sp_copyoutstr;
202 	rump_sysproxy_ops.rspo_anonmmap		= rumpuser_sp_anonmmap;
203 	rump_sysproxy_ops.rspo_raise		= rumpuser_sp_raise;
204 	rump_sysproxy_ops.rspo_fini		= rumpuser_sp_fini;
205 
206 	rump_sysproxy_ops.rspo_hyp_getpid	= hyp_getpid;
207 	rump_sysproxy_ops.rspo_hyp_syscall	= hyp_syscall;
208 	rump_sysproxy_ops.rspo_hyp_rfork	= hyp_rfork;
209 	rump_sysproxy_ops.rspo_hyp_lwpexit	= hyp_lwpexit;
210 	rump_sysproxy_ops.rspo_hyp_execnotify	= hyp_execnotify;
211 }
212