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