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; 425255219Spjd cap_rights_t rights; 426104893Ssobomax 427112630Smdodd error = 0; 42864921Smarcel bsd_args.flags = 0; 429162472Snetchild fp = NULL; 430162472Snetchild 431162472Snetchild /* 432162472Snetchild * Linux mmap(2): 433162472Snetchild * You must specify exactly one of MAP_SHARED and MAP_PRIVATE 434162472Snetchild */ 435198554Sjhb if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE))) 436162479Snetchild return (EINVAL); 437162472Snetchild 438198554Sjhb if (flags & LINUX_MAP_SHARED) 43964921Smarcel bsd_args.flags |= MAP_SHARED; 440198554Sjhb if (flags & LINUX_MAP_PRIVATE) 44164921Smarcel bsd_args.flags |= MAP_PRIVATE; 442198554Sjhb if (flags & LINUX_MAP_FIXED) 44364921Smarcel bsd_args.flags |= MAP_FIXED; 444208994Skan if (flags & LINUX_MAP_ANON) { 445208994Skan /* Enforce pos to be on page boundary, then ignore. */ 446208994Skan if ((pos & PAGE_MASK) != 0) 447208994Skan return (EINVAL); 448208994Skan pos = 0; 44964921Smarcel bsd_args.flags |= MAP_ANON; 450208994Skan } else 45173213Sdillon bsd_args.flags |= MAP_NOSYNC; 452198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) 45364921Smarcel bsd_args.flags |= MAP_STACK; 45464921Smarcel 455166727Sjkim /* 456166727Sjkim * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC 457166727Sjkim * on Linux/i386. We do this to ensure maximum compatibility. 458166727Sjkim * Linux/ia64 does the same in i386 emulation mode. 459166727Sjkim */ 460198554Sjhb bsd_args.prot = prot; 461166727Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 462166727Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 463166727Sjkim 464167048Sjkim /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */ 465198554Sjhb bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd; 466167048Sjkim if (bsd_args.fd != -1) { 467166727Sjkim /* 468166727Sjkim * Linux follows Solaris mmap(2) description: 469166727Sjkim * The file descriptor fildes is opened with 470166727Sjkim * read permission, regardless of the 471166727Sjkim * protection options specified. 472224778Srwatson * 473224778Srwatson * Checking just CAP_MMAP is fine here, since the real work 474224778Srwatson * is done in the FreeBSD mmap(). 475166727Sjkim */ 476166727Sjkim 477255219Spjd error = fget(td, bsd_args.fd, 478255219Spjd cap_rights_init(&rights, CAP_MMAP), &fp); 479255219Spjd if (error != 0) 480166727Sjkim return (error); 481166727Sjkim if (fp->f_type != DTYPE_VNODE) { 482166727Sjkim fdrop(fp, td); 483166727Sjkim return (EINVAL); 484166727Sjkim } 485166727Sjkim 486166727Sjkim /* Linux mmap() just fails for O_WRONLY files */ 487166727Sjkim if (!(fp->f_flag & FREAD)) { 488166727Sjkim fdrop(fp, td); 489166727Sjkim return (EACCES); 490166727Sjkim } 491166727Sjkim 492166727Sjkim fdrop(fp, td); 493166727Sjkim } 494166727Sjkim 495198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) { 496161365Snetchild /* 497198554Sjhb * The Linux MAP_GROWSDOWN option does not limit auto 49864921Smarcel * growth of the region. Linux mmap with this option 49964921Smarcel * takes as addr the inital BOS, and as len, the initial 50064921Smarcel * region size. It can then grow down from addr without 50164921Smarcel * limit. However, linux threads has an implicit internal 50264921Smarcel * limit to stack size of STACK_SIZE. Its just not 50364921Smarcel * enforced explicitly in linux. But, here we impose 50464921Smarcel * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 50564921Smarcel * region, since we can do this with our mmap. 50664921Smarcel * 50764921Smarcel * Our mmap with MAP_STACK takes addr as the maximum 50864921Smarcel * downsize limit on BOS, and as len the max size of 50964921Smarcel * the region. It them maps the top SGROWSIZ bytes, 510166944Snetchild * and auto grows the region down, up to the limit 51164921Smarcel * in addr. 51264921Smarcel * 51364921Smarcel * If we don't use the MAP_STACK option, the effect 51464921Smarcel * of this code is to allocate a stack region of a 51564921Smarcel * fixed size of (STACK_SIZE - GUARD_SIZE). 51664921Smarcel */ 51764921Smarcel 518198554Sjhb if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) { 519161365Snetchild /* 520161365Snetchild * Some linux apps will attempt to mmap 52167238Sgallatin * thread stacks near the top of their 52267238Sgallatin * address space. If their TOS is greater 52367238Sgallatin * than vm_maxsaddr, vm_map_growstack() 52467238Sgallatin * will confuse the thread stack with the 52567238Sgallatin * process stack and deliver a SEGV if they 52667238Sgallatin * attempt to grow the thread stack past their 52767238Sgallatin * current stacksize rlimit. To avoid this, 52867238Sgallatin * adjust vm_maxsaddr upwards to reflect 52967238Sgallatin * the current stacksize rlimit rather 53067238Sgallatin * than the maximum possible stacksize. 53167238Sgallatin * It would be better to adjust the 53267238Sgallatin * mmap'ed region, but some apps do not check 53367238Sgallatin * mmap's return value. 53467238Sgallatin */ 535125454Sjhb PROC_LOCK(p); 53667238Sgallatin p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - 537125454Sjhb lim_cur(p, RLIMIT_STACK); 538125454Sjhb PROC_UNLOCK(p); 53967238Sgallatin } 54067238Sgallatin 541176193Sjkim /* 542176193Sjkim * This gives us our maximum stack size and a new BOS. 543176193Sjkim * If we're using VM_STACK, then mmap will just map 544176193Sjkim * the top SGROWSIZ bytes, and let the stack grow down 545176193Sjkim * to the limit at BOS. If we're not using VM_STACK 546176193Sjkim * we map the full stack, since we don't have a way 547176193Sjkim * to autogrow it. 548176193Sjkim */ 549198554Sjhb if (len > STACK_SIZE - GUARD_SIZE) { 550198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 551198554Sjhb bsd_args.len = len; 552176193Sjkim } else { 553198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr) - 554198554Sjhb (STACK_SIZE - GUARD_SIZE - len); 555176193Sjkim bsd_args.len = STACK_SIZE - GUARD_SIZE; 556176193Sjkim } 55764921Smarcel } else { 558198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 559198554Sjhb bsd_args.len = len; 56064921Smarcel } 561198554Sjhb bsd_args.pos = pos; 56264921Smarcel 56364921Smarcel#ifdef DEBUG 56472543Sjlemon if (ldebug(mmap)) 565112630Smdodd printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", 566112630Smdodd __func__, 56772543Sjlemon (void *)bsd_args.addr, bsd_args.len, bsd_args.prot, 56872543Sjlemon bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 56964921Smarcel#endif 570225617Skmacy error = sys_mmap(td, &bsd_args); 571112630Smdodd#ifdef DEBUG 572112630Smdodd if (ldebug(mmap)) 573112630Smdodd printf("-> %s() return: 0x%x (0x%08x)\n", 574112630Smdodd __func__, error, (u_int)td->td_retval[0]); 575112630Smdodd#endif 576112630Smdodd return (error); 57764921Smarcel} 57864921Smarcel 57964921Smarcelint 580166727Sjkimlinux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 581166727Sjkim{ 582166727Sjkim struct mprotect_args bsd_args; 583166727Sjkim 584166727Sjkim bsd_args.addr = uap->addr; 585166727Sjkim bsd_args.len = uap->len; 586166727Sjkim bsd_args.prot = uap->prot; 587166727Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 588166727Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 589225617Skmacy return (sys_mprotect(td, &bsd_args)); 590166727Sjkim} 591166727Sjkim 592166727Sjkimint 59383366Sjulianlinux_ioperm(struct thread *td, struct linux_ioperm_args *args) 59464921Smarcel{ 595140862Ssobomax int error; 596140862Ssobomax struct i386_ioperm_args iia; 59764921Smarcel 598140862Ssobomax iia.start = args->start; 599140862Ssobomax iia.length = args->length; 600140862Ssobomax iia.enable = args->enable; 601140862Ssobomax error = i386_set_ioperm(td, &iia); 602140862Ssobomax return (error); 60364921Smarcel} 60464921Smarcel 60564921Smarcelint 60683366Sjulianlinux_iopl(struct thread *td, struct linux_iopl_args *args) 60764921Smarcel{ 60864921Smarcel int error; 60964921Smarcel 61064921Smarcel if (args->level < 0 || args->level > 3) 61164921Smarcel return (EINVAL); 612164033Srwatson if ((error = priv_check(td, PRIV_IO)) != 0) 61364921Smarcel return (error); 61491406Sjhb if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 61583981Srwatson return (error); 61683366Sjulian td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) | 61764921Smarcel (args->level * (PSL_IOPL / 3)); 61864921Smarcel return (0); 61964921Smarcel} 62064921Smarcel 62164921Smarcelint 622105441Smarkmlinux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap) 62364921Smarcel{ 62464921Smarcel int error; 625140862Ssobomax struct i386_ldt_args ldt; 62683221Smarcel struct l_descriptor ld; 627140862Ssobomax union descriptor desc; 628173937Skib int size, written; 62964921Smarcel 63064921Smarcel switch (uap->func) { 63164921Smarcel case 0x00: /* read_ldt */ 632140862Ssobomax ldt.start = 0; 633140862Ssobomax ldt.descs = uap->ptr; 634140862Ssobomax ldt.num = uap->bytecount / sizeof(union descriptor); 635140862Ssobomax error = i386_get_ldt(td, &ldt); 63683366Sjulian td->td_retval[0] *= sizeof(union descriptor); 63764921Smarcel break; 638173937Skib case 0x02: /* read_default_ldt = 0 */ 639173937Skib size = 5*sizeof(struct l_desc_struct); 640173937Skib if (size > uap->bytecount) 641173937Skib size = uap->bytecount; 642173937Skib for (written = error = 0; written < size && error == 0; written++) 643173937Skib error = subyte((char *)uap->ptr + written, 0); 644173937Skib td->td_retval[0] = written; 645173937Skib break; 64664921Smarcel case 0x01: /* write_ldt */ 64764921Smarcel case 0x11: /* write_ldt */ 64864921Smarcel if (uap->bytecount != sizeof(ld)) 64964921Smarcel return (EINVAL); 65064921Smarcel 65164921Smarcel error = copyin(uap->ptr, &ld, sizeof(ld)); 65264921Smarcel if (error) 65364921Smarcel return (error); 65464921Smarcel 655140862Ssobomax ldt.start = ld.entry_number; 656140862Ssobomax ldt.descs = &desc; 657140862Ssobomax ldt.num = 1; 658140862Ssobomax desc.sd.sd_lolimit = (ld.limit & 0x0000ffff); 659140862Ssobomax desc.sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; 660140862Ssobomax desc.sd.sd_lobase = (ld.base_addr & 0x00ffffff); 661140862Ssobomax desc.sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; 662140862Ssobomax desc.sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | 66364921Smarcel (ld.contents << 2); 664140862Ssobomax desc.sd.sd_dpl = 3; 665140862Ssobomax desc.sd.sd_p = (ld.seg_not_present ^ 1); 666140862Ssobomax desc.sd.sd_xx = 0; 667140862Ssobomax desc.sd.sd_def32 = ld.seg_32bit; 668140862Ssobomax desc.sd.sd_gran = ld.limit_in_pages; 669140862Ssobomax error = i386_set_ldt(td, &ldt, &desc); 67064921Smarcel break; 67164921Smarcel default: 672195074Sjhb error = ENOSYS; 67364921Smarcel break; 67464921Smarcel } 67564921Smarcel 67664921Smarcel if (error == EOPNOTSUPP) { 67764921Smarcel printf("linux: modify_ldt needs kernel option USER_LDT\n"); 67864921Smarcel error = ENOSYS; 67964921Smarcel } 68064921Smarcel 68164921Smarcel return (error); 68264921Smarcel} 68364921Smarcel 68464921Smarcelint 68583366Sjulianlinux_sigaction(struct thread *td, struct linux_sigaction_args *args) 68664921Smarcel{ 68783221Smarcel l_osigaction_t osa; 68883221Smarcel l_sigaction_t act, oact; 68964921Smarcel int error; 69064921Smarcel 69164921Smarcel#ifdef DEBUG 69272543Sjlemon if (ldebug(sigaction)) 69372543Sjlemon printf(ARGS(sigaction, "%d, %p, %p"), 69472543Sjlemon args->sig, (void *)args->nsa, (void *)args->osa); 69564921Smarcel#endif 69664921Smarcel 69764921Smarcel if (args->nsa != NULL) { 698111797Sdes error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 69964921Smarcel if (error) 70064921Smarcel return (error); 70164921Smarcel act.lsa_handler = osa.lsa_handler; 70264921Smarcel act.lsa_flags = osa.lsa_flags; 70364921Smarcel act.lsa_restorer = osa.lsa_restorer; 70464921Smarcel LINUX_SIGEMPTYSET(act.lsa_mask); 70564921Smarcel act.lsa_mask.__bits[0] = osa.lsa_mask; 70664921Smarcel } 70764921Smarcel 70883366Sjulian error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 70964921Smarcel args->osa ? &oact : NULL); 71064921Smarcel 71164921Smarcel if (args->osa != NULL && !error) { 71264921Smarcel osa.lsa_handler = oact.lsa_handler; 71364921Smarcel osa.lsa_flags = oact.lsa_flags; 71464921Smarcel osa.lsa_restorer = oact.lsa_restorer; 71564921Smarcel osa.lsa_mask = oact.lsa_mask.__bits[0]; 716111797Sdes error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 71764921Smarcel } 71864921Smarcel 71964921Smarcel return (error); 72064921Smarcel} 72164921Smarcel 72264921Smarcel/* 72364921Smarcel * Linux has two extra args, restart and oldmask. We dont use these, 72464921Smarcel * but it seems that "restart" is actually a context pointer that 72564921Smarcel * enables the signal to happen with a different register set. 72664921Smarcel */ 72764921Smarcelint 72883366Sjulianlinux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 72964921Smarcel{ 730102814Siedowse sigset_t sigmask; 73183221Smarcel l_sigset_t mask; 73264921Smarcel 73364921Smarcel#ifdef DEBUG 73472543Sjlemon if (ldebug(sigsuspend)) 73572543Sjlemon printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 73664921Smarcel#endif 73764921Smarcel 73864921Smarcel LINUX_SIGEMPTYSET(mask); 73964921Smarcel mask.__bits[0] = args->mask; 740102814Siedowse linux_to_bsd_sigset(&mask, &sigmask); 741102814Siedowse return (kern_sigsuspend(td, sigmask)); 74264921Smarcel} 74364921Smarcel 74464921Smarcelint 745105441Smarkmlinux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 74664921Smarcel{ 74783221Smarcel l_sigset_t lmask; 748102814Siedowse sigset_t sigmask; 74964921Smarcel int error; 75064921Smarcel 75164921Smarcel#ifdef DEBUG 75272543Sjlemon if (ldebug(rt_sigsuspend)) 75372543Sjlemon printf(ARGS(rt_sigsuspend, "%p, %d"), 75472543Sjlemon (void *)uap->newset, uap->sigsetsize); 75564921Smarcel#endif 75664921Smarcel 75783221Smarcel if (uap->sigsetsize != sizeof(l_sigset_t)) 75864921Smarcel return (EINVAL); 75964921Smarcel 76083221Smarcel error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 76164921Smarcel if (error) 76264921Smarcel return (error); 76364921Smarcel 764102814Siedowse linux_to_bsd_sigset(&lmask, &sigmask); 765102814Siedowse return (kern_sigsuspend(td, sigmask)); 76664921Smarcel} 76764921Smarcel 76864921Smarcelint 76983366Sjulianlinux_pause(struct thread *td, struct linux_pause_args *args) 77064921Smarcel{ 77183366Sjulian struct proc *p = td->td_proc; 772102814Siedowse sigset_t sigmask; 77364921Smarcel 77464921Smarcel#ifdef DEBUG 77572543Sjlemon if (ldebug(pause)) 77672543Sjlemon printf(ARGS(pause, "")); 77764921Smarcel#endif 77864921Smarcel 77971494Sjhb PROC_LOCK(p); 780112888Sjeff sigmask = td->td_sigmask; 78171494Sjhb PROC_UNLOCK(p); 782102814Siedowse return (kern_sigsuspend(td, sigmask)); 78364921Smarcel} 78464921Smarcel 78564921Smarcelint 78683366Sjulianlinux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 78764921Smarcel{ 788102814Siedowse stack_t ss, oss; 78983221Smarcel l_stack_t lss; 79064921Smarcel int error; 79164921Smarcel 79264921Smarcel#ifdef DEBUG 79372543Sjlemon if (ldebug(sigaltstack)) 79472543Sjlemon printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 79564921Smarcel#endif 79664921Smarcel 797102814Siedowse if (uap->uss != NULL) { 79883221Smarcel error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 79967051Sgallatin if (error) 80067051Sgallatin return (error); 80164921Smarcel 802102814Siedowse ss.ss_sp = lss.ss_sp; 803102814Siedowse ss.ss_size = lss.ss_size; 804102814Siedowse ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 80567051Sgallatin } 806134269Sjhb error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 807134269Sjhb (uap->uoss != NULL) ? &oss : NULL); 808102814Siedowse if (!error && uap->uoss != NULL) { 809102814Siedowse lss.ss_sp = oss.ss_sp; 810102814Siedowse lss.ss_size = oss.ss_size; 811102814Siedowse lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 81283221Smarcel error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 81364921Smarcel } 81464921Smarcel 81564921Smarcel return (error); 81664921Smarcel} 817104893Ssobomax 818104893Ssobomaxint 819104893Ssobomaxlinux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 820104893Ssobomax{ 821104893Ssobomax struct ftruncate_args sa; 822104893Ssobomax 823104893Ssobomax#ifdef DEBUG 824104893Ssobomax if (ldebug(ftruncate64)) 825104984Sbde printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 826104984Sbde (intmax_t)args->length); 827104893Ssobomax#endif 828104893Ssobomax 829104893Ssobomax sa.fd = args->fd; 830104893Ssobomax sa.length = args->length; 831225617Skmacy return sys_ftruncate(td, &sa); 832104893Ssobomax} 833134838Sdfr 834134838Sdfrint 835134838Sdfrlinux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) 836134838Sdfr{ 837161310Snetchild struct l_user_desc info; 838161310Snetchild int error; 839161310Snetchild int idx; 840161310Snetchild int a[2]; 841161310Snetchild struct segment_descriptor sd; 842161310Snetchild 843161310Snetchild error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 844161310Snetchild if (error) 845161310Snetchild return (error); 846161310Snetchild 847161310Snetchild#ifdef DEBUG 848161310Snetchild if (ldebug(set_thread_area)) 849161310Snetchild printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), 850161310Snetchild info.entry_number, 851161310Snetchild info.base_addr, 852161310Snetchild info.limit, 853161310Snetchild info.seg_32bit, 854161310Snetchild info.contents, 855161310Snetchild info.read_exec_only, 856161310Snetchild info.limit_in_pages, 857161310Snetchild info.seg_not_present, 858161310Snetchild info.useable); 859161310Snetchild#endif 860161310Snetchild 861161310Snetchild idx = info.entry_number; 862161365Snetchild /* 863166944Snetchild * Semantics of linux version: every thread in the system has array of 864166944Snetchild * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This 865166944Snetchild * syscall loads one of the selected tls decriptors with a value and 866166944Snetchild * also loads GDT descriptors 6, 7 and 8 with the content of the 867166944Snetchild * per-thread descriptors. 868161310Snetchild * 869166944Snetchild * Semantics of fbsd version: I think we can ignore that linux has 3 870166944Snetchild * per-thread descriptors and use just the 1st one. The tls_array[] 871166944Snetchild * is used only in set/get-thread_area() syscalls and for loading the 872166944Snetchild * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so 873166944Snetchild * we will load just one. 874166944Snetchild * 875166944Snetchild * XXX: this doesn't work when a user space process tries to use more 876166944Snetchild * than 1 TLS segment. Comment in the linux sources says wine might do 877166944Snetchild * this. 878134838Sdfr */ 879161310Snetchild 880161365Snetchild /* 881161365Snetchild * we support just GLIBC TLS now 882161310Snetchild * we should let 3 proceed as well because we use this segment so 883161310Snetchild * if code does two subsequent calls it should succeed 884161310Snetchild */ 885161310Snetchild if (idx != 6 && idx != -1 && idx != 3) 886161310Snetchild return (EINVAL); 887161310Snetchild 888161365Snetchild /* 889161365Snetchild * we have to copy out the GDT entry we use 890166944Snetchild * FreeBSD uses GDT entry #3 for storing %gs so load that 891166944Snetchild * 892166944Snetchild * XXX: what if a user space program doesn't check this value and tries 893161310Snetchild * to use 6, 7 or 8? 894161310Snetchild */ 895161310Snetchild idx = info.entry_number = 3; 896161310Snetchild error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 897161310Snetchild if (error) 898161310Snetchild return (error); 899161310Snetchild 900167157Sjkim if (LINUX_LDT_empty(&info)) { 901161310Snetchild a[0] = 0; 902161310Snetchild a[1] = 0; 903161310Snetchild } else { 904167157Sjkim a[0] = LINUX_LDT_entry_a(&info); 905167157Sjkim a[1] = LINUX_LDT_entry_b(&info); 906161310Snetchild } 907161310Snetchild 908161310Snetchild memcpy(&sd, &a, sizeof(a)); 909161310Snetchild#ifdef DEBUG 910161310Snetchild if (ldebug(set_thread_area)) 911161310Snetchild 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, 912161310Snetchild sd.sd_hibase, 913161310Snetchild sd.sd_lolimit, 914161310Snetchild sd.sd_hilimit, 915161310Snetchild sd.sd_type, 916161310Snetchild sd.sd_dpl, 917161310Snetchild sd.sd_p, 918161310Snetchild sd.sd_xx, 919161310Snetchild sd.sd_def32, 920161310Snetchild sd.sd_gran); 921161310Snetchild#endif 922161310Snetchild 923161310Snetchild /* this is taken from i386 version of cpu_set_user_tls() */ 924161310Snetchild critical_enter(); 925161310Snetchild /* set %gs */ 926161310Snetchild td->td_pcb->pcb_gsd = sd; 927161310Snetchild PCPU_GET(fsgs_gdt)[1] = sd; 928161310Snetchild load_gs(GSEL(GUGS_SEL, SEL_UPL)); 929161310Snetchild critical_exit(); 930161310Snetchild 931161310Snetchild return (0); 932134838Sdfr} 933134838Sdfr 934134838Sdfrint 935161310Snetchildlinux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) 936134838Sdfr{ 937161310Snetchild 938161310Snetchild struct l_user_desc info; 939161310Snetchild int error; 940161310Snetchild int idx; 941161310Snetchild struct l_desc_struct desc; 942161310Snetchild struct segment_descriptor sd; 943134838Sdfr 944161310Snetchild#ifdef DEBUG 945161310Snetchild if (ldebug(get_thread_area)) 946161310Snetchild printf(ARGS(get_thread_area, "%p"), args->desc); 947161310Snetchild#endif 948161310Snetchild 949161310Snetchild error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 950161310Snetchild if (error) 951161310Snetchild return (error); 952161310Snetchild 953161310Snetchild idx = info.entry_number; 954161310Snetchild /* XXX: I am not sure if we want 3 to be allowed too. */ 955161310Snetchild if (idx != 6 && idx != 3) 956161310Snetchild return (EINVAL); 957161310Snetchild 958161310Snetchild idx = 3; 959161310Snetchild 960161310Snetchild memset(&info, 0, sizeof(info)); 961161310Snetchild 962161310Snetchild sd = PCPU_GET(fsgs_gdt)[1]; 963161310Snetchild 964161310Snetchild memcpy(&desc, &sd, sizeof(desc)); 965161310Snetchild 966161310Snetchild info.entry_number = idx; 967167157Sjkim info.base_addr = LINUX_GET_BASE(&desc); 968167157Sjkim info.limit = LINUX_GET_LIMIT(&desc); 969167157Sjkim info.seg_32bit = LINUX_GET_32BIT(&desc); 970167157Sjkim info.contents = LINUX_GET_CONTENTS(&desc); 971167157Sjkim info.read_exec_only = !LINUX_GET_WRITABLE(&desc); 972167157Sjkim info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); 973167157Sjkim info.seg_not_present = !LINUX_GET_PRESENT(&desc); 974167157Sjkim info.useable = LINUX_GET_USEABLE(&desc); 975161310Snetchild 976161310Snetchild error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 977161310Snetchild if (error) 978161310Snetchild return (EFAULT); 979161310Snetchild 980134838Sdfr return (0); 981134838Sdfr} 982134838Sdfr 983161310Snetchild/* copied from kern/kern_time.c */ 984134838Sdfrint 985161310Snetchildlinux_timer_create(struct thread *td, struct linux_timer_create_args *args) 986134838Sdfr{ 987225617Skmacy return sys_ktimer_create(td, (struct ktimer_create_args *) args); 988161310Snetchild} 989134838Sdfr 990161310Snetchildint 991161310Snetchildlinux_timer_settime(struct thread *td, struct linux_timer_settime_args *args) 992161310Snetchild{ 993225617Skmacy return sys_ktimer_settime(td, (struct ktimer_settime_args *) args); 994134838Sdfr} 995134838Sdfr 996161310Snetchildint 997161310Snetchildlinux_timer_gettime(struct thread *td, struct linux_timer_gettime_args *args) 998161310Snetchild{ 999225617Skmacy return sys_ktimer_gettime(td, (struct ktimer_gettime_args *) args); 1000161310Snetchild} 1001161310Snetchild 1002161310Snetchildint 1003161310Snetchildlinux_timer_getoverrun(struct thread *td, struct linux_timer_getoverrun_args *args) 1004161310Snetchild{ 1005225617Skmacy return sys_ktimer_getoverrun(td, (struct ktimer_getoverrun_args *) args); 1006161310Snetchild} 1007161310Snetchild 1008161310Snetchildint 1009161310Snetchildlinux_timer_delete(struct thread *td, struct linux_timer_delete_args *args) 1010161310Snetchild{ 1011225617Skmacy return sys_ktimer_delete(td, (struct ktimer_delete_args *) args); 1012161310Snetchild} 1013161310Snetchild 1014161310Snetchild/* XXX: this wont work with module - convert it */ 1015161310Snetchildint 1016161310Snetchildlinux_mq_open(struct thread *td, struct linux_mq_open_args *args) 1017161310Snetchild{ 1018161310Snetchild#ifdef P1003_1B_MQUEUE 1019225617Skmacy return sys_kmq_open(td, (struct kmq_open_args *) args); 1020161310Snetchild#else 1021161310Snetchild return (ENOSYS); 1022161310Snetchild#endif 1023161310Snetchild} 1024161310Snetchild 1025161310Snetchildint 1026161310Snetchildlinux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) 1027161310Snetchild{ 1028161310Snetchild#ifdef P1003_1B_MQUEUE 1029225617Skmacy return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); 1030161310Snetchild#else 1031161310Snetchild return (ENOSYS); 1032161310Snetchild#endif 1033161310Snetchild} 1034161310Snetchild 1035161310Snetchildint 1036161310Snetchildlinux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) 1037161310Snetchild{ 1038161310Snetchild#ifdef P1003_1B_MQUEUE 1039225617Skmacy return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); 1040161310Snetchild#else 1041161310Snetchild return (ENOSYS); 1042161310Snetchild#endif 1043161310Snetchild} 1044161310Snetchild 1045161310Snetchildint 1046161310Snetchildlinux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) 1047161310Snetchild{ 1048161310Snetchild#ifdef P1003_1B_MQUEUE 1049225617Skmacy return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); 1050161310Snetchild#else 1051161310Snetchild return (ENOSYS); 1052161310Snetchild#endif 1053161310Snetchild} 1054161310Snetchild 1055161310Snetchildint 1056161310Snetchildlinux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) 1057161310Snetchild{ 1058161310Snetchild#ifdef P1003_1B_MQUEUE 1059225617Skmacy return sys_kmq_notify(td, (struct kmq_notify_args *) args); 1060161310Snetchild#else 1061161310Snetchild return (ENOSYS); 1062161310Snetchild#endif 1063161310Snetchild} 1064161310Snetchild 1065161310Snetchildint 1066161310Snetchildlinux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) 1067161310Snetchild{ 1068161310Snetchild#ifdef P1003_1B_MQUEUE 1069225617Skmacy return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); 1070161310Snetchild#else 1071161310Snetchild return (ENOSYS); 1072161310Snetchild#endif 1073161310Snetchild} 1074161310Snetchild 1075218030Sdchaginint 1076218030Sdchaginlinux_wait4(struct thread *td, struct linux_wait4_args *args) 1077218030Sdchagin{ 1078218030Sdchagin int error, options; 1079218030Sdchagin struct rusage ru, *rup; 1080218030Sdchagin 1081218030Sdchagin#ifdef DEBUG 1082218030Sdchagin if (ldebug(wait4)) 1083218030Sdchagin printf(ARGS(wait4, "%d, %p, %d, %p"), 1084218030Sdchagin args->pid, (void *)args->status, args->options, 1085218030Sdchagin (void *)args->rusage); 1086218030Sdchagin#endif 1087218030Sdchagin 1088218030Sdchagin options = (args->options & (WNOHANG | WUNTRACED)); 1089218030Sdchagin /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 1090218030Sdchagin if (args->options & __WCLONE) 1091218030Sdchagin options |= WLINUXCLONE; 1092218030Sdchagin 1093218030Sdchagin if (args->rusage != NULL) 1094218030Sdchagin rup = &ru; 1095218030Sdchagin else 1096218030Sdchagin rup = NULL; 1097218030Sdchagin error = linux_common_wait(td, args->pid, args->status, options, rup); 1098218030Sdchagin if (error) 1099218030Sdchagin return (error); 1100218030Sdchagin if (args->rusage != NULL) 1101218030Sdchagin error = copyout(&ru, args->rusage, sizeof(ru)); 1102218030Sdchagin 1103218030Sdchagin return (error); 1104218030Sdchagin} 1105