emul.c revision 1.29.6.5 1 /* $NetBSD: emul.c,v 1.29.6.5 2008/10/05 20:11:33 mjf 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 lwpid_t curlid = 2;
350
351 static void *
352 threadbouncer(void *arg)
353 {
354 struct kthdesc *k = arg;
355 void (*f)(void *);
356 void *thrarg;
357
358 f = k->f;
359 thrarg = k->arg;
360 rumpuser_set_curlwp(k->mylwp);
361 kmem_free(k, sizeof(struct kthdesc));
362
363 f(thrarg);
364 panic("unreachable, should kthread_exit()");
365 }
366
367 int
368 kthread_create(pri_t pri, int flags, struct cpu_info *ci,
369 void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...)
370 {
371 struct kthdesc *k;
372 struct lwp *l;
373 int rv;
374
375 if (!rump_threads) {
376 /* fake them */
377 if (strcmp(fmt, "vrele") == 0) {
378 printf("rump warning: threads not enabled, not starting"
379 " vrele thread\n");
380 return 0;
381 } else if (strcmp(fmt, "cachegc") == 0) {
382 printf("rump warning: threads not enabled, not starting"
383 " namecache g/c thread\n");
384 return 0;
385 } else
386 panic("threads not available, setenv RUMP_THREADS 1");
387 }
388
389 KASSERT(fmt != NULL);
390 if (ci != NULL)
391 panic("%s: bounded threads not supported", __func__);
392
393 k = kmem_alloc(sizeof(struct kthdesc), KM_SLEEP);
394 k->f = func;
395 k->arg = arg;
396 k->mylwp = l = rump_setup_curlwp(0, curlid++, 0);
397 rv = rumpuser_thread_create(threadbouncer, k);
398 if (rv)
399 return rv;
400
401 if (newlp)
402 *newlp = l;
403 return 0;
404 }
405
406 void
407 kthread_exit(int ecode)
408 {
409
410 rumpuser_thread_exit();
411 }
412
413 void
414 callout_init(callout_t *c, u_int flags)
415 {
416
417 panic("%s: not implemented", __func__);
418 }
419
420 void
421 callout_reset(callout_t *c, int ticks, void (*func)(void *), void *arg)
422 {
423
424 panic("%s: not implemented", __func__);
425 }
426
427 bool
428 callout_stop(callout_t *c)
429 {
430
431 panic("%s: not implemented", __func__);
432 }
433
434 void
435 callout_schedule(callout_t *c, int ticks)
436 {
437
438 panic("%s: not implemented", __func__);
439 }
440
441 void
442 callout_setfunc(callout_t *c, void (*func)(void *), void *arg)
443 {
444
445 panic("%s: not implemented", __func__);
446 }
447
448 struct proc *
449 p_find(pid_t pid, uint flags)
450 {
451
452 panic("%s: not implemented", __func__);
453 }
454
455 struct pgrp *
456 pg_find(pid_t pid, uint flags)
457 {
458
459 panic("%s: not implemented", __func__);
460 }
461
462 void
463 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
464 {
465
466 panic("%s: not implemented", __func__);
467 }
468
469 void
470 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
471 {
472
473 panic("%s: not implemented", __func__);
474 }
475
476 int
477 pgid_in_session(struct proc *p, pid_t pg_id)
478 {
479
480 panic("%s: not implemented", __func__);
481 }
482
483 int
484 sigispending(struct lwp *l, int signo)
485 {
486
487 return 0;
488 }
489
490 void
491 knote_fdclose(int fd)
492 {
493
494 /* since we don't add knotes, we don't have to remove them */
495 }
496
497 int
498 seltrue_kqfilter(dev_t dev, struct knote *kn)
499 {
500
501 panic("%s: not implemented", __func__);
502 }
503
504 int
505 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
506 {
507 extern int hz;
508 int rv, error;
509 struct timespec time;
510
511 if (mtx)
512 mutex_exit(mtx);
513
514 time.tv_sec = timeo / hz;
515 time.tv_nsec = (timeo % hz) * (1000000000 / hz);
516
517 rv = rumpuser_nanosleep(&time, NULL, &error);
518
519 if (mtx)
520 mutex_enter(mtx);
521
522 if (rv)
523 return error;
524
525 return 0;
526 }
527
528 void
529 suspendsched()
530 {
531
532 panic("%s: not implemented", __func__);
533 }
534
535 u_int
536 lwp_unsleep(lwp_t *l, bool cleanup)
537 {
538
539 KASSERT(mutex_owned(l->l_mutex));
540
541 return (*l->l_syncobj->sobj_unsleep)(l, cleanup);
542 }
543
544 vaddr_t
545 calc_cache_size(struct vm_map *map, int pct, int va_pct)
546 {
547 paddr_t t;
548
549 t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
550 if ((vaddr_t)t != t) {
551 panic("%s: needs tweak", __func__);
552 }
553 return t;
554 }
555
556 int
557 seltrue(dev_t dev, int events, struct lwp *l)
558 {
559 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
560 }
561
562 void
563 selrecord(lwp_t *selector, struct selinfo *sip)
564 {
565 }
566
567 void
568 selinit(struct selinfo *sip)
569 {
570 }
571
572 void
573 selnotify(struct selinfo *sip, int events, long knhint)
574 {
575 }
576
577 void
578 seldestroy(struct selinfo *sip)
579 {
580 }
581
582 const char *
583 device_xname(device_t dv)
584 {
585 return "bogus0";
586 }
587
588 void
589 assert_sleepable(void)
590 {
591
592 /* always sleepable, although we should improve this */
593 }
594
595 int
596 devsw_attach(const char *devname, const struct bdevsw *bdev, int *bmajor,
597 const struct cdevsw *cdev, int *cmajor)
598 {
599
600 panic("%s: not implemented", __func__);
601 }
602
603 int
604 devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev)
605 {
606
607 panic("%s: not implemented", __func__);
608 }
609
610 void
611 proc_crmod_enter()
612 {
613
614 panic("%s: not implemented", __func__);
615 }
616
617 void
618 proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
619 {
620
621 panic("%s: not implemented", __func__);
622 }
623