linux_misc.c revision 68583
19313Ssos/*- 29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt 39313Ssos * All rights reserved. 49313Ssos * 59313Ssos * Redistribution and use in source and binary forms, with or without 69313Ssos * modification, are permitted provided that the following conditions 79313Ssos * are met: 89313Ssos * 1. Redistributions of source code must retain the above copyright 914331Speter * notice, this list of conditions and the following disclaimer 109313Ssos * in this position and unchanged. 119313Ssos * 2. Redistributions in binary form must reproduce the above copyright 129313Ssos * notice, this list of conditions and the following disclaimer in the 139313Ssos * documentation and/or other materials provided with the distribution. 149313Ssos * 3. The name of the author may not be used to endorse or promote products 159313Ssos * derived from this software withough specific prior written permission 169313Ssos * 179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279313Ssos * 2850477Speter * $FreeBSD: head/sys/compat/linux/linux_misc.c 68583 2000-11-10 21:30:19Z marcel $ 299313Ssos */ 309313Ssos 3149842Smarcel#include "opt_compat.h" 3249842Smarcel 339313Ssos#include <sys/param.h> 349313Ssos#include <sys/systm.h> 3512458Sbde#include <sys/sysproto.h> 3612458Sbde#include <sys/kernel.h> 379313Ssos#include <sys/mman.h> 389313Ssos#include <sys/proc.h> 3924131Sbde#include <sys/fcntl.h> 409313Ssos#include <sys/imgact_aout.h> 419313Ssos#include <sys/mount.h> 429313Ssos#include <sys/namei.h> 439313Ssos#include <sys/resourcevar.h> 449313Ssos#include <sys/stat.h> 4512458Sbde#include <sys/sysctl.h> 4641931Sjulian#include <sys/unistd.h> 479313Ssos#include <sys/vnode.h> 489313Ssos#include <sys/wait.h> 4914331Speter#include <sys/time.h> 5051793Smarcel#include <sys/signalvar.h> 519313Ssos 5212652Sbde#include <vm/vm.h> 5312689Speter#include <vm/pmap.h> 5412458Sbde#include <vm/vm_kern.h> 5512689Speter#include <vm/vm_map.h> 5612842Sbde#include <vm/vm_extern.h> 5712458Sbde 5830855Skato#include <machine/frame.h> 5965106Smarcel#include <machine/limits.h> 6030837Skato#include <machine/psl.h> 6150818Smarcel#include <machine/sysarch.h> 6268201Sobrien#ifdef __i386__ 6350818Smarcel#include <machine/segments.h> 6468201Sobrien#endif 6530837Skato 6649849Smarcel#include <posix4/sched.h> 6749849Smarcel 6864909Smarcel#include <machine/../linux/linux.h> 6968583Smarcel#ifdef __alpha__ 7068201Sobrien#include <linux_proto.h> 7168583Smarcel#else 7268583Smarcel#include <machine/../linux/linux_proto.h> 7368583Smarcel#endif 7464909Smarcel#include <compat/linux/linux_mib.h> 7564909Smarcel#include <compat/linux/linux_util.h> 7664909Smarcel 7768201Sobrien#ifdef __alpha__ 7868201Sobrien#define BSD_TO_LINUX_SIGNAL(sig) (sig) 7968201Sobrien#else 8051793Smarcel#define BSD_TO_LINUX_SIGNAL(sig) \ 8151793Smarcel (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) 8268201Sobrien#endif 8351793Smarcel 8465099Smarcelstruct linux_rlimit { 8565099Smarcel unsigned long rlim_cur; 8665099Smarcel unsigned long rlim_max; 8765099Smarcel}; 8865099Smarcel 8968201Sobrien#ifndef __alpha__ 9049626Smarcelstatic unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = 9149626Smarcel{ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, 9249626Smarcel RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, 9349626Smarcel RLIMIT_MEMLOCK, -1 9449626Smarcel}; 9568201Sobrien#endif /*!__alpha__*/ 9649626Smarcel 9768201Sobrien#ifndef __alpha__ 989313Ssosint 9930994Sphklinux_alarm(struct proc *p, struct linux_alarm_args *args) 1009313Ssos{ 1019313Ssos struct itimerval it, old_it; 10212858Speter struct timeval tv; 1039313Ssos int s; 1049313Ssos 1059313Ssos#ifdef DEBUG 10638127Sbde printf("Linux-emul(%ld): alarm(%u)\n", (long)p->p_pid, args->secs); 1079313Ssos#endif 10838127Sbde if (args->secs > 100000000) 10938127Sbde return EINVAL; 1109313Ssos it.it_value.tv_sec = (long)args->secs; 1119313Ssos it.it_value.tv_usec = 0; 1129313Ssos it.it_interval.tv_sec = 0; 1139313Ssos it.it_interval.tv_usec = 0; 11438127Sbde s = splsoftclock(); 1159313Ssos old_it = p->p_realtimer; 11638127Sbde getmicrouptime(&tv); 11735058Sphk if (timevalisset(&old_it.it_value)) 11838127Sbde untimeout(realitexpire, (caddr_t)p, p->p_ithandle); 11938127Sbde if (it.it_value.tv_sec != 0) { 12038127Sbde p->p_ithandle = timeout(realitexpire, (caddr_t)p, tvtohz(&it.it_value)); 12112858Speter timevaladd(&it.it_value, &tv); 1229313Ssos } 1239313Ssos p->p_realtimer = it; 1249313Ssos splx(s); 12538127Sbde if (timevalcmp(&old_it.it_value, &tv, >)) { 12638127Sbde timevalsub(&old_it.it_value, &tv); 12738127Sbde if (old_it.it_value.tv_usec != 0) 12838127Sbde old_it.it_value.tv_sec++; 12938127Sbde p->p_retval[0] = old_it.it_value.tv_sec; 13038127Sbde } 1319313Ssos return 0; 1329313Ssos} 13368201Sobrien#endif /*!__alpha__*/ 1349313Ssos 1359313Ssosint 13630994Sphklinux_brk(struct proc *p, struct linux_brk_args *args) 1379313Ssos{ 1389313Ssos#if 0 1399313Ssos struct vmspace *vm = p->p_vmspace; 1409313Ssos vm_offset_t new, old; 1419313Ssos int error; 1429313Ssos 1439313Ssos if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) 1449313Ssos return EINVAL; 1459313Ssos if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) 1469313Ssos > p->p_rlimit[RLIMIT_DATA].rlim_cur) 1479313Ssos return ENOMEM; 1489313Ssos 1499313Ssos old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); 1509313Ssos new = round_page((vm_offset_t)args->dsend); 15130994Sphk p->p_retval[0] = old; 1529313Ssos if ((new-old) > 0) { 1539313Ssos if (swap_pager_full) 1549313Ssos return ENOMEM; 15513503Sdyson error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE, 15613503Sdyson VM_PROT_ALL, VM_PROT_ALL, 0); 15714331Speter if (error) 1589313Ssos return error; 1599313Ssos vm->vm_dsize += btoc((new-old)); 16030994Sphk p->p_retval[0] = (int)(vm->vm_daddr + ctob(vm->vm_dsize)); 1619313Ssos } 1629313Ssos return 0; 1639313Ssos#else 1649313Ssos struct vmspace *vm = p->p_vmspace; 1659313Ssos vm_offset_t new, old; 16612858Speter struct obreak_args /* { 16712858Speter char * nsize; 16812858Speter } */ tmp; 1699313Ssos 1709313Ssos#ifdef DEBUG 17137950Sbde printf("Linux-emul(%ld): brk(%p)\n", (long)p->p_pid, (void *)args->dsend); 1729313Ssos#endif 1739313Ssos old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); 1749313Ssos new = (vm_offset_t)args->dsend; 17512858Speter tmp.nsize = (char *) new; 17630994Sphk if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp)) 17768201Sobrien p->p_retval[0] = (long)new; 1789313Ssos else 17968201Sobrien p->p_retval[0] = (long)old; 1809313Ssos 1819313Ssos return 0; 1829313Ssos#endif 1839313Ssos} 1849313Ssos 1859313Ssosint 18630994Sphklinux_uselib(struct proc *p, struct linux_uselib_args *args) 1879313Ssos{ 1889313Ssos struct nameidata ni; 18912130Sdg struct vnode *vp; 19014114Speter struct exec *a_out; 1919313Ssos struct vattr attr; 19214703Sbde vm_offset_t vmaddr; 19314703Sbde unsigned long file_offset; 19414703Sbde vm_offset_t buffer; 19514703Sbde unsigned long bss_size; 1969313Ssos int error; 19714331Speter caddr_t sg; 19814114Speter int locked; 1999313Ssos 20014331Speter sg = stackgap_init(); 20114331Speter CHECKALTEXIST(p, &sg, args->library); 20214331Speter 2039313Ssos#ifdef DEBUG 20449959Smarcel printf("Linux-emul(%ld): uselib(%s)\n", (long)p->p_pid, args->library); 2059313Ssos#endif 2069313Ssos 20714114Speter a_out = NULL; 20814114Speter locked = 0; 20914114Speter vp = NULL; 21014114Speter 21149523Smarcel NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, args->library, p); 21246571Speter error = namei(&ni); 21346571Speter if (error) 21414114Speter goto cleanup; 2159313Ssos 21612130Sdg vp = ni.ni_vp; 21754655Seivind /* 21854655Seivind * XXX This looks like a bogus check - a LOCKLEAF namei should not succeed 21954655Seivind * without returning a vnode. 22054655Seivind */ 22114114Speter if (vp == NULL) { 22214114Speter error = ENOEXEC; /* ?? */ 22314114Speter goto cleanup; 22414114Speter } 22554655Seivind NDFREE(&ni, NDF_ONLY_PNBUF); 2269313Ssos 22714114Speter /* 22814114Speter * From here on down, we have a locked vnode that must be unlocked. 22914114Speter */ 23014114Speter locked++; 23114114Speter 23214114Speter /* 23314114Speter * Writable? 23414114Speter */ 23512130Sdg if (vp->v_writecount) { 23614114Speter error = ETXTBSY; 23714114Speter goto cleanup; 23811163Sjulian } 2399313Ssos 24014114Speter /* 24114114Speter * Executable? 24214114Speter */ 24346571Speter error = VOP_GETATTR(vp, &attr, p->p_ucred, p); 24446571Speter if (error) 24514114Speter goto cleanup; 2469313Ssos 24714114Speter if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 24814114Speter ((attr.va_mode & 0111) == 0) || 24914114Speter (attr.va_type != VREG)) { 25014114Speter error = ENOEXEC; 25114114Speter goto cleanup; 25211163Sjulian } 2539313Ssos 25414114Speter /* 25514114Speter * Sensible size? 25614114Speter */ 25711163Sjulian if (attr.va_size == 0) { 25814114Speter error = ENOEXEC; 25914114Speter goto cleanup; 26011163Sjulian } 2619313Ssos 26214114Speter /* 26314114Speter * Can we access it? 26414114Speter */ 26546571Speter error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 26646571Speter if (error) 26714114Speter goto cleanup; 2689313Ssos 26946571Speter error = VOP_OPEN(vp, FREAD, p->p_ucred, p); 27046571Speter if (error) 27114114Speter goto cleanup; 2729313Ssos 27314114Speter /* 27414114Speter * Lock no longer needed 27514114Speter */ 27622543Smpp VOP_UNLOCK(vp, 0, p); 27714114Speter locked = 0; 27811163Sjulian 27914114Speter /* 28014114Speter * Pull in executable header into kernel_map 28114114Speter */ 28214114Speter error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, 28312130Sdg VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); 2849313Ssos if (error) 28514114Speter goto cleanup; 2869313Ssos 2879313Ssos /* 2889313Ssos * Is it a Linux binary ? 2899313Ssos */ 29014114Speter if (((a_out->a_magic >> 16) & 0xff) != 0x64) { 29114114Speter error = ENOEXEC; 29214114Speter goto cleanup; 29314114Speter } 2949313Ssos 29514114Speter /* While we are here, we should REALLY do some more checks */ 29614114Speter 2979313Ssos /* 2989313Ssos * Set file/virtual offset based on a.out variant. 2999313Ssos */ 3009313Ssos switch ((int)(a_out->a_magic & 0xffff)) { 3019313Ssos case 0413: /* ZMAGIC */ 3029313Ssos file_offset = 1024; 3039313Ssos break; 3049313Ssos case 0314: /* QMAGIC */ 3059313Ssos file_offset = 0; 3069313Ssos break; 3079313Ssos default: 30814114Speter error = ENOEXEC; 30914114Speter goto cleanup; 3109313Ssos } 3119313Ssos 3129313Ssos bss_size = round_page(a_out->a_bss); 31314114Speter 3149313Ssos /* 31514114Speter * Check various fields in header for validity/bounds. 31614114Speter */ 31715538Sphk if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { 31814114Speter error = ENOEXEC; 31914114Speter goto cleanup; 32014114Speter } 32114114Speter 32214114Speter /* text + data can't exceed file size */ 32314114Speter if (a_out->a_data + a_out->a_text > attr.va_size) { 32414114Speter error = EFAULT; 32514114Speter goto cleanup; 32614114Speter } 32714114Speter 32814114Speter /* 32914114Speter * text/data/bss must not exceed limits 33014114Speter * XXX: this is not complete. it should check current usage PLUS 33114114Speter * the resources needed by this library. 33214114Speter */ 33333821Sbde if (a_out->a_text > MAXTSIZ || 33433821Sbde a_out->a_data + bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { 33514114Speter error = ENOMEM; 33614114Speter goto cleanup; 33714114Speter } 33814114Speter 33914114Speter /* 34014114Speter * prevent more writers 34114114Speter */ 34214114Speter vp->v_flag |= VTEXT; 34314114Speter 34414114Speter /* 3459313Ssos * Check if file_offset page aligned,. 3469313Ssos * Currently we cannot handle misalinged file offsets, 3479313Ssos * and so we read in the entire image (what a waste). 3489313Ssos */ 34915538Sphk if (file_offset & PAGE_MASK) { 3509313Ssos#ifdef DEBUG 35137950Sbdeprintf("uselib: Non page aligned binary %lu\n", file_offset); 3529313Ssos#endif 3539313Ssos /* 3549313Ssos * Map text+data read/write/execute 3559313Ssos */ 35614114Speter 35714114Speter /* a_entry is the load address and is page aligned */ 35814114Speter vmaddr = trunc_page(a_out->a_entry); 35914114Speter 36014114Speter /* get anon user mapping, read+write+execute */ 3619313Ssos error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 36214114Speter a_out->a_text + a_out->a_data, FALSE, 36314114Speter VM_PROT_ALL, VM_PROT_ALL, 0); 3649313Ssos if (error) 36514114Speter goto cleanup; 3669313Ssos 36714114Speter /* map file into kernel_map */ 3689313Ssos error = vm_mmap(kernel_map, &buffer, 3699313Ssos round_page(a_out->a_text + a_out->a_data + file_offset), 37014584Speter VM_PROT_READ, VM_PROT_READ, 0, 37112130Sdg (caddr_t)vp, trunc_page(file_offset)); 3729313Ssos if (error) 37314114Speter goto cleanup; 3749313Ssos 37514114Speter /* copy from kernel VM space to user space */ 37638354Sbde error = copyout((caddr_t)(void *)(uintptr_t)(buffer + file_offset), 37738354Sbde (caddr_t)vmaddr, a_out->a_text + a_out->a_data); 3789313Ssos 37914114Speter /* release temporary kernel space */ 38014114Speter vm_map_remove(kernel_map, buffer, 38114471Speter buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 3829313Ssos 3839313Ssos if (error) 38414114Speter goto cleanup; 3859313Ssos } 3869313Ssos else { 3879313Ssos#ifdef DEBUG 38837950Sbdeprintf("uselib: Page aligned binary %lu\n", file_offset); 3899313Ssos#endif 39014114Speter /* 39114114Speter * for QMAGIC, a_entry is 20 bytes beyond the load address 39214114Speter * to skip the executable header 39314114Speter */ 39414114Speter vmaddr = trunc_page(a_out->a_entry); 39514114Speter 39614114Speter /* 39714114Speter * Map it all into the process's space as a single copy-on-write 39814114Speter * "data" segment. 39914114Speter */ 4009313Ssos error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, 40114114Speter a_out->a_text + a_out->a_data, 4029313Ssos VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, 40312130Sdg (caddr_t)vp, file_offset); 4049313Ssos if (error) 40514114Speter goto cleanup; 4069313Ssos } 4079313Ssos#ifdef DEBUG 40868201Sobrienprintf("mem=%08lx = %08lx %08lx\n", vmaddr, ((long*)vmaddr)[0], ((long*)vmaddr)[1]); 4099313Ssos#endif 4109313Ssos if (bss_size != 0) { 41114114Speter /* 41214114Speter * Calculate BSS start address 41314114Speter */ 41414114Speter vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; 41514114Speter 41614114Speter /* 41714114Speter * allocate some 'anon' space 41814114Speter */ 41914331Speter error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 42013503Sdyson bss_size, FALSE, 42114114Speter VM_PROT_ALL, VM_PROT_ALL, 0); 4229313Ssos if (error) 42314114Speter goto cleanup; 4249313Ssos } 42514114Speter 42614114Spetercleanup: 42714114Speter /* 42814114Speter * Unlock vnode if needed 42914114Speter */ 43014114Speter if (locked) 43122543Smpp VOP_UNLOCK(vp, 0, p); 43214114Speter 43314114Speter /* 43414114Speter * Release the kernel mapping. 43514114Speter */ 43614114Speter if (a_out) 43714471Speter vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); 43814114Speter 43914114Speter return error; 4409313Ssos} 4419313Ssos 4429313Ssosint 44330994Sphklinux_newselect(struct proc *p, struct linux_newselect_args *args) 44414331Speter{ 44514331Speter struct select_args bsa; 44614331Speter struct timeval tv0, tv1, utv, *tvp; 44714331Speter caddr_t sg; 44814331Speter int error; 44914331Speter 4509313Ssos#ifdef DEBUG 45137950Sbde printf("Linux-emul(%ld): newselect(%d, %p, %p, %p, %p)\n", 45237950Sbde (long)p->p_pid, args->nfds, (void *)args->readfds, 45337950Sbde (void *)args->writefds, (void *)args->exceptfds, 45437950Sbde (void *)args->timeout); 4559313Ssos#endif 45614331Speter error = 0; 45714331Speter bsa.nd = args->nfds; 45814331Speter bsa.in = args->readfds; 45914331Speter bsa.ou = args->writefds; 46014331Speter bsa.ex = args->exceptfds; 46114331Speter bsa.tv = args->timeout; 46214331Speter 46314331Speter /* 46414331Speter * Store current time for computation of the amount of 46514331Speter * time left. 46614331Speter */ 46714331Speter if (args->timeout) { 46814331Speter if ((error = copyin(args->timeout, &utv, sizeof(utv)))) 46914331Speter goto select_out; 47014331Speter#ifdef DEBUG 47137950Sbde printf("Linux-emul(%ld): incoming timeout (%ld/%ld)\n", 47237950Sbde (long)p->p_pid, utv.tv_sec, utv.tv_usec); 47314331Speter#endif 47414331Speter if (itimerfix(&utv)) { 47514331Speter /* 47614331Speter * The timeval was invalid. Convert it to something 47714331Speter * valid that will act as it does under Linux. 47814331Speter */ 47914331Speter sg = stackgap_init(); 48014331Speter tvp = stackgap_alloc(&sg, sizeof(utv)); 48114331Speter utv.tv_sec += utv.tv_usec / 1000000; 48214331Speter utv.tv_usec %= 1000000; 48314331Speter if (utv.tv_usec < 0) { 48414331Speter utv.tv_sec -= 1; 48514331Speter utv.tv_usec += 1000000; 48614331Speter } 48714331Speter if (utv.tv_sec < 0) 48835058Sphk timevalclear(&utv); 48914331Speter if ((error = copyout(&utv, tvp, sizeof(utv)))) 49014331Speter goto select_out; 49114331Speter bsa.tv = tvp; 49214331Speter } 49314331Speter microtime(&tv0); 49414331Speter } 49514331Speter 49630994Sphk error = select(p, &bsa); 49714331Speter#ifdef DEBUG 49849959Smarcel printf("Linux-emul(%ld): real select returns %d\n", (long)p->p_pid, error); 49914331Speter#endif 50014331Speter 50114331Speter if (error) { 50214331Speter /* 50314331Speter * See fs/select.c in the Linux kernel. Without this, 50414331Speter * Maelstrom doesn't work. 50514331Speter */ 50614331Speter if (error == ERESTART) 50714331Speter error = EINTR; 50814331Speter goto select_out; 50914331Speter } 51014331Speter 51114331Speter if (args->timeout) { 51230994Sphk if (p->p_retval[0]) { 51314331Speter /* 51414331Speter * Compute how much time was left of the timeout, 51514331Speter * by subtracting the current time and the time 51614331Speter * before we started the call, and subtracting 51714331Speter * that result from the user-supplied value. 51814331Speter */ 51914331Speter microtime(&tv1); 52014331Speter timevalsub(&tv1, &tv0); 52114331Speter timevalsub(&utv, &tv1); 52214331Speter if (utv.tv_sec < 0) 52335058Sphk timevalclear(&utv); 52414331Speter } else 52535058Sphk timevalclear(&utv); 52614331Speter#ifdef DEBUG 52737950Sbde printf("Linux-emul(%ld): outgoing timeout (%ld/%ld)\n", 52837950Sbde (long)p->p_pid, utv.tv_sec, utv.tv_usec); 52914331Speter#endif 53014331Speter if ((error = copyout(&utv, args->timeout, sizeof(utv)))) 53114331Speter goto select_out; 53214331Speter } 53314331Speter 53414331Speterselect_out: 53514331Speter#ifdef DEBUG 53649959Smarcel printf("Linux-emul(%ld): newselect_out -> %d\n", (long)p->p_pid, error); 53714331Speter#endif 53814331Speter return error; 5399313Ssos} 5409313Ssos 5419313Ssosint 54230994Sphklinux_getpgid(struct proc *p, struct linux_getpgid_args *args) 5439313Ssos{ 54446129Sluoqi struct proc *curp; 5459313Ssos 5469313Ssos#ifdef DEBUG 54749959Smarcel printf("Linux-emul(%ld): getpgid(%d)\n", (long)p->p_pid, args->pid); 5489313Ssos#endif 5499313Ssos if (args->pid != p->p_pid) { 55046129Sluoqi if (!(curp = pfind(args->pid))) 5519313Ssos return ESRCH; 5529313Ssos } 5539313Ssos else 55446129Sluoqi curp = p; 55546129Sluoqi p->p_retval[0] = curp->p_pgid; 5569313Ssos return 0; 5579313Ssos} 5589313Ssos 55937548Sjkhint 56037548Sjkhlinux_mremap(struct proc *p, struct linux_mremap_args *args) 56137548Sjkh{ 56237548Sjkh struct munmap_args /* { 56337548Sjkh void *addr; 56437548Sjkh size_t len; 56537548Sjkh } */ bsd_args; 56637548Sjkh int error = 0; 56737548Sjkh 56837548Sjkh#ifdef DEBUG 56968201Sobrien printf("Linux-emul(%ld): mremap(%p, %08lx, %08lx, %08lx)\n", 57068201Sobrien (long)p->p_pid, (void *)args->addr, 57168201Sobrien (unsigned long)args->old_len, 57268201Sobrien (unsigned long)args->new_len, 57368201Sobrien (unsigned long)args->flags); 57437548Sjkh#endif 57537548Sjkh args->new_len = round_page(args->new_len); 57637548Sjkh args->old_len = round_page(args->old_len); 57737548Sjkh 57837548Sjkh if (args->new_len > args->old_len) { 57937548Sjkh p->p_retval[0] = 0; 58037548Sjkh return ENOMEM; 58137548Sjkh } 58237548Sjkh 58337548Sjkh if (args->new_len < args->old_len) { 58437548Sjkh bsd_args.addr = args->addr + args->new_len; 58537548Sjkh bsd_args.len = args->old_len - args->new_len; 58637548Sjkh error = munmap(p, &bsd_args); 58737548Sjkh } 58837548Sjkh 58968201Sobrien p->p_retval[0] = error ? 0 : (u_long)args->addr; 59037548Sjkh return error; 59137548Sjkh} 59237548Sjkh 59314331Speterint 59430994Sphklinux_msync(struct proc *p, struct linux_msync_args *args) 59514331Speter{ 59614331Speter struct msync_args bsd_args; 5979313Ssos 59814331Speter bsd_args.addr = args->addr; 59914331Speter bsd_args.len = args->len; 60014331Speter bsd_args.flags = 0; /* XXX ignore */ 60114331Speter 60230994Sphk return msync(p, &bsd_args); 60314331Speter} 60414331Speter 60568201Sobrien#ifndef __alpha__ 6069313Ssosint 60730994Sphklinux_time(struct proc *p, struct linux_time_args *args) 6089313Ssos{ 6099313Ssos struct timeval tv; 6109313Ssos linux_time_t tm; 6119313Ssos int error; 6129313Ssos 6139313Ssos#ifdef DEBUG 61449959Smarcel printf("Linux-emul(%ld): time(*)\n", (long)p->p_pid); 6159313Ssos#endif 6169313Ssos microtime(&tv); 6179313Ssos tm = tv.tv_sec; 61814331Speter if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t)))) 6199313Ssos return error; 62030994Sphk p->p_retval[0] = tm; 6219313Ssos return 0; 6229313Ssos} 62368201Sobrien#endif /*!__alpha__*/ 6249313Ssos 62514331Speterstruct linux_times_argv { 6269313Ssos long tms_utime; 6279313Ssos long tms_stime; 6289313Ssos long tms_cutime; 6299313Ssos long tms_cstime; 6309313Ssos}; 6319313Ssos 63214381Speter#define CLK_TCK 100 /* Linux uses 100 */ 63314381Speter#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 63414381Speter 6359313Ssosint 63630994Sphklinux_times(struct proc *p, struct linux_times_args *args) 6379313Ssos{ 6389313Ssos struct timeval tv; 63914331Speter struct linux_times_argv tms; 64014381Speter struct rusage ru; 64116322Sgpalmer int error; 6429313Ssos 6439313Ssos#ifdef DEBUG 64449959Smarcel printf("Linux-emul(%ld): times(*)\n", (long)p->p_pid); 6459313Ssos#endif 64614381Speter calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); 64714381Speter 64814381Speter tms.tms_utime = CONVTCK(ru.ru_utime); 64914381Speter tms.tms_stime = CONVTCK(ru.ru_stime); 65014381Speter 65114381Speter tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); 65214381Speter tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); 65314381Speter 65414381Speter if ((error = copyout((caddr_t)&tms, (caddr_t)args->buf, 65514381Speter sizeof(struct linux_times_argv)))) 65614381Speter return error; 65714381Speter 65836119Sphk microuptime(&tv); 65930994Sphk p->p_retval[0] = (int)CONVTCK(tv); 66014381Speter return 0; 6619313Ssos} 6629313Ssos 6639313Ssosint 66430994Sphklinux_newuname(struct proc *p, struct linux_newuname_args *args) 6659313Ssos{ 66650345Smarcel struct linux_new_utsname utsname; 66750465Smarcel char *osrelease, *osname; 6689313Ssos 6699313Ssos#ifdef DEBUG 67050345Smarcel printf("Linux-emul(%ld): newuname(*)\n", (long)p->p_pid); 6719313Ssos#endif 67250345Smarcel 67350465Smarcel osname = linux_get_osname(p); 67450465Smarcel osrelease = linux_get_osrelease(p); 67550465Smarcel 67650345Smarcel bzero(&utsname, sizeof(struct linux_new_utsname)); 67750465Smarcel strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1); 67850345Smarcel strncpy(utsname.nodename, hostname, LINUX_MAX_UTSNAME-1); 67950465Smarcel strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1); 68050345Smarcel strncpy(utsname.version, version, LINUX_MAX_UTSNAME-1); 68150345Smarcel strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1); 68250345Smarcel strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1); 68350345Smarcel 68450345Smarcel return (copyout((caddr_t)&utsname, (caddr_t)args->buf, 68550345Smarcel sizeof(struct linux_new_utsname))); 6869313Ssos} 6879313Ssos 68814381Speterstruct linux_utimbuf { 68914381Speter linux_time_t l_actime; 69014381Speter linux_time_t l_modtime; 69114381Speter}; 6929313Ssos 6939313Ssosint 69430994Sphklinux_utime(struct proc *p, struct linux_utime_args *args) 6959313Ssos{ 69612858Speter struct utimes_args /* { 69712858Speter char *path; 6989313Ssos struct timeval *tptr; 69912858Speter } */ bsdutimes; 70014381Speter struct timeval tv[2], *tvp; 70114381Speter struct linux_utimbuf lut; 70214381Speter int error; 70314331Speter caddr_t sg; 7049313Ssos 70514331Speter sg = stackgap_init(); 70614331Speter CHECKALTEXIST(p, &sg, args->fname); 70714331Speter 7089313Ssos#ifdef DEBUG 70949959Smarcel printf("Linux-emul(%ld): utime(%s, *)\n", (long)p->p_pid, args->fname); 7109313Ssos#endif 71114381Speter if (args->times) { 71214381Speter if ((error = copyin(args->times, &lut, sizeof lut))) 71314381Speter return error; 71414381Speter tv[0].tv_sec = lut.l_actime; 71514381Speter tv[0].tv_usec = 0; 71614381Speter tv[1].tv_sec = lut.l_modtime; 71714381Speter tv[1].tv_usec = 0; 71814381Speter /* so that utimes can copyin */ 71914381Speter tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); 72063778Smarcel if (tvp == NULL) 72163778Smarcel return (ENAMETOOLONG); 72214381Speter if ((error = copyout(tv, tvp, sizeof(tv)))) 72314381Speter return error; 72414381Speter bsdutimes.tptr = tvp; 72514381Speter } else 72614381Speter bsdutimes.tptr = NULL; 72714381Speter 72812858Speter bsdutimes.path = args->fname; 72930994Sphk return utimes(p, &bsdutimes); 7309313Ssos} 7319313Ssos 73244384Sjulian#define __WCLONE 0x80000000 73344384Sjulian 73468201Sobrien#ifndef __alpha__ 7359313Ssosint 73630994Sphklinux_waitpid(struct proc *p, struct linux_waitpid_args *args) 7379313Ssos{ 73812858Speter struct wait_args /* { 7399313Ssos int pid; 7409313Ssos int *status; 7419313Ssos int options; 7429313Ssos struct rusage *rusage; 74312858Speter } */ tmp; 7449313Ssos int error, tmpstat; 7459313Ssos 7469313Ssos#ifdef DEBUG 74737950Sbde printf("Linux-emul(%ld): waitpid(%d, %p, %d)\n", 74837950Sbde (long)p->p_pid, args->pid, (void *)args->status, args->options); 7499313Ssos#endif 7509313Ssos tmp.pid = args->pid; 7519313Ssos tmp.status = args->status; 75241931Sjulian tmp.options = (args->options & (WNOHANG | WUNTRACED)); 75344384Sjulian /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 75444384Sjulian if (args->options & __WCLONE) 75544384Sjulian tmp.options |= WLINUXCLONE; 7569313Ssos tmp.rusage = NULL; 7579313Ssos 75844384Sjulian if ((error = wait4(p, &tmp)) != 0) 7599313Ssos return error; 76043208Sjulian 76114331Speter if (args->status) { 76244384Sjulian if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0) 76314331Speter return error; 76457867Smarcel tmpstat &= 0xffff; 76514331Speter if (WIFSIGNALED(tmpstat)) 76614331Speter tmpstat = (tmpstat & 0xffffff80) | 76751793Smarcel BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 76814331Speter else if (WIFSTOPPED(tmpstat)) 76914331Speter tmpstat = (tmpstat & 0xffff00ff) | 77051793Smarcel (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 77114331Speter return copyout(&tmpstat, args->status, sizeof(int)); 77214331Speter } else 77314331Speter return 0; 7749313Ssos} 77568201Sobrien#endif /*!__alpha__*/ 7769313Ssos 77714331Speterint 77830994Sphklinux_wait4(struct proc *p, struct linux_wait4_args *args) 7799313Ssos{ 78012858Speter struct wait_args /* { 7819313Ssos int pid; 7829313Ssos int *status; 7839313Ssos int options; 7849313Ssos struct rusage *rusage; 78512858Speter } */ tmp; 7869313Ssos int error, tmpstat; 7879313Ssos 7889313Ssos#ifdef DEBUG 78937950Sbde printf("Linux-emul(%ld): wait4(%d, %p, %d, %p)\n", 79037950Sbde (long)p->p_pid, args->pid, (void *)args->status, args->options, 79137950Sbde (void *)args->rusage); 7929313Ssos#endif 7939313Ssos tmp.pid = args->pid; 7949313Ssos tmp.status = args->status; 79541931Sjulian tmp.options = (args->options & (WNOHANG | WUNTRACED)); 79644384Sjulian /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 79744384Sjulian if (args->options & __WCLONE) 79844384Sjulian tmp.options |= WLINUXCLONE; 7999313Ssos tmp.rusage = args->rusage; 8009313Ssos 80144384Sjulian if ((error = wait4(p, &tmp)) != 0) 8029313Ssos return error; 80314331Speter 80451793Smarcel SIGDELSET(p->p_siglist, SIGCHLD); 80514331Speter 80614331Speter if (args->status) { 80744384Sjulian if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0) 80814331Speter return error; 80957867Smarcel tmpstat &= 0xffff; 81014331Speter if (WIFSIGNALED(tmpstat)) 81114331Speter tmpstat = (tmpstat & 0xffffff80) | 81251793Smarcel BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); 81314331Speter else if (WIFSTOPPED(tmpstat)) 81414331Speter tmpstat = (tmpstat & 0xffff00ff) | 81551793Smarcel (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); 81614331Speter return copyout(&tmpstat, args->status, sizeof(int)); 81714331Speter } else 81814331Speter return 0; 8199313Ssos} 82013420Ssos 82114331Speterint 82230994Sphklinux_mknod(struct proc *p, struct linux_mknod_args *args) 82313420Ssos{ 82414331Speter caddr_t sg; 82514331Speter struct mknod_args bsd_mknod; 82614331Speter struct mkfifo_args bsd_mkfifo; 82714331Speter 82814331Speter sg = stackgap_init(); 82914331Speter 83014331Speter CHECKALTCREAT(p, &sg, args->path); 83114331Speter 83214331Speter#ifdef DEBUG 83349959Smarcel printf("Linux-emul(%ld): mknod(%s, %d, %d)\n", 83449959Smarcel (long)p->p_pid, args->path, args->mode, args->dev); 83514331Speter#endif 83614331Speter 83714331Speter if (args->mode & S_IFIFO) { 83814331Speter bsd_mkfifo.path = args->path; 83914331Speter bsd_mkfifo.mode = args->mode; 84030994Sphk return mkfifo(p, &bsd_mkfifo); 84114331Speter } else { 84214331Speter bsd_mknod.path = args->path; 84314331Speter bsd_mknod.mode = args->mode; 84414331Speter bsd_mknod.dev = args->dev; 84530994Sphk return mknod(p, &bsd_mknod); 84614331Speter } 84713420Ssos} 84814331Speter 84914331Speter/* 85014331Speter * UGH! This is just about the dumbest idea I've ever heard!! 85114331Speter */ 85214331Speterint 85330994Sphklinux_personality(struct proc *p, struct linux_personality_args *args) 85414331Speter{ 85514331Speter#ifdef DEBUG 85649959Smarcel printf("Linux-emul(%ld): personality(%d)\n", 85749959Smarcel (long)p->p_pid, args->per); 85814331Speter#endif 85968201Sobrien#ifndef __alpha__ 86014331Speter if (args->per != 0) 86114331Speter return EINVAL; 86268201Sobrien#endif 86314331Speter 86414331Speter /* Yes Jim, it's still a Linux... */ 86530994Sphk p->p_retval[0] = 0; 86614331Speter return 0; 86714331Speter} 86814331Speter 86914331Speter/* 87014331Speter * Wrappers for get/setitimer for debugging.. 87114331Speter */ 87214331Speterint 87330994Sphklinux_setitimer(struct proc *p, struct linux_setitimer_args *args) 87414331Speter{ 87514331Speter struct setitimer_args bsa; 87614331Speter struct itimerval foo; 87714331Speter int error; 87814331Speter 87914331Speter#ifdef DEBUG 88037950Sbde printf("Linux-emul(%ld): setitimer(%p, %p)\n", 88137950Sbde (long)p->p_pid, (void *)args->itv, (void *)args->oitv); 88214331Speter#endif 88314331Speter bsa.which = args->which; 88414331Speter bsa.itv = args->itv; 88514331Speter bsa.oitv = args->oitv; 88614331Speter if (args->itv) { 88714331Speter if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo, 88814331Speter sizeof(foo)))) 88914331Speter return error; 89014331Speter#ifdef DEBUG 89137950Sbde printf("setitimer: value: sec: %ld, usec: %ld\n", 89237950Sbde foo.it_value.tv_sec, foo.it_value.tv_usec); 89337950Sbde printf("setitimer: interval: sec: %ld, usec: %ld\n", 89437950Sbde foo.it_interval.tv_sec, foo.it_interval.tv_usec); 89514331Speter#endif 89614331Speter } 89730994Sphk return setitimer(p, &bsa); 89814331Speter} 89914331Speter 90014331Speterint 90130994Sphklinux_getitimer(struct proc *p, struct linux_getitimer_args *args) 90214331Speter{ 90314331Speter struct getitimer_args bsa; 90414331Speter#ifdef DEBUG 90537950Sbde printf("Linux-emul(%ld): getitimer(%p)\n", 90637950Sbde (long)p->p_pid, (void *)args->itv); 90714331Speter#endif 90814331Speter bsa.which = args->which; 90914331Speter bsa.itv = args->itv; 91030994Sphk return getitimer(p, &bsa); 91114331Speter} 91230837Skato 91368201Sobrien#ifndef __alpha__ 91430837Skatoint 91530994Sphklinux_nice(struct proc *p, struct linux_nice_args *args) 91630837Skato{ 91730837Skato struct setpriority_args bsd_args; 91830837Skato 91930837Skato bsd_args.which = PRIO_PROCESS; 92030837Skato bsd_args.who = 0; /* current process */ 92130837Skato bsd_args.prio = args->inc; 92230994Sphk return setpriority(p, &bsd_args); 92330837Skato} 92468201Sobrien#endif /*!__alpha__*/ 92530837Skato 92642185Ssosint 92742185Ssoslinux_setgroups(p, uap) 92850350Smarcel struct proc *p; 92950350Smarcel struct linux_setgroups_args *uap; 93042185Ssos{ 93150350Smarcel struct pcred *pc; 93250350Smarcel linux_gid_t linux_gidset[NGROUPS]; 93350350Smarcel gid_t *bsd_gidset; 93450350Smarcel int ngrp, error; 93542185Ssos 93650350Smarcel pc = p->p_cred; 93750350Smarcel ngrp = uap->gidsetsize; 93842185Ssos 93950350Smarcel /* 94050350Smarcel * cr_groups[0] holds egid. Setting the whole set from 94150350Smarcel * the supplied set will cause egid to be changed too. 94250350Smarcel * Keep cr_groups[0] unchanged to prevent that. 94350350Smarcel */ 94442185Ssos 94550350Smarcel if ((error = suser(p)) != 0) 94650350Smarcel return (error); 94742185Ssos 94850350Smarcel if (ngrp >= NGROUPS) 94950350Smarcel return (EINVAL); 95042185Ssos 95150350Smarcel pc->pc_ucred = crcopy(pc->pc_ucred); 95250350Smarcel if (ngrp > 0) { 95350350Smarcel error = copyin((caddr_t)uap->gidset, (caddr_t)linux_gidset, 95450350Smarcel ngrp * sizeof(linux_gid_t)); 95550350Smarcel if (error) 95650350Smarcel return (error); 95742185Ssos 95850350Smarcel pc->pc_ucred->cr_ngroups = ngrp + 1; 95950350Smarcel 96050350Smarcel bsd_gidset = pc->pc_ucred->cr_groups; 96150350Smarcel ngrp--; 96250350Smarcel while (ngrp >= 0) { 96350350Smarcel bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 96450350Smarcel ngrp--; 96550350Smarcel } 96650350Smarcel } 96750350Smarcel else 96850350Smarcel pc->pc_ucred->cr_ngroups = 1; 96950350Smarcel 97050350Smarcel setsugid(p); 97150350Smarcel return (0); 97242185Ssos} 97342185Ssos 97442185Ssosint 97542185Ssoslinux_getgroups(p, uap) 97650350Smarcel struct proc *p; 97750350Smarcel struct linux_getgroups_args *uap; 97842185Ssos{ 97950350Smarcel struct pcred *pc; 98050350Smarcel linux_gid_t linux_gidset[NGROUPS]; 98150350Smarcel gid_t *bsd_gidset; 98250350Smarcel int bsd_gidsetsz, ngrp, error; 98342185Ssos 98450350Smarcel pc = p->p_cred; 98550350Smarcel bsd_gidset = pc->pc_ucred->cr_groups; 98650546Smarcel bsd_gidsetsz = pc->pc_ucred->cr_ngroups - 1; 98742185Ssos 98850350Smarcel /* 98950350Smarcel * cr_groups[0] holds egid. Returning the whole set 99050350Smarcel * here will cause a duplicate. Exclude cr_groups[0] 99150350Smarcel * to prevent that. 99250350Smarcel */ 99342185Ssos 99450350Smarcel if ((ngrp = uap->gidsetsize) == 0) { 99550546Smarcel p->p_retval[0] = bsd_gidsetsz; 99650350Smarcel return (0); 99750350Smarcel } 99842185Ssos 99950546Smarcel if (ngrp < bsd_gidsetsz) 100050350Smarcel return (EINVAL); 100142185Ssos 100250546Smarcel ngrp = 0; 100350350Smarcel while (ngrp < bsd_gidsetsz) { 100450546Smarcel linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 100550350Smarcel ngrp++; 100650350Smarcel } 100750350Smarcel 100850350Smarcel if ((error = copyout((caddr_t)linux_gidset, (caddr_t)uap->gidset, 100950350Smarcel ngrp * sizeof(linux_gid_t)))) 101050350Smarcel return (error); 101150350Smarcel 101250546Smarcel p->p_retval[0] = ngrp; 101350350Smarcel return (0); 101442185Ssos} 101549626Smarcel 101668201Sobrien#ifndef __alpha__ 101749626Smarcelint 101849626Smarcellinux_setrlimit(p, uap) 101965099Smarcel struct proc *p; 102065099Smarcel struct linux_setrlimit_args *uap; 102149626Smarcel{ 102265099Smarcel struct __setrlimit_args bsd; 102365099Smarcel struct linux_rlimit rlim; 102465099Smarcel int error; 102565099Smarcel caddr_t sg = stackgap_init(); 102649842Smarcel 102749626Smarcel#ifdef DEBUG 102865099Smarcel printf("Linux-emul(%ld): setrlimit(%d, %p)\n", (long)p->p_pid, 102965099Smarcel uap->resource, (void *)uap->rlim); 103049626Smarcel#endif 103149626Smarcel 103265099Smarcel if (uap->resource >= LINUX_RLIM_NLIMITS) 103365099Smarcel return (EINVAL); 103449626Smarcel 103565099Smarcel bsd.which = linux_to_bsd_resource[uap->resource]; 103665099Smarcel if (bsd.which == -1) 103765099Smarcel return (EINVAL); 103849626Smarcel 103965099Smarcel error = copyin(uap->rlim, &rlim, sizeof(rlim)); 104065099Smarcel if (error) 104165099Smarcel return (error); 104249626Smarcel 104365099Smarcel bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); 104465099Smarcel bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur; 104565099Smarcel bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max; 104665099Smarcel return (setrlimit(p, &bsd)); 104749626Smarcel} 104849626Smarcel 104949626Smarcelint 105049626Smarcellinux_getrlimit(p, uap) 105165099Smarcel struct proc *p; 105265099Smarcel struct linux_getrlimit_args *uap; 105349626Smarcel{ 105465099Smarcel struct __getrlimit_args bsd; 105565099Smarcel struct linux_rlimit rlim; 105665099Smarcel int error; 105765099Smarcel caddr_t sg = stackgap_init(); 105849842Smarcel 105949626Smarcel#ifdef DEBUG 106065099Smarcel printf("Linux-emul(%ld): getrlimit(%d, %p)\n", (long)p->p_pid, 106165099Smarcel uap->resource, (void *)uap->rlim); 106249626Smarcel#endif 106349626Smarcel 106465099Smarcel if (uap->resource >= LINUX_RLIM_NLIMITS) 106565099Smarcel return (EINVAL); 106649626Smarcel 106765099Smarcel bsd.which = linux_to_bsd_resource[uap->resource]; 106865099Smarcel if (bsd.which == -1) 106965099Smarcel return (EINVAL); 107049626Smarcel 107165099Smarcel bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); 107265099Smarcel error = getrlimit(p, &bsd); 107365099Smarcel if (error) 107465099Smarcel return (error); 107549626Smarcel 107665099Smarcel rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur; 107765106Smarcel if (rlim.rlim_cur == ULONG_MAX) 107865106Smarcel rlim.rlim_cur = LONG_MAX; 107965099Smarcel rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max; 108065106Smarcel if (rlim.rlim_max == ULONG_MAX) 108165106Smarcel rlim.rlim_max = LONG_MAX; 108265099Smarcel return (copyout(&rlim, uap->rlim, sizeof(rlim))); 108349626Smarcel} 108468201Sobrien#endif /*!__alpha__*/ 108549849Smarcel 108649849Smarcelint 108749849Smarcellinux_sched_setscheduler(p, uap) 108849849Smarcel struct proc *p; 108949849Smarcel struct linux_sched_setscheduler_args *uap; 109049849Smarcel{ 109149849Smarcel struct sched_setscheduler_args bsd; 109249849Smarcel 109349849Smarcel#ifdef DEBUG 109449849Smarcel printf("Linux-emul(%ld): sched_setscheduler(%d, %d, %p)\n", 109551793Smarcel (long)p->p_pid, uap->pid, uap->policy, (const void *)uap->param); 109649849Smarcel#endif 109749849Smarcel 109849849Smarcel switch (uap->policy) { 109949849Smarcel case LINUX_SCHED_OTHER: 110049849Smarcel bsd.policy = SCHED_OTHER; 110149849Smarcel break; 110249849Smarcel case LINUX_SCHED_FIFO: 110349849Smarcel bsd.policy = SCHED_FIFO; 110449849Smarcel break; 110549849Smarcel case LINUX_SCHED_RR: 110649849Smarcel bsd.policy = SCHED_RR; 110749849Smarcel break; 110849849Smarcel default: 110949849Smarcel return EINVAL; 111049849Smarcel } 111149849Smarcel 111249849Smarcel bsd.pid = uap->pid; 111349849Smarcel bsd.param = uap->param; 111449849Smarcel return sched_setscheduler(p, &bsd); 111549849Smarcel} 111649849Smarcel 111749849Smarcelint 111849849Smarcellinux_sched_getscheduler(p, uap) 111949849Smarcel struct proc *p; 112049849Smarcel struct linux_sched_getscheduler_args *uap; 112149849Smarcel{ 112249849Smarcel struct sched_getscheduler_args bsd; 112349849Smarcel int error; 112449849Smarcel 112549849Smarcel#ifdef DEBUG 112649849Smarcel printf("Linux-emul(%ld): sched_getscheduler(%d)\n", 112749849Smarcel (long)p->p_pid, uap->pid); 112849849Smarcel#endif 112949849Smarcel 113049849Smarcel bsd.pid = uap->pid; 113149849Smarcel error = sched_getscheduler(p, &bsd); 113249849Smarcel 113349849Smarcel switch (p->p_retval[0]) { 113449849Smarcel case SCHED_OTHER: 113549849Smarcel p->p_retval[0] = LINUX_SCHED_OTHER; 113649849Smarcel break; 113749849Smarcel case SCHED_FIFO: 113849849Smarcel p->p_retval[0] = LINUX_SCHED_FIFO; 113949849Smarcel break; 114049849Smarcel case SCHED_RR: 114149849Smarcel p->p_retval[0] = LINUX_SCHED_RR; 114249849Smarcel break; 114349849Smarcel } 114449849Smarcel 114549849Smarcel return error; 114649849Smarcel} 1147