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