emul.c revision 1.119 1 /* $NetBSD: emul.c,v 1.119 2010/01/15 19:01:04 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 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.119 2010/01/15 19:01:04 pooka Exp $");
32
33 #include <sys/param.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/cpu.h>
47 #include <sys/kmem.h>
48 #include <sys/poll.h>
49 #include <sys/timetc.h>
50 #include <sys/tprintf.h>
51 #include <sys/module.h>
52 #include <sys/tty.h>
53 #include <sys/reboot.h>
54 #include <sys/syscallvar.h>
55 #include <sys/xcall.h>
56
57 #include <dev/cons.h>
58
59 #include <rump/rumpuser.h>
60
61 #include <uvm/uvm_map.h>
62
63 #include "rump_private.h"
64
65 time_t time_second = 1;
66
67 kmutex_t *proc_lock;
68 struct lwp lwp0;
69 struct vnode *rootvp;
70 dev_t rootdev;
71 int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */
72 int doing_shutdown;
73 const int schedppq = 1;
74 int hardclock_ticks;
75 bool mp_online = false;
76 struct vm_map *mb_map;
77 struct timeval boottime;
78 struct emul emul_netbsd;
79 int cold = 1;
80 int boothowto = AB_SILENT;
81 struct tty *constty;
82
83 char hostname[MAXHOSTNAMELEN];
84 size_t hostnamelen;
85
86 const char *panicstr;
87 const char *domainname;
88 int domainnamelen;
89
90 const struct filterops sig_filtops;
91
92 #define DEVSW_SIZE 255
93 const struct bdevsw *bdevsw0[DEVSW_SIZE]; /* XXX storage size */
94 const struct bdevsw **bdevsw = bdevsw0;
95 const int sys_cdevsws = DEVSW_SIZE;
96 int max_cdevsws = DEVSW_SIZE;
97
98 const struct cdevsw *cdevsw0[DEVSW_SIZE]; /* XXX storage size */
99 const struct cdevsw **cdevsw = cdevsw0;
100 const int sys_bdevsws = DEVSW_SIZE;
101 int max_bdevsws = DEVSW_SIZE;
102
103 struct devsw_conv devsw_conv0;
104 struct devsw_conv *devsw_conv = &devsw_conv0;
105 int max_devsw_convs = 0;
106 int mem_no = 2;
107
108 struct device *booted_device;
109 struct device *booted_wedge;
110 int booted_partition;
111
112 kmutex_t tty_lock;
113
114 /* sparc doesn't sport constant page size */
115 #ifdef __sparc__
116 int nbpg = 4096;
117 #endif
118
119 struct loadavg averunnable = {
120 { 0 * FSCALE,
121 1 * FSCALE,
122 11 * FSCALE, },
123 FSCALE,
124 };
125
126 devclass_t
127 device_class(device_t dev)
128 {
129
130 return dev->dv_class;
131 }
132
133 void
134 getnanouptime(struct timespec *ts)
135 {
136
137 rump_getuptime(ts);
138 }
139
140 void
141 getmicrouptime(struct timeval *tv)
142 {
143 struct timespec ts;
144
145 getnanouptime(&ts);
146 TIMESPEC_TO_TIMEVAL(tv, &ts);
147 }
148
149 static void
150 gettime(struct timespec *ts)
151 {
152 uint64_t sec, nsec;
153 int error;
154
155 rumpuser_gettime(&sec, &nsec, &error);
156 ts->tv_sec = sec;
157 ts->tv_nsec = nsec;
158 }
159
160 void
161 nanotime(struct timespec *ts)
162 {
163
164 if (rump_threads) {
165 rump_gettime(ts);
166 } else {
167 gettime(ts);
168 }
169 }
170
171 /* hooray for mick, so what if I do */
172 void
173 getnanotime(struct timespec *ts)
174 {
175
176 nanotime(ts);
177 }
178
179 void
180 microtime(struct timeval *tv)
181 {
182 struct timespec ts;
183
184 if (rump_threads) {
185 rump_gettime(&ts);
186 TIMESPEC_TO_TIMEVAL(tv, &ts);
187 } else {
188 gettime(&ts);
189 TIMESPEC_TO_TIMEVAL(tv, &ts);
190 }
191 }
192
193 void
194 getmicrotime(struct timeval *tv)
195 {
196
197 microtime(tv);
198 }
199
200 struct proc *
201 p_find(pid_t pid, uint flags)
202 {
203
204 panic("%s: not implemented", __func__);
205 }
206
207 struct pgrp *
208 pg_find(pid_t pid, uint flags)
209 {
210
211 panic("%s: not implemented", __func__);
212 }
213
214 void
215 psignal(struct proc *p, int signo)
216 {
217
218 switch (signo) {
219 case SIGSYS:
220 break;
221 default:
222 panic("unhandled signal %d\n", signo);
223 }
224 }
225
226 void
227 pgsignal(struct pgrp *pgrp, int sig, int checktty)
228 {
229
230 panic("%s: not implemented", __func__);
231 }
232
233 void
234 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
235 {
236
237 panic("%s: not implemented", __func__);
238 }
239
240 void
241 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
242 {
243
244 panic("%s: not implemented", __func__);
245 }
246
247 int
248 pgid_in_session(struct proc *p, pid_t pg_id)
249 {
250
251 panic("%s: not implemented", __func__);
252 }
253
254 int
255 sigispending(struct lwp *l, int signo)
256 {
257
258 return 0;
259 }
260
261 void
262 sigpending1(struct lwp *l, sigset_t *ss)
263 {
264
265 panic("%s: not implemented", __func__);
266 }
267
268 int
269 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
270 {
271 extern int hz;
272 int rv, error;
273 uint64_t sec, nsec;
274
275 if (mtx)
276 mutex_exit(mtx);
277
278 sec = timeo / hz;
279 nsec = (timeo % hz) * (1000000000 / hz);
280 rv = rumpuser_nanosleep(&sec, &nsec, &error);
281
282 if (mtx)
283 mutex_enter(mtx);
284
285 if (rv)
286 return error;
287
288 return 0;
289 }
290
291 void
292 suspendsched(void)
293 {
294
295 /* we don't control scheduling currently, can't do anything now */
296 }
297
298 void
299 lwp_unsleep(lwp_t *l, bool cleanup)
300 {
301
302 KASSERT(mutex_owned(l->l_mutex));
303
304 (*l->l_syncobj->sobj_unsleep)(l, cleanup);
305 }
306
307 vaddr_t
308 calc_cache_size(struct vm_map *map, int pct, int va_pct)
309 {
310 paddr_t t;
311
312 t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
313 if ((vaddr_t)t != t) {
314 panic("%s: needs tweak", __func__);
315 }
316 return t;
317 }
318
319 const char *
320 device_xname(device_t dv)
321 {
322 return "bogus0";
323 }
324
325 void
326 assert_sleepable(void)
327 {
328
329 /* always sleepable, although we should improve this */
330 }
331
332 void
333 tc_setclock(const struct timespec *ts)
334 {
335
336 panic("%s: not implemented", __func__);
337 }
338
339 int
340 proc_uidmatch(kauth_cred_t cred, kauth_cred_t target)
341 {
342
343 panic("%s: not implemented", __func__);
344 }
345
346 void
347 proc_crmod_enter(void)
348 {
349
350 panic("%s: not implemented", __func__);
351 }
352
353 void
354 proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
355 {
356
357 panic("%s: not implemented", __func__);
358 }
359
360 void
361 module_init_md(void)
362 {
363
364 /*
365 * Nothing for now. However, we should load the librump
366 * symbol table.
367 */
368 }
369
370 /* us and them, after all we're only ordinary seconds */
371 static void
372 rump_delay(unsigned int us)
373 {
374 uint64_t sec, nsec;
375 int error;
376
377 sec = us / 1000000;
378 nsec = (us % 1000000) * 1000;
379
380 if (__predict_false(sec != 0))
381 printf("WARNING: over 1s delay\n");
382
383 rumpuser_nanosleep(&sec, &nsec, &error);
384 }
385 void (*delay_func)(unsigned int) = rump_delay;
386
387 bool
388 kpreempt(uintptr_t where)
389 {
390
391 return false;
392 }
393
394 /*
395 * There is no kernel thread preemption in rump currently. But call
396 * the implementing macros anyway in case they grow some side-effects
397 * down the road.
398 */
399 void
400 kpreempt_disable(void)
401 {
402
403 KPREEMPT_DISABLE(curlwp);
404 }
405
406 void
407 kpreempt_enable(void)
408 {
409
410 KPREEMPT_ENABLE(curlwp);
411 }
412
413 void
414 proc_sesshold(struct session *ss)
415 {
416
417 panic("proc_sesshold() impossible, session %p", ss);
418 }
419
420 void
421 proc_sessrele(struct session *ss)
422 {
423
424 panic("proc_sessrele() impossible, session %p", ss);
425 }
426
427 int
428 proc_vmspace_getref(struct proc *p, struct vmspace **vm)
429 {
430
431 /* XXX */
432 *vm = p->p_vmspace;
433 return 0;
434 }
435
436 int
437 ttycheckoutq(struct tty *tp, int wait)
438 {
439
440 return 1;
441 }
442
443 void
444 cnputc(int c)
445 {
446 int error;
447
448 rumpuser_putchar(c, &error);
449 }
450
451 void
452 cnflush(void)
453 {
454
455 /* done */
456 }
457
458 int
459 tputchar(int c, int flags, struct tty *tp)
460 {
461
462 cnputc(c);
463 return 0;
464 }
465
466 void
467 cpu_reboot(int howto, char *bootstr)
468 {
469
470 rump_reboot(howto);
471
472 /* this function is __dead, we must exit */
473 rumpuser_exit(0);
474 }
475
476 int
477 syscall_establish(const struct emul *em, const struct syscall_package *sp)
478 {
479 extern struct sysent rump_sysent[];
480 int i;
481
482 KASSERT(em == NULL || em == &emul_netbsd);
483
484 for (i = 0; sp[i].sp_call; i++)
485 rump_sysent[sp[i].sp_code].sy_call = sp[i].sp_call;
486
487 return 0;
488 }
489
490 int
491 syscall_disestablish(const struct emul *em, const struct syscall_package *sp)
492 {
493
494 return 0;
495 }
496
497 void
498 calcru(struct proc *p, struct timeval *up, struct timeval *sp,
499 struct timeval *ip, struct timeval *rp)
500 {
501
502 panic("%s unimplemented", __func__);
503 }
504
505 int
506 sigismasked(struct lwp *l, int sig)
507 {
508
509 return 0;
510 }
511