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