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