2010-06-09 18:08:17 +04:00
|
|
|
/* $NetBSD: rump.c,v 1.177 2010/06/09 14:08:17 pooka Exp $ */
|
2007-08-06 02:28:00 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Development of this software was supported by Google Summer of Code.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2008-12-18 03:24:12 +03:00
|
|
|
#include <sys/cdefs.h>
|
2010-06-09 18:08:17 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.177 2010/06/09 14:08:17 pooka Exp $");
|
2010-04-28 03:30:29 +04:00
|
|
|
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#define ELFSIZE ARCH_ELFSIZE
|
2008-12-18 03:24:12 +03:00
|
|
|
|
2007-08-06 02:28:00 +04:00
|
|
|
#include <sys/param.h>
|
2008-10-10 17:14:41 +04:00
|
|
|
#include <sys/atomic.h>
|
2008-11-19 17:10:48 +03:00
|
|
|
#include <sys/buf.h>
|
2008-10-12 22:52:56 +04:00
|
|
|
#include <sys/callout.h>
|
2008-12-29 20:45:55 +03:00
|
|
|
#include <sys/conf.h>
|
2008-01-02 21:15:12 +03:00
|
|
|
#include <sys/cpu.h>
|
2009-12-03 15:35:34 +03:00
|
|
|
#include <sys/device.h>
|
2009-03-29 22:22:08 +04:00
|
|
|
#include <sys/evcnt.h>
|
2009-03-18 21:00:38 +03:00
|
|
|
#include <sys/event.h>
|
2009-11-26 12:20:07 +03:00
|
|
|
#include <sys/exec_elf.h>
|
2007-08-06 02:28:00 +04:00
|
|
|
#include <sys/filedesc.h>
|
2008-10-16 00:15:37 +04:00
|
|
|
#include <sys/iostat.h>
|
2007-08-06 02:28:00 +04:00
|
|
|
#include <sys/kauth.h>
|
2009-01-01 22:07:43 +03:00
|
|
|
#include <sys/kernel.h>
|
2007-10-31 18:57:19 +03:00
|
|
|
#include <sys/kmem.h>
|
2009-01-02 05:54:13 +03:00
|
|
|
#include <sys/kprintf.h>
|
2010-06-03 14:56:20 +04:00
|
|
|
#include <sys/kthread.h>
|
2009-01-08 00:11:19 +03:00
|
|
|
#include <sys/ksyms.h>
|
2009-01-02 05:54:13 +03:00
|
|
|
#include <sys/msgbuf.h>
|
2008-07-31 09:38:04 +04:00
|
|
|
#include <sys/module.h>
|
2008-10-15 17:04:26 +04:00
|
|
|
#include <sys/once.h>
|
2008-10-11 00:24:10 +04:00
|
|
|
#include <sys/percpu.h>
|
2009-11-26 20:36:22 +03:00
|
|
|
#include <sys/pipe.h>
|
2010-04-21 20:16:31 +04:00
|
|
|
#include <sys/pool.h>
|
2007-08-06 02:28:00 +04:00
|
|
|
#include <sys/queue.h>
|
2009-10-09 18:41:36 +04:00
|
|
|
#include <sys/reboot.h>
|
2007-08-06 02:28:00 +04:00
|
|
|
#include <sys/resourcevar.h>
|
2008-01-02 21:15:12 +03:00
|
|
|
#include <sys/select.h>
|
2008-08-01 23:34:51 +04:00
|
|
|
#include <sys/sysctl.h>
|
2009-02-20 21:08:12 +03:00
|
|
|
#include <sys/syscall.h>
|
2010-04-28 18:51:07 +04:00
|
|
|
#include <sys/syscallvar.h>
|
2010-04-14 14:27:53 +04:00
|
|
|
#include <sys/timetc.h>
|
2009-01-13 04:57:35 +03:00
|
|
|
#include <sys/tty.h>
|
|
|
|
#include <sys/uidinfo.h>
|
2009-01-23 16:14:16 +03:00
|
|
|
#include <sys/vmem.h>
|
2009-12-01 12:50:51 +03:00
|
|
|
#include <sys/xcall.h>
|
2007-08-06 02:28:00 +04:00
|
|
|
|
2008-07-29 17:17:40 +04:00
|
|
|
#include <rump/rumpuser.h>
|
|
|
|
|
First part of secmodel cleanup and other misc. changes:
- Separate the suser part of the bsd44 secmodel into its own secmodel
and directory, pending even more cleanups. For revision history
purposes, the original location of the files was
src/sys/secmodel/bsd44/secmodel_bsd44_suser.c
src/sys/secmodel/bsd44/suser.h
- Add a man-page for secmodel_suser(9) and update the one for
secmodel_bsd44(9).
- Add a "secmodel" module class and use it. Userland program and
documentation updated.
- Manage secmodel count (nsecmodels) through the module framework.
This eliminates the need for secmodel_{,de}register() calls in
secmodel code.
- Prepare for secmodel modularization by adding relevant module bits.
The secmodels don't allow auto unload. The bsd44 secmodel depends
on the suser and securelevel secmodels. The overlay secmodel depends
on the bsd44 secmodel. As the module class is only cosmetic, and to
prevent ambiguity, the bsd44 and overlay secmodels are prefixed with
"secmodel_".
- Adapt the overlay secmodel to recent changes (mainly vnode scope).
- Stop using link-sets for the sysctl node(s) creation.
- Keep sysctl variables under nodes of their relevant secmodels. In
other words, don't create duplicates for the suser/securelevel
secmodels under the bsd44 secmodel, as the latter is merely used
for "grouping".
- For the suser and securelevel secmodels, "advertise presence" in
relevant sysctl nodes (sysctl.security.models.{suser,securelevel}).
- Get rid of the LKM preprocessor stuff.
- As secmodels are now modules, there's no need for an explicit call
to secmodel_start(); it's handled by the module framework. That
said, the module framework was adjusted to properly load secmodels
early during system startup.
- Adapt rump to changes: Instead of using empty stubs for securelevel,
simply use the suser secmodel. Also replace secmodel_start() with a
call to secmodel_suser_start().
- 5.99.20.
Testing was done on i386 ("release" build). Spearated module_init()
changes were tested on sparc and sparc64 as well by martin@ (thanks!).
Mailing list reference:
http://mail-index.netbsd.org/tech-kern/2009/09/25/msg006135.html
2009-10-02 22:50:12 +04:00
|
|
|
#include <secmodel/suser/suser.h>
|
2009-04-16 18:07:17 +04:00
|
|
|
|
2009-09-13 23:09:13 +04:00
|
|
|
#include <prop/proplib.h>
|
|
|
|
|
2010-06-02 14:55:18 +04:00
|
|
|
#include <uvm/uvm_extern.h>
|
2009-11-10 20:02:36 +03:00
|
|
|
#include <uvm/uvm_readahead.h>
|
|
|
|
|
2007-08-20 19:58:13 +04:00
|
|
|
#include "rump_private.h"
|
2008-10-15 17:04:26 +04:00
|
|
|
#include "rump_net_private.h"
|
2008-11-19 17:10:48 +03:00
|
|
|
#include "rump_vfs_private.h"
|
2009-09-07 00:54:19 +04:00
|
|
|
#include "rump_dev_private.h"
|
2007-08-06 02:28:00 +04:00
|
|
|
|
2008-03-22 00:54:58 +03:00
|
|
|
struct proc proc0;
|
2009-01-02 05:54:13 +03:00
|
|
|
struct session rump_session = {
|
|
|
|
.s_count = 1,
|
|
|
|
.s_flags = 0,
|
|
|
|
.s_leader = &proc0,
|
|
|
|
.s_login = "rumphobo",
|
|
|
|
.s_sid = 0,
|
|
|
|
};
|
|
|
|
struct pgrp rump_pgrp = {
|
|
|
|
.pg_members = LIST_HEAD_INITIALIZER(pg_members),
|
|
|
|
.pg_session = &rump_session,
|
|
|
|
.pg_jobc = 1,
|
|
|
|
};
|
2007-08-06 02:28:00 +04:00
|
|
|
struct pstats rump_stats;
|
|
|
|
struct plimit rump_limits;
|
2008-03-22 00:54:58 +03:00
|
|
|
struct filedesc rump_filedesc0;
|
2008-03-11 13:50:16 +03:00
|
|
|
struct proclist allproc;
|
2010-04-27 00:10:23 +04:00
|
|
|
char machine[] = MACHINE;
|
2008-09-30 23:25:56 +04:00
|
|
|
static kauth_cred_t rump_susercred;
|
2007-08-06 02:28:00 +04:00
|
|
|
|
2009-04-16 18:07:17 +04:00
|
|
|
/* pretend the master rump proc is init */
|
|
|
|
struct proc *initproc = &proc0;
|
|
|
|
|
2008-12-13 18:37:13 +03:00
|
|
|
struct rumpuser_mtx *rump_giantlock;
|
2007-11-07 19:24:22 +03:00
|
|
|
|
2009-12-03 15:35:34 +03:00
|
|
|
struct device rump_rootdev = {
|
|
|
|
.dv_class = DV_VIRTUAL
|
|
|
|
};
|
|
|
|
|
2008-08-12 14:04:57 +04:00
|
|
|
#ifdef RUMP_WITHOUT_THREADS
|
|
|
|
int rump_threads = 0;
|
|
|
|
#else
|
|
|
|
int rump_threads = 1;
|
|
|
|
#endif
|
|
|
|
|
2010-03-31 15:35:33 +04:00
|
|
|
static char rump_msgbuf[16*1024]; /* 16k should be enough for std rump needs */
|
|
|
|
|
2007-10-31 18:57:19 +03:00
|
|
|
static void
|
|
|
|
rump_aiodone_worker(struct work *wk, void *dummy)
|
|
|
|
{
|
|
|
|
struct buf *bp = (struct buf *)wk;
|
|
|
|
|
|
|
|
KASSERT(&bp->b_work == wk);
|
|
|
|
bp->b_iodone(bp);
|
|
|
|
}
|
|
|
|
|
2008-08-01 23:34:51 +04:00
|
|
|
static int rump_inited;
|
2008-01-02 21:15:12 +03:00
|
|
|
|
2010-04-21 20:16:31 +04:00
|
|
|
/*
|
|
|
|
* Make sure pnbuf_cache is available even without vfs
|
|
|
|
*/
|
|
|
|
struct pool_cache *pnbuf_cache;
|
|
|
|
int rump_initpnbufpool(void);
|
|
|
|
int rump_initpnbufpool(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
pnbuf_cache = pool_cache_init(MAXPATHLEN, 0, 0, 0, "pnbufpl",
|
|
|
|
NULL, IPL_NONE, NULL, NULL, NULL);
|
|
|
|
return EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
2009-10-16 04:14:53 +04:00
|
|
|
int rump__unavailable(void);
|
|
|
|
int rump__unavailable() {return EOPNOTSUPP;}
|
2009-01-11 19:19:35 +03:00
|
|
|
__weak_alias(rump_net_init,rump__unavailable);
|
2010-04-21 20:16:31 +04:00
|
|
|
__weak_alias(rump_vfs_init,rump_initpnbufpool);
|
2009-09-07 00:54:19 +04:00
|
|
|
__weak_alias(rump_dev_init,rump__unavailable);
|
2008-11-19 17:10:48 +03:00
|
|
|
|
2009-10-09 18:41:36 +04:00
|
|
|
__weak_alias(rump_vfs_fini,rump__unavailable);
|
|
|
|
|
2009-09-09 00:10:44 +04:00
|
|
|
__weak_alias(biodone,rump__unavailable);
|
2009-10-16 04:14:53 +04:00
|
|
|
__weak_alias(sopoll,rump__unavailable);
|
2009-09-09 00:10:44 +04:00
|
|
|
|
2009-02-06 22:49:13 +03:00
|
|
|
void rump__unavailable_vfs_panic(void);
|
|
|
|
void rump__unavailable_vfs_panic() {panic("vfs component not available");}
|
2009-11-03 23:25:31 +03:00
|
|
|
__weak_alias(usermount_common_policy,rump__unavailable_vfs_panic);
|
2009-02-06 22:49:13 +03:00
|
|
|
|
2009-12-09 03:11:21 +03:00
|
|
|
rump_proc_vfs_init_fn rump_proc_vfs_init;
|
|
|
|
rump_proc_vfs_release_fn rump_proc_vfs_release;
|
2008-10-15 17:04:26 +04:00
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
static void add_linkedin_modules(const struct modinfo *const *, size_t);
|
|
|
|
|
2010-01-15 23:39:46 +03:00
|
|
|
static void __noinline
|
2009-04-30 20:59:32 +04:00
|
|
|
messthestack(void)
|
|
|
|
{
|
2010-01-15 23:39:46 +03:00
|
|
|
volatile uint32_t mess[64];
|
2009-04-30 20:59:32 +04:00
|
|
|
uint64_t d1, d2;
|
|
|
|
int i, error;
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++) {
|
|
|
|
rumpuser_gettime(&d1, &d2, &error);
|
|
|
|
mess[i] = d2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-31 22:56:07 +04:00
|
|
|
/*
|
|
|
|
* Create kern.hostname. why only this you ask. well, init_sysctl
|
|
|
|
* is a kitchen sink in need of some gardening. but i want to use
|
|
|
|
* kern.hostname today.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mksysctls(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
sysctl_createv(NULL, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL,
|
|
|
|
NULL, 0, NULL, 0, CTL_KERN, CTL_EOL);
|
|
|
|
|
|
|
|
/* XXX: setting hostnamelen is missing */
|
|
|
|
sysctl_createv(NULL, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRING, "hostname",
|
|
|
|
SYSCTL_DESCR("System hostname"), NULL, 0,
|
|
|
|
&hostname, MAXHOSTNAMELEN, CTL_KERN, KERN_HOSTNAME, CTL_EOL);
|
|
|
|
}
|
|
|
|
|
2008-10-08 03:16:59 +04:00
|
|
|
int
|
2009-01-08 00:12:30 +03:00
|
|
|
rump__init(int rump_version)
|
2007-08-06 02:28:00 +04:00
|
|
|
{
|
2008-03-11 13:50:16 +03:00
|
|
|
char buf[256];
|
2010-04-14 14:27:53 +04:00
|
|
|
struct timespec ts;
|
2010-03-31 16:16:15 +04:00
|
|
|
uint64_t sec, nsec;
|
2007-10-31 18:57:19 +03:00
|
|
|
struct proc *p;
|
|
|
|
struct lwp *l;
|
2010-04-28 04:43:16 +04:00
|
|
|
int i, numcpu;
|
2007-08-06 02:28:00 +04:00
|
|
|
int error;
|
|
|
|
|
2009-10-09 18:41:36 +04:00
|
|
|
/* not reentrant */
|
2008-01-02 21:15:12 +03:00
|
|
|
if (rump_inited)
|
2008-10-08 03:16:59 +04:00
|
|
|
return 0;
|
2009-10-09 18:41:36 +04:00
|
|
|
else if (rump_inited == -1)
|
|
|
|
panic("rump_init: host process restart required");
|
|
|
|
else
|
|
|
|
rump_inited = 1;
|
2008-01-02 21:15:12 +03:00
|
|
|
|
2010-06-09 18:08:17 +04:00
|
|
|
if (rumpuser_getversion() != RUMPUSER_VERSION) {
|
|
|
|
/* let's hope the ABI of rumpuser_dprintf is the same ;) */
|
|
|
|
rumpuser_dprintf("rumpuser version mismatch: %d vs. %d\n",
|
|
|
|
rumpuser_getversion(), RUMPUSER_VERSION);
|
|
|
|
return EPROGMISMATCH;
|
|
|
|
}
|
|
|
|
|
2010-01-13 03:07:40 +03:00
|
|
|
if (rumpuser_getenv("RUMP_VERBOSE", buf, sizeof(buf), &error) == 0) {
|
|
|
|
if (*buf != '0')
|
|
|
|
boothowto = AB_VERBOSE;
|
|
|
|
}
|
|
|
|
|
2010-04-28 15:34:18 +04:00
|
|
|
if (rumpuser_getenv("RUMP_NCPU", buf, sizeof(buf), &error) == 0)
|
|
|
|
error = 0;
|
2010-04-28 04:43:16 +04:00
|
|
|
/* non-x86 is missing CPU_INFO_FOREACH() support */
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
2010-04-28 15:34:18 +04:00
|
|
|
if (error == 0) {
|
|
|
|
numcpu = strtoll(buf, NULL, 10);
|
|
|
|
if (numcpu < 1)
|
|
|
|
numcpu = 1;
|
|
|
|
} else {
|
|
|
|
numcpu = rumpuser_getnhostcpu();
|
|
|
|
}
|
2010-04-28 04:43:16 +04:00
|
|
|
#else
|
2010-04-28 15:34:18 +04:00
|
|
|
if (error == 0)
|
|
|
|
printf("NCPU limited to 1 on this host\n");
|
2010-04-28 04:43:16 +04:00
|
|
|
numcpu = 1;
|
|
|
|
#endif
|
|
|
|
rump_cpus_bootstrap(numcpu);
|
2010-04-28 03:30:29 +04:00
|
|
|
|
2010-03-31 16:16:15 +04:00
|
|
|
rumpuser_gettime(&sec, &nsec, &error);
|
|
|
|
boottime.tv_sec = sec;
|
|
|
|
boottime.tv_nsec = nsec;
|
|
|
|
|
2010-03-31 15:35:33 +04:00
|
|
|
initmsgbuf(rump_msgbuf, sizeof(rump_msgbuf));
|
|
|
|
aprint_verbose("%s%s", copyright, version);
|
2009-12-16 23:59:04 +03:00
|
|
|
|
2009-04-30 20:59:32 +04:00
|
|
|
/*
|
|
|
|
* Seed arc4random() with a "reasonable" amount of randomness.
|
|
|
|
* Yes, this is a quick kludge which depends on the arc4random
|
|
|
|
* implementation.
|
|
|
|
*/
|
|
|
|
messthestack();
|
|
|
|
arc4random();
|
|
|
|
|
2008-10-08 03:16:59 +04:00
|
|
|
if (rump_version != RUMP_VERSION) {
|
|
|
|
printf("rump version mismatch, %d vs. %d\n",
|
|
|
|
rump_version, RUMP_VERSION);
|
|
|
|
return EPROGMISMATCH;
|
|
|
|
}
|
|
|
|
|
2008-08-12 14:04:57 +04:00
|
|
|
if (rumpuser_getenv("RUMP_THREADS", buf, sizeof(buf), &error) == 0) {
|
|
|
|
rump_threads = *buf != '0';
|
|
|
|
}
|
2009-10-15 04:28:46 +04:00
|
|
|
rumpuser_thrinit(rump_user_schedule, rump_user_unschedule,
|
|
|
|
rump_threads);
|
2009-12-01 12:50:51 +03:00
|
|
|
rump_intr_init();
|
2010-06-01 03:18:33 +04:00
|
|
|
rump_tsleep_init();
|
2008-03-11 13:50:16 +03:00
|
|
|
|
2009-11-03 23:22:33 +03:00
|
|
|
/* init minimal lwp/cpu context */
|
|
|
|
l = &lwp0;
|
|
|
|
l->l_lid = 1;
|
Improve the CPU scheduler for a host MP system with multithreaded
access. The old scheduler had a global freelist which caused a
cache crisis with multiple host threads trying to schedule a virtual
CPU simultaneously.
The rump scheduler is different from a normal thread scheduler, so
it has different requirements. First, we schedule a CPU for a
thread (which we get from the host scheduler) instead of scheduling
a thread onto a CPU. Second, scheduling points are at every
entry/exit to/from the rump kernel, including (but not limited to)
syscall entry points and hypercalls. This means scheduling happens
a lot more frequently than in a normal kernel.
For every lwp, cache the previously used CPU. When scheduling,
attempt to reuse the same CPU. If we get it, we can use it directly
without any memory barriers or expensive locks. If the CPU is
taken, migrate. Use a lock/wait only in the slowpath. Be very
wary of walking the entire CPU array because that does not lead to
a happy cacher.
The migration algorithm could probably benefit from improved
heuristics and tuning. Even as such, with the new scheduler an
application which has two threads making rlimit syscalls in a tight
loop experiences almost 400% speedup. The exact speedup is difficult
to pinpoint, though, since the old scheduler caused very jittery
results due to cache contention. Also, the rump version is now
70% faster than the counterpart which calls the host kernel.
2010-05-28 20:44:14 +04:00
|
|
|
l->l_cpu = l->l_target_cpu = rump_cpu;
|
2009-11-03 23:22:33 +03:00
|
|
|
rumpuser_set_curlwp(l);
|
|
|
|
|
2009-01-13 04:57:35 +03:00
|
|
|
mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_NONE);
|
2008-12-13 18:37:13 +03:00
|
|
|
rumpuser_mutex_recursive_init(&rump_giantlock);
|
2009-01-08 00:11:19 +03:00
|
|
|
ksyms_init();
|
2010-06-02 14:55:18 +04:00
|
|
|
uvm_init();
|
2009-03-29 22:22:08 +04:00
|
|
|
evcnt_init();
|
2009-01-23 16:14:16 +03:00
|
|
|
|
|
|
|
once_init();
|
2009-09-13 23:09:13 +04:00
|
|
|
prop_kern_init();
|
2009-01-23 16:14:16 +03:00
|
|
|
|
2009-01-26 17:35:50 +03:00
|
|
|
pool_subsystem_init();
|
2008-08-04 19:02:16 +04:00
|
|
|
kmem_init();
|
2009-04-24 17:27:03 +04:00
|
|
|
|
2009-11-10 20:02:36 +03:00
|
|
|
uvm_ra_init();
|
|
|
|
|
2009-11-04 16:32:39 +03:00
|
|
|
mutex_obj_init();
|
2009-12-01 12:50:51 +03:00
|
|
|
callout_startup();
|
2009-11-04 16:32:39 +03:00
|
|
|
|
2009-01-02 05:54:13 +03:00
|
|
|
kprintf_init();
|
|
|
|
loginit();
|
2008-08-04 19:02:16 +04:00
|
|
|
|
2008-09-30 23:25:56 +04:00
|
|
|
kauth_init();
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_susercred = rump_cred_create(0, 0, 0, NULL);
|
2008-09-30 23:25:56 +04:00
|
|
|
|
2009-11-03 23:22:33 +03:00
|
|
|
/* init proc0 and rest of lwp0 now that we can allocate memory */
|
2008-03-22 00:54:58 +03:00
|
|
|
p = &proc0;
|
2007-10-31 18:57:19 +03:00
|
|
|
p->p_stats = &rump_stats;
|
|
|
|
p->p_limit = &rump_limits;
|
2009-01-02 05:54:13 +03:00
|
|
|
p->p_pgrp = &rump_pgrp;
|
2007-10-31 18:57:19 +03:00
|
|
|
p->p_pid = 0;
|
2008-03-22 00:54:58 +03:00
|
|
|
p->p_fd = &rump_filedesc0;
|
2008-01-02 21:15:12 +03:00
|
|
|
p->p_vmspace = &rump_vmspace;
|
2010-04-17 20:34:29 +04:00
|
|
|
p->p_emul = &emul_netbsd;
|
2009-02-12 17:46:58 +03:00
|
|
|
p->p_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
|
2009-10-14 22:18:53 +04:00
|
|
|
l->l_cred = rump_cred_suserget();
|
2007-10-31 18:57:19 +03:00
|
|
|
l->l_proc = p;
|
2009-03-19 12:14:37 +03:00
|
|
|
LIST_INIT(&allproc);
|
2009-04-29 19:49:28 +04:00
|
|
|
LIST_INSERT_HEAD(&allproc, &proc0, p_list);
|
2009-01-26 17:41:28 +03:00
|
|
|
proc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
|
2010-06-09 17:51:02 +04:00
|
|
|
|
2010-04-13 02:17:23 +04:00
|
|
|
lwpinit_specificdata();
|
2010-06-09 17:51:02 +04:00
|
|
|
lwp_initspecific(&lwp0);
|
2008-03-11 13:50:16 +03:00
|
|
|
|
2010-04-21 20:16:31 +04:00
|
|
|
mutex_init(&rump_limits.pl_lock, MUTEX_DEFAULT, IPL_NONE);
|
2007-08-06 02:28:00 +04:00
|
|
|
rump_limits.pl_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
|
2008-01-02 21:15:12 +03:00
|
|
|
rump_limits.pl_rlimit[RLIMIT_NOFILE].rlim_cur = RLIM_INFINITY;
|
2008-10-13 23:41:13 +04:00
|
|
|
rump_limits.pl_rlimit[RLIMIT_SBSIZE].rlim_cur = RLIM_INFINITY;
|
2010-04-21 20:16:31 +04:00
|
|
|
rump_limits.pl_corename = defcorename;
|
2007-08-06 02:28:00 +04:00
|
|
|
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_scheduler_init();
|
2009-11-03 23:22:33 +03:00
|
|
|
/* revert temporary context and schedule a real context */
|
|
|
|
l->l_cpu = NULL;
|
|
|
|
rumpuser_set_curlwp(NULL);
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_schedule();
|
|
|
|
|
2010-01-15 22:01:04 +03:00
|
|
|
percpu_init();
|
2010-04-14 14:27:53 +04:00
|
|
|
inittimecounter();
|
|
|
|
ntp_init();
|
|
|
|
|
|
|
|
rumpuser_gettime(&sec, &nsec, &error);
|
|
|
|
ts.tv_sec = sec;
|
|
|
|
ts.tv_nsec = nsec;
|
|
|
|
tc_setclock(&ts);
|
2010-01-15 22:01:04 +03:00
|
|
|
|
2009-12-01 12:50:51 +03:00
|
|
|
/* we are mostly go. do per-cpu subsystem init */
|
|
|
|
for (i = 0; i < ncpu; i++) {
|
|
|
|
struct cpu_info *ci = cpu_lookup(i);
|
|
|
|
|
|
|
|
callout_init_cpu(ci);
|
|
|
|
softint_init(ci);
|
|
|
|
xc_init_cpu(ci);
|
|
|
|
pool_cache_cpu_init(ci);
|
|
|
|
selsysinit(ci);
|
2010-01-15 22:01:04 +03:00
|
|
|
percpu_init_cpu(ci);
|
2009-12-01 12:50:51 +03:00
|
|
|
}
|
2008-04-28 23:31:45 +04:00
|
|
|
|
2009-09-16 19:23:04 +04:00
|
|
|
sysctl_init();
|
2009-03-18 21:00:38 +03:00
|
|
|
kqueue_init();
|
2008-10-16 00:15:37 +04:00
|
|
|
iostat_init();
|
2008-10-13 22:03:53 +04:00
|
|
|
uid_init();
|
2008-04-28 23:31:45 +04:00
|
|
|
fd_sys_init();
|
2008-05-04 16:52:58 +04:00
|
|
|
module_init();
|
2008-12-29 20:45:55 +03:00
|
|
|
devsw_init();
|
2009-11-26 20:36:22 +03:00
|
|
|
pipe_init();
|
2010-04-21 20:16:31 +04:00
|
|
|
resource_init();
|
2008-01-25 01:41:07 +03:00
|
|
|
|
2010-06-03 14:56:20 +04:00
|
|
|
/* start page baroness */
|
|
|
|
if (rump_threads) {
|
|
|
|
if (kthread_create(PRI_PGDAEMON, KTHREAD_MPSAFE, NULL,
|
|
|
|
uvm_pageout, NULL, &uvm.pagedaemon_lwp, "pdaemon") != 0)
|
|
|
|
panic("pagedaemon create failed");
|
|
|
|
} else
|
|
|
|
uvm.pagedaemon_lwp = NULL; /* doesn't match curlwp */
|
|
|
|
|
|
|
|
/* process dso's */
|
2010-03-05 21:41:46 +03:00
|
|
|
rumpuser_dl_bootstrap(add_linkedin_modules, rump_kernelfsym_load);
|
|
|
|
|
2008-11-19 17:10:48 +03:00
|
|
|
/* these do nothing if not present */
|
|
|
|
rump_vfs_init();
|
|
|
|
rump_net_init();
|
2009-09-07 00:54:19 +04:00
|
|
|
rump_dev_init();
|
|
|
|
cold = 0;
|
2008-10-15 17:04:26 +04:00
|
|
|
|
2007-10-31 18:57:19 +03:00
|
|
|
/* aieeeedondest */
|
2008-08-12 14:04:57 +04:00
|
|
|
if (rump_threads) {
|
|
|
|
if (workqueue_create(&uvm.aiodone_queue, "aiodoned",
|
2009-07-21 04:33:28 +04:00
|
|
|
rump_aiodone_worker, NULL, 0, 0, WQ_MPSAFE))
|
2008-08-12 14:04:57 +04:00
|
|
|
panic("aiodoned");
|
|
|
|
}
|
2007-10-31 18:57:19 +03:00
|
|
|
|
2010-03-31 22:56:07 +04:00
|
|
|
mksysctls();
|
2009-09-16 19:23:04 +04:00
|
|
|
sysctl_finalize();
|
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
module_init_class(MODULE_CLASS_ANY);
|
2009-11-26 23:58:51 +03:00
|
|
|
|
2007-08-06 02:28:00 +04:00
|
|
|
rumpuser_gethostname(hostname, MAXHOSTNAMELEN, &error);
|
|
|
|
hostnamelen = strlen(hostname);
|
2007-12-31 02:29:06 +03:00
|
|
|
|
|
|
|
sigemptyset(&sigcantmask);
|
2008-01-02 21:15:12 +03:00
|
|
|
|
2008-09-08 00:17:03 +04:00
|
|
|
lwp0.l_fd = proc0.p_fd = fd_init(&rump_filedesc0);
|
2008-10-08 03:16:59 +04:00
|
|
|
|
2009-01-23 16:14:16 +03:00
|
|
|
if (rump_threads)
|
|
|
|
vmem_rehash_start();
|
|
|
|
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_unschedule();
|
2009-09-25 01:30:42 +04:00
|
|
|
|
2008-10-08 03:16:59 +04:00
|
|
|
return 0;
|
2007-08-06 02:28:00 +04:00
|
|
|
}
|
|
|
|
|
2009-10-09 18:41:36 +04:00
|
|
|
/* maybe support sys_reboot some day for remote shutdown */
|
|
|
|
void
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_reboot(int howto)
|
2009-10-09 18:41:36 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
/* dump means we really take the dive here */
|
|
|
|
if ((howto & RB_DUMP) || panicstr) {
|
|
|
|
rumpuser_exit(RUMPUSER_PANIC);
|
|
|
|
/*NOTREACHED*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try to sync */
|
|
|
|
if (!((howto & RB_NOSYNC) || panicstr)) {
|
|
|
|
rump_vfs_fini();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* your wish is my command */
|
|
|
|
if (howto & RB_HALT) {
|
|
|
|
for (;;) {
|
|
|
|
uint64_t sec = 5, nsec = 0;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
rumpuser_nanosleep(&sec, &nsec, &error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rump_inited = -1;
|
|
|
|
}
|
|
|
|
|
2007-08-20 19:58:13 +04:00
|
|
|
struct uio *
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_uio_setup(void *buf, size_t bufsize, off_t offset, enum rump_uiorw rw)
|
2007-08-20 19:58:13 +04:00
|
|
|
{
|
|
|
|
struct uio *uio;
|
|
|
|
enum uio_rw uiorw;
|
|
|
|
|
|
|
|
switch (rw) {
|
|
|
|
case RUMPUIO_READ:
|
|
|
|
uiorw = UIO_READ;
|
|
|
|
break;
|
|
|
|
case RUMPUIO_WRITE:
|
|
|
|
uiorw = UIO_WRITE;
|
|
|
|
break;
|
2007-09-02 02:10:10 +04:00
|
|
|
default:
|
|
|
|
panic("%s: invalid rw %d", __func__, rw);
|
2007-08-20 19:58:13 +04:00
|
|
|
}
|
|
|
|
|
2008-01-03 05:48:02 +03:00
|
|
|
uio = kmem_alloc(sizeof(struct uio), KM_SLEEP);
|
|
|
|
uio->uio_iov = kmem_alloc(sizeof(struct iovec), KM_SLEEP);
|
2007-08-20 19:58:13 +04:00
|
|
|
|
|
|
|
uio->uio_iov->iov_base = buf;
|
|
|
|
uio->uio_iov->iov_len = bufsize;
|
|
|
|
|
|
|
|
uio->uio_iovcnt = 1;
|
|
|
|
uio->uio_offset = offset;
|
|
|
|
uio->uio_resid = bufsize;
|
|
|
|
uio->uio_rw = uiorw;
|
|
|
|
uio->uio_vmspace = UIO_VMSPACE_SYS;
|
|
|
|
|
|
|
|
return uio;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_uio_getresid(struct uio *uio)
|
2007-08-20 19:58:13 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
return uio->uio_resid;
|
|
|
|
}
|
|
|
|
|
|
|
|
off_t
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_uio_getoff(struct uio *uio)
|
2007-08-20 19:58:13 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
return uio->uio_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_uio_free(struct uio *uio)
|
2007-08-20 19:58:13 +04:00
|
|
|
{
|
|
|
|
size_t resid;
|
|
|
|
|
|
|
|
resid = uio->uio_resid;
|
2008-01-03 05:48:02 +03:00
|
|
|
kmem_free(uio->uio_iov, sizeof(*uio->uio_iov));
|
|
|
|
kmem_free(uio, sizeof(*uio));
|
2007-08-20 19:58:13 +04:00
|
|
|
|
|
|
|
return resid;
|
|
|
|
}
|
|
|
|
|
2009-04-29 21:51:47 +04:00
|
|
|
static pid_t nextpid = 1;
|
|
|
|
struct lwp *
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_newproc_switch()
|
2009-04-29 21:51:47 +04:00
|
|
|
{
|
2009-10-15 20:39:22 +04:00
|
|
|
struct lwp *l;
|
2009-04-29 21:51:47 +04:00
|
|
|
pid_t mypid;
|
|
|
|
|
|
|
|
mypid = atomic_inc_uint_nv(&nextpid);
|
|
|
|
if (__predict_false(mypid == 0))
|
|
|
|
mypid = atomic_inc_uint_nv(&nextpid);
|
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
l = rump_lwp_alloc(mypid, 0);
|
|
|
|
rump_lwp_switch(l);
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct lwp *
|
|
|
|
rump_lwp_alloc_and_switch(pid_t pid, lwpid_t lid)
|
|
|
|
{
|
|
|
|
struct lwp *l;
|
2009-04-29 21:51:47 +04:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
l = rump_lwp_alloc(pid, lid);
|
|
|
|
rump_lwp_switch(l);
|
|
|
|
|
|
|
|
return l;
|
2009-04-29 21:51:47 +04:00
|
|
|
}
|
|
|
|
|
2007-10-31 18:57:19 +03:00
|
|
|
struct lwp *
|
2009-10-15 20:39:22 +04:00
|
|
|
rump_lwp_alloc(pid_t pid, lwpid_t lid)
|
2007-10-31 18:57:19 +03:00
|
|
|
{
|
|
|
|
struct lwp *l;
|
|
|
|
struct proc *p;
|
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
l = kmem_zalloc(sizeof(*l), KM_SLEEP);
|
2008-08-08 18:40:07 +04:00
|
|
|
if (pid != 0) {
|
2009-10-15 20:39:22 +04:00
|
|
|
p = kmem_zalloc(sizeof(*p), KM_SLEEP);
|
2009-12-09 03:11:21 +03:00
|
|
|
if (rump_proc_vfs_init)
|
|
|
|
rump_proc_vfs_init(p);
|
2008-08-08 18:40:07 +04:00
|
|
|
p->p_stats = &rump_stats;
|
2010-04-21 20:16:31 +04:00
|
|
|
p->p_limit = lim_copy(&rump_limits);
|
2008-08-08 18:40:07 +04:00
|
|
|
p->p_pid = pid;
|
|
|
|
p->p_vmspace = &rump_vmspace;
|
2010-04-17 20:34:29 +04:00
|
|
|
p->p_emul = &emul_netbsd;
|
2008-08-08 18:40:07 +04:00
|
|
|
p->p_fd = fd_init(NULL);
|
2009-09-04 16:27:09 +04:00
|
|
|
p->p_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
|
2010-05-11 18:57:20 +04:00
|
|
|
p->p_pgrp = &rump_pgrp;
|
2009-11-06 18:22:33 +03:00
|
|
|
l->l_cred = rump_cred_suserget();
|
2008-08-08 18:40:07 +04:00
|
|
|
} else {
|
|
|
|
p = &proc0;
|
2009-11-06 18:22:33 +03:00
|
|
|
l->l_cred = rump_susercred;
|
2008-08-08 18:40:07 +04:00
|
|
|
}
|
2008-03-12 14:17:33 +03:00
|
|
|
|
2007-10-31 18:57:19 +03:00
|
|
|
l->l_proc = p;
|
2008-08-08 18:40:07 +04:00
|
|
|
l->l_lid = lid;
|
|
|
|
l->l_fd = p->p_fd;
|
2009-10-15 04:28:46 +04:00
|
|
|
l->l_cpu = NULL;
|
Improve the CPU scheduler for a host MP system with multithreaded
access. The old scheduler had a global freelist which caused a
cache crisis with multiple host threads trying to schedule a virtual
CPU simultaneously.
The rump scheduler is different from a normal thread scheduler, so
it has different requirements. First, we schedule a CPU for a
thread (which we get from the host scheduler) instead of scheduling
a thread onto a CPU. Second, scheduling points are at every
entry/exit to/from the rump kernel, including (but not limited to)
syscall entry points and hypercalls. This means scheduling happens
a lot more frequently than in a normal kernel.
For every lwp, cache the previously used CPU. When scheduling,
attempt to reuse the same CPU. If we get it, we can use it directly
without any memory barriers or expensive locks. If the CPU is
taken, migrate. Use a lock/wait only in the slowpath. Be very
wary of walking the entire CPU array because that does not lead to
a happy cacher.
The migration algorithm could probably benefit from improved
heuristics and tuning. Even as such, with the new scheduler an
application which has two threads making rlimit syscalls in a tight
loop experiences almost 400% speedup. The exact speedup is difficult
to pinpoint, though, since the old scheduler caused very jittery
results due to cache contention. Also, the rump version is now
70% faster than the counterpart which calls the host kernel.
2010-05-28 20:44:14 +04:00
|
|
|
l->l_target_cpu = rump_cpu;
|
2010-04-13 02:17:23 +04:00
|
|
|
lwp_initspecific(l);
|
2010-04-14 14:27:53 +04:00
|
|
|
LIST_INSERT_HEAD(&alllwp, l, l_list);
|
2008-03-13 00:37:15 +03:00
|
|
|
|
2007-10-31 18:57:19 +03:00
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2009-04-29 21:51:47 +04:00
|
|
|
void
|
2009-10-15 20:39:22 +04:00
|
|
|
rump_lwp_switch(struct lwp *newlwp)
|
2009-04-29 21:51:47 +04:00
|
|
|
{
|
2009-10-15 20:39:22 +04:00
|
|
|
struct lwp *l = curlwp;
|
2009-04-29 21:51:47 +04:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
rumpuser_set_curlwp(NULL);
|
Improve the CPU scheduler for a host MP system with multithreaded
access. The old scheduler had a global freelist which caused a
cache crisis with multiple host threads trying to schedule a virtual
CPU simultaneously.
The rump scheduler is different from a normal thread scheduler, so
it has different requirements. First, we schedule a CPU for a
thread (which we get from the host scheduler) instead of scheduling
a thread onto a CPU. Second, scheduling points are at every
entry/exit to/from the rump kernel, including (but not limited to)
syscall entry points and hypercalls. This means scheduling happens
a lot more frequently than in a normal kernel.
For every lwp, cache the previously used CPU. When scheduling,
attempt to reuse the same CPU. If we get it, we can use it directly
without any memory barriers or expensive locks. If the CPU is
taken, migrate. Use a lock/wait only in the slowpath. Be very
wary of walking the entire CPU array because that does not lead to
a happy cacher.
The migration algorithm could probably benefit from improved
heuristics and tuning. Even as such, with the new scheduler an
application which has two threads making rlimit syscalls in a tight
loop experiences almost 400% speedup. The exact speedup is difficult
to pinpoint, though, since the old scheduler caused very jittery
results due to cache contention. Also, the rump version is now
70% faster than the counterpart which calls the host kernel.
2010-05-28 20:44:14 +04:00
|
|
|
newlwp->l_cpu = newlwp->l_target_cpu = l->l_cpu;
|
2009-10-16 04:14:53 +04:00
|
|
|
newlwp->l_mutex = l->l_mutex;
|
|
|
|
l->l_mutex = NULL;
|
|
|
|
l->l_cpu = NULL;
|
2009-10-15 20:39:22 +04:00
|
|
|
rumpuser_set_curlwp(newlwp);
|
|
|
|
if (l->l_flag & LW_WEXIT)
|
|
|
|
rump_lwp_free(l);
|
2009-04-29 21:51:47 +04:00
|
|
|
}
|
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
/* XXX: this has effect only on non-pid0 lwps */
|
2007-10-31 18:57:19 +03:00
|
|
|
void
|
2009-10-15 20:39:22 +04:00
|
|
|
rump_lwp_release(struct lwp *l)
|
2007-10-31 18:57:19 +03:00
|
|
|
{
|
2009-04-29 21:51:47 +04:00
|
|
|
struct proc *p;
|
2007-10-31 18:57:19 +03:00
|
|
|
|
2009-04-29 21:51:47 +04:00
|
|
|
p = l->l_proc;
|
|
|
|
if (p->p_pid != 0) {
|
2009-09-04 16:27:09 +04:00
|
|
|
mutex_obj_free(p->p_lock);
|
2008-08-08 18:40:07 +04:00
|
|
|
fd_free();
|
2009-12-09 03:11:21 +03:00
|
|
|
if (rump_proc_vfs_release)
|
|
|
|
rump_proc_vfs_release(p);
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_cred_put(l->l_cred);
|
2010-04-21 20:16:31 +04:00
|
|
|
limfree(p->p_limit);
|
2009-04-29 21:51:47 +04:00
|
|
|
kmem_free(p, sizeof(*p));
|
2008-08-08 18:40:07 +04:00
|
|
|
}
|
2009-10-15 20:39:22 +04:00
|
|
|
KASSERT((l->l_flag & LW_WEXIT) == 0);
|
|
|
|
l->l_flag |= LW_WEXIT;
|
|
|
|
}
|
2009-10-15 04:28:46 +04:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
void
|
|
|
|
rump_lwp_free(struct lwp *l)
|
|
|
|
{
|
|
|
|
|
|
|
|
KASSERT(l->l_flag & LW_WEXIT);
|
2009-10-16 04:14:53 +04:00
|
|
|
KASSERT(l->l_mutex == NULL);
|
2010-02-09 19:53:13 +03:00
|
|
|
if (l->l_name)
|
|
|
|
kmem_free(l->l_name, MAXCOMLEN);
|
2010-04-13 02:17:23 +04:00
|
|
|
lwp_finispecific(l);
|
2010-04-14 14:27:53 +04:00
|
|
|
LIST_REMOVE(l, l_list);
|
2009-10-15 20:39:22 +04:00
|
|
|
kmem_free(l, sizeof(*l));
|
2007-10-31 18:57:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
struct lwp *
|
2009-10-15 20:39:22 +04:00
|
|
|
rump_lwp_curlwp(void)
|
2007-10-31 18:57:19 +03:00
|
|
|
{
|
2009-10-15 20:39:22 +04:00
|
|
|
struct lwp *l = curlwp;
|
2007-10-31 18:57:19 +03:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
if (l->l_flag & LW_WEXIT)
|
|
|
|
return NULL;
|
2007-10-31 18:57:19 +03:00
|
|
|
return l;
|
|
|
|
}
|
2007-11-04 21:43:55 +03:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
/* rump private. NEEDS WORK! */
|
2009-05-07 20:04:25 +04:00
|
|
|
void
|
2009-10-15 20:39:22 +04:00
|
|
|
rump_set_vmspace(struct vmspace *vm)
|
2009-05-07 20:04:25 +04:00
|
|
|
{
|
2009-10-15 20:39:22 +04:00
|
|
|
struct proc *p = curproc;
|
2009-05-07 20:04:25 +04:00
|
|
|
|
2009-10-15 20:39:22 +04:00
|
|
|
p->p_vmspace = vm;
|
2009-05-07 20:04:25 +04:00
|
|
|
}
|
|
|
|
|
2008-09-30 23:25:56 +04:00
|
|
|
kauth_cred_t
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_cred_create(uid_t uid, gid_t gid, size_t ngroups, gid_t *groups)
|
2008-09-30 23:25:56 +04:00
|
|
|
{
|
|
|
|
kauth_cred_t cred;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
cred = kauth_cred_alloc();
|
|
|
|
kauth_cred_setuid(cred, uid);
|
|
|
|
kauth_cred_seteuid(cred, uid);
|
|
|
|
kauth_cred_setsvuid(cred, uid);
|
|
|
|
kauth_cred_setgid(cred, gid);
|
|
|
|
kauth_cred_setgid(cred, gid);
|
|
|
|
kauth_cred_setegid(cred, gid);
|
|
|
|
kauth_cred_setsvgid(cred, gid);
|
|
|
|
rv = kauth_cred_setgroups(cred, groups, ngroups, 0, UIO_SYSSPACE);
|
|
|
|
/* oh this is silly. and by "this" I mean kauth_cred_setgroups() */
|
|
|
|
assert(rv == 0);
|
|
|
|
|
|
|
|
return cred;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_cred_put(kauth_cred_t cred)
|
2008-09-30 23:25:56 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
kauth_cred_free(cred);
|
|
|
|
}
|
|
|
|
|
|
|
|
kauth_cred_t
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_cred_suserget(void)
|
2008-09-30 23:25:56 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
kauth_cred_hold(rump_susercred);
|
|
|
|
return rump_susercred;
|
|
|
|
}
|
|
|
|
|
2009-02-12 17:46:58 +03:00
|
|
|
/*
|
|
|
|
* Return the next system lwpid
|
|
|
|
*/
|
2008-10-10 17:14:41 +04:00
|
|
|
lwpid_t
|
2009-03-18 13:22:21 +03:00
|
|
|
rump_nextlid(void)
|
2008-10-10 17:14:41 +04:00
|
|
|
{
|
2009-02-12 17:46:58 +03:00
|
|
|
lwpid_t retid;
|
|
|
|
|
|
|
|
mutex_enter(proc0.p_lock);
|
|
|
|
/*
|
|
|
|
* Take next one, don't return 0
|
|
|
|
* XXX: most likely we'll have collisions in case this
|
|
|
|
* wraps around.
|
|
|
|
*/
|
|
|
|
if (++proc0.p_nlwpid == 0)
|
|
|
|
++proc0.p_nlwpid;
|
|
|
|
retid = proc0.p_nlwpid;
|
|
|
|
mutex_exit(proc0.p_lock);
|
|
|
|
|
|
|
|
return retid;
|
2008-10-10 17:14:41 +04:00
|
|
|
}
|
|
|
|
|
2010-03-01 16:12:19 +03:00
|
|
|
static int compcounter[RUMP_COMPONENT_MAX];
|
|
|
|
|
|
|
|
static void
|
|
|
|
rump_component_init_cb(struct rump_component *rc, int type)
|
|
|
|
{
|
|
|
|
|
|
|
|
KASSERT(type < RUMP_COMPONENT_MAX);
|
|
|
|
if (rc->rc_type == type) {
|
|
|
|
rc->rc_init();
|
|
|
|
compcounter[type]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rump_component_count(enum rump_component_type type)
|
|
|
|
{
|
|
|
|
|
|
|
|
KASSERT(type <= RUMP_COMPONENT_MAX);
|
|
|
|
return compcounter[type];
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rump_component_init(enum rump_component_type type)
|
|
|
|
{
|
|
|
|
|
|
|
|
rumpuser_dl_component_init(type, rump_component_init_cb);
|
|
|
|
}
|
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
/*
|
|
|
|
* Initialize a module which has already been loaded and linked
|
|
|
|
* with dlopen(). This is fundamentally the same as a builtin module.
|
|
|
|
*/
|
2008-11-21 09:09:51 +03:00
|
|
|
int
|
2010-03-05 21:41:46 +03:00
|
|
|
rump_module_init(const struct modinfo * const *mip, size_t nmodinfo)
|
2008-11-21 09:09:51 +03:00
|
|
|
{
|
2009-10-08 04:47:47 +04:00
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
return module_builtin_add(mip, nmodinfo, true);
|
2009-05-02 19:20:08 +04:00
|
|
|
}
|
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
/*
|
|
|
|
* Finish module (flawless victory, fatality!).
|
|
|
|
*/
|
2009-05-02 19:20:08 +04:00
|
|
|
int
|
2010-03-05 21:41:46 +03:00
|
|
|
rump_module_fini(const struct modinfo *mi)
|
2009-05-02 19:20:08 +04:00
|
|
|
{
|
2009-10-08 04:47:47 +04:00
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
return module_builtin_remove(mi, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add loaded and linked module to the builtin list. It will
|
|
|
|
* later be initialized with module_init_class().
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_linkedin_modules(const struct modinfo * const *mip, size_t nmodinfo)
|
|
|
|
{
|
2009-05-02 19:20:08 +04:00
|
|
|
|
2010-03-05 21:41:46 +03:00
|
|
|
module_builtin_add(mip, nmodinfo, false);
|
2008-11-21 09:09:51 +03:00
|
|
|
}
|
|
|
|
|
2009-11-26 12:20:07 +03:00
|
|
|
int
|
|
|
|
rump_kernelfsym_load(void *symtab, uint64_t symsize,
|
|
|
|
char *strtab, uint64_t strsize)
|
|
|
|
{
|
|
|
|
static int inited = 0;
|
|
|
|
Elf64_Ehdr ehdr;
|
|
|
|
|
|
|
|
if (inited)
|
|
|
|
return EBUSY;
|
|
|
|
inited = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use 64bit header since it's bigger. Shouldn't make a
|
|
|
|
* difference, since we're passing in all zeroes anyway.
|
|
|
|
*/
|
|
|
|
memset(&ehdr, 0, sizeof(ehdr));
|
|
|
|
ksyms_addsyms_explicit(&ehdr, symtab, symsize, strtab, strsize);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-20 20:58:22 +03:00
|
|
|
static int
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_sysproxy_local(int num, void *arg, uint8_t *data, size_t dlen,
|
2009-02-20 20:58:22 +03:00
|
|
|
register_t *retval)
|
|
|
|
{
|
|
|
|
struct lwp *l;
|
|
|
|
struct sysent *callp;
|
2009-10-15 04:28:46 +04:00
|
|
|
int rv;
|
2009-02-20 20:58:22 +03:00
|
|
|
|
|
|
|
if (__predict_false(num >= SYS_NSYSENT))
|
|
|
|
return ENOSYS;
|
|
|
|
|
|
|
|
callp = rump_sysent + num;
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_schedule();
|
2009-10-15 20:39:22 +04:00
|
|
|
l = curlwp;
|
2010-04-28 18:51:07 +04:00
|
|
|
rv = sy_call(callp, l, (void *)data, retval);
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_unschedule();
|
|
|
|
|
|
|
|
return rv;
|
2009-02-20 20:58:22 +03:00
|
|
|
}
|
|
|
|
|
2009-11-03 21:22:16 +03:00
|
|
|
int
|
|
|
|
rump_boot_gethowto()
|
|
|
|
{
|
|
|
|
|
|
|
|
return boothowto;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rump_boot_sethowto(int howto)
|
|
|
|
{
|
|
|
|
|
|
|
|
boothowto = howto;
|
|
|
|
}
|
|
|
|
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_sysproxy_t rump_sysproxy = rump_sysproxy_local;
|
2009-02-20 20:58:22 +03:00
|
|
|
void *rump_sysproxy_arg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This whole syscall-via-rpc is still taking form. For example, it
|
|
|
|
* may be necessary to set syscalls individually instead of lobbing
|
|
|
|
* them all to the same place. So don't think this interface is
|
|
|
|
* set in stone.
|
|
|
|
*/
|
|
|
|
int
|
2009-10-14 22:18:53 +04:00
|
|
|
rump_sysproxy_set(rump_sysproxy_t proxy, void *arg)
|
2009-02-20 20:58:22 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
if (rump_sysproxy_arg)
|
|
|
|
return EBUSY;
|
|
|
|
|
|
|
|
rump_sysproxy_arg = arg;
|
|
|
|
rump_sysproxy = proxy;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-05-22 12:34:14 +04:00
|
|
|
|
|
|
|
int
|
2009-10-15 04:28:46 +04:00
|
|
|
rump_getversion(void)
|
2009-05-22 12:34:14 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
return __NetBSD_Version__;
|
|
|
|
}
|
2010-05-01 18:40:36 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: may be called unscheduled. Not fully safe since no locking
|
|
|
|
* of allevents (currently that's not even available).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
rump_printevcnts()
|
|
|
|
{
|
|
|
|
struct evcnt *ev;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(ev, &allevents, ev_list)
|
|
|
|
rumpuser_dprintf("%s / %s: %" PRIu64 "\n",
|
|
|
|
ev->ev_group, ev->ev_name, ev->ev_count);
|
|
|
|
}
|