Sat Jan 22 18:33:25 2011 UTC ()
inverse inversely incorrect comment


(pooka)
diff -r1.220 -r1.221 src/sys/rump/librump/rumpkern/rump.c

cvs diff -r1.220 -r1.221 src/sys/rump/librump/rumpkern/rump.c (switch to unified diff)

--- src/sys/rump/librump/rumpkern/rump.c 2011/01/22 13:41:22 1.220
+++ src/sys/rump/librump/rumpkern/rump.c 2011/01/22 18:33:25 1.221
@@ -1,849 +1,849 @@ @@ -1,849 +1,849 @@
1/* $NetBSD: rump.c,v 1.220 2011/01/22 13:41:22 pooka Exp $ */ 1/* $NetBSD: rump.c,v 1.221 2011/01/22 18:33:25 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by Google Summer of Code. 6 * Development of this software was supported by Google Summer of Code.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE. 27 * SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.220 2011/01/22 13:41:22 pooka Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.221 2011/01/22 18:33:25 pooka Exp $");
32 32
33#include <sys/systm.h> 33#include <sys/systm.h>
34#define ELFSIZE ARCH_ELFSIZE 34#define ELFSIZE ARCH_ELFSIZE
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/atomic.h> 37#include <sys/atomic.h>
38#include <sys/buf.h> 38#include <sys/buf.h>
39#include <sys/callout.h> 39#include <sys/callout.h>
40#include <sys/conf.h> 40#include <sys/conf.h>
41#include <sys/cpu.h> 41#include <sys/cpu.h>
42#include <sys/device.h> 42#include <sys/device.h>
43#include <sys/evcnt.h> 43#include <sys/evcnt.h>
44#include <sys/event.h> 44#include <sys/event.h>
45#include <sys/exec_elf.h> 45#include <sys/exec_elf.h>
46#include <sys/filedesc.h> 46#include <sys/filedesc.h>
47#include <sys/iostat.h> 47#include <sys/iostat.h>
48#include <sys/kauth.h> 48#include <sys/kauth.h>
49#include <sys/kernel.h> 49#include <sys/kernel.h>
50#include <sys/kmem.h> 50#include <sys/kmem.h>
51#include <sys/kprintf.h> 51#include <sys/kprintf.h>
52#include <sys/kthread.h> 52#include <sys/kthread.h>
53#include <sys/ksyms.h> 53#include <sys/ksyms.h>
54#include <sys/msgbuf.h> 54#include <sys/msgbuf.h>
55#include <sys/module.h> 55#include <sys/module.h>
56#include <sys/once.h> 56#include <sys/once.h>
57#include <sys/percpu.h> 57#include <sys/percpu.h>
58#include <sys/pipe.h> 58#include <sys/pipe.h>
59#include <sys/pool.h> 59#include <sys/pool.h>
60#include <sys/queue.h> 60#include <sys/queue.h>
61#include <sys/reboot.h> 61#include <sys/reboot.h>
62#include <sys/resourcevar.h> 62#include <sys/resourcevar.h>
63#include <sys/select.h> 63#include <sys/select.h>
64#include <sys/sysctl.h> 64#include <sys/sysctl.h>
65#include <sys/syscall.h> 65#include <sys/syscall.h>
66#include <sys/syscallvar.h> 66#include <sys/syscallvar.h>
67#include <sys/timetc.h> 67#include <sys/timetc.h>
68#include <sys/tty.h> 68#include <sys/tty.h>
69#include <sys/uidinfo.h> 69#include <sys/uidinfo.h>
70#include <sys/vmem.h> 70#include <sys/vmem.h>
71#include <sys/xcall.h> 71#include <sys/xcall.h>
72#include <sys/simplelock.h> 72#include <sys/simplelock.h>
73 73
74#include <rump/rumpuser.h> 74#include <rump/rumpuser.h>
75 75
76#include <secmodel/suser/suser.h> 76#include <secmodel/suser/suser.h>
77 77
78#include <prop/proplib.h> 78#include <prop/proplib.h>
79 79
80#include <uvm/uvm_extern.h> 80#include <uvm/uvm_extern.h>
81#include <uvm/uvm_readahead.h> 81#include <uvm/uvm_readahead.h>
82 82
83#include "rump_private.h" 83#include "rump_private.h"
84#include "rump_net_private.h" 84#include "rump_net_private.h"
85#include "rump_vfs_private.h" 85#include "rump_vfs_private.h"
86#include "rump_dev_private.h" 86#include "rump_dev_private.h"
87 87
88char machine[] = MACHINE; 88char machine[] = MACHINE;
89 89
90struct proc *initproc; 90struct proc *initproc;
91 91
92struct device rump_rootdev = { 92struct device rump_rootdev = {
93 .dv_class = DV_VIRTUAL 93 .dv_class = DV_VIRTUAL
94}; 94};
95 95
96#ifdef RUMP_WITHOUT_THREADS 96#ifdef RUMP_WITHOUT_THREADS
97int rump_threads = 0; 97int rump_threads = 0;
98#else 98#else
99int rump_threads = 1; 99int rump_threads = 1;
100#endif 100#endif
101 101
102static int rump_proxy_syscall(int, void *, register_t *); 102static int rump_proxy_syscall(int, void *, register_t *);
103static int rump_proxy_rfork(void *, int); 103static int rump_proxy_rfork(void *, int);
104static void rump_proxy_procexit(void); 104static void rump_proxy_procexit(void);
105 105
106static char rump_msgbuf[16*1024]; /* 16k should be enough for std rump needs */ 106static char rump_msgbuf[16*1024]; /* 16k should be enough for std rump needs */
107 107
108#ifdef LOCKDEBUG 108#ifdef LOCKDEBUG
109const int rump_lockdebug = 1; 109const int rump_lockdebug = 1;
110#else 110#else
111const int rump_lockdebug = 0; 111const int rump_lockdebug = 0;
112#endif 112#endif
113bool rump_ttycomponent = false; 113bool rump_ttycomponent = false;
114 114
115static void 115static void
116rump_aiodone_worker(struct work *wk, void *dummy) 116rump_aiodone_worker(struct work *wk, void *dummy)
117{ 117{
118 struct buf *bp = (struct buf *)wk; 118 struct buf *bp = (struct buf *)wk;
119 119
120 KASSERT(&bp->b_work == wk); 120 KASSERT(&bp->b_work == wk);
121 bp->b_iodone(bp); 121 bp->b_iodone(bp);
122} 122}
123 123
124static int rump_inited; 124static int rump_inited;
125 125
126/* 126/*
127 * Make sure pnbuf_cache is available even without vfs 127 * Make sure pnbuf_cache is available even without vfs
128 */ 128 */
129struct pool_cache *pnbuf_cache; 129struct pool_cache *pnbuf_cache;
130int rump_initpnbufpool(void); 130int rump_initpnbufpool(void);
131int rump_initpnbufpool(void) 131int rump_initpnbufpool(void)
132{ 132{
133 133
134 pnbuf_cache = pool_cache_init(MAXPATHLEN, 0, 0, 0, "pnbufpl", 134 pnbuf_cache = pool_cache_init(MAXPATHLEN, 0, 0, 0, "pnbufpl",
135 NULL, IPL_NONE, NULL, NULL, NULL); 135 NULL, IPL_NONE, NULL, NULL, NULL);
136 return EOPNOTSUPP; 136 return EOPNOTSUPP;
137} 137}
138 138
139int rump__unavailable(void); 139int rump__unavailable(void);
140int rump__unavailable() {return EOPNOTSUPP;} 140int rump__unavailable() {return EOPNOTSUPP;}
141__weak_alias(rump_net_init,rump__unavailable); 141__weak_alias(rump_net_init,rump__unavailable);
142__weak_alias(rump_vfs_init,rump_initpnbufpool); 142__weak_alias(rump_vfs_init,rump_initpnbufpool);
143__weak_alias(rump_dev_init,rump__unavailable); 143__weak_alias(rump_dev_init,rump__unavailable);
144 144
145__weak_alias(rump_vfs_fini,rump__unavailable); 145__weak_alias(rump_vfs_fini,rump__unavailable);
146 146
147__weak_alias(biodone,rump__unavailable); 147__weak_alias(biodone,rump__unavailable);
148__weak_alias(sopoll,rump__unavailable); 148__weak_alias(sopoll,rump__unavailable);
149 149
150__weak_alias(rump_vfs_drainbufs,rump__unavailable); 150__weak_alias(rump_vfs_drainbufs,rump__unavailable);
151 151
152void rump__unavailable_vfs_panic(void); 152void rump__unavailable_vfs_panic(void);
153void rump__unavailable_vfs_panic() {panic("vfs component not available");} 153void rump__unavailable_vfs_panic() {panic("vfs component not available");}
154__weak_alias(usermount_common_policy,rump__unavailable_vfs_panic); 154__weak_alias(usermount_common_policy,rump__unavailable_vfs_panic);
155 155
156/* easier to write vfs-less clients */ 156/* easier to write vfs-less clients */
157__weak_alias(rump_pub_etfs_register,rump__unavailable); 157__weak_alias(rump_pub_etfs_register,rump__unavailable);
158__weak_alias(rump_pub_etfs_remove,rump__unavailable); 158__weak_alias(rump_pub_etfs_remove,rump__unavailable);
159 159
160rump_proc_vfs_init_fn rump_proc_vfs_init; 160rump_proc_vfs_init_fn rump_proc_vfs_init;
161rump_proc_vfs_release_fn rump_proc_vfs_release; 161rump_proc_vfs_release_fn rump_proc_vfs_release;
162 162
163static void add_linkedin_modules(const struct modinfo *const *, size_t); 163static void add_linkedin_modules(const struct modinfo *const *, size_t);
164 164
165static void __noinline 165static void __noinline
166messthestack(void) 166messthestack(void)
167{ 167{
168 volatile uint32_t mess[64]; 168 volatile uint32_t mess[64];
169 uint64_t d1, d2; 169 uint64_t d1, d2;
170 int i, error; 170 int i, error;
171 171
172 for (i = 0; i < 64; i++) { 172 for (i = 0; i < 64; i++) {
173 rumpuser_gettime(&d1, &d2, &error); 173 rumpuser_gettime(&d1, &d2, &error);
174 mess[i] = d2; 174 mess[i] = d2;
175 } 175 }
176} 176}
177 177
178/* 178/*
179 * Create kern.hostname. why only this you ask. well, init_sysctl 179 * Create kern.hostname. why only this you ask. well, init_sysctl
180 * is a kitchen sink in need of some gardening. but i want to use 180 * is a kitchen sink in need of some gardening. but i want to use
181 * kern.hostname today. 181 * kern.hostname today.
182 */ 182 */
183static void 183static void
184mksysctls(void) 184mksysctls(void)
185{ 185{
186 186
187 sysctl_createv(NULL, 0, NULL, NULL, 187 sysctl_createv(NULL, 0, NULL, NULL,
188 CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL, 188 CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL,
189 NULL, 0, NULL, 0, CTL_KERN, CTL_EOL); 189 NULL, 0, NULL, 0, CTL_KERN, CTL_EOL);
190 190
191 /* XXX: setting hostnamelen is missing */ 191 /* XXX: setting hostnamelen is missing */
192 sysctl_createv(NULL, 0, NULL, NULL, 192 sysctl_createv(NULL, 0, NULL, NULL,
193 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "hostname", 193 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "hostname",
194 SYSCTL_DESCR("System hostname"), NULL, 0, 194 SYSCTL_DESCR("System hostname"), NULL, 0,
195 &hostname, MAXHOSTNAMELEN, CTL_KERN, KERN_HOSTNAME, CTL_EOL); 195 &hostname, MAXHOSTNAMELEN, CTL_KERN, KERN_HOSTNAME, CTL_EOL);
196} 196}
197 197
198/* there's no convenient kernel entry point for this, so just craft out own */ 198/* there's no convenient kernel entry point for this, so just craft out own */
199static pid_t 199static pid_t
200spgetpid(void) 200spgetpid(void)
201{ 201{
202 202
203 return curproc->p_pid; 203 return curproc->p_pid;
204} 204}
205 205
206static const struct rumpuser_sp_ops spops = { 206static const struct rumpuser_sp_ops spops = {
207 .spop_schedule = rump_schedule, 207 .spop_schedule = rump_schedule,
208 .spop_unschedule = rump_unschedule, 208 .spop_unschedule = rump_unschedule,
209 .spop_lwproc_switch = rump_lwproc_switch, 209 .spop_lwproc_switch = rump_lwproc_switch,
210 .spop_lwproc_release = rump_lwproc_releaselwp, 210 .spop_lwproc_release = rump_lwproc_releaselwp,
211 .spop_lwproc_rfork = rump_proxy_rfork, 211 .spop_lwproc_rfork = rump_proxy_rfork,
212 .spop_lwproc_newlwp = rump_lwproc_newlwp, 212 .spop_lwproc_newlwp = rump_lwproc_newlwp,
213 .spop_lwproc_curlwp = rump_lwproc_curlwp, 213 .spop_lwproc_curlwp = rump_lwproc_curlwp,
214 .spop_procexit = rump_proxy_procexit, 214 .spop_procexit = rump_proxy_procexit,
215 .spop_syscall = rump_proxy_syscall, 215 .spop_syscall = rump_proxy_syscall,
216 .spop_getpid = spgetpid, 216 .spop_getpid = spgetpid,
217}; 217};
218 218
219int 219int
220rump_daemonize_begin(void) 220rump_daemonize_begin(void)
221{ 221{
222 222
223 if (rump_inited) 223 if (rump_inited)
224 return EALREADY; 224 return EALREADY;
225 225
226 return rumpuser_daemonize_begin(); 226 return rumpuser_daemonize_begin();
227} 227}
228 228
229int 229int
230rump_daemonize_done(int error) 230rump_daemonize_done(int error)
231{ 231{
232 232
233 return rumpuser_daemonize_done(error); 233 return rumpuser_daemonize_done(error);
234} 234}
235 235
236int 236int
237rump__init(int rump_version) 237rump__init(int rump_version)
238{ 238{
239 char buf[256]; 239 char buf[256];
240 struct timespec ts; 240 struct timespec ts;
241 uint64_t sec, nsec; 241 uint64_t sec, nsec;
242 struct lwp *l; 242 struct lwp *l;
243 int i, numcpu; 243 int i, numcpu;
244 int error; 244 int error;
245 245
246 /* not reentrant */ 246 /* not reentrant */
247 if (rump_inited) 247 if (rump_inited)
248 return 0; 248 return 0;
249 else if (rump_inited == -1) 249 else if (rump_inited == -1)
250 panic("rump_init: host process restart required"); 250 panic("rump_init: host process restart required");
251 else 251 else
252 rump_inited = 1; 252 rump_inited = 1;
253 253
254 if (rumpuser_getversion() != RUMPUSER_VERSION) { 254 if (rumpuser_getversion() != RUMPUSER_VERSION) {
255 /* let's hope the ABI of rumpuser_dprintf is the same ;) */ 255 /* let's hope the ABI of rumpuser_dprintf is the same ;) */
256 rumpuser_dprintf("rumpuser version mismatch: %d vs. %d\n", 256 rumpuser_dprintf("rumpuser version mismatch: %d vs. %d\n",
257 rumpuser_getversion(), RUMPUSER_VERSION); 257 rumpuser_getversion(), RUMPUSER_VERSION);
258 return EPROGMISMATCH; 258 return EPROGMISMATCH;
259 } 259 }
260 260
261 if (rumpuser_getenv("RUMP_VERBOSE", buf, sizeof(buf), &error) == 0) { 261 if (rumpuser_getenv("RUMP_VERBOSE", buf, sizeof(buf), &error) == 0) {
262 if (*buf != '0') 262 if (*buf != '0')
263 boothowto = AB_VERBOSE; 263 boothowto = AB_VERBOSE;
264 } 264 }
265 265
266 if (rumpuser_getenv("RUMP_NCPU", buf, sizeof(buf), &error) == 0) 266 if (rumpuser_getenv("RUMP_NCPU", buf, sizeof(buf), &error) == 0)
267 error = 0; 267 error = 0;
268 if (error == 0) { 268 if (error == 0) {
269 numcpu = strtoll(buf, NULL, 10); 269 numcpu = strtoll(buf, NULL, 10);
270 if (numcpu < 1) 270 if (numcpu < 1)
271 numcpu = 1; 271 numcpu = 1;
272 } else { 272 } else {
273 numcpu = rumpuser_getnhostcpu(); 273 numcpu = rumpuser_getnhostcpu();
274 } 274 }
275 rump_cpus_bootstrap(&numcpu); 275 rump_cpus_bootstrap(&numcpu);
276 276
277 rumpuser_gettime(&sec, &nsec, &error); 277 rumpuser_gettime(&sec, &nsec, &error);
278 boottime.tv_sec = sec; 278 boottime.tv_sec = sec;
279 boottime.tv_nsec = nsec; 279 boottime.tv_nsec = nsec;
280 280
281 initmsgbuf(rump_msgbuf, sizeof(rump_msgbuf)); 281 initmsgbuf(rump_msgbuf, sizeof(rump_msgbuf));
282 aprint_verbose("%s%s", copyright, version); 282 aprint_verbose("%s%s", copyright, version);
283 283
284 /* 284 /*
285 * Seed arc4random() with a "reasonable" amount of randomness. 285 * Seed arc4random() with a "reasonable" amount of randomness.
286 * Yes, this is a quick kludge which depends on the arc4random 286 * Yes, this is a quick kludge which depends on the arc4random
287 * implementation. 287 * implementation.
288 */ 288 */
289 messthestack(); 289 messthestack();
290 arc4random(); 290 arc4random();
291 291
292 if (rump_version != RUMP_VERSION) { 292 if (rump_version != RUMP_VERSION) {
293 printf("rump version mismatch, %d vs. %d\n", 293 printf("rump version mismatch, %d vs. %d\n",
294 rump_version, RUMP_VERSION); 294 rump_version, RUMP_VERSION);
295 return EPROGMISMATCH; 295 return EPROGMISMATCH;
296 } 296 }
297 297
298 if (rumpuser_getenv("RUMP_THREADS", buf, sizeof(buf), &error) == 0) { 298 if (rumpuser_getenv("RUMP_THREADS", buf, sizeof(buf), &error) == 0) {
299 rump_threads = *buf != '0'; 299 rump_threads = *buf != '0';
300 } 300 }
301 rumpuser_thrinit(rump_user_schedule, rump_user_unschedule, 301 rumpuser_thrinit(rump_user_schedule, rump_user_unschedule,
302 rump_threads); 302 rump_threads);
303 rump_intr_init(numcpu); 303 rump_intr_init(numcpu);
304 rump_tsleep_init(); 304 rump_tsleep_init();
305 305
306 /* init minimal lwp/cpu context */ 306 /* init minimal lwp/cpu context */
307 l = &lwp0; 307 l = &lwp0;
308 l->l_lid = 1; 308 l->l_lid = 1;
309 l->l_cpu = l->l_target_cpu = rump_cpu; 309 l->l_cpu = l->l_target_cpu = rump_cpu;
310 l->l_fd = &filedesc0; 310 l->l_fd = &filedesc0;
311 rumpuser_set_curlwp(l); 311 rumpuser_set_curlwp(l);
312 312
313 rumpuser_mutex_init(&rump_giantlock); 313 rumpuser_mutex_init(&rump_giantlock);
314 ksyms_init(); 314 ksyms_init();
315 uvm_init(); 315 uvm_init();
316 evcnt_init(); 316 evcnt_init();
317 317
318 once_init(); 318 once_init();
319 kernconfig_lock_init(); 319 kernconfig_lock_init();
320 prop_kern_init(); 320 prop_kern_init();
321 321
322 pool_subsystem_init(); 322 pool_subsystem_init();
323 kmem_init(); 323 kmem_init();
324 324
325 uvm_ra_init(); 325 uvm_ra_init();
326 uao_init(); 326 uao_init();
327 327
328 mutex_obj_init(); 328 mutex_obj_init();
329 callout_startup(); 329 callout_startup();
330 330
331 kprintf_init(); 331 kprintf_init();
332 loginit(); 332 loginit();
333 333
334 kauth_init(); 334 kauth_init();
335 335
336 procinit(); 336 procinit();
337 proc0_init(); 337 proc0_init();
338 uid_init(); 338 uid_init();
339 chgproccnt(0, 1); 339 chgproccnt(0, 1);
340 340
341 l->l_proc = &proc0; 341 l->l_proc = &proc0;
342 lwp_update_creds(l); 342 lwp_update_creds(l);
343 343
344 lwpinit_specificdata(); 344 lwpinit_specificdata();
345 lwp_initspecific(&lwp0); 345 lwp_initspecific(&lwp0);
346 346
347 rump_scheduler_init(numcpu); 347 rump_scheduler_init(numcpu);
348 /* revert temporary context and schedule a semireal context */ 348 /* revert temporary context and schedule a semireal context */
349 l->l_cpu = NULL; 349 l->l_cpu = NULL;
350 rumpuser_set_curlwp(NULL); 350 rumpuser_set_curlwp(NULL);
351 initproc = &proc0; /* borrow proc0 before we get initproc started */ 351 initproc = &proc0; /* borrow proc0 before we get initproc started */
352 rump_schedule(); 352 rump_schedule();
353 353
354 percpu_init(); 354 percpu_init();
355 inittimecounter(); 355 inittimecounter();
356 ntp_init(); 356 ntp_init();
357 357
358 rumpuser_gettime(&sec, &nsec, &error); 358 rumpuser_gettime(&sec, &nsec, &error);
359 ts.tv_sec = sec; 359 ts.tv_sec = sec;
360 ts.tv_nsec = nsec; 360 ts.tv_nsec = nsec;
361 tc_setclock(&ts); 361 tc_setclock(&ts);
362 362
363 /* we are mostly go. do per-cpu subsystem init */ 363 /* we are mostly go. do per-cpu subsystem init */
364 for (i = 0; i < numcpu; i++) { 364 for (i = 0; i < numcpu; i++) {
365 struct cpu_info *ci = cpu_lookup(i); 365 struct cpu_info *ci = cpu_lookup(i);
366 366
367 /* attach non-bootstrap CPUs */ 367 /* attach non-bootstrap CPUs */
368 if (i > 0) { 368 if (i > 0) {
369 rump_cpu_attach(ci); 369 rump_cpu_attach(ci);
370 ncpu++; 370 ncpu++;
371 } 371 }
372 372
373 callout_init_cpu(ci); 373 callout_init_cpu(ci);
374 softint_init(ci); 374 softint_init(ci);
375 xc_init_cpu(ci); 375 xc_init_cpu(ci);
376 pool_cache_cpu_init(ci); 376 pool_cache_cpu_init(ci);
377 selsysinit(ci); 377 selsysinit(ci);
378 percpu_init_cpu(ci); 378 percpu_init_cpu(ci);
379 379
380 TAILQ_INIT(&ci->ci_data.cpu_ld_locks); 380 TAILQ_INIT(&ci->ci_data.cpu_ld_locks);
381 __cpu_simple_lock_init(&ci->ci_data.cpu_ld_lock); 381 __cpu_simple_lock_init(&ci->ci_data.cpu_ld_lock);
382 382
383 aprint_verbose("cpu%d at thinair0: rump virtual cpu\n", i); 383 aprint_verbose("cpu%d at thinair0: rump virtual cpu\n", i);
384 } 384 }
385 385
386 sysctl_init(); 386 sysctl_init();
387 mksysctls(); 387 mksysctls();
388 kqueue_init(); 388 kqueue_init();
389 iostat_init(); 389 iostat_init();
390 fd_sys_init(); 390 fd_sys_init();
391 module_init(); 391 module_init();
392 devsw_init(); 392 devsw_init();
393 pipe_init(); 393 pipe_init();
394 resource_init(); 394 resource_init();
395 395
396 /* start page baroness */ 396 /* start page baroness */
397 if (rump_threads) { 397 if (rump_threads) {
398 if (kthread_create(PRI_PGDAEMON, KTHREAD_MPSAFE, NULL, 398 if (kthread_create(PRI_PGDAEMON, KTHREAD_MPSAFE, NULL,
399 uvm_pageout, NULL, &uvm.pagedaemon_lwp, "pdaemon") != 0) 399 uvm_pageout, NULL, &uvm.pagedaemon_lwp, "pdaemon") != 0)
400 panic("pagedaemon create failed"); 400 panic("pagedaemon create failed");
401 } else 401 } else
402 uvm.pagedaemon_lwp = NULL; /* doesn't match curlwp */ 402 uvm.pagedaemon_lwp = NULL; /* doesn't match curlwp */
403 403
404 /* process dso's */ 404 /* process dso's */
405 rumpuser_dl_bootstrap(add_linkedin_modules, rump_kernelfsym_load); 405 rumpuser_dl_bootstrap(add_linkedin_modules, rump_kernelfsym_load);
406 406
407 rump_component_init(RUMP_COMPONENT_KERN); 407 rump_component_init(RUMP_COMPONENT_KERN);
408 408
409 /* these do nothing if not present */ 409 /* these do nothing if not present */
410 rump_vfs_init(); 410 rump_vfs_init();
411 rump_net_init(); 411 rump_net_init();
412 rump_dev_init(); 412 rump_dev_init();
413 413
414 rump_component_init(RUMP_COMPONENT_KERN_VFS); 414 rump_component_init(RUMP_COMPONENT_KERN_VFS);
415 415
416 /* 416 /*
417 * if we initialized the tty component above, the tyttymtx is 417 * if we initialized the tty component above, the tyttymtx is
418 * now initialized. otherwise, we need to initialize it. 418 * now initialized. otherwise, we need to initialize it.
419 */ 419 */
420 if (!rump_ttycomponent) 420 if (!rump_ttycomponent)
421 mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM); 421 mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM);
422 422
423 cold = 0; 423 cold = 0;
424 424
425 /* aieeeedondest */ 425 /* aieeeedondest */
426 if (rump_threads) { 426 if (rump_threads) {
427 if (workqueue_create(&uvm.aiodone_queue, "aiodoned", 427 if (workqueue_create(&uvm.aiodone_queue, "aiodoned",
428 rump_aiodone_worker, NULL, 0, 0, WQ_MPSAFE)) 428 rump_aiodone_worker, NULL, 0, 0, WQ_MPSAFE))
429 panic("aiodoned"); 429 panic("aiodoned");
430 } 430 }
431 431
432 sysctl_finalize(); 432 sysctl_finalize();
433 433
434 module_init_class(MODULE_CLASS_ANY); 434 module_init_class(MODULE_CLASS_ANY);
435 435
436 rumpuser_gethostname(hostname, MAXHOSTNAMELEN, &error); 436 rumpuser_gethostname(hostname, MAXHOSTNAMELEN, &error);
437 hostnamelen = strlen(hostname); 437 hostnamelen = strlen(hostname);
438 438
439 sigemptyset(&sigcantmask); 439 sigemptyset(&sigcantmask);
440 440
441 if (rump_threads) 441 if (rump_threads)
442 vmem_rehash_start(); 442 vmem_rehash_start();
443 443
444 /* 444 /*
445 * Create init, used to attach implicit threads in rump. 445 * Create init, used to attach implicit threads in rump.
446 * (note: must be done after vfsinit to get cwdi) 446 * (note: must be done after vfsinit to get cwdi)
447 */ 447 */
448 (void)rump__lwproc_alloclwp(NULL); /* dummy thread for initproc */ 448 (void)rump__lwproc_alloclwp(NULL); /* dummy thread for initproc */
449 mutex_enter(proc_lock); 449 mutex_enter(proc_lock);
450 initproc = proc_find_raw(1); 450 initproc = proc_find_raw(1);
451 mutex_exit(proc_lock); 451 mutex_exit(proc_lock);
452 if (initproc == NULL) 452 if (initproc == NULL)
453 panic("where in the world is initproc?"); 453 panic("where in the world is initproc?");
454 454
455 /* 455 /*
456 * Adjust syscall vector in case factions were dlopen()'d 456 * Adjust syscall vector in case factions were dlopen()'d
457 * before calling rump_init(). 457 * before calling rump_init().
458 * (modules will handle dynamic syscalls the usual way) 458 * (modules will handle dynamic syscalls the usual way)
459 * 459 *
460 * Note: this will adjust the function vectors of 460 * Note: this will adjust the function vectors of
461 * syscalls which use a funcalias (getpid etc.), but 461 * syscalls which use a funcalias (getpid etc.), but
462 * it makes no difference. 462 * it makes no difference.
463 */ 463 */
464 for (i = 0; i < SYS_NSYSENT; i++) { 464 for (i = 0; i < SYS_NSYSENT; i++) {
465 void *sym; 465 void *sym;
466 466
467 if (rump_sysent[i].sy_flags & SYCALL_NOSYS || 467 if (rump_sysent[i].sy_flags & SYCALL_NOSYS ||
468 *syscallnames[i] == '#' || 468 *syscallnames[i] == '#' ||
469 rump_sysent[i].sy_call == sys_nomodule) 469 rump_sysent[i].sy_call == sys_nomodule)
470 continue; 470 continue;
471 471
472 /* if present, adjust symbol value */ 472 /* if present, adjust symbol value */
473 sprintf(buf, "rumpns_sys_%s", syscallnames[i]); 473 sprintf(buf, "rumpns_sys_%s", syscallnames[i]);
474 if ((sym = rumpuser_dl_globalsym(buf)) != NULL 474 if ((sym = rumpuser_dl_globalsym(buf)) != NULL
475 && sym != rump_sysent[i].sy_call) { 475 && sym != rump_sysent[i].sy_call) {
476#if 0 476#if 0
477 rumpuser_dprintf("adjusting %s: %p (old %p)\n", 477 rumpuser_dprintf("adjusting %s: %p (old %p)\n",
478 syscallnames[i], sym, rump_sysent[i].sy_call); 478 syscallnames[i], sym, rump_sysent[i].sy_call);
479#endif 479#endif
480 rump_sysent[i].sy_call = sym; 480 rump_sysent[i].sy_call = sym;
481 } 481 }
482 } 482 }
483 483
484 /* release cpu */ 484 /* release cpu */
485 rump_unschedule(); 485 rump_unschedule();
486 486
487 return 0; 487 return 0;
488} 488}
489 489
490int 490int
491rump_init_server(const char *url) 491rump_init_server(const char *url)
492{ 492{
493 493
494 return rumpuser_sp_init(url, &spops, ostype, osrelease, MACHINE); 494 return rumpuser_sp_init(url, &spops, ostype, osrelease, MACHINE);
495} 495}
496 496
497void 497void
498cpu_reboot(int howto, char *bootstr) 498cpu_reboot(int howto, char *bootstr)
499{ 499{
500 int ruhow = 0; 500 int ruhow = 0;
501 void *finiarg; 501 void *finiarg;
502 502
503 printf("rump kernel halting...\n"); 503 printf("rump kernel halting...\n");
504 504
505 if (!RUMP_LOCALPROC_P(curproc)) 505 if (!RUMP_LOCALPROC_P(curproc))
506 finiarg = curproc->p_vmspace->vm_map.pmap; 506 finiarg = curproc->p_vmspace->vm_map.pmap;
507 else 507 else
508 finiarg = NULL; 508 finiarg = NULL;
509 rumpuser_sp_fini(finiarg); 509 rumpuser_sp_fini(finiarg);
510 510
511 /* dump means we really take the dive here */ 511 /* dump means we really take the dive here */
512 if ((howto & RB_DUMP) || panicstr) { 512 if ((howto & RB_DUMP) || panicstr) {
513 ruhow = RUMPUSER_PANIC; 513 ruhow = RUMPUSER_PANIC;
514 goto out; 514 goto out;
515 } 515 }
516 516
517 /* try to sync */ 517 /* try to sync */
518 if (!((howto & RB_NOSYNC) || panicstr)) { 518 if (!((howto & RB_NOSYNC) || panicstr)) {
519 rump_vfs_fini(); 519 rump_vfs_fini();
520 } 520 }
521 521
522 /* your wish is my command */ 522 /* your wish is my command */
523 if (howto & RB_HALT) { 523 if (howto & RB_HALT) {
524 printf("rump kernel halted\n"); 524 printf("rump kernel halted\n");
525 for (;;) { 525 for (;;) {
526 uint64_t sec = 5, nsec = 0; 526 uint64_t sec = 5, nsec = 0;
527 int error; 527 int error;
528 528
529 rumpuser_nanosleep(&sec, &nsec, &error); 529 rumpuser_nanosleep(&sec, &nsec, &error);
530 } 530 }
531 } 531 }
532 532
533 /* this function is __dead, we must exit */ 533 /* this function is __dead, we must exit */
534 out: 534 out:
535 printf("halted\n"); 535 printf("halted\n");
536 rumpuser_exit(ruhow); 536 rumpuser_exit(ruhow);
537} 537}
538 538
539struct uio * 539struct uio *
540rump_uio_setup(void *buf, size_t bufsize, off_t offset, enum rump_uiorw rw) 540rump_uio_setup(void *buf, size_t bufsize, off_t offset, enum rump_uiorw rw)
541{ 541{
542 struct uio *uio; 542 struct uio *uio;
543 enum uio_rw uiorw; 543 enum uio_rw uiorw;
544 544
545 switch (rw) { 545 switch (rw) {
546 case RUMPUIO_READ: 546 case RUMPUIO_READ:
547 uiorw = UIO_READ; 547 uiorw = UIO_READ;
548 break; 548 break;
549 case RUMPUIO_WRITE: 549 case RUMPUIO_WRITE:
550 uiorw = UIO_WRITE; 550 uiorw = UIO_WRITE;
551 break; 551 break;
552 default: 552 default:
553 panic("%s: invalid rw %d", __func__, rw); 553 panic("%s: invalid rw %d", __func__, rw);
554 } 554 }
555 555
556 uio = kmem_alloc(sizeof(struct uio), KM_SLEEP); 556 uio = kmem_alloc(sizeof(struct uio), KM_SLEEP);
557 uio->uio_iov = kmem_alloc(sizeof(struct iovec), KM_SLEEP); 557 uio->uio_iov = kmem_alloc(sizeof(struct iovec), KM_SLEEP);
558 558
559 uio->uio_iov->iov_base = buf; 559 uio->uio_iov->iov_base = buf;
560 uio->uio_iov->iov_len = bufsize; 560 uio->uio_iov->iov_len = bufsize;
561 561
562 uio->uio_iovcnt = 1; 562 uio->uio_iovcnt = 1;
563 uio->uio_offset = offset; 563 uio->uio_offset = offset;
564 uio->uio_resid = bufsize; 564 uio->uio_resid = bufsize;
565 uio->uio_rw = uiorw; 565 uio->uio_rw = uiorw;
566 UIO_SETUP_SYSSPACE(uio); 566 UIO_SETUP_SYSSPACE(uio);
567 567
568 return uio; 568 return uio;
569} 569}
570 570
571size_t 571size_t
572rump_uio_getresid(struct uio *uio) 572rump_uio_getresid(struct uio *uio)
573{ 573{
574 574
575 return uio->uio_resid; 575 return uio->uio_resid;
576} 576}
577 577
578off_t 578off_t
579rump_uio_getoff(struct uio *uio) 579rump_uio_getoff(struct uio *uio)
580{ 580{
581 581
582 return uio->uio_offset; 582 return uio->uio_offset;
583} 583}
584 584
585size_t 585size_t
586rump_uio_free(struct uio *uio) 586rump_uio_free(struct uio *uio)
587{ 587{
588 size_t resid; 588 size_t resid;
589 589
590 resid = uio->uio_resid; 590 resid = uio->uio_resid;
591 kmem_free(uio->uio_iov, sizeof(*uio->uio_iov)); 591 kmem_free(uio->uio_iov, sizeof(*uio->uio_iov));
592 kmem_free(uio, sizeof(*uio)); 592 kmem_free(uio, sizeof(*uio));
593 593
594 return resid; 594 return resid;
595} 595}
596 596
597kauth_cred_t 597kauth_cred_t
598rump_cred_create(uid_t uid, gid_t gid, size_t ngroups, gid_t *groups) 598rump_cred_create(uid_t uid, gid_t gid, size_t ngroups, gid_t *groups)
599{ 599{
600 kauth_cred_t cred; 600 kauth_cred_t cred;
601 int rv; 601 int rv;
602 602
603 cred = kauth_cred_alloc(); 603 cred = kauth_cred_alloc();
604 kauth_cred_setuid(cred, uid); 604 kauth_cred_setuid(cred, uid);
605 kauth_cred_seteuid(cred, uid); 605 kauth_cred_seteuid(cred, uid);
606 kauth_cred_setsvuid(cred, uid); 606 kauth_cred_setsvuid(cred, uid);
607 kauth_cred_setgid(cred, gid); 607 kauth_cred_setgid(cred, gid);
608 kauth_cred_setgid(cred, gid); 608 kauth_cred_setgid(cred, gid);
609 kauth_cred_setegid(cred, gid); 609 kauth_cred_setegid(cred, gid);
610 kauth_cred_setsvgid(cred, gid); 610 kauth_cred_setsvgid(cred, gid);
611 rv = kauth_cred_setgroups(cred, groups, ngroups, 0, UIO_SYSSPACE); 611 rv = kauth_cred_setgroups(cred, groups, ngroups, 0, UIO_SYSSPACE);
612 /* oh this is silly. and by "this" I mean kauth_cred_setgroups() */ 612 /* oh this is silly. and by "this" I mean kauth_cred_setgroups() */
613 assert(rv == 0); 613 assert(rv == 0);
614 614
615 return cred; 615 return cred;
616} 616}
617 617
618void 618void
619rump_cred_put(kauth_cred_t cred) 619rump_cred_put(kauth_cred_t cred)
620{ 620{
621 621
622 kauth_cred_free(cred); 622 kauth_cred_free(cred);
623} 623}
624 624
625static int compcounter[RUMP_COMPONENT_MAX]; 625static int compcounter[RUMP_COMPONENT_MAX];
626 626
627static void 627static void
628rump_component_init_cb(struct rump_component *rc, int type) 628rump_component_init_cb(struct rump_component *rc, int type)
629{ 629{
630 630
631 KASSERT(type < RUMP_COMPONENT_MAX); 631 KASSERT(type < RUMP_COMPONENT_MAX);
632 if (rc->rc_type == type) { 632 if (rc->rc_type == type) {
633 rc->rc_init(); 633 rc->rc_init();
634 compcounter[type]++; 634 compcounter[type]++;
635 } 635 }
636} 636}
637 637
638int 638int
639rump_component_count(enum rump_component_type type) 639rump_component_count(enum rump_component_type type)
640{ 640{
641 641
642 KASSERT(type <= RUMP_COMPONENT_MAX); 642 KASSERT(type <= RUMP_COMPONENT_MAX);
643 return compcounter[type]; 643 return compcounter[type];
644} 644}
645 645
646void 646void
647rump_component_init(enum rump_component_type type) 647rump_component_init(enum rump_component_type type)
648{ 648{
649 649
650 rumpuser_dl_component_init(type, rump_component_init_cb); 650 rumpuser_dl_component_init(type, rump_component_init_cb);
651} 651}
652 652
653/* 653/*
654 * Initialize a module which has already been loaded and linked 654 * Initialize a module which has already been loaded and linked
655 * with dlopen(). This is fundamentally the same as a builtin module. 655 * with dlopen(). This is fundamentally the same as a builtin module.
656 */ 656 */
657int 657int
658rump_module_init(const struct modinfo * const *mip, size_t nmodinfo) 658rump_module_init(const struct modinfo * const *mip, size_t nmodinfo)
659{ 659{
660 660
661 return module_builtin_add(mip, nmodinfo, true); 661 return module_builtin_add(mip, nmodinfo, true);
662} 662}
663 663
664/* 664/*
665 * Finish module (flawless victory, fatality!). 665 * Finish module (flawless victory, fatality!).
666 */ 666 */
667int 667int
668rump_module_fini(const struct modinfo *mi) 668rump_module_fini(const struct modinfo *mi)
669{ 669{
670 670
671 return module_builtin_remove(mi, true); 671 return module_builtin_remove(mi, true);
672} 672}
673 673
674/* 674/*
675 * Add loaded and linked module to the builtin list. It will 675 * Add loaded and linked module to the builtin list. It will
676 * later be initialized with module_init_class(). 676 * later be initialized with module_init_class().
677 */ 677 */
678 678
679static void 679static void
680add_linkedin_modules(const struct modinfo * const *mip, size_t nmodinfo) 680add_linkedin_modules(const struct modinfo * const *mip, size_t nmodinfo)
681{ 681{
682 682
683 module_builtin_add(mip, nmodinfo, false); 683 module_builtin_add(mip, nmodinfo, false);
684} 684}
685 685
686int 686int
687rump_kernelfsym_load(void *symtab, uint64_t symsize, 687rump_kernelfsym_load(void *symtab, uint64_t symsize,
688 char *strtab, uint64_t strsize) 688 char *strtab, uint64_t strsize)
689{ 689{
690 static int inited = 0; 690 static int inited = 0;
691 Elf64_Ehdr ehdr; 691 Elf64_Ehdr ehdr;
692 692
693 if (inited) 693 if (inited)
694 return EBUSY; 694 return EBUSY;
695 inited = 1; 695 inited = 1;
696 696
697 /* 697 /*
698 * Use 64bit header since it's bigger. Shouldn't make a 698 * Use 64bit header since it's bigger. Shouldn't make a
699 * difference, since we're passing in all zeroes anyway. 699 * difference, since we're passing in all zeroes anyway.
700 */ 700 */
701 memset(&ehdr, 0, sizeof(ehdr)); 701 memset(&ehdr, 0, sizeof(ehdr));
702 ksyms_addsyms_explicit(&ehdr, symtab, symsize, strtab, strsize); 702 ksyms_addsyms_explicit(&ehdr, symtab, symsize, strtab, strsize);
703 703
704 return 0; 704 return 0;
705} 705}
706 706
707static int 707static int
708rump_proxy_syscall(int num, void *arg, register_t *retval) 708rump_proxy_syscall(int num, void *arg, register_t *retval)
709{ 709{
710 struct lwp *l; 710 struct lwp *l;
711 struct sysent *callp; 711 struct sysent *callp;
712 int rv; 712 int rv;
713 713
714 if (__predict_false(num >= SYS_NSYSENT)) 714 if (__predict_false(num >= SYS_NSYSENT))
715 return ENOSYS; 715 return ENOSYS;
716 716
717 callp = rump_sysent + num; 717 callp = rump_sysent + num;
718 l = curlwp; 718 l = curlwp;
719 rv = sy_call(callp, l, (void *)arg, retval); 719 rv = sy_call(callp, l, (void *)arg, retval);
720 720
721 return rv; 721 return rv;
722} 722}
723 723
724static int 724static int
725rump_proxy_rfork(void *priv, int flags) 725rump_proxy_rfork(void *priv, int flags)
726{ 726{
727 struct vmspace *newspace; 727 struct vmspace *newspace;
728 int error; 728 int error;
729 729
730 if ((error = rump_lwproc_rfork(flags)) != 0) 730 if ((error = rump_lwproc_rfork(flags)) != 0)
731 return error; 731 return error;
732 732
733 /* 733 /*
734 * Since it's a proxy proc, adjust the vmspace. 734 * Since it's a proxy proc, adjust the vmspace.
735 * Refcount will eternally be 1. 735 * Refcount will eternally be 1.
736 */ 736 */
737 newspace = kmem_alloc(sizeof(*newspace), KM_SLEEP); 737 newspace = kmem_alloc(sizeof(*newspace), KM_SLEEP);
738 newspace->vm_refcnt = 1; 738 newspace->vm_refcnt = 1;
739 newspace->vm_map.pmap = priv; 739 newspace->vm_map.pmap = priv;
740 KASSERT(curproc->p_vmspace == vmspace_kernel()); 740 KASSERT(curproc->p_vmspace == vmspace_kernel());
741 curproc->p_vmspace = newspace; 741 curproc->p_vmspace = newspace;
742 742
743 return 0; 743 return 0;
744} 744}
745 745
746static void 746static void
747rump_proxy_procexit(void) 747rump_proxy_procexit(void)
748{ 748{
749 struct proc *p = curproc; 749 struct proc *p = curproc;
750 uint64_t where; 750 uint64_t where;
751 struct lwp *l; 751 struct lwp *l;
752 752
753 mutex_enter(p->p_lock); 753 mutex_enter(p->p_lock);
754 /* 754 /*
755 * First pass: mark all lwps in the process with LSDEAD 755 * First pass: mark all lwps in the process with LSDEAD
756 * so that they know they should exit. 756 * so that they know they should exit.
757 */ 757 */
758 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 758 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
759 if (l == curlwp) 759 if (l == curlwp)
760 continue; 760 continue;
761 l->l_stat = LSDEAD; 761 l->l_stat = LSDEAD;
762 } 762 }
763 mutex_exit(p->p_lock); 763 mutex_exit(p->p_lock);
764 764
765 /* 765 /*
766 * Next, make sure everyone on all CPUs sees our status 766 * Next, make sure everyone on all CPUs sees our status
767 * update. This keeps threads inside cv_wait() and makes 767 * update. This keeps threads inside cv_wait() and makes
768 * sure we don't access a stale cv pointer later when 768 * sure we don't access a stale cv pointer later when
769 * we wake up the threads. 769 * we wake up the threads.
770 */ 770 */
771 771
772 where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); 772 where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
773 xc_wait(where); 773 xc_wait(where);
774 774
775 /* 775 /*
776 * Ok, all lwps are either: 776 * Ok, all lwps are either:
777 * 1) not in the cv code 777 * 1) not in the cv code
778 * 2) sleeping on l->l_private 778 * 2) sleeping on l->l_private
779 * 3) sleeping on p->p_waitcv 779 * 3) sleeping on p->p_waitcv
780 * 780 *
781 * Either way, l_private is stable until we change the lwps 781 * Either way, l_private is stable until we change the lwps
782 * state to LSZOMB. 782 * state to LSZOMB.
783 */ 783 */
784 784
785 mutex_enter(p->p_lock); 785 mutex_enter(p->p_lock);
786 LIST_FOREACH(l, &p->p_lwps, l_sibling) { 786 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
787 if (l->l_private) 787 if (l->l_private)
788 cv_broadcast(l->l_private); 788 cv_broadcast(l->l_private);
789 l->l_stat = LSZOMB; 789 l->l_stat = LSZOMB;
790 } 790 }
791 cv_broadcast(&p->p_waitcv); 791 cv_broadcast(&p->p_waitcv);
792 mutex_exit(p->p_lock); 792 mutex_exit(p->p_lock);
793 793
794 /* 794 /*
795 * Don't wait for lwps to exit. There's refcounting in the 795 * Don't wait for lwps to exit. There's refcounting in the
796 * rumpuser sp code which makes this safe. Also, this routine 796 * rumpuser sp code which makes this safe. Also, this routine
797 * should sleep for a long time. 797 * should not sleep for a long time.
798 */ 798 */
799} 799}
800 800
801int 801int
802rump_boot_gethowto() 802rump_boot_gethowto()
803{ 803{
804 804
805 return boothowto; 805 return boothowto;
806} 806}
807 807
808void 808void
809rump_boot_sethowto(int howto) 809rump_boot_sethowto(int howto)
810{ 810{
811 811
812 boothowto = howto; 812 boothowto = howto;
813} 813}
814 814
815int 815int
816rump_getversion(void) 816rump_getversion(void)
817{ 817{
818 818
819 return __NetBSD_Version__; 819 return __NetBSD_Version__;
820} 820}
821 821
822/* 822/*
823 * Note: may be called unscheduled. Not fully safe since no locking 823 * Note: may be called unscheduled. Not fully safe since no locking
824 * of allevents (currently that's not even available). 824 * of allevents (currently that's not even available).
825 */ 825 */
826void 826void
827rump_printevcnts() 827rump_printevcnts()
828{ 828{
829 struct evcnt *ev; 829 struct evcnt *ev;
830 830
831 TAILQ_FOREACH(ev, &allevents, ev_list) 831 TAILQ_FOREACH(ev, &allevents, ev_list)
832 rumpuser_dprintf("%s / %s: %" PRIu64 "\n", 832 rumpuser_dprintf("%s / %s: %" PRIu64 "\n",
833 ev->ev_group, ev->ev_name, ev->ev_count); 833 ev->ev_group, ev->ev_name, ev->ev_count);
834} 834}
835 835
836/* 836/*
837 * If you use this interface ... well ... all bets are off. 837 * If you use this interface ... well ... all bets are off.
838 * The original purpose is for the p2k fs server library to be 838 * The original purpose is for the p2k fs server library to be
839 * able to use the same pid/lid for VOPs as the host kernel. 839 * able to use the same pid/lid for VOPs as the host kernel.
840 */ 840 */
841void 841void
842rump_allbetsareoff_setid(pid_t pid, int lid) 842rump_allbetsareoff_setid(pid_t pid, int lid)
843{ 843{
844 struct lwp *l = curlwp; 844 struct lwp *l = curlwp;
845 struct proc *p = l->l_proc; 845 struct proc *p = l->l_proc;
846 846
847 l->l_lid = lid; 847 l->l_lid = lid;
848 p->p_pid = pid; 848 p->p_pid = pid;
849} 849}