emul.c revision 1.53 1 /* $NetBSD: emul.c,v 1.53 2008/10/14 10:42:27 pooka 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 #include <sys/tprintf.h>
51 #include <sys/timetc.h>
52
53 #include <machine/stdarg.h>
54
55 #include <rump/rumpuser.h>
56
57 #include <uvm/uvm_map.h>
58
59 #include "rump_private.h"
60
61 time_t time_second = 1;
62
63 kmutex_t *proc_lock;
64 struct lwp lwp0;
65 struct vnode *rootvp;
66 struct device *root_device;
67 dev_t rootdev;
68 int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */
69 int doing_shutdown;
70 int ncpu = 1;
71 const int schedppq = 1;
72 int hardclock_ticks;
73 bool mp_online = false;
74 struct vm_map *mb_map;
75
76 char hostname[MAXHOSTNAMELEN];
77 size_t hostnamelen;
78
79 u_long bufmem_valimit;
80 u_long bufmem_hiwater;
81 u_long bufmem_lowater;
82 u_long bufmem;
83 u_int nbuf;
84
85 const char *panicstr;
86 const char ostype[] = "NetBSD";
87 const char osrelease[] = "999"; /* paradroid 4evah */
88 const char kernel_ident[] = "RUMP-ROAST";
89 const char *domainname;
90 int domainnamelen;
91
92 const struct filterops seltrue_filtops;
93
94 void
95 panic(const char *fmt, ...)
96 {
97 va_list ap;
98
99 va_start(ap, fmt);
100 printf("panic: ");
101 vprintf(fmt, ap);
102 va_end(ap);
103 printf("\n");
104 abort();
105 }
106
107 void
108 log(int level, const char *fmt, ...)
109 {
110 va_list ap;
111
112 va_start(ap, fmt);
113 vprintf(fmt, ap);
114 va_end(ap);
115 }
116
117 void
118 vlog(int level, const char *fmt, va_list ap)
119 {
120
121 vprintf(fmt, ap);
122 }
123
124 void
125 uprintf(const char *fmt, ...)
126 {
127 va_list ap;
128
129 va_start(ap, fmt);
130 vprintf(fmt, ap);
131 va_end(ap);
132 }
133
134 /* relegate this to regular printf */
135 tpr_t
136 tprintf_open(struct proc *p)
137 {
138
139 return (tpr_t)0x111;
140 }
141
142 void
143 tprintf(tpr_t tpr, const char *fmt, ...)
144 {
145 va_list ap;
146
147 va_start(ap, fmt);
148 vprintf(fmt, ap);
149 va_end(ap);
150 }
151
152 void
153 tprintf_close(tpr_t tpr)
154 {
155
156 }
157
158 void
159 printf_nolog(const char *fmt, ...)
160 {
161 va_list ap;
162
163 va_start(ap, fmt);
164 vprintf(fmt, ap);
165 va_end(ap);
166 }
167
168 void
169 aprint_normal(const char *fmt, ...)
170 {
171 va_list ap;
172
173 va_start(ap, fmt);
174 vprintf(fmt, ap);
175 va_end(ap);
176 }
177
178 int
179 copyin(const void *uaddr, void *kaddr, size_t len)
180 {
181
182 memcpy(kaddr, uaddr, len);
183 return 0;
184 }
185
186 int
187 copyout(const void *kaddr, void *uaddr, size_t len)
188 {
189
190 memcpy(uaddr, kaddr, len);
191 return 0;
192 }
193
194 int
195 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
196 {
197
198 return copyinstr(kfaddr, kdaddr, len, done);
199 }
200
201 int
202 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
203 {
204
205 strlcpy(kaddr, uaddr, len);
206 if (done)
207 *done = strlen(kaddr)+1; /* includes termination */
208 return 0;
209 }
210
211 int
212 copyin_vmspace(struct vmspace *vm, const void *uaddr, void *kaddr, size_t len)
213 {
214
215 return copyin(uaddr, kaddr, len);
216 }
217
218 int
219 copyout_vmspace(struct vmspace *vm, const void *kaddr, void *uaddr, size_t len)
220 {
221
222 return copyout(kaddr, uaddr, len);
223 }
224
225 int
226 kcopy(const void *src, void *dst, size_t len)
227 {
228
229 memcpy(dst, src, len);
230 return 0;
231 }
232
233 int
234 uiomove(void *buf, size_t n, struct uio *uio)
235 {
236 struct iovec *iov;
237 uint8_t *b = buf;
238 size_t cnt;
239 int rv;
240
241 if (uio->uio_vmspace != UIO_VMSPACE_SYS)
242 panic("%s: vmspace != UIO_VMSPACE_SYS", __func__);
243
244 /*
245 * See if rump ubc code claims the offset. This is of course
246 * a blatant violation of abstraction levels, but let's keep
247 * me simple & stupid for now.
248 */
249 if (rump_ubc_magic_uiomove(buf, n, uio, &rv, NULL))
250 return rv;
251
252 while (n && uio->uio_resid) {
253 iov = uio->uio_iov;
254 cnt = iov->iov_len;
255 if (cnt == 0) {
256 uio->uio_iov++;
257 uio->uio_iovcnt--;
258 continue;
259 }
260 if (cnt > n)
261 cnt = n;
262
263 if (uio->uio_rw == UIO_READ)
264 memcpy(iov->iov_base, b, cnt);
265 else
266 memcpy(b, iov->iov_base, cnt);
267
268 iov->iov_base = (uint8_t *)iov->iov_base + cnt;
269 iov->iov_len -= cnt;
270 b += cnt;
271 uio->uio_resid -= cnt;
272 uio->uio_offset += cnt;
273 n -= cnt;
274 }
275
276 return 0;
277 }
278
279 void
280 uio_setup_sysspace(struct uio *uio)
281 {
282
283 uio->uio_vmspace = UIO_VMSPACE_SYS;
284 }
285
286 const struct bdevsw *
287 bdevsw_lookup(dev_t dev)
288 {
289
290 return (const struct bdevsw *)1;
291 }
292
293 devclass_t
294 device_class(device_t dev)
295 {
296
297 if (dev != root_device)
298 panic("%s: dev != root_device not supported", __func__);
299
300 return DV_DISK;
301 }
302
303 void
304 getmicrouptime(struct timeval *tvp)
305 {
306 int error;
307
308 rumpuser_gettimeofday(tvp, &error);
309 }
310
311 void
312 malloc_type_attach(struct malloc_type *type)
313 {
314
315 return;
316 }
317
318 void
319 malloc_type_detach(struct malloc_type *type)
320 {
321
322 return;
323 }
324
325 void *
326 __wrap_malloc(unsigned long size, struct malloc_type *type, int flags)
327 {
328 void *rv;
329
330 rv = rumpuser_malloc(size, (flags & (M_CANFAIL | M_NOWAIT)) != 0);
331 if (rv && flags & M_ZERO)
332 memset(rv, 0, size);
333
334 return rv;
335 }
336
337 void
338 nanotime(struct timespec *ts)
339 {
340 struct timeval tv;
341 int error;
342
343 rumpuser_gettimeofday(&tv, &error);
344 TIMEVAL_TO_TIMESPEC(&tv, ts);
345 }
346
347 /* hooray for mick, so what if I do */
348 void
349 getnanotime(struct timespec *ts)
350 {
351
352 nanotime(ts);
353 }
354
355 void
356 microtime(struct timeval *tv)
357 {
358 int error;
359
360 rumpuser_gettimeofday(tv, &error);
361 }
362
363 void
364 getmicrotime(struct timeval *tv)
365 {
366 int error;
367
368 rumpuser_gettimeofday(tv, &error);
369 }
370
371 void
372 bdev_strategy(struct buf *bp)
373 {
374
375 panic("%s: not supported", __func__);
376 }
377
378 int
379 bdev_type(dev_t dev)
380 {
381
382 return D_DISK;
383 }
384
385 struct kthdesc {
386 void (*f)(void *);
387 void *arg;
388 struct lwp *mylwp;
389 };
390
391 static void *
392 threadbouncer(void *arg)
393 {
394 struct kthdesc *k = arg;
395 void (*f)(void *);
396 void *thrarg;
397
398 f = k->f;
399 thrarg = k->arg;
400 rumpuser_set_curlwp(k->mylwp);
401 kmem_free(k, sizeof(struct kthdesc));
402
403 f(thrarg);
404 panic("unreachable, should kthread_exit()");
405 }
406
407 int
408 kthread_create(pri_t pri, int flags, struct cpu_info *ci,
409 void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...)
410 {
411 struct kthdesc *k;
412 struct lwp *l;
413 int rv;
414
415 if (!rump_threads) {
416 /* fake them */
417 if (strcmp(fmt, "vrele") == 0) {
418 printf("rump warning: threads not enabled, not starting"
419 " vrele thread\n");
420 return 0;
421 } else if (strcmp(fmt, "cachegc") == 0) {
422 printf("rump warning: threads not enabled, not starting"
423 " namecache g/c thread\n");
424 return 0;
425 } else
426 panic("threads not available, setenv RUMP_THREADS 1");
427 }
428
429 KASSERT(fmt != NULL);
430 if (ci != NULL)
431 panic("%s: bounded threads not supported", __func__);
432
433 k = kmem_alloc(sizeof(struct kthdesc), KM_SLEEP);
434 k->f = func;
435 k->arg = arg;
436 k->mylwp = l = rump_setup_curlwp(0, rump_nextlid(), 0);
437 rv = rumpuser_thread_create(threadbouncer, k);
438 if (rv)
439 return rv;
440
441 if (newlp)
442 *newlp = l;
443 return 0;
444 }
445
446 void
447 kthread_exit(int ecode)
448 {
449
450 rumpuser_thread_exit();
451 }
452
453 struct proc *
454 p_find(pid_t pid, uint flags)
455 {
456
457 panic("%s: not implemented", __func__);
458 }
459
460 struct pgrp *
461 pg_find(pid_t pid, uint flags)
462 {
463
464 panic("%s: not implemented", __func__);
465 }
466
467 void
468 psignal(struct proc *p, int signo)
469 {
470
471 switch (signo) {
472 case SIGSYS:
473 break;
474 default:
475 panic("unhandled signal %d", signo);
476 }
477 }
478
479 void
480 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
481 {
482
483 panic("%s: not implemented", __func__);
484 }
485
486 void
487 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
488 {
489
490 panic("%s: not implemented", __func__);
491 }
492
493 int
494 pgid_in_session(struct proc *p, pid_t pg_id)
495 {
496
497 panic("%s: not implemented", __func__);
498 }
499
500 int
501 sigispending(struct lwp *l, int signo)
502 {
503
504 return 0;
505 }
506
507 void
508 sigpending1(struct lwp *l, sigset_t *ss)
509 {
510
511 panic("%s: not implemented", __func__);
512 }
513
514 void
515 knote_fdclose(int fd)
516 {
517
518 /* since we don't add knotes, we don't have to remove them */
519 }
520
521 int
522 seltrue_kqfilter(dev_t dev, struct knote *kn)
523 {
524
525 panic("%s: not implemented", __func__);
526 }
527
528 int
529 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
530 {
531 extern int hz;
532 int rv, error;
533 struct timespec time;
534
535 if (mtx)
536 mutex_exit(mtx);
537
538 time.tv_sec = timeo / hz;
539 time.tv_nsec = (timeo % hz) * (1000000000 / hz);
540
541 rv = rumpuser_nanosleep(&time, NULL, &error);
542
543 if (mtx)
544 mutex_enter(mtx);
545
546 if (rv)
547 return error;
548
549 return 0;
550 }
551
552 void
553 suspendsched()
554 {
555
556 panic("%s: not implemented", __func__);
557 }
558
559 u_int
560 lwp_unsleep(lwp_t *l, bool cleanup)
561 {
562
563 KASSERT(mutex_owned(l->l_mutex));
564
565 return (*l->l_syncobj->sobj_unsleep)(l, cleanup);
566 }
567
568 vaddr_t
569 calc_cache_size(struct vm_map *map, int pct, int va_pct)
570 {
571 paddr_t t;
572
573 t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
574 if ((vaddr_t)t != t) {
575 panic("%s: needs tweak", __func__);
576 }
577 return t;
578 }
579
580 int
581 seltrue(dev_t dev, int events, struct lwp *l)
582 {
583 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
584 }
585
586 void
587 selrecord(lwp_t *selector, struct selinfo *sip)
588 {
589 }
590
591 void
592 selinit(struct selinfo *sip)
593 {
594 }
595
596 void
597 selnotify(struct selinfo *sip, int events, long knhint)
598 {
599 }
600
601 void
602 seldestroy(struct selinfo *sip)
603 {
604 }
605
606 const char *
607 device_xname(device_t dv)
608 {
609 return "bogus0";
610 }
611
612 void
613 assert_sleepable(void)
614 {
615
616 /* always sleepable, although we should improve this */
617 }
618
619 int
620 devsw_attach(const char *devname, const struct bdevsw *bdev, int *bmajor,
621 const struct cdevsw *cdev, int *cmajor)
622 {
623
624 panic("%s: not implemented", __func__);
625 }
626
627 int
628 devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev)
629 {
630
631 panic("%s: not implemented", __func__);
632 }
633
634 void
635 tc_setclock(struct timespec *ts)
636 {
637
638 panic("%s: not implemented", __func__);
639 }
640
641 void
642 proc_crmod_enter()
643 {
644
645 panic("%s: not implemented", __func__);
646 }
647
648 void
649 proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
650 {
651
652 panic("%s: not implemented", __func__);
653 }
654