1*ac23d067Sbad /* $NetBSD: emul.c,v 1.202 2024/07/28 13:01:55 bad Exp $ */ 2daafee87Spooka 3daafee87Spooka /* 423bbd0e0Spooka * Copyright (c) 2007-2011 Antti Kantee. All Rights Reserved. 5daafee87Spooka * 6daafee87Spooka * Redistribution and use in source and binary forms, with or without 7daafee87Spooka * modification, are permitted provided that the following conditions 8daafee87Spooka * are met: 9daafee87Spooka * 1. Redistributions of source code must retain the above copyright 10daafee87Spooka * notice, this list of conditions and the following disclaimer. 11daafee87Spooka * 2. Redistributions in binary form must reproduce the above copyright 12daafee87Spooka * notice, this list of conditions and the following disclaimer in the 13daafee87Spooka * documentation and/or other materials provided with the distribution. 14daafee87Spooka * 15daafee87Spooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16daafee87Spooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17daafee87Spooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18daafee87Spooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19daafee87Spooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20daafee87Spooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21daafee87Spooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22daafee87Spooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23daafee87Spooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24daafee87Spooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25daafee87Spooka * SUCH DAMAGE. 26daafee87Spooka */ 27daafee87Spooka 28a768afd6Spooka #include <sys/cdefs.h> 29*ac23d067Sbad __KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.202 2024/07/28 13:01:55 bad Exp $"); 30cfd4dc8fSpooka 31daafee87Spooka #include <sys/param.h> 3285df50f3Spooka #include <sys/cprng.h> 33934cd9a8Spooka #include <sys/filedesc.h> 348a83906aShannken #include <sys/fstrans.h> 3585df50f3Spooka #include <sys/kauth.h> 369a722ef7Spooka #include <sys/module.h> 37167269d4Spooka #include <sys/reboot.h> 38e1ef9449Spooka #include <sys/syscall.h> 399e8ba65aSozaki-r #include <sys/pserialize.h> 40eef1a9e4Sozaki-r #ifdef LOCKDEBUG 41eef1a9e4Sozaki-r #include <sys/sleepq.h> 42eef1a9e4Sozaki-r #endif 4306525b99Sriastradh #include <sys/syncobj.h> 44167269d4Spooka 45167269d4Spooka #include <dev/cons.h> 46daafee87Spooka 476bb51422Spooka #include <rump-sys/kern.h> 48bdf6e0b0Spooka 496bb51422Spooka #include <rump/rumpuser.h> 50daafee87Spooka 512cd42818Spooka void (*rump_vfs_fini)(void) = (void *)nullop; 522cd42818Spooka 530ec2770cSpooka /* 540ec2770cSpooka * physmem is largely unused (except for nmbcluster calculations), 550ec2770cSpooka * so pick a default value which suits ZFS. if an application wants 560ec2770cSpooka * a very small memory footprint, it can still adjust this before 570ec2770cSpooka * calling rump_init() 580ec2770cSpooka */ 590ec2770cSpooka #define PHYSMEM 512*256 603a405f03Scherry psize_t physmem = PHYSMEM; 61c1da2a84Sskrll size_t nkmempages = PHYSMEM/2; /* from le chapeau */ 620ec2770cSpooka #undef PHYSMEM 630ec2770cSpooka 64daafee87Spooka struct vnode *rootvp; 6559e540bbSpooka dev_t rootdev = NODEV; 660ec2770cSpooka 67f48aa71aSpooka const int schedppq = 1; 689a722ef7Spooka int cold = 1; 69d6c967bbSthorpej int shutting_down; 70dfd2ba19Spooka int boothowto = AB_SILENT; 71167269d4Spooka struct tty *constty; 72daafee87Spooka 7353d420f9Spooka const struct bdevsw *bdevsw0[255]; 74614c3350Spooka const struct bdevsw **bdevsw = bdevsw0; 75*ac23d067Sbad const int sys_bdevsws = 255; 76*ac23d067Sbad int max_bdevsws = 255; 77614c3350Spooka 7853d420f9Spooka const struct cdevsw *cdevsw0[255]; 79614c3350Spooka const struct cdevsw **cdevsw = cdevsw0; 80*ac23d067Sbad const int sys_cdevsws = 255; 81*ac23d067Sbad int max_cdevsws = 255; 82614c3350Spooka 8307334a46Spooka int mem_no = 2; 8407334a46Spooka 85cbab9cadSchs device_t booted_device; 86cbab9cadSchs device_t booted_wedge; 8774e84221Smanu daddr_t booted_startblk; 8874e84221Smanu uint64_t booted_nblks; 89f42da039Spooka int booted_partition; 903284574bSchristos const char *booted_method; 91f42da039Spooka 9288447903Spooka /* XXX: unused */ 9307334a46Spooka kmutex_t tty_lock; 9488447903Spooka krwlock_t exec_lock; 95614c3350Spooka 9683474ef4Spooka /* sparc doesn't sport constant page size, pretend we have 4k pages */ 97d502da58Spooka #ifdef __sparc__ 98d502da58Spooka int nbpg = 4096; 9983474ef4Spooka int pgofset = 4096-1; 10083474ef4Spooka int pgshift = 12; 101d502da58Spooka #endif 102d502da58Spooka 1038e16588bStsutsui /* on sun3 VM_MAX_ADDRESS is a const variable */ 1048e16588bStsutsui /* XXX: should be moved into rump.c and initialize for sun3 and sun3x? */ 105a2b72aafSpooka #ifdef sun3 1068e16588bStsutsui const vaddr_t kernbase = KERNBASE3; 1077ed9d6c4Spooka #endif 1087ed9d6c4Spooka 1098bb03ea9Spooka struct loadavg averunnable = { 1108bb03ea9Spooka { 0 * FSCALE, 1118bb03ea9Spooka 1 * FSCALE, 1128bb03ea9Spooka 11 * FSCALE, }, 1138bb03ea9Spooka FSCALE, 1148bb03ea9Spooka }; 1158bb03ea9Spooka 116e04dc482Spgoyette /* 117e04dc482Spgoyette * Include the autogenerated list of auto-loadable syscalls 118e04dc482Spgoyette */ 119e04dc482Spgoyette #include <kern/syscalls_autoload.c> 120e04dc482Spgoyette 1218b923892Spooka struct emul emul_netbsd = { 1228b923892Spooka .e_name = "netbsd-rump", 1238b923892Spooka .e_sysent = rump_sysent, 1243cd7406aSpgoyette .e_nomodbits = rump_sysent_nomodbits, 125e1ef9449Spooka #ifndef __HAVE_MINIMAL_EMUL 126e1ef9449Spooka .e_nsysent = SYS_NSYSENT, 127e1ef9449Spooka #endif 1289cf6a575Spooka .e_vm_default_addr = uvm_default_mapaddr, 129eacf4402Spooka #ifdef __HAVE_SYSCALL_INTERN 130eacf4402Spooka .e_syscall_intern = syscall_intern, 131eacf4402Spooka #endif 132e04dc482Spgoyette .e_sc_autoload = netbsd_syscalls_autoload, 1338b923892Spooka }; 1348b923892Spooka 1350d177642Spooka /* not used, but need the symbols for pointer comparisons */ 1360d177642Spooka syncobj_t mutex_syncobj, rw_syncobj; 1370d177642Spooka 1384f69d01dSpooka int 1394f69d01dSpooka kpause(const char *wmesg, bool intr, int timeo, kmutex_t *mtx) 1404f69d01dSpooka { 1414f69d01dSpooka extern int hz; 142129ca10eSjustin int rv __diagused; 1438c19023aSpooka uint64_t sec, nsec; 1444f69d01dSpooka 1454f69d01dSpooka if (mtx) 1464f69d01dSpooka mutex_exit(mtx); 147441a8c67Spooka 1488c19023aSpooka sec = timeo / hz; 1498c19023aSpooka nsec = (timeo % hz) * (1000000000 / hz); 150152588e3Spooka rv = rumpuser_clock_sleep(RUMPUSER_CLOCK_RELWALL, sec, nsec); 151a53a2a53Spooka KASSERT(rv == 0); 152441a8c67Spooka 1534f69d01dSpooka if (mtx) 1544f69d01dSpooka mutex_enter(mtx); 1554f69d01dSpooka 1564f69d01dSpooka return 0; 1574f69d01dSpooka } 158fb310736Spooka 159c3c197baSyamt vaddr_t 16082aa1e7eSpara calc_cache_size(vsize_t vasz, int pct, int va_pct) 161c3c197baSyamt { 162c3c197baSyamt paddr_t t; 163c3c197baSyamt 164c3c197baSyamt t = (paddr_t)physmem * pct / 100 * PAGE_SIZE; 165c3c197baSyamt if ((vaddr_t)t != t) { 166c3c197baSyamt panic("%s: needs tweak", __func__); 167c3c197baSyamt } 168c3c197baSyamt return t; 169c3c197baSyamt } 17099c43f07Smartin 171683f5aa5Sozaki-r #define RETURN_ADDRESS (uintptr_t)__builtin_return_address(0) 172683f5aa5Sozaki-r 173d496f014Spooka void 174d496f014Spooka assert_sleepable(void) 175d496f014Spooka { 176683f5aa5Sozaki-r const char *reason = NULL; 177d496f014Spooka 178d496f014Spooka /* always sleepable, although we should improve this */ 179683f5aa5Sozaki-r 180683f5aa5Sozaki-r if (!pserialize_not_in_read_section()) { 181683f5aa5Sozaki-r reason = "pserialize"; 182683f5aa5Sozaki-r } 183683f5aa5Sozaki-r 184683f5aa5Sozaki-r if (reason) { 185683f5aa5Sozaki-r panic("%s: %s caller=%p", __func__, reason, 186683f5aa5Sozaki-r (void *)RETURN_ADDRESS); 187683f5aa5Sozaki-r } 188d496f014Spooka } 1894a0d2098Spooka 1909a722ef7Spooka void 191df7f595eScegger module_init_md(void) 1929a722ef7Spooka { 1939a722ef7Spooka 1949a722ef7Spooka /* 1959a722ef7Spooka * Nothing for now. However, we should load the librump 1969a722ef7Spooka * symbol table. 1979a722ef7Spooka */ 1989a722ef7Spooka } 199167269d4Spooka 200ef964280Spooka /* 201ef964280Spooka * Try to emulate all the MD definitions of DELAY() / delay(). 202ef964280Spooka * Would be nice to fix the #defines in MD headers, but this quicker. 203a0d2bb5eSpooka * 204a0d2bb5eSpooka * XXX: we'd need a rumpuser_clock_sleep_nowrap() here. Since we 205a0d2bb5eSpooka * don't have it in the current hypercall revision, busyloop. 206a0d2bb5eSpooka * Note that rather than calibrate a loop delay and work with that, 207a0d2bb5eSpooka * get call gettime (which does not block) in a loop to make sure 208a0d2bb5eSpooka * we didn't get virtual ghosttime. That might be slightly inaccurate 209a0d2bb5eSpooka * for very small delays ... 210a0d2bb5eSpooka * 211a0d2bb5eSpooka * The other option would be to run a thread in the hypervisor which 212a0d2bb5eSpooka * sleeps for us and we can wait for it using rumpuser_cv_wait_nowrap() 213a0d2bb5eSpooka * Probably too fussy. Better just wait for hypercall rev 18 ;) 214ef964280Spooka */ 215055c86bdSpooka static void 216055c86bdSpooka rump_delay(unsigned int us) 217167269d4Spooka { 218a0d2bb5eSpooka struct timespec target, tmp; 219a0d2bb5eSpooka uint64_t sec, sec_ini, sec_now; 220a0d2bb5eSpooka long nsec, nsec_ini, nsec_now; 221a0d2bb5eSpooka int loops; 222a0d2bb5eSpooka 223a0d2bb5eSpooka rumpuser_clock_gettime(RUMPUSER_CLOCK_ABSMONO, &sec_ini, &nsec_ini); 224167269d4Spooka 225ef964280Spooka #ifdef __mac68k__ 226ef964280Spooka sec = us / 1000; 227ef964280Spooka nsec = (us % 1000) * 1000000; 228ef964280Spooka #else 2298c19023aSpooka sec = us / 1000000; 2308c19023aSpooka nsec = (us % 1000000) * 1000; 231ef964280Spooka #endif 232167269d4Spooka 233a0d2bb5eSpooka target.tv_sec = sec_ini; 234a0d2bb5eSpooka tmp.tv_sec = sec; 235a0d2bb5eSpooka target.tv_nsec = nsec_ini; 236a0d2bb5eSpooka tmp.tv_nsec = nsec; 237a0d2bb5eSpooka timespecadd(&target, &tmp, &target); 238a0d2bb5eSpooka 2398c19023aSpooka if (__predict_false(sec != 0)) 240167269d4Spooka printf("WARNING: over 1s delay\n"); 241167269d4Spooka 242a0d2bb5eSpooka for (loops = 0; loops < 1000*1000*100; loops++) { 243a0d2bb5eSpooka struct timespec cur; 244a0d2bb5eSpooka 245a0d2bb5eSpooka rumpuser_clock_gettime(RUMPUSER_CLOCK_ABSMONO, 246a0d2bb5eSpooka &sec_now, &nsec_now); 247a0d2bb5eSpooka cur.tv_sec = sec_now; 248a0d2bb5eSpooka cur.tv_nsec = nsec_now; 249a0d2bb5eSpooka if (timespeccmp(&cur, &target, >=)) { 250a0d2bb5eSpooka return; 251a0d2bb5eSpooka } 252a0d2bb5eSpooka } 253a0d2bb5eSpooka printf("WARNING: DELAY ESCAPED\n"); 254167269d4Spooka } 255055c86bdSpooka void (*delay_func)(unsigned int) = rump_delay; 256ef964280Spooka __strong_alias(delay,rump_delay); 257ef964280Spooka __strong_alias(_delay,rump_delay); 258167269d4Spooka 25967d3f625Skre /* Weak alias for getcwd_common to be used unless librumpvfs is present. */ 26067d3f625Skre 26167d3f625Skre int rump_getcwd_common(struct vnode *, struct vnode *, char **, char *, 26267d3f625Skre int, int, struct lwp *); 26367d3f625Skre int 26467d3f625Skre rump_getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp, 26567d3f625Skre int limit, int flags, struct lwp *l) 26667d3f625Skre { 26767d3f625Skre 26867d3f625Skre return ENOENT; 26967d3f625Skre } 27067d3f625Skre __weak_alias(getcwd_common,rump_getcwd_common); 27167d3f625Skre 272c3c178f6Sbad /* Weak alias for vnode_to_path to be used unless librumpvfs is present. */ 273c3c178f6Sbad 274c3c178f6Sbad int rump_vnode_to_path(char *, size_t, struct vnode *, struct lwp *, 275c3c178f6Sbad struct proc *); 276c3c178f6Sbad int 277c3c178f6Sbad rump_vnode_to_path(char *path, size_t len, struct vnode *vp, struct lwp *curl, 278c3c178f6Sbad struct proc *p) 279c3c178f6Sbad { 280c3c178f6Sbad 281c3c178f6Sbad return ENOENT; /* pretend getcwd_common() failed. */ 282c3c178f6Sbad } 283c3c178f6Sbad __weak_alias(vnode_to_path,rump_vnode_to_path); 284c3c178f6Sbad 285c3c178f6Sbad 2868a83906aShannken /* Weak aliases for fstrans to be used unless librumpvfs is present. */ 2878a83906aShannken 288287643b0Shannken void rump_fstrans_start(struct mount *); 289287643b0Shannken void 290287643b0Shannken rump_fstrans_start(struct mount *mp) 291287643b0Shannken { 292287643b0Shannken 293287643b0Shannken } 294287643b0Shannken __weak_alias(fstrans_start,rump_fstrans_start); 295287643b0Shannken 296287643b0Shannken int rump_fstrans_start_nowait(struct mount *); 2978a83906aShannken int 298287643b0Shannken rump_fstrans_start_nowait(struct mount *mp) 2998a83906aShannken { 3008a83906aShannken 3018a83906aShannken return 0; 3028a83906aShannken } 303287643b0Shannken __weak_alias(fstrans_start_nowait,rump_fstrans_start_nowait); 3048a83906aShannken 305fef73d22Shannken void rump_fstrans_start_lazy(struct mount *); 306fef73d22Shannken void 307fef73d22Shannken rump_fstrans_start_lazy(struct mount *mp) 308fef73d22Shannken { 309fef73d22Shannken 310fef73d22Shannken } 311fef73d22Shannken __weak_alias(fstrans_start_lazy,rump_fstrans_start_lazy); 312fef73d22Shannken 313fef73d22Shannken 3148a83906aShannken void rump_fstrans_done(struct mount *); 3158a83906aShannken void 3168a83906aShannken rump_fstrans_done(struct mount *mp) 3178a83906aShannken { 3188a83906aShannken 3198a83906aShannken } 3208a83906aShannken __weak_alias(fstrans_done,rump_fstrans_done); 3218a83906aShannken 32201a7e2e4Shannken 32301a7e2e4Shannken void rump_fstrans_lwp_dtor(struct lwp *); 32401a7e2e4Shannken void 32501a7e2e4Shannken rump_fstrans_lwp_dtor(struct lwp *l) 32601a7e2e4Shannken { 32701a7e2e4Shannken 32801a7e2e4Shannken } 32901a7e2e4Shannken __weak_alias(fstrans_lwp_dtor,rump_fstrans_lwp_dtor); 33001a7e2e4Shannken 33140ce89a2Sriastradh static int 33240ce89a2Sriastradh rump_filt_fsattach(struct knote *kn) 33340ce89a2Sriastradh { 33440ce89a2Sriastradh 33540ce89a2Sriastradh return EOPNOTSUPP; 33640ce89a2Sriastradh } 33740ce89a2Sriastradh 33840ce89a2Sriastradh struct filterops rump_fs_filtops = { 33940ce89a2Sriastradh .f_attach = rump_filt_fsattach, 34040ce89a2Sriastradh }; 34140ce89a2Sriastradh __weak_alias(fs_filtops,rump_fs_filtops); 34240ce89a2Sriastradh 34301ab3089Sriastradh struct pool_cache *rump_pnbuf_cache; 34401ab3089Sriastradh __weak_alias(pnbuf_cache,rump_pnbuf_cache); 34501ab3089Sriastradh 34607333402Spooka /* 34707333402Spooka * Provide weak aliases for tty routines used by printf. 34807333402Spooka * They will be used unless the rumpkern_tty component is present. 34907333402Spooka */ 35007333402Spooka 35107333402Spooka int rump_ttycheckoutq(struct tty *, int); 352a69d5558Spooka int 35307333402Spooka rump_ttycheckoutq(struct tty *tp, int wait) 354167269d4Spooka { 355167269d4Spooka 356167269d4Spooka return 1; 357167269d4Spooka } 35807333402Spooka __weak_alias(ttycheckoutq,rump_ttycheckoutq); 359167269d4Spooka 36007333402Spooka int rump_tputchar(int, int, struct tty *); 36107333402Spooka int 36207333402Spooka rump_tputchar(int c, int flags, struct tty *tp) 36307333402Spooka { 36407333402Spooka 36507333402Spooka cnputc(c); 36607333402Spooka return 0; 36707333402Spooka } 36807333402Spooka __weak_alias(tputchar,rump_tputchar); 36907333402Spooka 370167269d4Spooka void 371167269d4Spooka cnputc(int c) 372167269d4Spooka { 373167269d4Spooka 37432a34307Spooka rumpuser_putchar(c); 375167269d4Spooka } 376167269d4Spooka 377167269d4Spooka void 378df7f595eScegger cnflush(void) 379167269d4Spooka { 380167269d4Spooka 381167269d4Spooka /* done */ 382167269d4Spooka } 383167269d4Spooka 384b7c666f3Spooka void 385b7c666f3Spooka resettodr(void) 386b7c666f3Spooka { 387b7c666f3Spooka 388b7c666f3Spooka /* setting clocks is not in the jurisdiction of rump kernels */ 389b7c666f3Spooka } 390b7c666f3Spooka 391eacf4402Spooka #ifdef __HAVE_SYSCALL_INTERN 392eacf4402Spooka void 393eacf4402Spooka syscall_intern(struct proc *p) 394eacf4402Spooka { 395eacf4402Spooka 396f5bd9f40Spooka p->p_emuldata = NULL; 397eacf4402Spooka } 398eacf4402Spooka #endif 399c15f18f4Spooka 400cd73d116Spooka #ifdef LOCKDEBUG 401cd73d116Spooka void 402cd73d116Spooka turnstile_print(volatile void *obj, void (*pr)(const char *, ...)) 403cd73d116Spooka { 404cd73d116Spooka 405cd73d116Spooka /* nada */ 406cd73d116Spooka } 407cd73d116Spooka #endif 4082cd42818Spooka 4092cd42818Spooka void 4102cd42818Spooka cpu_reboot(int howto, char *bootstr) 4112cd42818Spooka { 4122cd42818Spooka int ruhow = 0; 4132cd42818Spooka void *finiarg; 4142cd42818Spooka 4152cd42818Spooka printf("rump kernel halting...\n"); 4162cd42818Spooka 4172cd42818Spooka if (!RUMP_LOCALPROC_P(curproc)) 4186195daadSpooka finiarg = RUMP_SPVM2CTL(curproc->p_vmspace); 4192cd42818Spooka else 4202cd42818Spooka finiarg = NULL; 4212cd42818Spooka 4222cd42818Spooka /* dump means we really take the dive here */ 4232cd42818Spooka if ((howto & RB_DUMP) || panicstr) { 4242cd42818Spooka ruhow = RUMPUSER_PANIC; 4252cd42818Spooka goto out; 4262cd42818Spooka } 4272cd42818Spooka 4282cd42818Spooka /* try to sync */ 4292cd42818Spooka if (!((howto & RB_NOSYNC) || panicstr)) { 4302cd42818Spooka rump_vfs_fini(); 4312cd42818Spooka } 4322cd42818Spooka 4332cd42818Spooka doshutdownhooks(); 4342cd42818Spooka 4352cd42818Spooka /* your wish is my command */ 4362cd42818Spooka if (howto & RB_HALT) { 4375ede295bSpooka printf("rump kernel halted (with RB_HALT, not exiting)\n"); 438787cba47Spooka rump_sysproxy_fini(finiarg); 4392cd42818Spooka for (;;) { 4402cd42818Spooka rumpuser_clock_sleep(RUMPUSER_CLOCK_RELWALL, 10, 0); 4412cd42818Spooka } 4422cd42818Spooka } 4432cd42818Spooka 4442cd42818Spooka /* this function is __dead, we must exit */ 4452cd42818Spooka out: 446787cba47Spooka rump_sysproxy_fini(finiarg); 4472cd42818Spooka rumpuser_exit(ruhow); 4482cd42818Spooka } 449