1 /* $NetBSD: emul.c,v 1.38 2008/04/24 17:02:18 ad Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by Google Summer of Code. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #define malloc(a,b,c) __wrap_malloc(a,b,c) 31 32 #include <sys/param.h> 33 #include <sys/malloc.h> 34 #include <sys/null.h> 35 #include <sys/vnode.h> 36 #include <sys/stat.h> 37 #include <sys/select.h> 38 #include <sys/syslog.h> 39 #include <sys/namei.h> 40 #include <sys/kauth.h> 41 #include <sys/conf.h> 42 #include <sys/device.h> 43 #include <sys/queue.h> 44 #include <sys/file.h> 45 #include <sys/filedesc.h> 46 #include <sys/kthread.h> 47 #include <sys/cpu.h> 48 #include <sys/kmem.h> 49 #include <sys/poll.h> 50 51 #include <machine/stdarg.h> 52 53 #include <uvm/uvm_map.h> 54 55 #include "rump_private.h" 56 #include "rumpuser.h" 57 58 time_t time_second = 1; 59 60 kmutex_t *proc_lock; 61 struct lwp lwp0; 62 struct vnode *rootvp; 63 struct device *root_device; 64 dev_t rootdev; 65 struct vm_map *kernel_map; 66 int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */ 67 int doing_shutdown; 68 int ncpu = 1; 69 const int schedppq = 1; 70 int hardclock_ticks; 71 72 MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure"); 73 MALLOC_DEFINE(M_TEMP, "temp", "misc. temporary data buffers"); 74 MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); 75 MALLOC_DEFINE(M_KEVENT, "kevent", "kevents/knotes"); 76 77 char hostname[MAXHOSTNAMELEN]; 78 size_t hostnamelen; 79 80 u_long bufmem_valimit; 81 u_long bufmem_hiwater; 82 u_long bufmem_lowater; 83 u_long bufmem; 84 u_int nbuf; 85 86 const char *panicstr; 87 const char ostype[] = "NetBSD"; 88 const char osrelease[] = "999"; /* paradroid 4evah */ 89 const char kernel_ident[] = "RUMP-ROAST"; 90 const char *domainname; 91 int domainnamelen; 92 93 const struct filterops seltrue_filtops; 94 95 void 96 panic(const char *fmt, ...) 97 { 98 va_list ap; 99 100 va_start(ap, fmt); 101 printf("panic: "); 102 vprintf(fmt, ap); 103 va_end(ap); 104 printf("\n"); 105 abort(); 106 } 107 108 void 109 log(int level, const char *fmt, ...) 110 { 111 va_list ap; 112 113 va_start(ap, fmt); 114 vprintf(fmt, ap); 115 va_end(ap); 116 } 117 118 void 119 uprintf(const char *fmt, ...) 120 { 121 va_list ap; 122 123 va_start(ap, fmt); 124 vprintf(fmt, ap); 125 va_end(ap); 126 } 127 128 void 129 printf_nolog(const char *fmt, ...) 130 { 131 va_list ap; 132 133 va_start(ap, fmt); 134 vprintf(fmt, ap); 135 va_end(ap); 136 } 137 138 void 139 aprint_normal(const char *fmt, ...) 140 { 141 va_list ap; 142 143 va_start(ap, fmt); 144 vprintf(fmt, ap); 145 va_end(ap); 146 } 147 148 int 149 copyin(const void *uaddr, void *kaddr, size_t len) 150 { 151 152 memcpy(kaddr, uaddr, len); 153 return 0; 154 } 155 156 int 157 copyout(const void *kaddr, void *uaddr, size_t len) 158 { 159 160 memcpy(uaddr, kaddr, len); 161 return 0; 162 } 163 164 int 165 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) 166 { 167 168 return copyinstr(kfaddr, kdaddr, len, done); 169 } 170 171 int 172 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 173 { 174 175 strlcpy(kaddr, uaddr, len); 176 if (done) 177 *done = strlen(kaddr)+1; /* includes termination */ 178 return 0; 179 } 180 181 int 182 uiomove(void *buf, size_t n, struct uio *uio) 183 { 184 struct iovec *iov; 185 uint8_t *b = buf; 186 size_t cnt; 187 int rv; 188 189 if (uio->uio_vmspace != UIO_VMSPACE_SYS) 190 panic("%s: vmspace != UIO_VMSPACE_SYS", __func__); 191 192 /* 193 * See if rump ubc code claims the offset. This is of course 194 * a blatant violation of abstraction levels, but let's keep 195 * me simple & stupid for now. 196 */ 197 if (rump_ubc_magic_uiomove(buf, n, uio, &rv, NULL)) 198 return rv; 199 200 while (n && uio->uio_resid) { 201 iov = uio->uio_iov; 202 cnt = iov->iov_len; 203 if (cnt == 0) { 204 uio->uio_iov++; 205 uio->uio_iovcnt--; 206 continue; 207 } 208 if (cnt > n) 209 cnt = n; 210 211 if (uio->uio_rw == UIO_READ) 212 memcpy(iov->iov_base, b, cnt); 213 else 214 memcpy(b, iov->iov_base, cnt); 215 216 iov->iov_base = (uint8_t *)iov->iov_base + cnt; 217 iov->iov_len -= cnt; 218 b += cnt; 219 uio->uio_resid -= cnt; 220 uio->uio_offset += cnt; 221 n -= cnt; 222 } 223 224 return 0; 225 } 226 227 void 228 uio_setup_sysspace(struct uio *uio) 229 { 230 231 uio->uio_vmspace = UIO_VMSPACE_SYS; 232 } 233 234 const struct bdevsw * 235 bdevsw_lookup(dev_t dev) 236 { 237 238 return (const struct bdevsw *)1; 239 } 240 241 devclass_t 242 device_class(device_t dev) 243 { 244 245 if (dev != root_device) 246 panic("%s: dev != root_device not supported", __func__); 247 248 return DV_DISK; 249 } 250 251 void 252 getmicrouptime(struct timeval *tvp) 253 { 254 int error; 255 256 rumpuser_gettimeofday(tvp, &error); 257 } 258 259 void 260 malloc_type_attach(struct malloc_type *type) 261 { 262 263 return; 264 } 265 266 void 267 malloc_type_detach(struct malloc_type *type) 268 { 269 270 return; 271 } 272 273 void * 274 __wrap_malloc(unsigned long size, struct malloc_type *type, int flags) 275 { 276 void *rv; 277 278 rv = rumpuser_malloc(size, (flags & (M_CANFAIL | M_NOWAIT)) != 0); 279 if (rv && flags & M_ZERO) 280 memset(rv, 0, size); 281 282 return rv; 283 } 284 285 void 286 nanotime(struct timespec *ts) 287 { 288 struct timeval tv; 289 int error; 290 291 rumpuser_gettimeofday(&tv, &error); 292 TIMEVAL_TO_TIMESPEC(&tv, ts); 293 } 294 295 /* hooray for mick, so what if I do */ 296 void 297 getnanotime(struct timespec *ts) 298 { 299 300 nanotime(ts); 301 } 302 303 void 304 microtime(struct timeval *tv) 305 { 306 int error; 307 308 rumpuser_gettimeofday(tv, &error); 309 } 310 311 void 312 getmicrotime(struct timeval *tv) 313 { 314 int error; 315 316 rumpuser_gettimeofday(tv, &error); 317 } 318 319 void 320 bdev_strategy(struct buf *bp) 321 { 322 323 panic("%s: not supported", __func__); 324 } 325 326 int 327 bdev_type(dev_t dev) 328 { 329 330 return D_DISK; 331 } 332 333 struct kthdesc { 334 void (*f)(void *); 335 void *arg; 336 struct lwp *mylwp; 337 }; 338 339 static lwpid_t curlid = 2; 340 341 static void * 342 threadbouncer(void *arg) 343 { 344 struct kthdesc *k = arg; 345 void (*f)(void *); 346 void *thrarg; 347 348 f = k->f; 349 thrarg = k->arg; 350 rumpuser_set_curlwp(k->mylwp); 351 kmem_free(k, sizeof(struct kthdesc)); 352 353 f(thrarg); 354 panic("unreachable, should kthread_exit()"); 355 } 356 357 int 358 kthread_create(pri_t pri, int flags, struct cpu_info *ci, 359 void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...) 360 { 361 struct kthdesc *k; 362 struct lwp *l; 363 int rv; 364 365 #ifdef RUMP_WITHOUT_THREADS 366 /* XXX: fake it */ 367 if (strcmp(fmt, "vrele") == 0) 368 return 0; 369 else 370 panic("threads not available, undef RUMP_WITHOUT_THREADS"); 371 #endif 372 373 KASSERT(fmt != NULL); 374 if (ci != NULL) 375 panic("%s: bounded threads not supported", __func__); 376 377 k = kmem_alloc(sizeof(struct kthdesc), KM_SLEEP); 378 k->f = func; 379 k->arg = arg; 380 k->mylwp = l = rump_setup_curlwp(0, curlid++, 0); 381 rv = rumpuser_thread_create(threadbouncer, k); 382 if (rv) 383 return rv; 384 385 if (newlp) 386 *newlp = l; 387 return 0; 388 } 389 390 void 391 kthread_exit(int ecode) 392 { 393 394 rumpuser_thread_exit(); 395 } 396 397 void 398 callout_init(callout_t *c, u_int flags) 399 { 400 401 panic("%s: not implemented", __func__); 402 } 403 404 void 405 callout_reset(callout_t *c, int ticks, void (*func)(void *), void *arg) 406 { 407 408 panic("%s: not implemented", __func__); 409 } 410 411 bool 412 callout_stop(callout_t *c) 413 { 414 415 panic("%s: not implemented", __func__); 416 } 417 418 struct proc * 419 p_find(pid_t pid, uint flags) 420 { 421 422 panic("%s: not implemented", __func__); 423 } 424 425 struct pgrp * 426 pg_find(pid_t pid, uint flags) 427 { 428 429 panic("%s: not implemented", __func__); 430 } 431 432 void 433 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data) 434 { 435 436 panic("%s: not implemented", __func__); 437 } 438 439 void 440 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty) 441 { 442 443 panic("%s: not implemented", __func__); 444 } 445 446 int 447 pgid_in_session(struct proc *p, pid_t pg_id) 448 { 449 450 panic("%s: not implemented", __func__); 451 } 452 453 int 454 sigispending(struct lwp *l, int signo) 455 { 456 457 return 0; 458 } 459 460 void 461 knote_fdclose(int fd) 462 { 463 464 /* since we don't add knotes, we don't have to remove them */ 465 } 466 467 int 468 seltrue_kqfilter(dev_t dev, struct knote *kn) 469 { 470 471 panic("%s: not implemented", __func__); 472 } 473 474 int 475 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx) 476 { 477 extern int hz; 478 int rv, error; 479 480 if (mtx) 481 mutex_exit(mtx); 482 rv = rumpuser_usleep(timeo * (1000000 / hz), &error); 483 if (mtx) 484 mutex_enter(mtx); 485 486 if (rv) 487 return error; 488 489 return 0; 490 } 491 492 void 493 suspendsched() 494 { 495 496 panic("%s: not implemented", __func__); 497 } 498 499 void 500 yield(void) 501 { 502 503 rumpuser_yield(); 504 } 505 506 507 u_int 508 lwp_unsleep(lwp_t *l, bool cleanup) 509 { 510 511 KASSERT(mutex_owned(l->l_mutex)); 512 513 return (*l->l_syncobj->sobj_unsleep)(l, cleanup); 514 } 515 516 vaddr_t 517 calc_cache_size(struct vm_map *map, int pct, int va_pct) 518 { 519 paddr_t t; 520 521 t = (paddr_t)physmem * pct / 100 * PAGE_SIZE; 522 if ((vaddr_t)t != t) { 523 panic("%s: needs tweak", __func__); 524 } 525 return t; 526 } 527 528 int 529 seltrue(dev_t dev, int events, struct lwp *l) 530 { 531 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 532 } 533 534 void 535 selrecord(lwp_t *selector, struct selinfo *sip) 536 { 537 } 538 539 void 540 selinit(struct selinfo *sip) 541 { 542 } 543 544 void 545 selnotify(struct selinfo *sip, int events, long knhint) 546 { 547 } 548 549 void 550 seldestroy(struct selinfo *sip) 551 { 552 } 553 554 const char * 555 device_xname(device_t dv) 556 { 557 return "bogus0"; 558 } 559