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