164921Smarcel/*- 264921Smarcel * Copyright (c) 2000 Marcel Moolenaar 364921Smarcel * All rights reserved. 464921Smarcel * 564921Smarcel * Redistribution and use in source and binary forms, with or without 664921Smarcel * modification, are permitted provided that the following conditions 764921Smarcel * are met: 864921Smarcel * 1. Redistributions of source code must retain the above copyright 9111798Sdes * notice, this list of conditions and the following disclaimer 1064921Smarcel * in this position and unchanged. 1164921Smarcel * 2. Redistributions in binary form must reproduce the above copyright 1264921Smarcel * notice, this list of conditions and the following disclaimer in the 1364921Smarcel * documentation and/or other materials provided with the distribution. 1464921Smarcel * 3. The name of the author may not be used to endorse or promote products 1565067Smarcel * derived from this software without specific prior written permission. 1664921Smarcel * 1764921Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1864921Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1964921Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2064921Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2164921Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2264921Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2364921Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2464921Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2564921Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2664921Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2764921Smarcel */ 2864921Smarcel 29115705Sobrien#include <sys/cdefs.h> 30115705Sobrien__FBSDID("$FreeBSD$"); 31115705Sobrien 3264921Smarcel#include <sys/param.h> 3376166Smarkm#include <sys/systm.h> 34224778Srwatson#include <sys/capability.h> 35162472Snetchild#include <sys/file.h> 36162472Snetchild#include <sys/fcntl.h> 37140992Ssobomax#include <sys/imgact.h> 3884811Sjhb#include <sys/lock.h> 39140992Ssobomax#include <sys/malloc.h> 4064921Smarcel#include <sys/mman.h> 4176166Smarkm#include <sys/mutex.h> 42161310Snetchild#include <sys/sx.h> 43164033Srwatson#include <sys/priv.h> 4464921Smarcel#include <sys/proc.h> 45161310Snetchild#include <sys/queue.h> 4676166Smarkm#include <sys/resource.h> 4776166Smarkm#include <sys/resourcevar.h> 48134838Sdfr#include <sys/signalvar.h> 49102814Siedowse#include <sys/syscallsubr.h> 5064921Smarcel#include <sys/sysproto.h> 5164921Smarcel#include <sys/unistd.h> 52161310Snetchild#include <sys/wait.h> 53166188Sjeff#include <sys/sched.h> 5464921Smarcel 5564921Smarcel#include <machine/frame.h> 5664921Smarcel#include <machine/psl.h> 5764921Smarcel#include <machine/segments.h> 5864921Smarcel#include <machine/sysarch.h> 5964921Smarcel 6067238Sgallatin#include <vm/vm.h> 6167238Sgallatin#include <vm/pmap.h> 6267238Sgallatin#include <vm/vm_map.h> 6367238Sgallatin 6464921Smarcel#include <i386/linux/linux.h> 6568583Smarcel#include <i386/linux/linux_proto.h> 6664921Smarcel#include <compat/linux/linux_ipc.h> 67218030Sdchagin#include <compat/linux/linux_misc.h> 6864921Smarcel#include <compat/linux/linux_signal.h> 6964921Smarcel#include <compat/linux/linux_util.h> 70161310Snetchild#include <compat/linux/linux_emul.h> 7164921Smarcel 72161310Snetchild#include <i386/include/pcb.h> /* needed for pcb definition in linux_set_thread_area */ 73161310Snetchild 74161310Snetchild#include "opt_posix.h" 75161310Snetchild 76161310Snetchildextern struct sysentvec elf32_freebsd_sysvec; /* defined in i386/i386/elf_machdep.c */ 77161310Snetchild 7883221Smarcelstruct l_descriptor { 7983221Smarcel l_uint entry_number; 8083221Smarcel l_ulong base_addr; 8183221Smarcel l_uint limit; 8283221Smarcel l_uint seg_32bit:1; 8383221Smarcel l_uint contents:2; 8483221Smarcel l_uint read_exec_only:1; 8583221Smarcel l_uint limit_in_pages:1; 8683221Smarcel l_uint seg_not_present:1; 8783221Smarcel l_uint useable:1; 8864921Smarcel}; 8964921Smarcel 9083221Smarcelstruct l_old_select_argv { 9183221Smarcel l_int nfds; 9283221Smarcel l_fd_set *readfds; 9383221Smarcel l_fd_set *writefds; 9483221Smarcel l_fd_set *exceptfds; 9583221Smarcel struct l_timeval *timeout; 9664921Smarcel}; 9764921Smarcel 98198554Sjhbstatic int linux_mmap_common(struct thread *td, l_uintptr_t addr, 99198554Sjhb l_size_t len, l_int prot, l_int flags, l_int fd, 100198554Sjhb l_loff_t pos); 101198554Sjhb 10264921Smarcelint 10367051Sgallatinlinux_to_bsd_sigaltstack(int lsa) 10467051Sgallatin{ 10567051Sgallatin int bsa = 0; 10667051Sgallatin 10767051Sgallatin if (lsa & LINUX_SS_DISABLE) 10867051Sgallatin bsa |= SS_DISABLE; 10967051Sgallatin if (lsa & LINUX_SS_ONSTACK) 11067051Sgallatin bsa |= SS_ONSTACK; 11167051Sgallatin return (bsa); 11267051Sgallatin} 11367051Sgallatin 11467051Sgallatinint 11567051Sgallatinbsd_to_linux_sigaltstack(int bsa) 11667051Sgallatin{ 11767051Sgallatin int lsa = 0; 11867051Sgallatin 11967051Sgallatin if (bsa & SS_DISABLE) 12067051Sgallatin lsa |= LINUX_SS_DISABLE; 12167051Sgallatin if (bsa & SS_ONSTACK) 12267051Sgallatin lsa |= LINUX_SS_ONSTACK; 12367051Sgallatin return (lsa); 12467051Sgallatin} 12567051Sgallatin 12667051Sgallatinint 12783366Sjulianlinux_execve(struct thread *td, struct linux_execve_args *args) 12864921Smarcel{ 129140992Ssobomax int error; 130140992Ssobomax char *newpath; 131140992Ssobomax struct image_args eargs; 13264921Smarcel 133141468Sjhb LCONVPATHEXIST(td, args->path, &newpath); 13464921Smarcel 13564921Smarcel#ifdef DEBUG 13672543Sjlemon if (ldebug(execve)) 137140992Ssobomax printf(ARGS(execve, "%s"), newpath); 13864921Smarcel#endif 13964921Smarcel 140140992Ssobomax error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE, 141140992Ssobomax args->argp, args->envp); 142140992Ssobomax free(newpath, M_TEMP); 143140992Ssobomax if (error == 0) 144148623Ssobomax error = kern_execve(td, &eargs, NULL); 145161310Snetchild if (error == 0) 146161310Snetchild /* linux process can exec fbsd one, dont attempt 147161310Snetchild * to create emuldata for such process using 148161310Snetchild * linux_proc_init, this leads to a panic on KASSERT 149161310Snetchild * because such process has p->p_emuldata == NULL 150161310Snetchild */ 151217896Sdchagin if (SV_PROC_ABI(td->td_proc) == SV_ABI_LINUX) 152217896Sdchagin error = linux_proc_init(td, 0, 0); 153140992Ssobomax return (error); 15464921Smarcel} 15564921Smarcel 15683221Smarcelstruct l_ipc_kludge { 15783221Smarcel struct l_msgbuf *msgp; 15883221Smarcel l_long msgtyp; 15983221Smarcel}; 16083221Smarcel 16164921Smarcelint 16283366Sjulianlinux_ipc(struct thread *td, struct linux_ipc_args *args) 16364921Smarcel{ 16483221Smarcel 16583221Smarcel switch (args->what & 0xFFFF) { 16683221Smarcel case LINUX_SEMOP: { 16783221Smarcel struct linux_semop_args a; 16883221Smarcel 16983221Smarcel a.semid = args->arg1; 17083221Smarcel a.tsops = args->ptr; 17183221Smarcel a.nsops = args->arg2; 17283366Sjulian return (linux_semop(td, &a)); 17364921Smarcel } 17483221Smarcel case LINUX_SEMGET: { 17583221Smarcel struct linux_semget_args a; 17664921Smarcel 17783221Smarcel a.key = args->arg1; 17883221Smarcel a.nsems = args->arg2; 17983221Smarcel a.semflg = args->arg3; 18083366Sjulian return (linux_semget(td, &a)); 18183221Smarcel } 18283221Smarcel case LINUX_SEMCTL: { 18383221Smarcel struct linux_semctl_args a; 18483221Smarcel int error; 18583221Smarcel 18683221Smarcel a.semid = args->arg1; 18783221Smarcel a.semnum = args->arg2; 18883221Smarcel a.cmd = args->arg3; 189111797Sdes error = copyin(args->ptr, &a.arg, sizeof(a.arg)); 19083221Smarcel if (error) 19183221Smarcel return (error); 19283366Sjulian return (linux_semctl(td, &a)); 19383221Smarcel } 19483221Smarcel case LINUX_MSGSND: { 19583221Smarcel struct linux_msgsnd_args a; 19683221Smarcel 19783221Smarcel a.msqid = args->arg1; 19883221Smarcel a.msgp = args->ptr; 19983221Smarcel a.msgsz = args->arg2; 20083221Smarcel a.msgflg = args->arg3; 20183366Sjulian return (linux_msgsnd(td, &a)); 20283221Smarcel } 20383221Smarcel case LINUX_MSGRCV: { 20483221Smarcel struct linux_msgrcv_args a; 20583221Smarcel 20683221Smarcel a.msqid = args->arg1; 20783221Smarcel a.msgsz = args->arg2; 20883221Smarcel a.msgflg = args->arg3; 20983221Smarcel if ((args->what >> 16) == 0) { 21083221Smarcel struct l_ipc_kludge tmp; 21183221Smarcel int error; 21283221Smarcel 21383221Smarcel if (args->ptr == NULL) 21483221Smarcel return (EINVAL); 215111797Sdes error = copyin(args->ptr, &tmp, sizeof(tmp)); 21683221Smarcel if (error) 21783221Smarcel return (error); 21883221Smarcel a.msgp = tmp.msgp; 21983221Smarcel a.msgtyp = tmp.msgtyp; 22083221Smarcel } else { 22183221Smarcel a.msgp = args->ptr; 22283221Smarcel a.msgtyp = args->arg5; 22383221Smarcel } 22483366Sjulian return (linux_msgrcv(td, &a)); 22583221Smarcel } 22683221Smarcel case LINUX_MSGGET: { 22783221Smarcel struct linux_msgget_args a; 22883221Smarcel 22983221Smarcel a.key = args->arg1; 23083221Smarcel a.msgflg = args->arg2; 23183366Sjulian return (linux_msgget(td, &a)); 23283221Smarcel } 23383221Smarcel case LINUX_MSGCTL: { 23483221Smarcel struct linux_msgctl_args a; 23583221Smarcel 23683221Smarcel a.msqid = args->arg1; 23783221Smarcel a.cmd = args->arg2; 23883221Smarcel a.buf = args->ptr; 23983366Sjulian return (linux_msgctl(td, &a)); 24083221Smarcel } 24183221Smarcel case LINUX_SHMAT: { 24283221Smarcel struct linux_shmat_args a; 24383221Smarcel 24483221Smarcel a.shmid = args->arg1; 24583221Smarcel a.shmaddr = args->ptr; 24683221Smarcel a.shmflg = args->arg2; 24783221Smarcel a.raddr = (l_ulong *)args->arg3; 24883366Sjulian return (linux_shmat(td, &a)); 24983221Smarcel } 25083221Smarcel case LINUX_SHMDT: { 25183221Smarcel struct linux_shmdt_args a; 25283221Smarcel 25383221Smarcel a.shmaddr = args->ptr; 25483366Sjulian return (linux_shmdt(td, &a)); 25583221Smarcel } 25683221Smarcel case LINUX_SHMGET: { 25783221Smarcel struct linux_shmget_args a; 25883221Smarcel 25983221Smarcel a.key = args->arg1; 26083221Smarcel a.size = args->arg2; 26183221Smarcel a.shmflg = args->arg3; 26283366Sjulian return (linux_shmget(td, &a)); 26383221Smarcel } 26483221Smarcel case LINUX_SHMCTL: { 26583221Smarcel struct linux_shmctl_args a; 26683221Smarcel 26783221Smarcel a.shmid = args->arg1; 26883221Smarcel a.cmd = args->arg2; 26983221Smarcel a.buf = args->ptr; 27083366Sjulian return (linux_shmctl(td, &a)); 27183221Smarcel } 27283221Smarcel default: 27383221Smarcel break; 27483221Smarcel } 27583221Smarcel 27683221Smarcel return (EINVAL); 27764921Smarcel} 27864921Smarcel 27964921Smarcelint 28083366Sjulianlinux_old_select(struct thread *td, struct linux_old_select_args *args) 28164921Smarcel{ 28283221Smarcel struct l_old_select_argv linux_args; 28383221Smarcel struct linux_select_args newsel; 28464921Smarcel int error; 28564921Smarcel 28683221Smarcel#ifdef DEBUG 28783221Smarcel if (ldebug(old_select)) 28891437Speter printf(ARGS(old_select, "%p"), args->ptr); 28964921Smarcel#endif 29064921Smarcel 291111797Sdes error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 29264921Smarcel if (error) 29364921Smarcel return (error); 29464921Smarcel 29564921Smarcel newsel.nfds = linux_args.nfds; 29664921Smarcel newsel.readfds = linux_args.readfds; 29764921Smarcel newsel.writefds = linux_args.writefds; 29864921Smarcel newsel.exceptfds = linux_args.exceptfds; 29964921Smarcel newsel.timeout = linux_args.timeout; 30083366Sjulian return (linux_select(td, &newsel)); 30164921Smarcel} 30264921Smarcel 30364921Smarcelint 304218612Sdchaginlinux_set_cloned_tls(struct thread *td, void *desc) 305218612Sdchagin{ 306218612Sdchagin struct segment_descriptor sd; 307218612Sdchagin struct l_user_desc info; 308218612Sdchagin int idx, error; 309218612Sdchagin int a[2]; 310218612Sdchagin 311218612Sdchagin error = copyin(desc, &info, sizeof(struct l_user_desc)); 312218612Sdchagin if (error) { 313218612Sdchagin printf(LMSG("copyin failed!")); 314218612Sdchagin } else { 315218612Sdchagin idx = info.entry_number; 316218612Sdchagin 317218612Sdchagin /* 318218612Sdchagin * looks like we're getting the idx we returned 319218612Sdchagin * in the set_thread_area() syscall 320218612Sdchagin */ 321218612Sdchagin if (idx != 6 && idx != 3) { 322218612Sdchagin printf(LMSG("resetting idx!")); 323218612Sdchagin idx = 3; 324218612Sdchagin } 325218612Sdchagin 326218612Sdchagin /* this doesnt happen in practice */ 327218612Sdchagin if (idx == 6) { 328218612Sdchagin /* we might copy out the entry_number as 3 */ 329218612Sdchagin info.entry_number = 3; 330218612Sdchagin error = copyout(&info, desc, sizeof(struct l_user_desc)); 331218612Sdchagin if (error) 332218612Sdchagin printf(LMSG("copyout failed!")); 333218612Sdchagin } 334218612Sdchagin 335218612Sdchagin a[0] = LINUX_LDT_entry_a(&info); 336218612Sdchagin a[1] = LINUX_LDT_entry_b(&info); 337218612Sdchagin 338218612Sdchagin memcpy(&sd, &a, sizeof(a)); 339218612Sdchagin#ifdef DEBUG 340218612Sdchagin if (ldebug(clone)) 341218612Sdchagin printf("Segment created in clone with " 342218612Sdchagin "CLONE_SETTLS: lobase: %x, hibase: %x, " 343218612Sdchagin "lolimit: %x, hilimit: %x, type: %i, " 344218612Sdchagin "dpl: %i, p: %i, xx: %i, def32: %i, " 345218612Sdchagin "gran: %i\n", sd.sd_lobase, sd.sd_hibase, 346218612Sdchagin sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, 347218612Sdchagin sd.sd_dpl, sd.sd_p, sd.sd_xx, 348218612Sdchagin sd.sd_def32, sd.sd_gran); 349218612Sdchagin#endif 350218612Sdchagin 351218612Sdchagin /* set %gs */ 352218612Sdchagin td->td_pcb->pcb_gsd = sd; 353218612Sdchagin td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); 354218612Sdchagin } 355218612Sdchagin 356218612Sdchagin return (error); 357218612Sdchagin} 358218612Sdchagin 35964921Smarcelint 360218613Sdchaginlinux_set_upcall_kse(struct thread *td, register_t stack) 361218613Sdchagin{ 362218613Sdchagin 363218613Sdchagin td->td_frame->tf_esp = stack; 364218613Sdchagin 365218613Sdchagin return (0); 366218613Sdchagin} 367218613Sdchagin 36864921Smarcel#define STACK_SIZE (2 * 1024 * 1024) 36964921Smarcel#define GUARD_SIZE (4 * PAGE_SIZE) 37064921Smarcel 37164921Smarcelint 372104893Ssobomaxlinux_mmap2(struct thread *td, struct linux_mmap2_args *args) 373104893Ssobomax{ 374104893Ssobomax 375104893Ssobomax#ifdef DEBUG 376104893Ssobomax if (ldebug(mmap2)) 377111798Sdes printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"), 378111798Sdes (void *)args->addr, args->len, args->prot, 379111798Sdes args->flags, args->fd, args->pgoff); 380104893Ssobomax#endif 381104893Ssobomax 382198554Sjhb return (linux_mmap_common(td, args->addr, args->len, args->prot, 383198554Sjhb args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * 384198554Sjhb PAGE_SIZE)); 385104893Ssobomax} 386104893Ssobomax 387104893Ssobomaxint 38883366Sjulianlinux_mmap(struct thread *td, struct linux_mmap_args *args) 38964921Smarcel{ 39064921Smarcel int error; 39183221Smarcel struct l_mmap_argv linux_args; 39264921Smarcel 393111797Sdes error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 39464921Smarcel if (error) 39564921Smarcel return (error); 39664921Smarcel 39764921Smarcel#ifdef DEBUG 39872543Sjlemon if (ldebug(mmap)) 39972543Sjlemon printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"), 400104984Sbde (void *)linux_args.addr, linux_args.len, linux_args.prot, 401166727Sjkim linux_args.flags, linux_args.fd, linux_args.pgoff); 40264921Smarcel#endif 40364921Smarcel 404198554Sjhb return (linux_mmap_common(td, linux_args.addr, linux_args.len, 405198554Sjhb linux_args.prot, linux_args.flags, linux_args.fd, 406198554Sjhb (uint32_t)linux_args.pgoff)); 407104893Ssobomax} 408104893Ssobomax 409104893Ssobomaxstatic int 410198554Sjhblinux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, 411198554Sjhb l_int flags, l_int fd, l_loff_t pos) 412104893Ssobomax{ 413104893Ssobomax struct proc *p = td->td_proc; 414104893Ssobomax struct mmap_args /* { 415104893Ssobomax caddr_t addr; 416104893Ssobomax size_t len; 417104893Ssobomax int prot; 418104893Ssobomax int flags; 419104893Ssobomax int fd; 420104893Ssobomax long pad; 421104893Ssobomax off_t pos; 422104893Ssobomax } */ bsd_args; 423112630Smdodd int error; 424162472Snetchild struct file *fp; 425104893Ssobomax 426112630Smdodd error = 0; 42764921Smarcel bsd_args.flags = 0; 428162472Snetchild fp = NULL; 429162472Snetchild 430162472Snetchild /* 431162472Snetchild * Linux mmap(2): 432162472Snetchild * You must specify exactly one of MAP_SHARED and MAP_PRIVATE 433162472Snetchild */ 434198554Sjhb if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE))) 435162479Snetchild return (EINVAL); 436162472Snetchild 437198554Sjhb if (flags & LINUX_MAP_SHARED) 43864921Smarcel bsd_args.flags |= MAP_SHARED; 439198554Sjhb if (flags & LINUX_MAP_PRIVATE) 44064921Smarcel bsd_args.flags |= MAP_PRIVATE; 441198554Sjhb if (flags & LINUX_MAP_FIXED) 44264921Smarcel bsd_args.flags |= MAP_FIXED; 443208994Skan if (flags & LINUX_MAP_ANON) { 444208994Skan /* Enforce pos to be on page boundary, then ignore. */ 445208994Skan if ((pos & PAGE_MASK) != 0) 446208994Skan return (EINVAL); 447208994Skan pos = 0; 44864921Smarcel bsd_args.flags |= MAP_ANON; 449208994Skan } else 45073213Sdillon bsd_args.flags |= MAP_NOSYNC; 451198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) 45264921Smarcel bsd_args.flags |= MAP_STACK; 45364921Smarcel 454166727Sjkim /* 455166727Sjkim * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC 456166727Sjkim * on Linux/i386. We do this to ensure maximum compatibility. 457166727Sjkim * Linux/ia64 does the same in i386 emulation mode. 458166727Sjkim */ 459198554Sjhb bsd_args.prot = prot; 460166727Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 461166727Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 462166727Sjkim 463167048Sjkim /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */ 464198554Sjhb bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd; 465167048Sjkim if (bsd_args.fd != -1) { 466166727Sjkim /* 467166727Sjkim * Linux follows Solaris mmap(2) description: 468166727Sjkim * The file descriptor fildes is opened with 469166727Sjkim * read permission, regardless of the 470166727Sjkim * protection options specified. 471224778Srwatson * 472224778Srwatson * Checking just CAP_MMAP is fine here, since the real work 473224778Srwatson * is done in the FreeBSD mmap(). 474166727Sjkim */ 475166727Sjkim 476224778Srwatson if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) 477166727Sjkim return (error); 478166727Sjkim if (fp->f_type != DTYPE_VNODE) { 479166727Sjkim fdrop(fp, td); 480166727Sjkim return (EINVAL); 481166727Sjkim } 482166727Sjkim 483166727Sjkim /* Linux mmap() just fails for O_WRONLY files */ 484166727Sjkim if (!(fp->f_flag & FREAD)) { 485166727Sjkim fdrop(fp, td); 486166727Sjkim return (EACCES); 487166727Sjkim } 488166727Sjkim 489166727Sjkim fdrop(fp, td); 490166727Sjkim } 491166727Sjkim 492198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) { 493161365Snetchild /* 494198554Sjhb * The Linux MAP_GROWSDOWN option does not limit auto 49564921Smarcel * growth of the region. Linux mmap with this option 49664921Smarcel * takes as addr the inital BOS, and as len, the initial 49764921Smarcel * region size. It can then grow down from addr without 49864921Smarcel * limit. However, linux threads has an implicit internal 49964921Smarcel * limit to stack size of STACK_SIZE. Its just not 50064921Smarcel * enforced explicitly in linux. But, here we impose 50164921Smarcel * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 50264921Smarcel * region, since we can do this with our mmap. 50364921Smarcel * 50464921Smarcel * Our mmap with MAP_STACK takes addr as the maximum 50564921Smarcel * downsize limit on BOS, and as len the max size of 50664921Smarcel * the region. It them maps the top SGROWSIZ bytes, 507166944Snetchild * and auto grows the region down, up to the limit 50864921Smarcel * in addr. 50964921Smarcel * 51064921Smarcel * If we don't use the MAP_STACK option, the effect 51164921Smarcel * of this code is to allocate a stack region of a 51264921Smarcel * fixed size of (STACK_SIZE - GUARD_SIZE). 51364921Smarcel */ 51464921Smarcel 515198554Sjhb if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) { 516161365Snetchild /* 517161365Snetchild * Some linux apps will attempt to mmap 51867238Sgallatin * thread stacks near the top of their 51967238Sgallatin * address space. If their TOS is greater 52067238Sgallatin * than vm_maxsaddr, vm_map_growstack() 52167238Sgallatin * will confuse the thread stack with the 52267238Sgallatin * process stack and deliver a SEGV if they 52367238Sgallatin * attempt to grow the thread stack past their 52467238Sgallatin * current stacksize rlimit. To avoid this, 52567238Sgallatin * adjust vm_maxsaddr upwards to reflect 52667238Sgallatin * the current stacksize rlimit rather 52767238Sgallatin * than the maximum possible stacksize. 52867238Sgallatin * It would be better to adjust the 52967238Sgallatin * mmap'ed region, but some apps do not check 53067238Sgallatin * mmap's return value. 53167238Sgallatin */ 532125454Sjhb PROC_LOCK(p); 53367238Sgallatin p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - 534125454Sjhb lim_cur(p, RLIMIT_STACK); 535125454Sjhb PROC_UNLOCK(p); 53667238Sgallatin } 53767238Sgallatin 538176193Sjkim /* 539176193Sjkim * This gives us our maximum stack size and a new BOS. 540176193Sjkim * If we're using VM_STACK, then mmap will just map 541176193Sjkim * the top SGROWSIZ bytes, and let the stack grow down 542176193Sjkim * to the limit at BOS. If we're not using VM_STACK 543176193Sjkim * we map the full stack, since we don't have a way 544176193Sjkim * to autogrow it. 545176193Sjkim */ 546198554Sjhb if (len > STACK_SIZE - GUARD_SIZE) { 547198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 548198554Sjhb bsd_args.len = len; 549176193Sjkim } else { 550198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr) - 551198554Sjhb (STACK_SIZE - GUARD_SIZE - len); 552176193Sjkim bsd_args.len = STACK_SIZE - GUARD_SIZE; 553176193Sjkim } 55464921Smarcel } else { 555198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 556198554Sjhb bsd_args.len = len; 55764921Smarcel } 558198554Sjhb bsd_args.pos = pos; 55964921Smarcel 56064921Smarcel#ifdef DEBUG 56172543Sjlemon if (ldebug(mmap)) 562112630Smdodd printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", 563112630Smdodd __func__, 56472543Sjlemon (void *)bsd_args.addr, bsd_args.len, bsd_args.prot, 56572543Sjlemon bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 56664921Smarcel#endif 567225617Skmacy error = sys_mmap(td, &bsd_args); 568112630Smdodd#ifdef DEBUG 569112630Smdodd if (ldebug(mmap)) 570112630Smdodd printf("-> %s() return: 0x%x (0x%08x)\n", 571112630Smdodd __func__, error, (u_int)td->td_retval[0]); 572112630Smdodd#endif 573112630Smdodd return (error); 57464921Smarcel} 57564921Smarcel 57664921Smarcelint 577166727Sjkimlinux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 578166727Sjkim{ 579166727Sjkim struct mprotect_args bsd_args; 580166727Sjkim 581166727Sjkim bsd_args.addr = uap->addr; 582166727Sjkim bsd_args.len = uap->len; 583166727Sjkim bsd_args.prot = uap->prot; 584166727Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 585166727Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 586225617Skmacy return (sys_mprotect(td, &bsd_args)); 587166727Sjkim} 588166727Sjkim 589166727Sjkimint 59083366Sjulianlinux_ioperm(struct thread *td, struct linux_ioperm_args *args) 59164921Smarcel{ 592140862Ssobomax int error; 593140862Ssobomax struct i386_ioperm_args iia; 59464921Smarcel 595140862Ssobomax iia.start = args->start; 596140862Ssobomax iia.length = args->length; 597140862Ssobomax iia.enable = args->enable; 598140862Ssobomax error = i386_set_ioperm(td, &iia); 599140862Ssobomax return (error); 60064921Smarcel} 60164921Smarcel 60264921Smarcelint 60383366Sjulianlinux_iopl(struct thread *td, struct linux_iopl_args *args) 60464921Smarcel{ 60564921Smarcel int error; 60664921Smarcel 60764921Smarcel if (args->level < 0 || args->level > 3) 60864921Smarcel return (EINVAL); 609164033Srwatson if ((error = priv_check(td, PRIV_IO)) != 0) 61064921Smarcel return (error); 61191406Sjhb if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 61283981Srwatson return (error); 61383366Sjulian td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) | 61464921Smarcel (args->level * (PSL_IOPL / 3)); 61564921Smarcel return (0); 61664921Smarcel} 61764921Smarcel 61864921Smarcelint 619105441Smarkmlinux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap) 62064921Smarcel{ 62164921Smarcel int error; 622140862Ssobomax struct i386_ldt_args ldt; 62383221Smarcel struct l_descriptor ld; 624140862Ssobomax union descriptor desc; 625173937Skib int size, written; 62664921Smarcel 62764921Smarcel switch (uap->func) { 62864921Smarcel case 0x00: /* read_ldt */ 629140862Ssobomax ldt.start = 0; 630140862Ssobomax ldt.descs = uap->ptr; 631140862Ssobomax ldt.num = uap->bytecount / sizeof(union descriptor); 632140862Ssobomax error = i386_get_ldt(td, &ldt); 63383366Sjulian td->td_retval[0] *= sizeof(union descriptor); 63464921Smarcel break; 635173937Skib case 0x02: /* read_default_ldt = 0 */ 636173937Skib size = 5*sizeof(struct l_desc_struct); 637173937Skib if (size > uap->bytecount) 638173937Skib size = uap->bytecount; 639173937Skib for (written = error = 0; written < size && error == 0; written++) 640173937Skib error = subyte((char *)uap->ptr + written, 0); 641173937Skib td->td_retval[0] = written; 642173937Skib break; 64364921Smarcel case 0x01: /* write_ldt */ 64464921Smarcel case 0x11: /* write_ldt */ 64564921Smarcel if (uap->bytecount != sizeof(ld)) 64664921Smarcel return (EINVAL); 64764921Smarcel 64864921Smarcel error = copyin(uap->ptr, &ld, sizeof(ld)); 64964921Smarcel if (error) 65064921Smarcel return (error); 65164921Smarcel 652140862Ssobomax ldt.start = ld.entry_number; 653140862Ssobomax ldt.descs = &desc; 654140862Ssobomax ldt.num = 1; 655140862Ssobomax desc.sd.sd_lolimit = (ld.limit & 0x0000ffff); 656140862Ssobomax desc.sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; 657140862Ssobomax desc.sd.sd_lobase = (ld.base_addr & 0x00ffffff); 658140862Ssobomax desc.sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; 659140862Ssobomax desc.sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | 66064921Smarcel (ld.contents << 2); 661140862Ssobomax desc.sd.sd_dpl = 3; 662140862Ssobomax desc.sd.sd_p = (ld.seg_not_present ^ 1); 663140862Ssobomax desc.sd.sd_xx = 0; 664140862Ssobomax desc.sd.sd_def32 = ld.seg_32bit; 665140862Ssobomax desc.sd.sd_gran = ld.limit_in_pages; 666140862Ssobomax error = i386_set_ldt(td, &ldt, &desc); 66764921Smarcel break; 66864921Smarcel default: 669195074Sjhb error = ENOSYS; 67064921Smarcel break; 67164921Smarcel } 67264921Smarcel 67364921Smarcel if (error == EOPNOTSUPP) { 67464921Smarcel printf("linux: modify_ldt needs kernel option USER_LDT\n"); 67564921Smarcel error = ENOSYS; 67664921Smarcel } 67764921Smarcel 67864921Smarcel return (error); 67964921Smarcel} 68064921Smarcel 68164921Smarcelint 68283366Sjulianlinux_sigaction(struct thread *td, struct linux_sigaction_args *args) 68364921Smarcel{ 68483221Smarcel l_osigaction_t osa; 68583221Smarcel l_sigaction_t act, oact; 68664921Smarcel int error; 68764921Smarcel 68864921Smarcel#ifdef DEBUG 68972543Sjlemon if (ldebug(sigaction)) 69072543Sjlemon printf(ARGS(sigaction, "%d, %p, %p"), 69172543Sjlemon args->sig, (void *)args->nsa, (void *)args->osa); 69264921Smarcel#endif 69364921Smarcel 69464921Smarcel if (args->nsa != NULL) { 695111797Sdes error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 69664921Smarcel if (error) 69764921Smarcel return (error); 69864921Smarcel act.lsa_handler = osa.lsa_handler; 69964921Smarcel act.lsa_flags = osa.lsa_flags; 70064921Smarcel act.lsa_restorer = osa.lsa_restorer; 70164921Smarcel LINUX_SIGEMPTYSET(act.lsa_mask); 70264921Smarcel act.lsa_mask.__bits[0] = osa.lsa_mask; 70364921Smarcel } 70464921Smarcel 70583366Sjulian error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 70664921Smarcel args->osa ? &oact : NULL); 70764921Smarcel 70864921Smarcel if (args->osa != NULL && !error) { 70964921Smarcel osa.lsa_handler = oact.lsa_handler; 71064921Smarcel osa.lsa_flags = oact.lsa_flags; 71164921Smarcel osa.lsa_restorer = oact.lsa_restorer; 71264921Smarcel osa.lsa_mask = oact.lsa_mask.__bits[0]; 713111797Sdes error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 71464921Smarcel } 71564921Smarcel 71664921Smarcel return (error); 71764921Smarcel} 71864921Smarcel 71964921Smarcel/* 72064921Smarcel * Linux has two extra args, restart and oldmask. We dont use these, 72164921Smarcel * but it seems that "restart" is actually a context pointer that 72264921Smarcel * enables the signal to happen with a different register set. 72364921Smarcel */ 72464921Smarcelint 72583366Sjulianlinux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 72664921Smarcel{ 727102814Siedowse sigset_t sigmask; 72883221Smarcel l_sigset_t mask; 72964921Smarcel 73064921Smarcel#ifdef DEBUG 73172543Sjlemon if (ldebug(sigsuspend)) 73272543Sjlemon printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 73364921Smarcel#endif 73464921Smarcel 73564921Smarcel LINUX_SIGEMPTYSET(mask); 73664921Smarcel mask.__bits[0] = args->mask; 737102814Siedowse linux_to_bsd_sigset(&mask, &sigmask); 738102814Siedowse return (kern_sigsuspend(td, sigmask)); 73964921Smarcel} 74064921Smarcel 74164921Smarcelint 742105441Smarkmlinux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 74364921Smarcel{ 74483221Smarcel l_sigset_t lmask; 745102814Siedowse sigset_t sigmask; 74664921Smarcel int error; 74764921Smarcel 74864921Smarcel#ifdef DEBUG 74972543Sjlemon if (ldebug(rt_sigsuspend)) 75072543Sjlemon printf(ARGS(rt_sigsuspend, "%p, %d"), 75172543Sjlemon (void *)uap->newset, uap->sigsetsize); 75264921Smarcel#endif 75364921Smarcel 75483221Smarcel if (uap->sigsetsize != sizeof(l_sigset_t)) 75564921Smarcel return (EINVAL); 75664921Smarcel 75783221Smarcel error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 75864921Smarcel if (error) 75964921Smarcel return (error); 76064921Smarcel 761102814Siedowse linux_to_bsd_sigset(&lmask, &sigmask); 762102814Siedowse return (kern_sigsuspend(td, sigmask)); 76364921Smarcel} 76464921Smarcel 76564921Smarcelint 76683366Sjulianlinux_pause(struct thread *td, struct linux_pause_args *args) 76764921Smarcel{ 76883366Sjulian struct proc *p = td->td_proc; 769102814Siedowse sigset_t sigmask; 77064921Smarcel 77164921Smarcel#ifdef DEBUG 77272543Sjlemon if (ldebug(pause)) 77372543Sjlemon printf(ARGS(pause, "")); 77464921Smarcel#endif 77564921Smarcel 77671494Sjhb PROC_LOCK(p); 777112888Sjeff sigmask = td->td_sigmask; 77871494Sjhb PROC_UNLOCK(p); 779102814Siedowse return (kern_sigsuspend(td, sigmask)); 78064921Smarcel} 78164921Smarcel 78264921Smarcelint 78383366Sjulianlinux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 78464921Smarcel{ 785102814Siedowse stack_t ss, oss; 78683221Smarcel l_stack_t lss; 78764921Smarcel int error; 78864921Smarcel 78964921Smarcel#ifdef DEBUG 79072543Sjlemon if (ldebug(sigaltstack)) 79172543Sjlemon printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 79264921Smarcel#endif 79364921Smarcel 794102814Siedowse if (uap->uss != NULL) { 79583221Smarcel error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 79667051Sgallatin if (error) 79767051Sgallatin return (error); 79864921Smarcel 799102814Siedowse ss.ss_sp = lss.ss_sp; 800102814Siedowse ss.ss_size = lss.ss_size; 801102814Siedowse ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 80267051Sgallatin } 803134269Sjhb error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 804134269Sjhb (uap->uoss != NULL) ? &oss : NULL); 805102814Siedowse if (!error && uap->uoss != NULL) { 806102814Siedowse lss.ss_sp = oss.ss_sp; 807102814Siedowse lss.ss_size = oss.ss_size; 808102814Siedowse lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 80983221Smarcel error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 81064921Smarcel } 81164921Smarcel 81264921Smarcel return (error); 81364921Smarcel} 814104893Ssobomax 815104893Ssobomaxint 816104893Ssobomaxlinux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 817104893Ssobomax{ 818104893Ssobomax struct ftruncate_args sa; 819104893Ssobomax 820104893Ssobomax#ifdef DEBUG 821104893Ssobomax if (ldebug(ftruncate64)) 822104984Sbde printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 823104984Sbde (intmax_t)args->length); 824104893Ssobomax#endif 825104893Ssobomax 826104893Ssobomax sa.fd = args->fd; 827104893Ssobomax sa.length = args->length; 828225617Skmacy return sys_ftruncate(td, &sa); 829104893Ssobomax} 830134838Sdfr 831134838Sdfrint 832134838Sdfrlinux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) 833134838Sdfr{ 834161310Snetchild struct l_user_desc info; 835161310Snetchild int error; 836161310Snetchild int idx; 837161310Snetchild int a[2]; 838161310Snetchild struct segment_descriptor sd; 839161310Snetchild 840161310Snetchild error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 841161310Snetchild if (error) 842161310Snetchild return (error); 843161310Snetchild 844161310Snetchild#ifdef DEBUG 845161310Snetchild if (ldebug(set_thread_area)) 846161310Snetchild printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), 847161310Snetchild info.entry_number, 848161310Snetchild info.base_addr, 849161310Snetchild info.limit, 850161310Snetchild info.seg_32bit, 851161310Snetchild info.contents, 852161310Snetchild info.read_exec_only, 853161310Snetchild info.limit_in_pages, 854161310Snetchild info.seg_not_present, 855161310Snetchild info.useable); 856161310Snetchild#endif 857161310Snetchild 858161310Snetchild idx = info.entry_number; 859161365Snetchild /* 860166944Snetchild * Semantics of linux version: every thread in the system has array of 861166944Snetchild * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This 862166944Snetchild * syscall loads one of the selected tls decriptors with a value and 863166944Snetchild * also loads GDT descriptors 6, 7 and 8 with the content of the 864166944Snetchild * per-thread descriptors. 865161310Snetchild * 866166944Snetchild * Semantics of fbsd version: I think we can ignore that linux has 3 867166944Snetchild * per-thread descriptors and use just the 1st one. The tls_array[] 868166944Snetchild * is used only in set/get-thread_area() syscalls and for loading the 869166944Snetchild * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so 870166944Snetchild * we will load just one. 871166944Snetchild * 872166944Snetchild * XXX: this doesn't work when a user space process tries to use more 873166944Snetchild * than 1 TLS segment. Comment in the linux sources says wine might do 874166944Snetchild * this. 875134838Sdfr */ 876161310Snetchild 877161365Snetchild /* 878161365Snetchild * we support just GLIBC TLS now 879161310Snetchild * we should let 3 proceed as well because we use this segment so 880161310Snetchild * if code does two subsequent calls it should succeed 881161310Snetchild */ 882161310Snetchild if (idx != 6 && idx != -1 && idx != 3) 883161310Snetchild return (EINVAL); 884161310Snetchild 885161365Snetchild /* 886161365Snetchild * we have to copy out the GDT entry we use 887166944Snetchild * FreeBSD uses GDT entry #3 for storing %gs so load that 888166944Snetchild * 889166944Snetchild * XXX: what if a user space program doesn't check this value and tries 890161310Snetchild * to use 6, 7 or 8? 891161310Snetchild */ 892161310Snetchild idx = info.entry_number = 3; 893161310Snetchild error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 894161310Snetchild if (error) 895161310Snetchild return (error); 896161310Snetchild 897167157Sjkim if (LINUX_LDT_empty(&info)) { 898161310Snetchild a[0] = 0; 899161310Snetchild a[1] = 0; 900161310Snetchild } else { 901167157Sjkim a[0] = LINUX_LDT_entry_a(&info); 902167157Sjkim a[1] = LINUX_LDT_entry_b(&info); 903161310Snetchild } 904161310Snetchild 905161310Snetchild memcpy(&sd, &a, sizeof(a)); 906161310Snetchild#ifdef DEBUG 907161310Snetchild if (ldebug(set_thread_area)) 908161310Snetchild printf("Segment created in set_thread_area: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, 909161310Snetchild sd.sd_hibase, 910161310Snetchild sd.sd_lolimit, 911161310Snetchild sd.sd_hilimit, 912161310Snetchild sd.sd_type, 913161310Snetchild sd.sd_dpl, 914161310Snetchild sd.sd_p, 915161310Snetchild sd.sd_xx, 916161310Snetchild sd.sd_def32, 917161310Snetchild sd.sd_gran); 918161310Snetchild#endif 919161310Snetchild 920161310Snetchild /* this is taken from i386 version of cpu_set_user_tls() */ 921161310Snetchild critical_enter(); 922161310Snetchild /* set %gs */ 923161310Snetchild td->td_pcb->pcb_gsd = sd; 924161310Snetchild PCPU_GET(fsgs_gdt)[1] = sd; 925161310Snetchild load_gs(GSEL(GUGS_SEL, SEL_UPL)); 926161310Snetchild critical_exit(); 927161310Snetchild 928161310Snetchild return (0); 929134838Sdfr} 930134838Sdfr 931134838Sdfrint 932161310Snetchildlinux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) 933134838Sdfr{ 934161310Snetchild 935161310Snetchild struct l_user_desc info; 936161310Snetchild int error; 937161310Snetchild int idx; 938161310Snetchild struct l_desc_struct desc; 939161310Snetchild struct segment_descriptor sd; 940134838Sdfr 941161310Snetchild#ifdef DEBUG 942161310Snetchild if (ldebug(get_thread_area)) 943161310Snetchild printf(ARGS(get_thread_area, "%p"), args->desc); 944161310Snetchild#endif 945161310Snetchild 946161310Snetchild error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 947161310Snetchild if (error) 948161310Snetchild return (error); 949161310Snetchild 950161310Snetchild idx = info.entry_number; 951161310Snetchild /* XXX: I am not sure if we want 3 to be allowed too. */ 952161310Snetchild if (idx != 6 && idx != 3) 953161310Snetchild return (EINVAL); 954161310Snetchild 955161310Snetchild idx = 3; 956161310Snetchild 957161310Snetchild memset(&info, 0, sizeof(info)); 958161310Snetchild 959161310Snetchild sd = PCPU_GET(fsgs_gdt)[1]; 960161310Snetchild 961161310Snetchild memcpy(&desc, &sd, sizeof(desc)); 962161310Snetchild 963161310Snetchild info.entry_number = idx; 964167157Sjkim info.base_addr = LINUX_GET_BASE(&desc); 965167157Sjkim info.limit = LINUX_GET_LIMIT(&desc); 966167157Sjkim info.seg_32bit = LINUX_GET_32BIT(&desc); 967167157Sjkim info.contents = LINUX_GET_CONTENTS(&desc); 968167157Sjkim info.read_exec_only = !LINUX_GET_WRITABLE(&desc); 969167157Sjkim info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); 970167157Sjkim info.seg_not_present = !LINUX_GET_PRESENT(&desc); 971167157Sjkim info.useable = LINUX_GET_USEABLE(&desc); 972161310Snetchild 973161310Snetchild error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 974161310Snetchild if (error) 975161310Snetchild return (EFAULT); 976161310Snetchild 977134838Sdfr return (0); 978134838Sdfr} 979134838Sdfr 980161310Snetchild/* copied from kern/kern_time.c */ 981134838Sdfrint 982161310Snetchildlinux_timer_create(struct thread *td, struct linux_timer_create_args *args) 983134838Sdfr{ 984225617Skmacy return sys_ktimer_create(td, (struct ktimer_create_args *) args); 985161310Snetchild} 986134838Sdfr 987161310Snetchildint 988161310Snetchildlinux_timer_settime(struct thread *td, struct linux_timer_settime_args *args) 989161310Snetchild{ 990225617Skmacy return sys_ktimer_settime(td, (struct ktimer_settime_args *) args); 991134838Sdfr} 992134838Sdfr 993161310Snetchildint 994161310Snetchildlinux_timer_gettime(struct thread *td, struct linux_timer_gettime_args *args) 995161310Snetchild{ 996225617Skmacy return sys_ktimer_gettime(td, (struct ktimer_gettime_args *) args); 997161310Snetchild} 998161310Snetchild 999161310Snetchildint 1000161310Snetchildlinux_timer_getoverrun(struct thread *td, struct linux_timer_getoverrun_args *args) 1001161310Snetchild{ 1002225617Skmacy return sys_ktimer_getoverrun(td, (struct ktimer_getoverrun_args *) args); 1003161310Snetchild} 1004161310Snetchild 1005161310Snetchildint 1006161310Snetchildlinux_timer_delete(struct thread *td, struct linux_timer_delete_args *args) 1007161310Snetchild{ 1008225617Skmacy return sys_ktimer_delete(td, (struct ktimer_delete_args *) args); 1009161310Snetchild} 1010161310Snetchild 1011161310Snetchild/* XXX: this wont work with module - convert it */ 1012161310Snetchildint 1013161310Snetchildlinux_mq_open(struct thread *td, struct linux_mq_open_args *args) 1014161310Snetchild{ 1015161310Snetchild#ifdef P1003_1B_MQUEUE 1016225617Skmacy return sys_kmq_open(td, (struct kmq_open_args *) args); 1017161310Snetchild#else 1018161310Snetchild return (ENOSYS); 1019161310Snetchild#endif 1020161310Snetchild} 1021161310Snetchild 1022161310Snetchildint 1023161310Snetchildlinux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) 1024161310Snetchild{ 1025161310Snetchild#ifdef P1003_1B_MQUEUE 1026225617Skmacy return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); 1027161310Snetchild#else 1028161310Snetchild return (ENOSYS); 1029161310Snetchild#endif 1030161310Snetchild} 1031161310Snetchild 1032161310Snetchildint 1033161310Snetchildlinux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) 1034161310Snetchild{ 1035161310Snetchild#ifdef P1003_1B_MQUEUE 1036225617Skmacy return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); 1037161310Snetchild#else 1038161310Snetchild return (ENOSYS); 1039161310Snetchild#endif 1040161310Snetchild} 1041161310Snetchild 1042161310Snetchildint 1043161310Snetchildlinux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) 1044161310Snetchild{ 1045161310Snetchild#ifdef P1003_1B_MQUEUE 1046225617Skmacy return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); 1047161310Snetchild#else 1048161310Snetchild return (ENOSYS); 1049161310Snetchild#endif 1050161310Snetchild} 1051161310Snetchild 1052161310Snetchildint 1053161310Snetchildlinux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) 1054161310Snetchild{ 1055161310Snetchild#ifdef P1003_1B_MQUEUE 1056225617Skmacy return sys_kmq_notify(td, (struct kmq_notify_args *) args); 1057161310Snetchild#else 1058161310Snetchild return (ENOSYS); 1059161310Snetchild#endif 1060161310Snetchild} 1061161310Snetchild 1062161310Snetchildint 1063161310Snetchildlinux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) 1064161310Snetchild{ 1065161310Snetchild#ifdef P1003_1B_MQUEUE 1066225617Skmacy return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); 1067161310Snetchild#else 1068161310Snetchild return (ENOSYS); 1069161310Snetchild#endif 1070161310Snetchild} 1071161310Snetchild 1072218030Sdchaginint 1073218030Sdchaginlinux_wait4(struct thread *td, struct linux_wait4_args *args) 1074218030Sdchagin{ 1075218030Sdchagin int error, options; 1076218030Sdchagin struct rusage ru, *rup; 1077218030Sdchagin 1078218030Sdchagin#ifdef DEBUG 1079218030Sdchagin if (ldebug(wait4)) 1080218030Sdchagin printf(ARGS(wait4, "%d, %p, %d, %p"), 1081218030Sdchagin args->pid, (void *)args->status, args->options, 1082218030Sdchagin (void *)args->rusage); 1083218030Sdchagin#endif 1084218030Sdchagin 1085218030Sdchagin options = (args->options & (WNOHANG | WUNTRACED)); 1086218030Sdchagin /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 1087218030Sdchagin if (args->options & __WCLONE) 1088218030Sdchagin options |= WLINUXCLONE; 1089218030Sdchagin 1090218030Sdchagin if (args->rusage != NULL) 1091218030Sdchagin rup = &ru; 1092218030Sdchagin else 1093218030Sdchagin rup = NULL; 1094218030Sdchagin error = linux_common_wait(td, args->pid, args->status, options, rup); 1095218030Sdchagin if (error) 1096218030Sdchagin return (error); 1097218030Sdchagin if (args->rusage != NULL) 1098218030Sdchagin error = copyout(&ru, args->rusage, sizeof(ru)); 1099218030Sdchagin 1100218030Sdchagin return (error); 1101218030Sdchagin} 1102