1 /* $NetBSD: rump.c,v 1.357 2023/08/05 11:51:47 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 2007-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: rump.c,v 1.357 2023/08/05 11:51:47 riastradh Exp $"); 30 31 #include <sys/systm.h> 32 #define ELFSIZE ARCH_ELFSIZE 33 34 #include <sys/param.h> 35 #include <sys/atomic.h> 36 #include <sys/buf.h> 37 #include <sys/callout.h> 38 #include <sys/conf.h> 39 #include <sys/cpu.h> 40 #include <sys/device.h> 41 #include <sys/device_impl.h> 42 #include <sys/evcnt.h> 43 #include <sys/event.h> 44 #include <sys/exec_elf.h> 45 #include <sys/filedesc.h> 46 #include <sys/iostat.h> 47 #include <sys/kauth.h> 48 #include <sys/kcpuset.h> 49 #include <sys/kernel.h> 50 #include <sys/kmem.h> 51 #include <sys/kprintf.h> 52 #include <sys/kthread.h> 53 #include <sys/ksyms.h> 54 #include <sys/msgbuf.h> 55 #include <sys/module.h> 56 #include <sys/module_hook.h> 57 #include <sys/namei.h> 58 #include <sys/once.h> 59 #include <sys/percpu.h> 60 #include <sys/pipe.h> 61 #include <sys/pool.h> 62 #include <sys/queue.h> 63 #include <sys/reboot.h> 64 #include <sys/resourcevar.h> 65 #include <sys/select.h> 66 #include <sys/sysctl.h> 67 #include <sys/syscall.h> 68 #include <sys/syscallvar.h> 69 #include <sys/threadpool.h> 70 #include <sys/timetc.h> 71 #include <sys/tty.h> 72 #include <sys/uidinfo.h> 73 #include <sys/vmem.h> 74 #include <sys/xcall.h> 75 #include <sys/cprng.h> 76 #include <sys/rnd.h> 77 #include <sys/ktrace.h> 78 #include <sys/pserialize.h> 79 #include <sys/psref.h> 80 81 #include <rump-sys/kern.h> 82 #include <rump-sys/dev.h> 83 #include <rump-sys/net.h> 84 #include <rump-sys/vfs.h> 85 86 #include <rump/rumpuser.h> 87 88 #include <prop/proplib.h> 89 90 #include <uvm/uvm_extern.h> 91 #include <uvm/uvm_readahead.h> 92 93 char machine[] = MACHINE; 94 char machine_arch[] = MACHINE_ARCH; 95 96 struct proc *initproc; 97 98 struct device rump_rootdev = { 99 .dv_class = DV_VIRTUAL 100 }; 101 102 #ifdef RUMP_WITHOUT_THREADS 103 int rump_threads = 0; 104 #else 105 int rump_threads = 1; 106 #endif 107 108 static void rump_component_addlocal(void); 109 static struct lwp *bootlwp; 110 111 /* 16k should be enough for std rump needs */ 112 static char rump_msgbuf[16*1024] __aligned(256); 113 114 bool rump_ttycomponent = false; 115 116 extern pool_cache_t pnbuf_cache; 117 118 static int rump_inited; 119 120 void (*rump_vfs_drainbufs)(int) = (void *)nullop; 121 int (*rump_vfs_makeonedevnode)(dev_t, const char *, 122 devmajor_t, devminor_t) = (void *)nullop; 123 int (*rump_vfs_makedevnodes)(dev_t, const char *, char, 124 devmajor_t, devminor_t, int) = (void *)nullop; 125 int (*rump_vfs_makesymlink)(const char *, const char *) = (void *)nullop; 126 127 rump_proc_vfs_init_fn rump_proc_vfs_init = (void *)nullop; 128 rump_proc_vfs_release_fn rump_proc_vfs_release = (void *)nullop; 129 130 static void add_linkedin_modules(const struct modinfo *const *, size_t); 131 static void add_static_evcnt(struct evcnt *); 132 133 static pid_t rspo_wrap_getpid(void) { 134 return rump_sysproxy_hyp_getpid(); 135 } 136 static int rspo_wrap_syscall(int num, void *arg, long *retval) { 137 return rump_sysproxy_hyp_syscall(num, arg, retval); 138 } 139 static int rspo_wrap_rfork(void *priv, int flag, const char *comm) { 140 return rump_sysproxy_hyp_rfork(priv, flag, comm); 141 } 142 static void rspo_wrap_lwpexit(void) { 143 rump_sysproxy_hyp_lwpexit(); 144 } 145 static void rspo_wrap_execnotify(const char *comm) { 146 rump_sysproxy_hyp_execnotify(comm); 147 } 148 static const struct rumpuser_hyperup hyp = { 149 .hyp_schedule = rump_schedule, 150 .hyp_unschedule = rump_unschedule, 151 .hyp_backend_unschedule = rump_user_unschedule, 152 .hyp_backend_schedule = rump_user_schedule, 153 .hyp_lwproc_switch = rump_lwproc_switch, 154 .hyp_lwproc_release = rump_lwproc_releaselwp, 155 .hyp_lwproc_newlwp = rump_lwproc_newlwp, 156 .hyp_lwproc_curlwp = rump_lwproc_curlwp, 157 158 .hyp_getpid = rspo_wrap_getpid, 159 .hyp_syscall = rspo_wrap_syscall, 160 .hyp_lwproc_rfork = rspo_wrap_rfork, 161 .hyp_lwpexit = rspo_wrap_lwpexit, 162 .hyp_execnotify = rspo_wrap_execnotify, 163 }; 164 struct rump_sysproxy_ops rump_sysproxy_ops = { 165 .rspo_copyin = (void *)enxio, 166 .rspo_copyinstr = (void *)enxio, 167 .rspo_copyout = (void *)enxio, 168 .rspo_copyoutstr = (void *)enxio, 169 .rspo_anonmmap = (void *)enxio, 170 .rspo_raise = (void *)enxio, 171 .rspo_fini = (void *)enxio, 172 .rspo_hyp_getpid = (void *)enxio, 173 .rspo_hyp_syscall = (void *)enxio, 174 .rspo_hyp_rfork = (void *)enxio, 175 .rspo_hyp_lwpexit = (void *)enxio, 176 .rspo_hyp_execnotify = (void *)enxio, 177 }; 178 179 int 180 rump_daemonize_begin(void) 181 { 182 183 if (rump_inited) 184 return EALREADY; 185 186 return rumpuser_daemonize_begin(); 187 } 188 189 int 190 rump_daemonize_done(int error) 191 { 192 193 return rumpuser_daemonize_done(error); 194 } 195 196 #ifdef RUMP_USE_CTOR 197 198 /* sysctl bootstrap handling */ 199 struct sysctl_boot_chain sysctl_boot_chain \ 200 = LIST_HEAD_INITIALIZER(sysctl_boot_chain); 201 __link_set_add_text(sysctl_funcs,voidop); /* ensure linkset is non-empty */ 202 203 #else /* RUMP_USE_CTOR */ 204 205 RUMP_COMPONENT(RUMP_COMPONENT_POSTINIT) 206 { 207 __link_set_decl(rump_components, struct rump_component); 208 209 /* 210 * Trick compiler into generating references so that statically 211 * linked rump kernels are generated with the link set symbols. 212 */ 213 asm("" :: "r"(__start_link_set_rump_components)); 214 asm("" :: "r"(__stop_link_set_rump_components)); 215 } 216 217 #endif /* RUMP_USE_CTOR */ 218 219 int 220 rump_init_callback(void (*cpuinit_callback) (void)) 221 { 222 char buf[256]; 223 struct timespec bts; 224 int64_t sec; 225 long nsec; 226 struct lwp *l, *initlwp; 227 int i, numcpu; 228 229 /* not reentrant */ 230 if (rump_inited) 231 return 0; 232 else if (rump_inited == -1) 233 panic("%s: host process restart required", __func__); 234 else 235 rump_inited = 1; 236 237 /* initialize hypervisor */ 238 if (rumpuser_init(RUMPUSER_VERSION, &hyp) != 0) { 239 rumpuser_dprintf("rumpuser init failed\n"); 240 return EINVAL; 241 } 242 243 /* init minimal lwp/cpu context */ 244 rump_lwproc_init(); 245 l = &lwp0; 246 l->l_cpu = l->l_target_cpu = &rump_bootcpu; 247 rump_lwproc_curlwp_set(l); 248 249 /* retrieve env vars which affect the early stage of bootstrap */ 250 if (rumpuser_getparam("RUMP_THREADS", buf, sizeof(buf)) == 0) { 251 rump_threads = *buf != '0'; 252 } 253 if (rumpuser_getparam("RUMP_VERBOSE", buf, sizeof(buf)) == 0) { 254 if (*buf != '0') 255 boothowto = AB_VERBOSE; 256 } 257 258 if (rumpuser_getparam(RUMPUSER_PARAM_NCPU, buf, sizeof(buf)) != 0) 259 panic("%s: mandatory hypervisor configuration (NCPU) missing", 260 __func__); 261 numcpu = strtoll(buf, NULL, 10); 262 if (numcpu < 1) { 263 panic("%s: rump kernels are not lightweight enough for %d CPUs", 264 __func__, numcpu); 265 } 266 267 rump_thread_init(); 268 rump_cpus_bootstrap(&numcpu); 269 270 rumpuser_clock_gettime(RUMPUSER_CLOCK_RELWALL, &sec, &nsec); 271 bts.tv_sec = sec; 272 bts.tv_nsec = nsec; 273 274 initmsgbuf(rump_msgbuf, sizeof(rump_msgbuf)); 275 aprint_verbose("%s%s", copyright, version); 276 277 rump_intr_init(numcpu); 278 279 rump_tsleep_init(); 280 281 rumpuser_mutex_init(&rump_giantlock, RUMPUSER_MTX_SPIN); 282 ksyms_init(); 283 uvm_init(); 284 evcnt_init(); 285 286 kcpuset_sysinit(); 287 once_init(); 288 kernconfig_lock_init(); 289 prop_kern_init(); 290 291 kmem_init(); 292 293 uvm_ra_init(); 294 uao_init(); 295 296 mutex_obj_init(); 297 rw_obj_init(); 298 callout_startup(); 299 300 kprintf_init(); 301 percpu_init(); 302 pserialize_init(); 303 304 kauth_init(); 305 306 secmodel_init(); 307 sysctl_init(); 308 /* 309 * The above call to sysctl_init() only initializes sysctl nodes 310 * from link sets. Initialize sysctls in case we used ctors. 311 */ 312 #ifdef RUMP_USE_CTOR 313 { 314 struct sysctl_setup_chain *ssc; 315 316 while ((ssc = LIST_FIRST(&sysctl_boot_chain)) != NULL) { 317 LIST_REMOVE(ssc, ssc_entries); 318 ssc->ssc_func(NULL); 319 } 320 } 321 #endif /* RUMP_USE_CTOR */ 322 323 rnd_init(); 324 rump_hyperentropy_init(); 325 326 procinit(); 327 proc0_init(); 328 uid_init(); 329 chgproccnt(0, 1); 330 331 l->l_proc = &proc0; 332 lwp_update_creds(l); 333 334 lwpinit_specificdata(); 335 lwp_initspecific(&lwp0); 336 337 /* Must be called after lwpinit_specificdata */ 338 psref_init(); 339 340 threadpools_init(); 341 342 loginit(); 343 344 rump_biglock_init(); 345 346 rump_scheduler_init(numcpu); 347 /* revert temporary context and schedule a semireal context */ 348 rump_lwproc_curlwp_clear(l); 349 initproc = &proc0; /* borrow proc0 before we get initproc started */ 350 rump_schedule(); 351 bootlwp = curlwp; 352 353 inittimecounter(); 354 ntp_init(); 355 356 #ifdef KTRACE 357 ktrinit(); 358 #endif 359 360 tc_setclock(&bts); 361 362 extern krwlock_t exec_lock; 363 rw_init(&exec_lock); 364 365 /* we are mostly go. do per-cpu subsystem init */ 366 for (i = 0; i < numcpu; i++) { 367 struct cpu_info *ci = cpu_lookup(i); 368 369 /* attach non-bootstrap CPUs */ 370 if (i > 0) { 371 rump_cpu_attach(ci); 372 ncpu++; 373 } 374 snprintf(ci->ci_cpuname, sizeof ci->ci_cpuname, "cpu%d", i); 375 376 callout_init_cpu(ci); 377 softint_init(ci); 378 xc_init_cpu(ci); 379 pool_cache_cpu_init(ci); 380 selsysinit(ci); 381 percpu_init_cpu(ci); 382 383 TAILQ_INIT(&ci->ci_data.cpu_ld_locks); 384 __cpu_simple_lock_init(&ci->ci_data.cpu_ld_lock); 385 386 aprint_verbose("cpu%d at thinair0: rump virtual cpu\n", i); 387 } 388 ncpuonline = ncpu; 389 390 /* Once all CPUs are detected, initialize the per-CPU cprng_fast. */ 391 cprng_init(); 392 cprng_fast_init(); 393 394 mp_online = true; 395 396 if (cpuinit_callback) 397 (*cpuinit_callback)(); 398 399 /* CPUs are up. allow kernel threads to run */ 400 rump_thread_allow(NULL); 401 402 rnd_init_softint(); 403 404 kqueue_init(); 405 iostat_init(); 406 fd_sys_init(); 407 module_init(); 408 module_hook_init(); 409 devsw_init(); 410 pipe_init(); 411 resource_init(); 412 procinit_sysctl(); 413 time_init(); 414 config_init(); 415 416 /* start page baroness */ 417 if (rump_threads) { 418 if (kthread_create(PRI_PGDAEMON, KTHREAD_MPSAFE, NULL, 419 uvm_pageout, NULL, &uvm.pagedaemon_lwp, "pdaemon") != 0) 420 panic("%s: pagedaemon create failed", __func__); 421 } else 422 uvm.pagedaemon_lwp = NULL; /* doesn't match curlwp */ 423 424 /* process dso's */ 425 rumpuser_dl_bootstrap(add_linkedin_modules, 426 rump_kernelfsym_load, rump_component_load, add_static_evcnt); 427 428 rump_component_addlocal(); 429 rump_component_init(RUMP_COMPONENT_KERN); 430 431 /* initialize factions, if present */ 432 rump_component_init(RUMP__FACTION_VFS); 433 /* pnbuf_cache is used even without vfs */ 434 if (rump_component_count(RUMP__FACTION_VFS) == 0) { 435 pnbuf_cache = pool_cache_init(MAXPATHLEN, 0, 0, 0, "pnbufpl", 436 NULL, IPL_NONE, NULL, NULL, NULL); 437 } 438 rump_component_init(RUMP__FACTION_NET); 439 rump_component_init(RUMP__FACTION_DEV); 440 KASSERT(rump_component_count(RUMP__FACTION_VFS) <= 1 441 && rump_component_count(RUMP__FACTION_NET) <= 1 442 && rump_component_count(RUMP__FACTION_DEV) <= 1); 443 444 rump_component_init(RUMP_COMPONENT_KERN_VFS); 445 446 /* 447 * if we initialized the tty component above, the tyttymtx is 448 * now initialized. otherwise, we need to initialize it. 449 */ 450 if (!rump_ttycomponent) 451 mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM); 452 453 cold = 0; 454 455 sysctl_finalize(); 456 457 module_init_class(MODULE_CLASS_ANY); 458 459 if (rumpuser_getparam(RUMPUSER_PARAM_HOSTNAME, 460 hostname, MAXHOSTNAMELEN) != 0) { 461 panic( 462 "%s: mandatory hypervisor configuration (HOSTNAME) missing", 463 __func__); 464 } 465 hostnamelen = strlen(hostname); 466 467 sigemptyset(&sigcantmask); 468 469 if (rump_threads) 470 vmem_rehash_start(); 471 472 /* 473 * Create init (proc 1), used to attach implicit threads in rump. 474 * (note: must be done after vfsinit to get cwdi) 475 */ 476 initlwp = rump__lwproc_alloclwp(NULL); 477 mutex_enter(&proc_lock); 478 initproc = proc_find_raw(1); 479 mutex_exit(&proc_lock); 480 if (initproc == NULL) 481 panic("%s: where in the world is initproc?", __func__); 482 strlcpy(initproc->p_comm, "rumplocal", sizeof(initproc->p_comm)); 483 484 rump_component_init(RUMP_COMPONENT_POSTINIT); 485 486 /* load syscalls */ 487 rump_component_init(RUMP_COMPONENT_SYSCALL); 488 489 /* component inits done */ 490 bootlwp = NULL; 491 492 /* open 0/1/2 for init */ 493 KASSERT(rump_lwproc_curlwp() == NULL); 494 rump_lwproc_switch(initlwp); 495 rump_consdev_init(); 496 rump_lwproc_switch(NULL); 497 498 /* release cpu */ 499 rump_unschedule(); 500 501 return 0; 502 } 503 504 int 505 rump_init(void) 506 { 507 return rump_init_callback(NULL); 508 } 509 510 /* historic compat */ 511 __strong_alias(rump__init,rump_init); 512 513 static int compcounter[RUMP_COMPONENT_MAX]; 514 static int compinited[RUMP_COMPONENT_MAX]; 515 516 /* 517 * Yea, this is O(n^2), but we're only looking at a handful of components. 518 * Components are always initialized from the thread that called rump_init(). 519 */ 520 static LIST_HEAD(, rump_component) rchead = LIST_HEAD_INITIALIZER(rchead); 521 522 #ifdef RUMP_USE_CTOR 523 struct modinfo_boot_chain modinfo_boot_chain \ 524 = LIST_HEAD_INITIALIZER(modinfo_boot_chain); 525 526 static void 527 rump_component_addlocal(void) 528 { 529 struct modinfo_chain *mc; 530 531 while ((mc = LIST_FIRST(&modinfo_boot_chain)) != NULL) { 532 LIST_REMOVE(mc, mc_entries); 533 module_builtin_add(&mc->mc_info, 1, false); 534 } 535 } 536 537 #else /* RUMP_USE_CTOR */ 538 539 static void 540 rump_component_addlocal(void) 541 { 542 __link_set_decl(rump_components, struct rump_component); 543 struct rump_component *const *rc; 544 545 __link_set_foreach(rc, rump_components) { 546 rump_component_load(*rc); 547 } 548 } 549 #endif /* RUMP_USE_CTOR */ 550 551 void 552 rump_component_load(const struct rump_component *rc_const) 553 { 554 struct rump_component *rc, *rc_iter; 555 556 /* time for rump component loading and unloading has passed */ 557 if (!cold) 558 return; 559 560 /* 561 * XXX: this is ok since the "const" was removed from the 562 * definition of RUMP_COMPONENT(). 563 * 564 * However, to preserve the hypercall interface, the const 565 * remains here. This can be fixed in the next hypercall revision. 566 */ 567 rc = __UNCONST(rc_const); 568 569 KASSERT(!rump_inited || curlwp == bootlwp); 570 571 LIST_FOREACH(rc_iter, &rchead, rc_entries) { 572 if (rc_iter == rc) 573 return; 574 } 575 576 LIST_INSERT_HEAD(&rchead, rc, rc_entries); 577 KASSERT(rc->rc_type < RUMP_COMPONENT_MAX); 578 compcounter[rc->rc_type]++; 579 } 580 581 void 582 rump_component_unload(struct rump_component *rc) 583 { 584 585 /* 586 * Checking for cold is enough because rump_init() both 587 * flips it and handles component loading. 588 */ 589 if (!cold) 590 return; 591 592 LIST_REMOVE(rc, rc_entries); 593 } 594 595 int 596 rump_component_count(enum rump_component_type type) 597 { 598 599 KASSERT(curlwp == bootlwp); 600 KASSERT(type < RUMP_COMPONENT_MAX); 601 return compcounter[type]; 602 } 603 604 void 605 rump_component_init(enum rump_component_type type) 606 { 607 struct rump_component *rc, *rc_next, rc_marker; 608 609 KASSERT(curlwp == bootlwp); 610 KASSERT(!compinited[type]); 611 612 rc_marker.rc_type = RUMP_COMPONENT_MAX; 613 rc_marker.rc_init = NULL; 614 for (rc = LIST_FIRST(&rchead); rc != NULL; rc = rc_next) { 615 if (rc->rc_type == type) { 616 LIST_INSERT_AFTER(rc, &rc_marker, rc_entries); 617 rc->rc_init(); 618 LIST_REMOVE(rc, rc_entries); 619 rc_next = LIST_NEXT(&rc_marker, rc_entries); 620 LIST_REMOVE(&rc_marker, rc_entries); 621 } else { 622 rc_next = LIST_NEXT(rc, rc_entries); 623 } 624 } 625 compinited[type] = 1; 626 } 627 628 /* 629 * Initialize a module which has already been loaded and linked 630 * with dlopen(). This is fundamentally the same as a builtin module. 631 * 632 * XXX: this interface does not really work in the RUMP_USE_CTOR case, 633 * but I'm not sure it's anything to cry about. In feeling blue, 634 * things could somehow be handled via modinfo_boot_chain. 635 */ 636 int 637 rump_module_init(const struct modinfo * const *mip, size_t nmodinfo) 638 { 639 640 return module_builtin_add(mip, nmodinfo, true); 641 } 642 643 /* 644 * Finish module (flawless victory, fatality!). 645 */ 646 int 647 rump_module_fini(const struct modinfo *mi) 648 { 649 650 return module_builtin_remove(mi, true); 651 } 652 653 /* 654 * Add loaded and linked module to the builtin list. It will 655 * later be initialized with module_init_class(). 656 */ 657 658 static void 659 add_linkedin_modules(const struct modinfo * const *mip, size_t nmodinfo) 660 { 661 662 module_builtin_add(mip, nmodinfo, false); 663 } 664 665 /* 666 * Add an evcnt. 667 */ 668 static void 669 add_static_evcnt(struct evcnt *ev) 670 { 671 672 evcnt_attach_static(ev); 673 } 674 675 int 676 rump_kernelfsym_load(void *symtab, uint64_t symsize, 677 char *strtab, uint64_t strsize) 678 { 679 static int inited = 0; 680 Elf64_Ehdr ehdr; 681 682 if (inited) 683 return EBUSY; 684 inited = 1; 685 686 /* 687 * Use 64bit header since it's bigger. Shouldn't make a 688 * difference, since we're passing in all zeroes anyway. 689 */ 690 memset(&ehdr, 0, sizeof(ehdr)); 691 ksyms_addsyms_explicit(&ehdr, symtab, symsize, strtab, strsize); 692 693 return 0; 694 } 695 696 int 697 rump_boot_gethowto() 698 { 699 700 return boothowto; 701 } 702 703 void 704 rump_boot_sethowto(int howto) 705 { 706 707 boothowto = howto; 708 } 709 710 int 711 rump_getversion(void) 712 { 713 714 return __NetBSD_Version__; 715 } 716 /* compat */ 717 __strong_alias(rump_pub_getversion,rump_getversion); 718 719 /* 720 * Note: may be called unscheduled. Not fully safe since no locking 721 * of allevents (currently that's not even available). 722 */ 723 void 724 rump_printevcnts() 725 { 726 struct evcnt *ev; 727 728 TAILQ_FOREACH(ev, &allevents, ev_list) 729 rumpuser_dprintf("%s / %s: %" PRIu64 "\n", 730 ev->ev_group, ev->ev_name, ev->ev_count); 731 } 732 733 /* 734 * If you use this interface ... well ... all bets are off. 735 * The original purpose is for the p2k fs server library to be 736 * able to use the same pid/lid for VOPs as the host kernel. 737 */ 738 void 739 rump_allbetsareoff_setid(pid_t pid, int lid) 740 { 741 struct lwp *l = curlwp; 742 struct proc *p = l->l_proc; 743 744 l->l_lid = lid; 745 p->p_pid = pid; 746 } 747 748 static void 749 ipiemu(void *a1, void *a2) 750 { 751 752 xc__highpri_intr(NULL); 753 } 754 755 void 756 rump_xc_highpri(struct cpu_info *ci) 757 { 758 759 if (ci) 760 xc_unicast(0, ipiemu, NULL, NULL, ci); 761 else 762 xc_broadcast(0, ipiemu, NULL, NULL); 763 } 764 765 int 766 rump_syscall(int num, void *data, size_t dlen, register_t *retval) 767 { 768 struct proc *p; 769 struct emul *e; 770 struct sysent *callp; 771 const int *etrans = NULL; 772 int rv; 773 774 rump_schedule(); 775 p = curproc; 776 e = p->p_emul; 777 #ifndef __HAVE_MINIMAL_EMUL 778 num &= e->e_nsysent - 1; 779 #else 780 num &= SYS_NSYSENT - 1; 781 #endif 782 callp = e->e_sysent + num; 783 784 rv = sy_invoke(callp, curlwp, data, retval, num); 785 786 /* 787 * I hope that (!__HAVE_MINIMAL_EMUL || __HAVE_SYSCALL_INTERN) is 788 * an invariant ... 789 */ 790 #if !defined(__HAVE_MINIMAL_EMUL) 791 etrans = e->e_errno; 792 #elif defined(__HAVE_SYSCALL_INTERN) 793 etrans = p->p_emuldata; 794 #endif 795 796 if (etrans) { 797 rv = etrans[rv]; 798 /* 799 * XXX: small hack since Linux etrans vectors on some 800 * archs contain negative errnos, but rump_syscalls 801 * uses the -1 + errno ABI. Note that these 802 * negative values are always the result of translation, 803 * otherwise the above translation method would not 804 * work very well. 805 */ 806 if (rv < 0) 807 rv = -rv; 808 } 809 rump_unschedule(); 810 811 return rv; 812 } 813 814 void 815 rump_syscall_boot_establish(const struct rump_onesyscall *calls, size_t ncall) 816 { 817 struct sysent *callp; 818 size_t i; 819 820 for (i = 0; i < ncall; i++) { 821 callp = rump_sysent + calls[i].ros_num; 822 KASSERT(bootlwp != NULL 823 && callp->sy_call == (sy_call_t *)(void *)enosys); 824 callp->sy_call = calls[i].ros_handler; 825 } 826 } 827 828 struct rump_boot_etfs *ebstart; 829 void 830 rump_boot_etfs_register(struct rump_boot_etfs *eb) 831 { 832 833 /* 834 * Could use atomics, but, since caller would need to synchronize 835 * against calling rump_init() anyway, easier to just specify the 836 * interface as "caller serializes". This solve-by-specification 837 * approach avoids the grey area of using atomics before rump_init() 838 * runs. 839 */ 840 eb->_eb_next = ebstart; 841 eb->eb_status = -1; 842 ebstart = eb; 843 } 844