emul.c revision 1.115 1 /* $NetBSD: emul.c,v 1.115 2010/01/08 20:04:06 dyoung 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.115 2010/01/08 20:04:06 dyoung 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 kmutex_t sysctl_file_marker_lock;
115
116 /* sparc doesn't sport constant page size */
117 #ifdef __sparc__
118 int nbpg = 4096;
119 #endif
120
121 devclass_t
122 device_class(device_t dev)
123 {
124
125 return dev->dv_class;
126 }
127
128 void
129 getnanouptime(struct timespec *ts)
130 {
131
132 rump_getuptime(ts);
133 }
134
135 void
136 getmicrouptime(struct timeval *tv)
137 {
138 struct timespec ts;
139
140 getnanouptime(&ts);
141 TIMESPEC_TO_TIMEVAL(tv, &ts);
142 }
143
144 static void
145 gettime(struct timespec *ts)
146 {
147 uint64_t sec, nsec;
148 int error;
149
150 rumpuser_gettime(&sec, &nsec, &error);
151 ts->tv_sec = sec;
152 ts->tv_nsec = nsec;
153 }
154
155 void
156 nanotime(struct timespec *ts)
157 {
158
159 if (rump_threads) {
160 rump_gettime(ts);
161 } else {
162 gettime(ts);
163 }
164 }
165
166 /* hooray for mick, so what if I do */
167 void
168 getnanotime(struct timespec *ts)
169 {
170
171 nanotime(ts);
172 }
173
174 void
175 microtime(struct timeval *tv)
176 {
177 struct timespec ts;
178
179 if (rump_threads) {
180 rump_gettime(&ts);
181 TIMESPEC_TO_TIMEVAL(tv, &ts);
182 } else {
183 gettime(&ts);
184 TIMESPEC_TO_TIMEVAL(tv, &ts);
185 }
186 }
187
188 void
189 getmicrotime(struct timeval *tv)
190 {
191
192 microtime(tv);
193 }
194
195 struct proc *
196 p_find(pid_t pid, uint flags)
197 {
198
199 panic("%s: not implemented", __func__);
200 }
201
202 struct pgrp *
203 pg_find(pid_t pid, uint flags)
204 {
205
206 panic("%s: not implemented", __func__);
207 }
208
209 void
210 psignal(struct proc *p, int signo)
211 {
212
213 switch (signo) {
214 case SIGSYS:
215 break;
216 default:
217 panic("unhandled signal %d\n", signo);
218 }
219 }
220
221 void
222 kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
223 {
224
225 panic("%s: not implemented", __func__);
226 }
227
228 void
229 kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
230 {
231
232 panic("%s: not implemented", __func__);
233 }
234
235 int
236 pgid_in_session(struct proc *p, pid_t pg_id)
237 {
238
239 panic("%s: not implemented", __func__);
240 }
241
242 int
243 sigispending(struct lwp *l, int signo)
244 {
245
246 return 0;
247 }
248
249 void
250 sigpending1(struct lwp *l, sigset_t *ss)
251 {
252
253 panic("%s: not implemented", __func__);
254 }
255
256 int
257 kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx)
258 {
259 extern int hz;
260 int rv, error;
261 uint64_t sec, nsec;
262
263 if (mtx)
264 mutex_exit(mtx);
265
266 sec = timeo / hz;
267 nsec = (timeo % hz) * (1000000000 / hz);
268 rv = rumpuser_nanosleep(&sec, &nsec, &error);
269
270 if (mtx)
271 mutex_enter(mtx);
272
273 if (rv)
274 return error;
275
276 return 0;
277 }
278
279 void
280 suspendsched(void)
281 {
282
283 /* we don't control scheduling currently, can't do anything now */
284 }
285
286 void
287 lwp_unsleep(lwp_t *l, bool cleanup)
288 {
289
290 KASSERT(mutex_owned(l->l_mutex));
291
292 (*l->l_syncobj->sobj_unsleep)(l, cleanup);
293 }
294
295 vaddr_t
296 calc_cache_size(struct vm_map *map, int pct, int va_pct)
297 {
298 paddr_t t;
299
300 t = (paddr_t)physmem * pct / 100 * PAGE_SIZE;
301 if ((vaddr_t)t != t) {
302 panic("%s: needs tweak", __func__);
303 }
304 return t;
305 }
306
307 const char *
308 device_xname(device_t dv)
309 {
310 return "bogus0";
311 }
312
313 void
314 assert_sleepable(void)
315 {
316
317 /* always sleepable, although we should improve this */
318 }
319
320 void
321 tc_setclock(const struct timespec *ts)
322 {
323
324 panic("%s: not implemented", __func__);
325 }
326
327 int
328 proc_uidmatch(kauth_cred_t cred, kauth_cred_t target)
329 {
330
331 panic("%s: not implemented", __func__);
332 }
333
334 void
335 proc_crmod_enter(void)
336 {
337
338 panic("%s: not implemented", __func__);
339 }
340
341 void
342 proc_crmod_leave(kauth_cred_t c1, kauth_cred_t c2, bool sugid)
343 {
344
345 panic("%s: not implemented", __func__);
346 }
347
348 void
349 module_init_md(void)
350 {
351
352 /*
353 * Nothing for now. However, we should load the librump
354 * symbol table.
355 */
356 }
357
358 /* us and them, after all we're only ordinary seconds */
359 static void
360 rump_delay(unsigned int us)
361 {
362 uint64_t sec, nsec;
363 int error;
364
365 sec = us / 1000000;
366 nsec = (us % 1000000) * 1000;
367
368 if (__predict_false(sec != 0))
369 printf("WARNING: over 1s delay\n");
370
371 rumpuser_nanosleep(&sec, &nsec, &error);
372 }
373 void (*delay_func)(unsigned int) = rump_delay;
374
375 void
376 kpreempt_disable(void)
377 {
378
379 /* XXX: see below */
380 KPREEMPT_DISABLE(curlwp);
381 }
382
383 void
384 kpreempt_enable(void)
385 {
386
387 /* try to make sure kpreempt_disable() is only used from panic() */
388 panic("kpreempt not supported");
389 }
390
391 void
392 proc_sesshold(struct session *ss)
393 {
394
395 panic("proc_sesshold() impossible, session %p", ss);
396 }
397
398 void
399 proc_sessrele(struct session *ss)
400 {
401
402 panic("proc_sessrele() impossible, session %p", ss);
403 }
404
405 int
406 proc_vmspace_getref(struct proc *p, struct vmspace **vm)
407 {
408
409 /* XXX */
410 *vm = p->p_vmspace;
411 return 0;
412 }
413
414 int
415 ttycheckoutq(struct tty *tp, int wait)
416 {
417
418 return 1;
419 }
420
421 void
422 cnputc(int c)
423 {
424 int error;
425
426 rumpuser_putchar(c, &error);
427 }
428
429 void
430 cnflush(void)
431 {
432
433 /* done */
434 }
435
436 int
437 tputchar(int c, int flags, struct tty *tp)
438 {
439
440 cnputc(c);
441 return 0;
442 }
443
444 void
445 cpu_reboot(int howto, char *bootstr)
446 {
447
448 rump_reboot(howto);
449
450 /* this function is __dead, we must exit */
451 rumpuser_exit(0);
452 }
453
454 bool
455 pmf_device_register1(struct device *dev,
456 bool (*suspend)(device_t, pmf_qual_t),
457 bool (*resume)(device_t, pmf_qual_t),
458 bool (*shutdown)(device_t, int))
459 {
460
461 return true;
462 }
463
464 void
465 pmf_device_deregister(struct device *dev)
466 {
467
468 /* nada */
469 }
470
471 int
472 syscall_establish(const struct emul *em, const struct syscall_package *sp)
473 {
474 extern struct sysent rump_sysent[];
475 int i;
476
477 KASSERT(em == NULL || em == &emul_netbsd);
478
479 for (i = 0; sp[i].sp_call; i++)
480 rump_sysent[sp[i].sp_code].sy_call = sp[i].sp_call;
481
482 return 0;
483 }
484
485 int
486 syscall_disestablish(const struct emul *em, const struct syscall_package *sp)
487 {
488
489 return 0;
490 }
491