Home | History | Annotate | Line # | Download | only in librumpuser
rumpuser.c revision 1.60
      1  1.60  justin /*	$NetBSD: rumpuser.c,v 1.60 2014/07/09 23:41:40 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.60  justin __RCSID("$NetBSD: rumpuser.c,v 1.60 2014/07/09 23:41:40 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.2   pooka #include <signal.h>
     42   1.1   pooka #include <stdarg.h>
     43   1.1   pooka #include <stdint.h>
     44   1.1   pooka #include <stdio.h>
     45   1.1   pooka #include <stdlib.h>
     46   1.1   pooka #include <string.h>
     47   1.1   pooka #include <time.h>
     48   1.1   pooka #include <unistd.h>
     49   1.1   pooka 
     50   1.1   pooka #include <rump/rumpuser.h>
     51   1.1   pooka 
     52   1.1   pooka #include "rumpuser_int.h"
     53   1.1   pooka 
     54  1.41   pooka struct rumpuser_hyperup rumpuser__hyp;
     55  1.30   pooka 
     56   1.1   pooka int
     57  1.41   pooka rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
     58   1.8   pooka {
     59   1.8   pooka 
     60  1.30   pooka 	if (version != RUMPUSER_VERSION) {
     61  1.30   pooka 		fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
     62  1.30   pooka 		    version, RUMPUSER_VERSION);
     63  1.30   pooka 		return 1;
     64  1.30   pooka 	}
     65  1.30   pooka 
     66  1.33   pooka #ifdef RUMPUSER_USE_DEVRANDOM
     67  1.30   pooka 	uint32_t rv;
     68  1.30   pooka 	int fd;
     69  1.30   pooka 
     70  1.30   pooka 	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
     71  1.30   pooka 		srandom(time(NULL));
     72  1.30   pooka 	} else {
     73  1.30   pooka 		if (read(fd, &rv, sizeof(rv)) != sizeof(rv))
     74  1.30   pooka 			srandom(time(NULL));
     75  1.30   pooka 		else
     76  1.30   pooka 			srandom(rv);
     77  1.30   pooka 		close(fd);
     78  1.30   pooka 	}
     79  1.30   pooka #endif
     80  1.30   pooka 
     81  1.30   pooka 	rumpuser__thrinit();
     82  1.41   pooka 	rumpuser__hyp = *hyp;
     83  1.30   pooka 
     84  1.30   pooka 	return 0;
     85   1.8   pooka }
     86   1.8   pooka 
     87   1.8   pooka int
     88  1.51   pooka rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
     89   1.1   pooka {
     90  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
     91  1.36   pooka 	struct timespec ts;
     92  1.36   pooka 	clockid_t clk;
     93   1.1   pooka 	int rv;
     94   1.1   pooka 
     95  1.36   pooka 	switch (rclk) {
     96  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
     97  1.36   pooka 		clk = CLOCK_REALTIME;
     98  1.36   pooka 		break;
     99  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
    100  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
    101  1.36   pooka 		clk = CLOCK_MONOTONIC;
    102  1.36   pooka #else
    103  1.36   pooka 		clk = CLOCK_REALTIME;
    104  1.36   pooka #endif
    105  1.36   pooka 		break;
    106  1.36   pooka 	default:
    107  1.36   pooka 		abort();
    108  1.36   pooka 	}
    109  1.36   pooka 
    110  1.47   pooka 	if (clock_gettime(clk, &ts) == -1) {
    111  1.45   pooka 		rv = errno;
    112  1.45   pooka 	} else {
    113  1.45   pooka 		*sec = ts.tv_sec;
    114  1.45   pooka 		*nsec = ts.tv_nsec;
    115  1.45   pooka 		rv = 0;
    116   1.1   pooka 	}
    117   1.1   pooka 
    118  1.47   pooka 	ET(rv);
    119  1.36   pooka }
    120  1.36   pooka 
    121  1.36   pooka int
    122  1.51   pooka rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
    123  1.36   pooka {
    124  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
    125  1.36   pooka 	struct timespec rqt, rmt;
    126  1.36   pooka 	int nlocks;
    127  1.36   pooka 	int rv;
    128  1.36   pooka 
    129  1.41   pooka 	rumpkern_unsched(&nlocks, NULL);
    130  1.36   pooka 
    131  1.36   pooka 	/*LINTED*/
    132  1.36   pooka 	rqt.tv_sec = sec;
    133  1.36   pooka 	/*LINTED*/
    134  1.36   pooka 	rqt.tv_nsec = nsec;
    135   1.1   pooka 
    136  1.51   pooka 	switch (rclk) {
    137  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
    138  1.36   pooka 		do {
    139  1.36   pooka 			rv = nanosleep(&rqt, &rmt);
    140  1.36   pooka 			rqt = rmt;
    141  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    142  1.36   pooka 		if (rv == -1) {
    143  1.36   pooka 			rv = errno;
    144  1.36   pooka 		}
    145  1.36   pooka 		break;
    146  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
    147  1.36   pooka 		do {
    148  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
    149  1.36   pooka 			rv = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
    150  1.36   pooka 			    &rqt, NULL);
    151  1.36   pooka #else
    152  1.36   pooka 			/* le/la/der/die/das sigh. timevalspec tailspin */
    153  1.36   pooka 			struct timespec ts, tsr;
    154  1.36   pooka 			clock_gettime(CLOCK_REALTIME, &ts);
    155  1.36   pooka 			if (ts.tv_sec == rqt.tv_sec ?
    156  1.36   pooka 			    ts.tv_nsec > rqt.tv_nsec : ts.tv_sec > rqt.tv_sec) {
    157  1.36   pooka 				rv = 0;
    158  1.36   pooka 			} else {
    159  1.36   pooka 				tsr.tv_sec = rqt.tv_sec - ts.tv_sec;
    160  1.36   pooka 				tsr.tv_nsec = rqt.tv_nsec - ts.tv_nsec;
    161  1.36   pooka 				if (tsr.tv_nsec < 0) {
    162  1.36   pooka 					tsr.tv_sec--;
    163  1.36   pooka 					tsr.tv_nsec += 1000*1000*1000;
    164  1.36   pooka 				}
    165  1.36   pooka 				rv = nanosleep(&tsr, NULL);
    166  1.36   pooka 			}
    167  1.36   pooka #endif
    168  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    169  1.36   pooka 		if (rv == -1) {
    170  1.36   pooka 			rv = errno;
    171  1.36   pooka 		}
    172  1.36   pooka 		break;
    173  1.36   pooka 	default:
    174  1.36   pooka 		abort();
    175  1.36   pooka 	}
    176  1.36   pooka 
    177  1.41   pooka 	rumpkern_sched(nlocks, NULL);
    178  1.47   pooka 
    179  1.47   pooka 	ET(rv);
    180   1.1   pooka }
    181   1.1   pooka 
    182  1.43   pooka static int
    183  1.43   pooka gethostncpu(void)
    184   1.1   pooka {
    185  1.59   pooka 	int ncpu = 1; /* unknown, really */
    186  1.43   pooka 
    187  1.59   pooka #ifdef _SC_NPROCESSORS_ONLN
    188  1.43   pooka 	ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    189  1.43   pooka #endif
    190  1.43   pooka 
    191  1.43   pooka 	return ncpu;
    192   1.1   pooka }
    193   1.1   pooka 
    194   1.1   pooka int
    195  1.43   pooka rumpuser_getparam(const char *name, void *buf, size_t blen)
    196   1.1   pooka {
    197  1.45   pooka 	int rv;
    198   1.1   pooka 
    199  1.43   pooka 	if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
    200  1.43   pooka 		int ncpu;
    201  1.43   pooka 
    202  1.43   pooka 		if (getenv_r("RUMP_NCPU", buf, blen) == -1) {
    203  1.54   pooka 			sprintf(buf, "2"); /* default */
    204  1.54   pooka 		} else if (strcmp(buf, "host") == 0) {
    205  1.43   pooka 			ncpu = gethostncpu();
    206  1.43   pooka 			snprintf(buf, blen, "%d", ncpu);
    207  1.43   pooka 		}
    208  1.45   pooka 		rv = 0;
    209  1.43   pooka 	} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
    210  1.43   pooka 		char tmp[MAXHOSTNAMELEN];
    211  1.43   pooka 
    212  1.43   pooka 		if (gethostname(tmp, sizeof(tmp)) == -1) {
    213  1.43   pooka 			snprintf(buf, blen, "rump-%05d", (int)getpid());
    214  1.43   pooka 		} else {
    215  1.43   pooka 			snprintf(buf, blen, "rump-%05d.%s",
    216  1.43   pooka 			    (int)getpid(), tmp);
    217  1.43   pooka 		}
    218  1.45   pooka 		rv = 0;
    219  1.43   pooka 	} else if (*name == '_') {
    220  1.45   pooka 		rv = EINVAL;
    221  1.13   pooka 	} else {
    222  1.43   pooka 		if (getenv_r(name, buf, blen) == -1)
    223  1.45   pooka 			rv = errno;
    224  1.43   pooka 		else
    225  1.45   pooka 			rv = 0;
    226  1.13   pooka 	}
    227  1.45   pooka 
    228  1.47   pooka 	ET(rv);
    229   1.1   pooka }
    230   1.1   pooka 
    231  1.45   pooka void
    232  1.45   pooka rumpuser_putchar(int c)
    233   1.1   pooka {
    234   1.1   pooka 
    235  1.45   pooka 	putchar(c);
    236   1.1   pooka }
    237   1.1   pooka 
    238  1.55   rmind __dead void
    239   1.1   pooka rumpuser_exit(int rv)
    240   1.1   pooka {
    241   1.1   pooka 
    242   1.1   pooka 	if (rv == RUMPUSER_PANIC)
    243   1.1   pooka 		abort();
    244   1.1   pooka 	else
    245   1.1   pooka 		exit(rv);
    246   1.1   pooka }
    247   1.1   pooka 
    248   1.1   pooka void
    249   1.1   pooka rumpuser_seterrno(int error)
    250   1.1   pooka {
    251   1.1   pooka 
    252   1.1   pooka 	errno = error;
    253   1.1   pooka }
    254   1.1   pooka 
    255  1.21   pooka /*
    256   1.1   pooka  * This is meant for safe debugging prints from the kernel.
    257   1.1   pooka  */
    258  1.45   pooka void
    259   1.1   pooka rumpuser_dprintf(const char *format, ...)
    260   1.1   pooka {
    261   1.1   pooka 	va_list ap;
    262   1.1   pooka 
    263   1.1   pooka 	va_start(ap, format);
    264  1.45   pooka 	vfprintf(stderr, format, ap);
    265   1.1   pooka 	va_end(ap);
    266   1.1   pooka }
    267   1.2   pooka 
    268   1.2   pooka int
    269  1.56   pooka rumpuser_kill(int64_t pid, int rumpsig)
    270   1.2   pooka {
    271  1.57   pooka 	int sig;
    272  1.49   pooka 
    273  1.56   pooka 	sig = rumpuser__sig_rump2host(rumpsig);
    274  1.57   pooka 	if (sig > 0)
    275  1.57   pooka 		raise(sig);
    276  1.57   pooka 	return 0;
    277   1.2   pooka }
    278   1.4   pooka 
    279  1.45   pooka int
    280  1.45   pooka rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
    281  1.16     tls {
    282  1.33   pooka 	size_t origlen = buflen;
    283  1.33   pooka 	uint32_t *p = buf;
    284  1.33   pooka 	uint32_t tmp;
    285  1.33   pooka 	int chunk;
    286  1.18   pooka 
    287  1.33   pooka 	do {
    288  1.33   pooka 		chunk = buflen < 4 ? buflen : 4; /* portable MIN ... */
    289  1.33   pooka 		tmp = RUMPUSER_RANDOM();
    290  1.33   pooka 		memcpy(p, &tmp, chunk);
    291  1.33   pooka 		p++;
    292  1.33   pooka 		buflen -= chunk;
    293  1.33   pooka 	} while (chunk);
    294  1.33   pooka 
    295  1.45   pooka 	*retp = origlen;
    296  1.47   pooka 	ET(0);
    297  1.16     tls }
    298