NetBSD-5.0.2/sys/rump/librump/rumpkern/emul.c

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: emul.c,v 1.53 2008/10/14 10:42:27 pooka Exp $	*/

/*
 * 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.
 */

#define malloc(a,b,c) __wrap_malloc(a,b,c)

#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/null.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/syslog.h>
#include <sys/namei.h>
#include <sys/kauth.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/queue.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/kthread.h>
#include <sys/cpu.h>
#include <sys/kmem.h>
#include <sys/poll.h>
#include <sys/tprintf.h>
#include <sys/timetc.h>

#include <machine/stdarg.h>

#include <rump/rumpuser.h>

#include <uvm/uvm_map.h>

#include "rump_private.h"

time_t time_second = 1;

kmutex_t *proc_lock;
struct lwp lwp0;
struct vnode *rootvp;
struct device *root_device;
dev_t rootdev;
int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */
int doing_shutdown;
int ncpu = 1;
const int schedppq = 1;
int hardclock_ticks;
bool mp_online = false;
struct vm_map *mb_map;

char hostname[MAXHOSTNAMELEN];
size_t hostnamelen;

u_long	bufmem_valimit;
u_long	bufmem_hiwater;
u_long	bufmem_lowater;
u_long	bufmem;
u_int	nbuf;

const char *panicstr;
const char ostype[] = "NetBSD";
const char osrelease[] = "999"; /* paradroid 4evah */
const char kernel_ident[] = "RUMP-ROAST";
const char *domainname;
int domainnamelen;

const struct filterops seltrue_filtops;

void
panic(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	printf("panic: ");
	vprintf(fmt, ap);
	va_end(ap);
	printf("\n");
	abort();
}

void
log(int level, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

void
vlog(int level, const char *fmt, va_list ap)
{

	vprintf(fmt, ap);
}

void
uprintf(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

/* relegate this to regular printf */
tpr_t
tprintf_open(struct proc *p)
{

	return (tpr_t)0x111;
}

void
tprintf(tpr_t tpr, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

void
tprintf_close(tpr_t tpr)
{

}

void
printf_nolog(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

void
aprint_normal(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}

int
copyin(const void *uaddr, void *kaddr, size_t len)
{

	memcpy(kaddr, uaddr, len);
	return 0;
}

int
copyout(const void *kaddr, void *uaddr, size_t len)
{

	memcpy(uaddr, kaddr, len);
	return 0;
}

int
copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
{

	return copyinstr(kfaddr, kdaddr, len, done);
}

int
copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
{

	strlcpy(kaddr, uaddr, len);
	if (done)
		*done = strlen(kaddr)+1; /* includes termination */
	return 0;
}

int
copyin_vmspace(struct vmspace *vm, const void *uaddr, void *kaddr, size_t len)
{

	return copyin(uaddr, kaddr, len);
}

int
copyout_vmspace(struct vmspace *vm, const void *kaddr, void *uaddr, size_t len)
{

	return copyout(kaddr, uaddr, len);
}

int
kcopy(const void *src, void *dst, size_t len)
{

	memcpy(dst, src, len);
	return 0;
}

int
uiomove(void *buf, size_t n, struct uio *uio)
{
	struct iovec *iov;
	uint8_t *b = buf;
	size_t cnt;
	int rv;

	if (uio->uio_vmspace != UIO_VMSPACE_SYS)
		panic("%s: vmspace != UIO_VMSPACE_SYS", __func__);

	/*
	 * See if rump ubc code claims the offset.  This is of course
	 * a blatant violation of abstraction levels, but let's keep
	 * me simple & stupid for now.
	 */
	if (rump_ubc_magic_uiomove(buf, n, uio, &rv, NULL))
		return rv;

	while (n && uio->uio_resid) {
		iov = uio->uio_iov;
		cnt = iov->iov_len;
		if (cnt == 0) {
			uio->uio_iov++;
			uio->uio_iovcnt--;
			continue;
		}
		if (cnt > n)
			cnt = n;

		if (uio->uio_rw == UIO_READ)
			memcpy(iov->iov_base, b, cnt);
		else
			memcpy(b, iov->iov_base, cnt);

		iov->iov_base = (uint8_t *)iov->iov_base + cnt;
		iov->iov_len -= cnt;
		b += cnt;
		uio->uio_resid -= cnt;
		uio->uio_offset += cnt;
		n -= cnt;
	}

	return 0;
}

void
uio_setup_sysspace(struct uio *uio)
{

	uio->uio_vmspace = UIO_VMSPACE_SYS;
}

const struct bdevsw *
bdevsw_lookup(dev_t dev)
{

	return (const struct bdevsw *)1;
}

devclass_t
device_class(device_t dev)
{

	if (dev != root_device)
		panic("%s: dev != root_device not supported", __func__);

	return DV_DISK;
}

void
getmicrouptime(struct timeval *tvp)
{
	int error;

	rumpuser_gettimeofday(tvp, &error);
}

void
malloc_type_attach(struct malloc_type *type)
{

	return;
}

void
malloc_type_detach(struct malloc_type *type)
{

	return;
}

void *
__wrap_malloc(unsigned long size, struct malloc_type *type, int flags)
{
	void *rv;

	rv = rumpuser_malloc(size, (flags & (M_CANFAIL | M_NOWAIT)) != 0);
	if (rv && flags & M_ZERO)
		memset(rv, 0, size);

	return rv;
}

void
nanotime(struct timespec *ts)
{
	struct timeval tv;
	int error;

	rumpuser_gettimeofday(&tv, &error);
	TIMEVAL_TO_TIMESPEC(&tv, ts);
}

/* hooray for mick, so what if I do */
void
getnanotime(struct timespec *ts)
{

	nanotime(ts);
}

void
microtime(struct timeval *tv)
{
	int error;

	rumpuser_gettimeofday(tv, &error);
}

void
getmicrotime(struct timeval *tv)
{
	int error;

	rumpuser_gettimeofday(tv, &error);
}

void
bdev_strategy(struct buf *bp)
{

	panic("%s: not supported", __func__);
}

int
bdev_type(dev_t dev)
{

	return D_DISK;
}

struct kthdesc {
	void (*f)(void *);
	void *arg;
	struct lwp *mylwp;
};

static void *
threadbouncer(void *arg)
{
	struct kthdesc *k = arg;
	void (*f)(void *);
	void *thrarg;

	f = k->f;
	thrarg = k->arg;
	rumpuser_set_curlwp(k->mylwp);
	kmem_free(k, sizeof(struct kthdesc));

	f(thrarg);
	panic("unreachable, should kthread_exit()");
}

int
kthread_create(pri_t pri, int flags, struct cpu_info *ci,
	void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...)
{
	struct kthdesc *k;
	struct lwp *l;
	int rv;

	if (!rump_threads) {
		/* fake them */
		if (strcmp(fmt, "vrele") == 0) {
			printf("rump warning: threads not enabled, not starting"
			   " vrele thread\n");
			return 0;
		} else if (strcmp(fmt, "cachegc") == 0) {
			printf("rump warning: threads not enabled, not starting"
			   " namecache g/c thread\n");
			return 0;
		} else
			panic("threads not available, setenv RUMP_THREADS 1");
	}

	KASSERT(fmt != NULL);
	if (ci != NULL)
		panic("%s: bounded threads not supported", __func__);

	k = kmem_alloc(sizeof(struct kthdesc), KM_SLEEP);
	k->f = func;
	k->arg = arg;
	k->mylwp = l = rump_setup_curlwp(0, rump_nextlid(), 0);
	rv = rumpuser_thread_create(threadbouncer, k);
	if (rv)
		return rv;

	if (newlp)
		*newlp = l;
	return 0;
}

void
kthread_exit(int ecode)
{

	rumpuser_thread_exit();
}

struct proc *
p_find(pid_t pid, uint flags)
{

	panic("%s: not implemented", __func__);
}

struct pgrp *
pg_find(pid_t pid, uint flags)
{

	panic("%s: not implemented", __func__);
}

void
psignal(struct proc *p, int signo)
{

	switch (signo) {
	case SIGSYS:
		break;
	default:
		panic("unhandled signal %d", signo);
	}
}

void
kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
{

	panic("%s: not implemented", __func__);
}

void
kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
{

	panic("%s: not implemented", __func__);
}

int
pgid_in_session(struct proc *p, pid_t pg_id)
{

	panic("%s: not implemented", __func__);
}

int
sigispending(struct lwp *l, int signo)
{

	return 0;
}

void
sigpending1(struct lwp *l, sigset_t *ss)
{

	panic("%s: not implemented", __func__);
}

void
knote_fdclose(int fd)
{

	/* since we don't add knotes, we don't have to remove them */
}

int
seltrue_kqfilter(dev_t dev, struct knote *kn)
{

	panic("%s: not implemented", __func__);
}

int
kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
{
	extern int hz;
	int rv, error;
	struct timespec time;
	
	if (mtx)
		mutex_exit(mtx);

	time.tv_sec = timeo / hz;
	time.tv_nsec = (timeo % hz) * (1000000000 / hz);

	rv = rumpuser_nanosleep(&time, NULL, &error);
	
	if (mtx)
		mutex_enter(mtx);

	if (rv)
		return error;

	return 0;
}

void
suspendsched()
{

	panic("%s: not implemented", __func__);
}

u_int
lwp_unsleep(lwp_t *l, bool cleanup)
{

	KASSERT(mutex_owned(l->l_mutex));

	return (*l->l_syncobj->sobj_unsleep)(l, cleanup);
}

vaddr_t
calc_cache_size(struct vm_map *map, int pct, int va_pct)
{
	paddr_t t;

	t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
	if ((vaddr_t)t != t) {
		panic("%s: needs tweak", __func__);
	}
	return t;
}

int
seltrue(dev_t dev, int events, struct lwp *l)
{
        return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
}

void
selrecord(lwp_t *selector, struct selinfo *sip)
{
}

void
selinit(struct selinfo *sip)
{
}

void
selnotify(struct selinfo *sip, int events, long knhint)
{
}

void
seldestroy(struct selinfo *sip)
{
}

const char *
device_xname(device_t dv)
{
	return "bogus0";
}

void
assert_sleepable(void)
{

	/* always sleepable, although we should improve this */
}

int
devsw_attach(const char *devname, const struct bdevsw *bdev, int *bmajor,
	const struct cdevsw *cdev, int *cmajor)
{

	panic("%s: not implemented", __func__);
}

int
devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev)
{

	panic("%s: not implemented", __func__);
}

void
tc_setclock(struct timespec *ts)
{

	panic("%s: not implemented", __func__);
}

void
proc_crmod_enter()
{

	panic("%s: not implemented", __func__);
}

void
proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
{

	panic("%s: not implemented", __func__);
}