Home | History | Annotate | Line # | Download | only in librumpuser
rumpuser.c revision 1.61
      1  1.61  justin /*	$NetBSD: rumpuser.c,v 1.61 2014/07/10 08:17:43 justin Exp $	*/
      2   1.1   pooka 
      3   1.1   pooka /*
      4   1.1   pooka  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
      5   1.1   pooka  *
      6   1.1   pooka  * Redistribution and use in source and binary forms, with or without
      7   1.1   pooka  * modification, are permitted provided that the following conditions
      8   1.1   pooka  * are met:
      9   1.1   pooka  * 1. Redistributions of source code must retain the above copyright
     10   1.1   pooka  *    notice, this list of conditions and the following disclaimer.
     11   1.1   pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1   pooka  *    notice, this list of conditions and the following disclaimer in the
     13   1.1   pooka  *    documentation and/or other materials provided with the distribution.
     14   1.1   pooka  *
     15   1.1   pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16   1.1   pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17   1.1   pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18   1.1   pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19   1.1   pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20   1.1   pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21   1.1   pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22   1.1   pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23   1.1   pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24   1.1   pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25   1.1   pooka  * SUCH DAMAGE.
     26   1.1   pooka  */
     27   1.1   pooka 
     28  1.18   pooka #include "rumpuser_port.h"
     29  1.18   pooka 
     30   1.1   pooka #if !defined(lint)
     31  1.61  justin __RCSID("$NetBSD: rumpuser.c,v 1.61 2014/07/10 08:17:43 justin Exp $");
     32   1.1   pooka #endif /* !lint */
     33   1.1   pooka 
     34  1.18   pooka #include <sys/stat.h>
     35  1.18   pooka #include <sys/time.h>
     36  1.60  justin #include <sys/types.h>
     37   1.1   pooka 
     38   1.1   pooka #include <assert.h>
     39   1.1   pooka #include <errno.h>
     40   1.1   pooka #include <fcntl.h>
     41  1.61  justin #include <netdb.h>
     42   1.2   pooka #include <signal.h>
     43   1.1   pooka #include <stdarg.h>
     44   1.1   pooka #include <stdint.h>
     45   1.1   pooka #include <stdio.h>
     46   1.1   pooka #include <stdlib.h>
     47   1.1   pooka #include <string.h>
     48   1.1   pooka #include <time.h>
     49   1.1   pooka #include <unistd.h>
     50   1.1   pooka 
     51   1.1   pooka #include <rump/rumpuser.h>
     52   1.1   pooka 
     53   1.1   pooka #include "rumpuser_int.h"
     54   1.1   pooka 
     55  1.41   pooka struct rumpuser_hyperup rumpuser__hyp;
     56  1.30   pooka 
     57   1.1   pooka int
     58  1.41   pooka rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
     59   1.8   pooka {
     60   1.8   pooka 
     61  1.30   pooka 	if (version != RUMPUSER_VERSION) {
     62  1.30   pooka 		fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
     63  1.30   pooka 		    version, RUMPUSER_VERSION);
     64  1.30   pooka 		return 1;
     65  1.30   pooka 	}
     66  1.30   pooka 
     67  1.33   pooka #ifdef RUMPUSER_USE_DEVRANDOM
     68  1.30   pooka 	uint32_t rv;
     69  1.30   pooka 	int fd;
     70  1.30   pooka 
     71  1.30   pooka 	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
     72  1.30   pooka 		srandom(time(NULL));
     73  1.30   pooka 	} else {
     74  1.30   pooka 		if (read(fd, &rv, sizeof(rv)) != sizeof(rv))
     75  1.30   pooka 			srandom(time(NULL));
     76  1.30   pooka 		else
     77  1.30   pooka 			srandom(rv);
     78  1.30   pooka 		close(fd);
     79  1.30   pooka 	}
     80  1.30   pooka #endif
     81  1.30   pooka 
     82  1.30   pooka 	rumpuser__thrinit();
     83  1.41   pooka 	rumpuser__hyp = *hyp;
     84  1.30   pooka 
     85  1.30   pooka 	return 0;
     86   1.8   pooka }
     87   1.8   pooka 
     88   1.8   pooka int
     89  1.51   pooka rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
     90   1.1   pooka {
     91  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
     92  1.36   pooka 	struct timespec ts;
     93  1.36   pooka 	clockid_t clk;
     94   1.1   pooka 	int rv;
     95   1.1   pooka 
     96  1.36   pooka 	switch (rclk) {
     97  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
     98  1.36   pooka 		clk = CLOCK_REALTIME;
     99  1.36   pooka 		break;
    100  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
    101  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
    102  1.36   pooka 		clk = CLOCK_MONOTONIC;
    103  1.36   pooka #else
    104  1.36   pooka 		clk = CLOCK_REALTIME;
    105  1.36   pooka #endif
    106  1.36   pooka 		break;
    107  1.36   pooka 	default:
    108  1.36   pooka 		abort();
    109  1.36   pooka 	}
    110  1.36   pooka 
    111  1.47   pooka 	if (clock_gettime(clk, &ts) == -1) {
    112  1.45   pooka 		rv = errno;
    113  1.45   pooka 	} else {
    114  1.45   pooka 		*sec = ts.tv_sec;
    115  1.45   pooka 		*nsec = ts.tv_nsec;
    116  1.45   pooka 		rv = 0;
    117   1.1   pooka 	}
    118   1.1   pooka 
    119  1.47   pooka 	ET(rv);
    120  1.36   pooka }
    121  1.36   pooka 
    122  1.36   pooka int
    123  1.51   pooka rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
    124  1.36   pooka {
    125  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
    126  1.36   pooka 	struct timespec rqt, rmt;
    127  1.36   pooka 	int nlocks;
    128  1.36   pooka 	int rv;
    129  1.36   pooka 
    130  1.41   pooka 	rumpkern_unsched(&nlocks, NULL);
    131  1.36   pooka 
    132  1.36   pooka 	/*LINTED*/
    133  1.36   pooka 	rqt.tv_sec = sec;
    134  1.36   pooka 	/*LINTED*/
    135  1.36   pooka 	rqt.tv_nsec = nsec;
    136   1.1   pooka 
    137  1.51   pooka 	switch (rclk) {
    138  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
    139  1.36   pooka 		do {
    140  1.36   pooka 			rv = nanosleep(&rqt, &rmt);
    141  1.36   pooka 			rqt = rmt;
    142  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    143  1.36   pooka 		if (rv == -1) {
    144  1.36   pooka 			rv = errno;
    145  1.36   pooka 		}
    146  1.36   pooka 		break;
    147  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
    148  1.36   pooka 		do {
    149  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
    150  1.36   pooka 			rv = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
    151  1.36   pooka 			    &rqt, NULL);
    152  1.36   pooka #else
    153  1.36   pooka 			/* le/la/der/die/das sigh. timevalspec tailspin */
    154  1.36   pooka 			struct timespec ts, tsr;
    155  1.36   pooka 			clock_gettime(CLOCK_REALTIME, &ts);
    156  1.36   pooka 			if (ts.tv_sec == rqt.tv_sec ?
    157  1.36   pooka 			    ts.tv_nsec > rqt.tv_nsec : ts.tv_sec > rqt.tv_sec) {
    158  1.36   pooka 				rv = 0;
    159  1.36   pooka 			} else {
    160  1.36   pooka 				tsr.tv_sec = rqt.tv_sec - ts.tv_sec;
    161  1.36   pooka 				tsr.tv_nsec = rqt.tv_nsec - ts.tv_nsec;
    162  1.36   pooka 				if (tsr.tv_nsec < 0) {
    163  1.36   pooka 					tsr.tv_sec--;
    164  1.36   pooka 					tsr.tv_nsec += 1000*1000*1000;
    165  1.36   pooka 				}
    166  1.36   pooka 				rv = nanosleep(&tsr, NULL);
    167  1.36   pooka 			}
    168  1.36   pooka #endif
    169  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    170  1.36   pooka 		if (rv == -1) {
    171  1.36   pooka 			rv = errno;
    172  1.36   pooka 		}
    173  1.36   pooka 		break;
    174  1.36   pooka 	default:
    175  1.36   pooka 		abort();
    176  1.36   pooka 	}
    177  1.36   pooka 
    178  1.41   pooka 	rumpkern_sched(nlocks, NULL);
    179  1.47   pooka 
    180  1.47   pooka 	ET(rv);
    181   1.1   pooka }
    182   1.1   pooka 
    183  1.43   pooka static int
    184  1.43   pooka gethostncpu(void)
    185   1.1   pooka {
    186  1.59   pooka 	int ncpu = 1; /* unknown, really */
    187  1.43   pooka 
    188  1.59   pooka #ifdef _SC_NPROCESSORS_ONLN
    189  1.43   pooka 	ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    190  1.43   pooka #endif
    191  1.43   pooka 
    192  1.43   pooka 	return ncpu;
    193   1.1   pooka }
    194   1.1   pooka 
    195   1.1   pooka int
    196  1.43   pooka rumpuser_getparam(const char *name, void *buf, size_t blen)
    197   1.1   pooka {
    198  1.45   pooka 	int rv;
    199   1.1   pooka 
    200  1.43   pooka 	if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
    201  1.43   pooka 		int ncpu;
    202  1.43   pooka 
    203  1.43   pooka 		if (getenv_r("RUMP_NCPU", buf, blen) == -1) {
    204  1.54   pooka 			sprintf(buf, "2"); /* default */
    205  1.54   pooka 		} else if (strcmp(buf, "host") == 0) {
    206  1.43   pooka 			ncpu = gethostncpu();
    207  1.43   pooka 			snprintf(buf, blen, "%d", ncpu);
    208  1.43   pooka 		}
    209  1.45   pooka 		rv = 0;
    210  1.43   pooka 	} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
    211  1.43   pooka 		char tmp[MAXHOSTNAMELEN];
    212  1.43   pooka 
    213  1.43   pooka 		if (gethostname(tmp, sizeof(tmp)) == -1) {
    214  1.43   pooka 			snprintf(buf, blen, "rump-%05d", (int)getpid());
    215  1.43   pooka 		} else {
    216  1.43   pooka 			snprintf(buf, blen, "rump-%05d.%s",
    217  1.43   pooka 			    (int)getpid(), tmp);
    218  1.43   pooka 		}
    219  1.45   pooka 		rv = 0;
    220  1.43   pooka 	} else if (*name == '_') {
    221  1.45   pooka 		rv = EINVAL;
    222  1.13   pooka 	} else {
    223  1.43   pooka 		if (getenv_r(name, buf, blen) == -1)
    224  1.45   pooka 			rv = errno;
    225  1.43   pooka 		else
    226  1.45   pooka 			rv = 0;
    227  1.13   pooka 	}
    228  1.45   pooka 
    229  1.47   pooka 	ET(rv);
    230   1.1   pooka }
    231   1.1   pooka 
    232  1.45   pooka void
    233  1.45   pooka rumpuser_putchar(int c)
    234   1.1   pooka {
    235   1.1   pooka 
    236  1.45   pooka 	putchar(c);
    237   1.1   pooka }
    238   1.1   pooka 
    239  1.55   rmind __dead void
    240   1.1   pooka rumpuser_exit(int rv)
    241   1.1   pooka {
    242   1.1   pooka 
    243   1.1   pooka 	if (rv == RUMPUSER_PANIC)
    244   1.1   pooka 		abort();
    245   1.1   pooka 	else
    246   1.1   pooka 		exit(rv);
    247   1.1   pooka }
    248   1.1   pooka 
    249   1.1   pooka void
    250   1.1   pooka rumpuser_seterrno(int error)
    251   1.1   pooka {
    252   1.1   pooka 
    253   1.1   pooka 	errno = error;
    254   1.1   pooka }
    255   1.1   pooka 
    256  1.21   pooka /*
    257   1.1   pooka  * This is meant for safe debugging prints from the kernel.
    258   1.1   pooka  */
    259  1.45   pooka void
    260   1.1   pooka rumpuser_dprintf(const char *format, ...)
    261   1.1   pooka {
    262   1.1   pooka 	va_list ap;
    263   1.1   pooka 
    264   1.1   pooka 	va_start(ap, format);
    265  1.45   pooka 	vfprintf(stderr, format, ap);
    266   1.1   pooka 	va_end(ap);
    267   1.1   pooka }
    268   1.2   pooka 
    269   1.2   pooka int
    270  1.56   pooka rumpuser_kill(int64_t pid, int rumpsig)
    271   1.2   pooka {
    272  1.57   pooka 	int sig;
    273  1.49   pooka 
    274  1.56   pooka 	sig = rumpuser__sig_rump2host(rumpsig);
    275  1.57   pooka 	if (sig > 0)
    276  1.57   pooka 		raise(sig);
    277  1.57   pooka 	return 0;
    278   1.2   pooka }
    279   1.4   pooka 
    280  1.45   pooka int
    281  1.45   pooka rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
    282  1.16     tls {
    283  1.33   pooka 	size_t origlen = buflen;
    284  1.33   pooka 	uint32_t *p = buf;
    285  1.33   pooka 	uint32_t tmp;
    286  1.33   pooka 	int chunk;
    287  1.18   pooka 
    288  1.33   pooka 	do {
    289  1.33   pooka 		chunk = buflen < 4 ? buflen : 4; /* portable MIN ... */
    290  1.33   pooka 		tmp = RUMPUSER_RANDOM();
    291  1.33   pooka 		memcpy(p, &tmp, chunk);
    292  1.33   pooka 		p++;
    293  1.33   pooka 		buflen -= chunk;
    294  1.33   pooka 	} while (chunk);
    295  1.33   pooka 
    296  1.45   pooka 	*retp = origlen;
    297  1.47   pooka 	ET(0);
    298  1.16     tls }
    299