Home | History | Annotate | Line # | Download | only in rumpkern
emul.c revision 1.115
      1 /*	$NetBSD: emul.c,v 1.115 2010/01/08 20:04:06 dyoung Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
      5  *
      6  * Development of this software was supported by Google Summer of Code.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.115 2010/01/08 20:04:06 dyoung Exp $");
     32 
     33 #include <sys/param.h>
     34 #include <sys/null.h>
     35 #include <sys/vnode.h>
     36 #include <sys/stat.h>
     37 #include <sys/select.h>
     38 #include <sys/syslog.h>
     39 #include <sys/namei.h>
     40 #include <sys/kauth.h>
     41 #include <sys/conf.h>
     42 #include <sys/device.h>
     43 #include <sys/queue.h>
     44 #include <sys/file.h>
     45 #include <sys/filedesc.h>
     46 #include <sys/cpu.h>
     47 #include <sys/kmem.h>
     48 #include <sys/poll.h>
     49 #include <sys/timetc.h>
     50 #include <sys/tprintf.h>
     51 #include <sys/module.h>
     52 #include <sys/tty.h>
     53 #include <sys/reboot.h>
     54 #include <sys/syscallvar.h>
     55 #include <sys/xcall.h>
     56 
     57 #include <dev/cons.h>
     58 
     59 #include <rump/rumpuser.h>
     60 
     61 #include <uvm/uvm_map.h>
     62 
     63 #include "rump_private.h"
     64 
     65 time_t time_second = 1;
     66 
     67 kmutex_t *proc_lock;
     68 struct lwp lwp0;
     69 struct vnode *rootvp;
     70 dev_t rootdev;
     71 int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */
     72 int doing_shutdown;
     73 const int schedppq = 1;
     74 int hardclock_ticks;
     75 bool mp_online = false;
     76 struct vm_map *mb_map;
     77 struct timeval boottime;
     78 struct emul emul_netbsd;
     79 int cold = 1;
     80 int boothowto = AB_SILENT;
     81 struct tty *constty;
     82 
     83 char hostname[MAXHOSTNAMELEN];
     84 size_t hostnamelen;
     85 
     86 const char *panicstr;
     87 const char *domainname;
     88 int domainnamelen;
     89 
     90 const struct filterops sig_filtops;
     91 
     92 #define DEVSW_SIZE 255
     93 const struct bdevsw *bdevsw0[DEVSW_SIZE]; /* XXX storage size */
     94 const struct bdevsw **bdevsw = bdevsw0;
     95 const int sys_cdevsws = DEVSW_SIZE;
     96 int max_cdevsws = DEVSW_SIZE;
     97 
     98 const struct cdevsw *cdevsw0[DEVSW_SIZE]; /* XXX storage size */
     99 const struct cdevsw **cdevsw = cdevsw0;
    100 const int sys_bdevsws = DEVSW_SIZE;
    101 int max_bdevsws = DEVSW_SIZE;
    102 
    103 struct devsw_conv devsw_conv0;
    104 struct devsw_conv *devsw_conv = &devsw_conv0;
    105 int max_devsw_convs = 0;
    106 int mem_no = 2;
    107 
    108 struct device *booted_device;
    109 struct device *booted_wedge;
    110 int booted_partition;
    111 
    112 kmutex_t tty_lock;
    113 
    114 kmutex_t sysctl_file_marker_lock;
    115 
    116 /* sparc doesn't sport constant page size */
    117 #ifdef __sparc__
    118 int nbpg = 4096;
    119 #endif
    120 
    121 devclass_t
    122 device_class(device_t dev)
    123 {
    124 
    125 	return dev->dv_class;
    126 }
    127 
    128 void
    129 getnanouptime(struct timespec *ts)
    130 {
    131 
    132 	rump_getuptime(ts);
    133 }
    134 
    135 void
    136 getmicrouptime(struct timeval *tv)
    137 {
    138 	struct timespec ts;
    139 
    140 	getnanouptime(&ts);
    141 	TIMESPEC_TO_TIMEVAL(tv, &ts);
    142 }
    143 
    144 static void
    145 gettime(struct timespec *ts)
    146 {
    147 	uint64_t sec, nsec;
    148 	int error;
    149 
    150 	rumpuser_gettime(&sec, &nsec, &error);
    151 	ts->tv_sec = sec;
    152 	ts->tv_nsec = nsec;
    153 }
    154 
    155 void
    156 nanotime(struct timespec *ts)
    157 {
    158 
    159 	if (rump_threads) {
    160 		rump_gettime(ts);
    161 	} else {
    162 		gettime(ts);
    163 	}
    164 }
    165 
    166 /* hooray for mick, so what if I do */
    167 void
    168 getnanotime(struct timespec *ts)
    169 {
    170 
    171 	nanotime(ts);
    172 }
    173 
    174 void
    175 microtime(struct timeval *tv)
    176 {
    177 	struct timespec ts;
    178 
    179 	if (rump_threads) {
    180 		rump_gettime(&ts);
    181 		TIMESPEC_TO_TIMEVAL(tv, &ts);
    182 	} else {
    183 		gettime(&ts);
    184 		TIMESPEC_TO_TIMEVAL(tv, &ts);
    185 	}
    186 }
    187 
    188 void
    189 getmicrotime(struct timeval *tv)
    190 {
    191 
    192 	microtime(tv);
    193 }
    194 
    195 struct proc *
    196 p_find(pid_t pid, uint flags)
    197 {
    198 
    199 	panic("%s: not implemented", __func__);
    200 }
    201 
    202 struct pgrp *
    203 pg_find(pid_t pid, uint flags)
    204 {
    205 
    206 	panic("%s: not implemented", __func__);
    207 }
    208 
    209 void
    210 psignal(struct proc *p, int signo)
    211 {
    212 
    213 	switch (signo) {
    214 	case SIGSYS:
    215 		break;
    216 	default:
    217 		panic("unhandled signal %d\n", signo);
    218 	}
    219 }
    220 
    221 void
    222 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
    223 {
    224 
    225 	panic("%s: not implemented", __func__);
    226 }
    227 
    228 void
    229 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
    230 {
    231 
    232 	panic("%s: not implemented", __func__);
    233 }
    234 
    235 int
    236 pgid_in_session(struct proc *p, pid_t pg_id)
    237 {
    238 
    239 	panic("%s: not implemented", __func__);
    240 }
    241 
    242 int
    243 sigispending(struct lwp *l, int signo)
    244 {
    245 
    246 	return 0;
    247 }
    248 
    249 void
    250 sigpending1(struct lwp *l, sigset_t *ss)
    251 {
    252 
    253 	panic("%s: not implemented", __func__);
    254 }
    255 
    256 int
    257 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
    258 {
    259 	extern int hz;
    260 	int rv, error;
    261 	uint64_t sec, nsec;
    262 
    263 	if (mtx)
    264 		mutex_exit(mtx);
    265 
    266 	sec = timeo / hz;
    267 	nsec = (timeo % hz) * (1000000000 / hz);
    268 	rv = rumpuser_nanosleep(&sec, &nsec, &error);
    269 
    270 	if (mtx)
    271 		mutex_enter(mtx);
    272 
    273 	if (rv)
    274 		return error;
    275 
    276 	return 0;
    277 }
    278 
    279 void
    280 suspendsched(void)
    281 {
    282 
    283 	/* we don't control scheduling currently, can't do anything now */
    284 }
    285 
    286 void
    287 lwp_unsleep(lwp_t *l, bool cleanup)
    288 {
    289 
    290 	KASSERT(mutex_owned(l->l_mutex));
    291 
    292 	(*l->l_syncobj->sobj_unsleep)(l, cleanup);
    293 }
    294 
    295 vaddr_t
    296 calc_cache_size(struct vm_map *map, int pct, int va_pct)
    297 {
    298 	paddr_t t;
    299 
    300 	t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
    301 	if ((vaddr_t)t != t) {
    302 		panic("%s: needs tweak", __func__);
    303 	}
    304 	return t;
    305 }
    306 
    307 const char *
    308 device_xname(device_t dv)
    309 {
    310 	return "bogus0";
    311 }
    312 
    313 void
    314 assert_sleepable(void)
    315 {
    316 
    317 	/* always sleepable, although we should improve this */
    318 }
    319 
    320 void
    321 tc_setclock(const struct timespec *ts)
    322 {
    323 
    324 	panic("%s: not implemented", __func__);
    325 }
    326 
    327 int
    328 proc_uidmatch(kauth_cred_t cred, kauth_cred_t target)
    329 {
    330 
    331 	panic("%s: not implemented", __func__);
    332 }
    333 
    334 void
    335 proc_crmod_enter(void)
    336 {
    337 
    338 	panic("%s: not implemented", __func__);
    339 }
    340 
    341 void
    342 proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
    343 {
    344 
    345 	panic("%s: not implemented", __func__);
    346 }
    347 
    348 void
    349 module_init_md(void)
    350 {
    351 
    352 	/*
    353 	 * Nothing for now.  However, we should load the librump
    354 	 * symbol table.
    355 	 */
    356 }
    357 
    358 /* us and them, after all we're only ordinary seconds */
    359 static void
    360 rump_delay(unsigned int us)
    361 {
    362 	uint64_t sec, nsec;
    363 	int error;
    364 
    365 	sec = us / 1000000;
    366 	nsec = (us % 1000000) * 1000;
    367 
    368 	if (__predict_false(sec != 0))
    369 		printf("WARNING: over 1s delay\n");
    370 
    371 	rumpuser_nanosleep(&sec, &nsec, &error);
    372 }
    373 void (*delay_func)(unsigned int) = rump_delay;
    374 
    375 void
    376 kpreempt_disable(void)
    377 {
    378 
    379 	/* XXX: see below */
    380 	KPREEMPT_DISABLE(curlwp);
    381 }
    382 
    383 void
    384 kpreempt_enable(void)
    385 {
    386 
    387 	/* try to make sure kpreempt_disable() is only used from panic() */
    388 	panic("kpreempt not supported");
    389 }
    390 
    391 void
    392 proc_sesshold(struct session *ss)
    393 {
    394 
    395 	panic("proc_sesshold() impossible, session %p", ss);
    396 }
    397 
    398 void
    399 proc_sessrele(struct session *ss)
    400 {
    401 
    402 	panic("proc_sessrele() impossible, session %p", ss);
    403 }
    404 
    405 int
    406 proc_vmspace_getref(struct proc *p, struct vmspace **vm)
    407 {
    408 
    409 	/* XXX */
    410 	*vm = p->p_vmspace;
    411 	return 0;
    412 }
    413 
    414 int
    415 ttycheckoutq(struct tty *tp, int wait)
    416 {
    417 
    418 	return 1;
    419 }
    420 
    421 void
    422 cnputc(int c)
    423 {
    424 	int error;
    425 
    426 	rumpuser_putchar(c, &error);
    427 }
    428 
    429 void
    430 cnflush(void)
    431 {
    432 
    433 	/* done */
    434 }
    435 
    436 int
    437 tputchar(int c, int flags, struct tty *tp)
    438 {
    439 
    440 	cnputc(c);
    441 	return 0;
    442 }
    443 
    444 void
    445 cpu_reboot(int howto, char *bootstr)
    446 {
    447 
    448 	rump_reboot(howto);
    449 
    450 	/* this function is __dead, we must exit */
    451 	rumpuser_exit(0);
    452 }
    453 
    454 bool
    455 pmf_device_register1(struct device *dev,
    456 	bool (*suspend)(device_t, pmf_qual_t),
    457 	bool (*resume)(device_t, pmf_qual_t),
    458 	bool (*shutdown)(device_t, int))
    459 {
    460 
    461 	return true;
    462 }
    463 
    464 void
    465 pmf_device_deregister(struct device *dev)
    466 {
    467 
    468 	/* nada */
    469 }
    470 
    471 int
    472 syscall_establish(const struct emul *em, const struct syscall_package *sp)
    473 {
    474 	extern struct sysent rump_sysent[];
    475 	int i;
    476 
    477 	KASSERT(em == NULL || em == &emul_netbsd);
    478 
    479 	for (i = 0; sp[i].sp_call; i++)
    480 		rump_sysent[sp[i].sp_code].sy_call = sp[i].sp_call;
    481 
    482 	return 0;
    483 }
    484 
    485 int
    486 syscall_disestablish(const struct emul *em, const struct syscall_package *sp)
    487 {
    488 
    489 	return 0;
    490 }
    491