1 /* $NetBSD: emul.c,v 1.19 2007/11/11 17:18:47 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/syslog.h> 38 #include <sys/namei.h> 39 #include <sys/kauth.h> 40 #include <sys/conf.h> 41 #include <sys/device.h> 42 #include <sys/queue.h> 43 #include <sys/filedesc.h> 44 #include <sys/kthread.h> 45 #include <sys/cpu.h> 46 #include <sys/kmem.h> 47 48 #include <machine/stdarg.h> 49 50 #include <uvm/uvm_map.h> 51 52 #include "rump_private.h" 53 #include "rumpuser.h" 54 55 #ifdef __HAVE_TIMECOUNTER 56 time_t time_second = 1; 57 #else 58 volatile struct timeval time = { 1, 0 }; 59 #endif 60 61 kmutex_t proclist_mutex; 62 kmutex_t proclist_lock; 63 struct lwp lwp0; 64 struct vnode *rootvp; 65 struct device *root_device; 66 dev_t rootdev; 67 struct vm_map *kernel_map; 68 int physmem; 69 int doing_shutdown; 70 int ncpu = 1; 71 const int schedppq = 1; 72 73 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct"); 74 MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure"); 75 MALLOC_DEFINE(M_TEMP, "temp", "misc. temporary data buffers"); 76 MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); 77 MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 78 79 char hostname[MAXHOSTNAMELEN]; 80 size_t hostnamelen; 81 82 u_long bufmem_valimit; 83 u_long bufmem_hiwater; 84 u_long bufmem_lowater; 85 u_long bufmem; 86 u_int nbuf; 87 88 const char *panicstr; 89 90 void 91 panic(const char *fmt, ...) 92 { 93 va_list ap; 94 95 va_start(ap, fmt); 96 vprintf(fmt, ap); 97 va_end(ap); 98 printf("\n"); 99 abort(); 100 } 101 102 void 103 log(int level, const char *fmt, ...) 104 { 105 va_list ap; 106 107 va_start(ap, fmt); 108 vprintf(fmt, ap); 109 va_end(ap); 110 } 111 112 void 113 uprintf(const char *fmt, ...) 114 { 115 va_list ap; 116 117 va_start(ap, fmt); 118 vprintf(fmt, ap); 119 va_end(ap); 120 } 121 122 void 123 printf_nolog(const char *fmt, ...) 124 { 125 va_list ap; 126 127 va_start(ap, fmt); 128 vprintf(fmt, ap); 129 va_end(ap); 130 } 131 132 int 133 copyin(const void *uaddr, void *kaddr, size_t len) 134 { 135 136 memcpy(kaddr, uaddr, len); 137 return 0; 138 } 139 140 int 141 copyout(const void *kaddr, void *uaddr, size_t len) 142 { 143 144 memcpy(uaddr, kaddr, len); 145 return 0; 146 } 147 148 int 149 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done) 150 { 151 152 return copyinstr(kfaddr, kdaddr, len, done); 153 } 154 155 int 156 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 157 { 158 159 strlcpy(kaddr, uaddr, len); 160 *done = strlen(kaddr); 161 return 0; 162 } 163 164 int 165 uiomove(void *buf, size_t n, struct uio *uio) 166 { 167 struct iovec *iov; 168 uint8_t *b = buf; 169 size_t cnt; 170 int rv; 171 172 if (uio->uio_vmspace != UIO_VMSPACE_SYS) 173 panic("%s: vmspace != UIO_VMSPACE_SYS", __func__); 174 175 /* 176 * See if rump ubc code claims the offset. This is of course 177 * a blatant violation of abstraction levels, but let's keep 178 * me simple & stupid for now. 179 */ 180 if (rump_ubc_magic_uiomove(buf, n, uio, &rv, NULL)) 181 return rv; 182 183 while (n && uio->uio_resid) { 184 iov = uio->uio_iov; 185 cnt = iov->iov_len; 186 if (cnt == 0) { 187 uio->uio_iov++; 188 uio->uio_iovcnt--; 189 continue; 190 } 191 if (cnt > n) 192 cnt = n; 193 194 if (uio->uio_rw == UIO_READ) 195 memcpy(iov->iov_base, b, cnt); 196 else 197 memcpy(b, iov->iov_base, cnt); 198 199 iov->iov_base = (uint8_t *)iov->iov_base + cnt; 200 iov->iov_len -= cnt; 201 b += cnt; 202 uio->uio_resid -= cnt; 203 uio->uio_offset += cnt; 204 n -= cnt; 205 } 206 207 return 0; 208 } 209 210 void 211 uio_setup_sysspace(struct uio *uio) 212 { 213 214 uio->uio_vmspace = UIO_VMSPACE_SYS; 215 } 216 217 const struct bdevsw * 218 bdevsw_lookup(dev_t dev) 219 { 220 221 return (const struct bdevsw *)1; 222 } 223 224 devclass_t 225 device_class(device_t dev) 226 { 227 228 if (dev != root_device) 229 panic("%s: dev != root_device not supported", __func__); 230 231 return DV_DISK; 232 } 233 234 void 235 getmicrouptime(struct timeval *tvp) 236 { 237 int error; 238 239 rumpuser_gettimeofday(tvp, &error); 240 } 241 242 void 243 malloc_type_attach(struct malloc_type *type) 244 { 245 246 return; 247 } 248 249 void 250 malloc_type_detach(struct malloc_type *type) 251 { 252 253 return; 254 } 255 256 void * 257 __wrap_malloc(unsigned long size, struct malloc_type *type, int flags) 258 { 259 void *rv; 260 261 rv = rumpuser_malloc(size, (flags & (M_CANFAIL | M_NOWAIT)) != 0); 262 if (rv && flags & M_ZERO) 263 memset(rv, 0, size); 264 265 return rv; 266 } 267 268 void 269 nanotime(struct timespec *ts) 270 { 271 struct timeval tv; 272 int error; 273 274 rumpuser_gettimeofday(&tv, &error); 275 TIMEVAL_TO_TIMESPEC(&tv, ts); 276 } 277 278 /* hooray for mick, so what if I do */ 279 void 280 getnanotime(struct timespec *ts) 281 { 282 283 nanotime(ts); 284 } 285 286 void 287 microtime(struct timeval *tv) 288 { 289 int error; 290 291 rumpuser_gettimeofday(tv, &error); 292 } 293 294 void 295 getmicrotime(struct timeval *tv) 296 { 297 int error; 298 299 rumpuser_gettimeofday(tv, &error); 300 } 301 302 void 303 bdev_strategy(struct buf *bp) 304 { 305 306 panic("%s: not supported", __func__); 307 } 308 309 int 310 bdev_type(dev_t dev) 311 { 312 313 return D_DISK; 314 } 315 316 struct kthdesc { 317 void (*f)(void *); 318 void *arg; 319 struct lwp *mylwp; 320 }; 321 322 static lwpid_t curlid = 2; 323 324 static void * 325 threadbouncer(void *arg) 326 { 327 struct kthdesc *k = arg; 328 void (*f)(void *); 329 void *thrarg; 330 331 f = k->f; 332 thrarg = k->arg; 333 rumpuser_set_curlwp(k->mylwp); 334 kmem_free(k, sizeof(struct kthdesc)); 335 336 f(thrarg); 337 panic("unreachable, should kthread_exit()"); 338 } 339 340 int 341 kthread_create(pri_t pri, int flags, struct cpu_info *ci, 342 void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...) 343 { 344 struct kthdesc *k; 345 struct lwp *l; 346 int rv; 347 348 KASSERT(fmt != NULL); 349 if (ci != NULL) 350 panic("%s: bounded threads not supported", __func__); 351 352 k = kmem_alloc(sizeof(struct kthdesc), KM_SLEEP); 353 k->f = func; 354 k->arg = arg; 355 k->mylwp = l = rump_setup_curlwp(0, curlid++, 0); 356 rv = rumpuser_thread_create(threadbouncer, k); 357 if (rv) 358 return rv; 359 360 if (newlp) 361 *newlp = l; 362 return 0; 363 } 364 365 void 366 kthread_exit(int ecode) 367 { 368 369 rumpuser_thread_exit(); 370 } 371 372 void 373 callout_init(callout_t *c, u_int flags) 374 { 375 376 panic("%s: not implemented", __func__); 377 } 378 379 void 380 callout_reset(callout_t *c, int ticks, void (*func)(void *), void *arg) 381 { 382 383 panic("%s: not implemented", __func__); 384 } 385 386 bool 387 callout_stop(callout_t *c) 388 { 389 390 panic("%s: not implemented", __func__); 391 } 392