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