Index: user/dchagin/lemul/sys/amd64/linux32/linux32_dummy.c =================================================================== --- user/dchagin/lemul/sys/amd64/linux32/linux32_dummy.c (revision 247218) +++ user/dchagin/lemul/sys/amd64/linux32/linux32_dummy.c (revision 247219) @@ -1,176 +1,175 @@ /*- * Copyright (c) 1994-1995 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_kdtrace.h" #include #include #include #include #include #include #include #include #include /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); DUMMY(stime); DUMMY(olduname); DUMMY(syslog); DUMMY(uname); DUMMY(vhangup); DUMMY(swapoff); DUMMY(adjtimex); DUMMY(create_module); DUMMY(init_module); DUMMY(delete_module); DUMMY(get_kernel_syms); DUMMY(quotactl); DUMMY(bdflush); DUMMY(sysfs); DUMMY(query_module); DUMMY(nfsservctl); DUMMY(rt_sigqueueinfo); DUMMY(sendfile); DUMMY(setfsuid); DUMMY(setfsgid); DUMMY(pivot_root); DUMMY(mincore); DUMMY(ptrace); DUMMY(lookup_dcookie); DUMMY(epoll_create); DUMMY(epoll_ctl); DUMMY(epoll_wait); DUMMY(remap_file_pages); DUMMY(timer_create); DUMMY(timer_settime); DUMMY(timer_gettime); DUMMY(timer_getoverrun); DUMMY(timer_delete); DUMMY(fstatfs64); DUMMY(mbind); DUMMY(get_mempolicy); DUMMY(set_mempolicy); DUMMY(mq_open); DUMMY(mq_unlink); DUMMY(mq_timedsend); DUMMY(mq_timedreceive); DUMMY(mq_notify); DUMMY(mq_getsetattr); DUMMY(kexec_load); -DUMMY(waitid); /* linux 2.6.11: */ DUMMY(add_key); DUMMY(request_key); DUMMY(keyctl); /* linux 2.6.13: */ DUMMY(ioprio_set); DUMMY(ioprio_get); DUMMY(inotify_init); DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); /* linux 2.6.16: */ DUMMY(migrate_pages); DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); /* linux 2.6.17: */ DUMMY(splice); DUMMY(sync_file_range); DUMMY(tee); DUMMY(vmsplice); /* linux 2.6.18: */ DUMMY(move_pages); /* linux 2.6.19: */ DUMMY(getcpu); DUMMY(epoll_pwait); /* linux 2.6.22: */ DUMMY(utimensat); DUMMY(signalfd); DUMMY(timerfd_create); DUMMY(eventfd); /* linux 2.6.23: */ DUMMY(fallocate); /* linux 2.6.25: */ DUMMY(timerfd_settime); DUMMY(timerfd_gettime); /* linux 2.6.27: */ DUMMY(signalfd4); DUMMY(eventfd2); DUMMY(epoll_create1); DUMMY(dup3); DUMMY(inotify_init1); /* linux 2.6.30: */ DUMMY(preadv); DUMMY(pwritev); /* linux 2.6.31: */ DUMMY(rt_tsigqueueinfo); DUMMY(perf_event_open); /* linux 2.6.33: */ DUMMY(recvmmsg); DUMMY(fanotify_init); DUMMY(fanotify_mark); /* linux 2.6.36: */ DUMMY(prlimit64); /* later: */ DUMMY(name_to_handle_at); DUMMY(open_by_handle_at); DUMMY(clock_adjtime); DUMMY(syncfs); DUMMY(sendmmsg); DUMMY(setns); DUMMY(process_vm_readv); DUMMY(process_vm_writev); #define DUMMY_XATTR(s) \ int \ linux_ ## s ## xattr( \ struct thread *td, struct linux_ ## s ## xattr_args *arg) \ { \ \ return (ENOATTR); \ } DUMMY_XATTR(set); DUMMY_XATTR(lset); DUMMY_XATTR(fset); DUMMY_XATTR(get); DUMMY_XATTR(lget); DUMMY_XATTR(fget); DUMMY_XATTR(list); DUMMY_XATTR(llist); DUMMY_XATTR(flist); DUMMY_XATTR(remove); DUMMY_XATTR(lremove); DUMMY_XATTR(fremove); Index: user/dchagin/lemul/sys/amd64/linux32/linux32_machdep.c =================================================================== --- user/dchagin/lemul/sys/amd64/linux32/linux32_machdep.c (revision 247218) +++ user/dchagin/lemul/sys/amd64/linux32/linux32_machdep.c (revision 247219) @@ -1,1048 +1,1109 @@ /*- * Copyright (c) 2004 Tim J. Robbins * Copyright (c) 2002 Doug Rabson * Copyright (c) 2000 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct l_old_select_argv { l_int nfds; l_uintptr_t readfds; l_uintptr_t writefds; l_uintptr_t exceptfds; l_uintptr_t timeout; } __packed; int linux_to_bsd_sigaltstack(int lsa) { int bsa = 0; if (lsa & LINUX_SS_DISABLE) bsa |= SS_DISABLE; if (lsa & LINUX_SS_ONSTACK) bsa |= SS_ONSTACK; return (bsa); } static int linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, l_int flags, l_int fd, l_loff_t pos); int bsd_to_linux_sigaltstack(int bsa) { int lsa = 0; if (bsa & SS_DISABLE) lsa |= LINUX_SS_DISABLE; if (bsa & SS_ONSTACK) lsa |= LINUX_SS_ONSTACK; return (lsa); } static void bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru) { lru->ru_utime.tv_sec = ru->ru_utime.tv_sec; lru->ru_utime.tv_usec = ru->ru_utime.tv_usec; lru->ru_stime.tv_sec = ru->ru_stime.tv_sec; lru->ru_stime.tv_usec = ru->ru_stime.tv_usec; lru->ru_maxrss = ru->ru_maxrss; lru->ru_ixrss = ru->ru_ixrss; lru->ru_idrss = ru->ru_idrss; lru->ru_isrss = ru->ru_isrss; lru->ru_minflt = ru->ru_minflt; lru->ru_majflt = ru->ru_majflt; lru->ru_nswap = ru->ru_nswap; lru->ru_inblock = ru->ru_inblock; lru->ru_oublock = ru->ru_oublock; lru->ru_msgsnd = ru->ru_msgsnd; lru->ru_msgrcv = ru->ru_msgrcv; lru->ru_nsignals = ru->ru_nsignals; lru->ru_nvcsw = ru->ru_nvcsw; lru->ru_nivcsw = ru->ru_nivcsw; } int linux_execve(struct thread *td, struct linux_execve_args *args) { struct image_args eargs; char *path; int error; LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(execve)) printf(ARGS(execve, "%s"), path); #endif error = freebsd32_exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp, args->envp); free(path, M_TEMP); if (error == 0) error = kern_execve(td, &eargs, NULL); return (error); } CTASSERT(sizeof(struct l_iovec32) == 8); static int linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop) { struct l_iovec32 iov32; struct iovec *iov; struct uio *uio; uint32_t iovlen; int error, i; *uiop = NULL; if (iovcnt > UIO_MAXIOV) return (EINVAL); iovlen = iovcnt * sizeof(struct iovec); uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK); iov = (struct iovec *)(uio + 1); for (i = 0; i < iovcnt; i++) { error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32)); if (error) { free(uio, M_IOV); return (error); } iov[i].iov_base = PTRIN(iov32.iov_base); iov[i].iov_len = iov32.iov_len; } uio->uio_iov = iov; uio->uio_iovcnt = iovcnt; uio->uio_segflg = UIO_USERSPACE; uio->uio_offset = -1; uio->uio_resid = 0; for (i = 0; i < iovcnt; i++) { if (iov->iov_len > INT_MAX - uio->uio_resid) { free(uio, M_IOV); return (EINVAL); } uio->uio_resid += iov->iov_len; iov++; } *uiop = uio; return (0); } int linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp, int error) { struct l_iovec32 iov32; struct iovec *iov; uint32_t iovlen; int i; *iovp = NULL; if (iovcnt > UIO_MAXIOV) return (error); iovlen = iovcnt * sizeof(struct iovec); iov = malloc(iovlen, M_IOV, M_WAITOK); for (i = 0; i < iovcnt; i++) { error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32)); if (error) { free(iov, M_IOV); return (error); } iov[i].iov_base = PTRIN(iov32.iov_base); iov[i].iov_len = iov32.iov_len; } *iovp = iov; return(0); } int linux_readv(struct thread *td, struct linux_readv_args *uap) { struct uio *auio; int error; error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); if (error) return (error); error = kern_readv(td, uap->fd, auio); free(auio, M_IOV); return (error); } int linux_writev(struct thread *td, struct linux_writev_args *uap) { struct uio *auio; int error; error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); if (error) return (error); error = kern_writev(td, uap->fd, auio); free(auio, M_IOV); return (error); } struct l_ipc_kludge { l_uintptr_t msgp; l_long msgtyp; } __packed; int linux_ipc(struct thread *td, struct linux_ipc_args *args) { switch (args->what & 0xFFFF) { case LINUX_SEMOP: { struct linux_semop_args a; a.semid = args->arg1; a.tsops = args->ptr; a.nsops = args->arg2; return (linux_semop(td, &a)); } case LINUX_SEMGET: { struct linux_semget_args a; a.key = args->arg1; a.nsems = args->arg2; a.semflg = args->arg3; return (linux_semget(td, &a)); } case LINUX_SEMCTL: { struct linux_semctl_args a; int error; a.semid = args->arg1; a.semnum = args->arg2; a.cmd = args->arg3; error = copyin(args->ptr, &a.arg, sizeof(a.arg)); if (error) return (error); return (linux_semctl(td, &a)); } case LINUX_MSGSND: { struct linux_msgsnd_args a; a.msqid = args->arg1; a.msgp = args->ptr; a.msgsz = args->arg2; a.msgflg = args->arg3; return (linux_msgsnd(td, &a)); } case LINUX_MSGRCV: { struct linux_msgrcv_args a; a.msqid = args->arg1; a.msgsz = args->arg2; a.msgflg = args->arg3; if ((args->what >> 16) == 0) { struct l_ipc_kludge tmp; int error; if (args->ptr == 0) return (EINVAL); error = copyin(args->ptr, &tmp, sizeof(tmp)); if (error) return (error); a.msgp = PTRIN(tmp.msgp); a.msgtyp = tmp.msgtyp; } else { a.msgp = args->ptr; a.msgtyp = args->arg5; } return (linux_msgrcv(td, &a)); } case LINUX_MSGGET: { struct linux_msgget_args a; a.key = args->arg1; a.msgflg = args->arg2; return (linux_msgget(td, &a)); } case LINUX_MSGCTL: { struct linux_msgctl_args a; a.msqid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_msgctl(td, &a)); } case LINUX_SHMAT: { struct linux_shmat_args a; a.shmid = args->arg1; a.shmaddr = args->ptr; a.shmflg = args->arg2; a.raddr = PTRIN((l_uint)args->arg3); return (linux_shmat(td, &a)); } case LINUX_SHMDT: { struct linux_shmdt_args a; a.shmaddr = args->ptr; return (linux_shmdt(td, &a)); } case LINUX_SHMGET: { struct linux_shmget_args a; a.key = args->arg1; a.size = args->arg2; a.shmflg = args->arg3; return (linux_shmget(td, &a)); } case LINUX_SHMCTL: { struct linux_shmctl_args a; a.shmid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_shmctl(td, &a)); } default: break; } return (EINVAL); } int linux_old_select(struct thread *td, struct linux_old_select_args *args) { struct l_old_select_argv linux_args; struct linux_select_args newsel; int error; #ifdef DEBUG if (ldebug(old_select)) printf(ARGS(old_select, "%p"), args->ptr); #endif error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); newsel.nfds = linux_args.nfds; newsel.readfds = PTRIN(linux_args.readfds); newsel.writefds = PTRIN(linux_args.writefds); newsel.exceptfds = PTRIN(linux_args.exceptfds); newsel.timeout = PTRIN(linux_args.timeout); return (linux_select(td, &newsel)); } int linux_set_cloned_tls(struct thread *td, void *desc) { struct user_segment_descriptor sd; struct l_user_desc info; struct pcb *pcb; int error; int a[2]; error = copyin(desc, &info, sizeof(struct l_user_desc)); if (error) { printf(LMSG("copyin failed!")); } else { /* We might copy out the entry_number as GUGS32_SEL. */ info.entry_number = GUGS32_SEL; error = copyout(&info, desc, sizeof(struct l_user_desc)); if (error) printf(LMSG("copyout failed!")); a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(clone)) printf("Segment created in clone with " "CLONE_SETTLS: lobase: %x, hibase: %x, " "lolimit: %x, hilimit: %x, type: %i, " "dpl: %i, p: %i, xx: %i, long: %i, " "def32: %i, gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_long, sd.sd_def32, sd.sd_gran); #endif pcb = td->td_pcb; pcb->pcb_gsbase = (register_t)info.base_addr; /* XXXKIB pcb->pcb_gs32sd = sd; */ td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); set_pcb_flags(pcb, PCB_GS32BIT | PCB_32BIT); } return (error); } int linux_set_upcall_kse(struct thread *td, register_t stack) { if (stack) td->td_frame->tf_rsp = stack; /* * The newly created Linux thread returns * to the user space by the same path that a parent do. */ td->td_frame->tf_rax = 0; return (0); } #define STACK_SIZE (2 * 1024 * 1024) #define GUARD_SIZE (4 * PAGE_SIZE) int linux_mmap2(struct thread *td, struct linux_mmap2_args *args) { #ifdef DEBUG if (ldebug(mmap2)) printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"), args->addr, args->len, args->prot, args->flags, args->fd, args->pgoff); #endif return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * PAGE_SIZE)); } int linux_mmap(struct thread *td, struct linux_mmap_args *args) { int error; struct l_mmap_argv linux_args; error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); #ifdef DEBUG if (ldebug(mmap)) printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"), linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pgoff); #endif return (linux_mmap_common(td, linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, (uint32_t)linux_args.pgoff)); } static int linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, l_int flags, l_int fd, l_loff_t pos) { struct proc *p = td->td_proc; struct mmap_args /* { caddr_t addr; size_t len; int prot; int flags; int fd; long pad; off_t pos; } */ bsd_args; int error; struct file *fp; error = 0; bsd_args.flags = 0; fp = NULL; /* * Linux mmap(2): * You must specify exactly one of MAP_SHARED and MAP_PRIVATE */ if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE))) return (EINVAL); if (flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; if (flags & LINUX_MAP_FIXED) bsd_args.flags |= MAP_FIXED; if (flags & LINUX_MAP_ANON) { /* Enforce pos to be on page boundary, then ignore. */ if ((pos & PAGE_MASK) != 0) return (EINVAL); pos = 0; bsd_args.flags |= MAP_ANON; } else bsd_args.flags |= MAP_NOSYNC; if (flags & LINUX_MAP_GROWSDOWN) bsd_args.flags |= MAP_STACK; /* * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC * on Linux/i386. We do this to ensure maximum compatibility. * Linux/ia64 does the same in i386 emulation mode. */ bsd_args.prot = prot; if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) bsd_args.prot |= PROT_READ | PROT_EXEC; /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */ bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd; if (bsd_args.fd != -1) { /* * Linux follows Solaris mmap(2) description: * The file descriptor fildes is opened with * read permission, regardless of the * protection options specified. */ if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); return (EINVAL); } /* Linux mmap() just fails for O_WRONLY files */ if (!(fp->f_flag & FREAD)) { fdrop(fp, td); return (EACCES); } fdrop(fp, td); } if (flags & LINUX_MAP_GROWSDOWN) { /* * The Linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option * takes as addr the inital BOS, and as len, the initial * region size. It can then grow down from addr without * limit. However, Linux threads has an implicit internal * limit to stack size of STACK_SIZE. Its just not * enforced explicitly in Linux. But, here we impose * a limit of (STACK_SIZE - GUARD_SIZE) on the stack * region, since we can do this with our mmap. * * Our mmap with MAP_STACK takes addr as the maximum * downsize limit on BOS, and as len the max size of * the region. It then maps the top SGROWSIZ bytes, * and auto grows the region down, up to the limit * in addr. * * If we don't use the MAP_STACK option, the effect * of this code is to allocate a stack region of a * fixed size of (STACK_SIZE - GUARD_SIZE). */ if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) { /* * Some Linux apps will attempt to mmap * thread stacks near the top of their * address space. If their TOS is greater * than vm_maxsaddr, vm_map_growstack() * will confuse the thread stack with the * process stack and deliver a SEGV if they * attempt to grow the thread stack past their * current stacksize rlimit. To avoid this, * adjust vm_maxsaddr upwards to reflect * the current stacksize rlimit rather * than the maximum possible stacksize. * It would be better to adjust the * mmap'ed region, but some apps do not check * mmap's return value. */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK - lim_cur(p, RLIMIT_STACK); PROC_UNLOCK(p); } /* * This gives us our maximum stack size and a new BOS. * If we're using VM_STACK, then mmap will just map * the top SGROWSIZ bytes, and let the stack grow down * to the limit at BOS. If we're not using VM_STACK * we map the full stack, since we don't have a way * to autogrow it. */ if (len > STACK_SIZE - GUARD_SIZE) { bsd_args.addr = (caddr_t)PTRIN(addr); bsd_args.len = len; } else { bsd_args.addr = (caddr_t)PTRIN(addr) - (STACK_SIZE - GUARD_SIZE - len); bsd_args.len = STACK_SIZE - GUARD_SIZE; } } else { bsd_args.addr = (caddr_t)PTRIN(addr); bsd_args.len = len; } bsd_args.pos = pos; #ifdef DEBUG if (ldebug(mmap)) printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", __func__, (void *)bsd_args.addr, (int)bsd_args.len, bsd_args.prot, bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); #endif error = sys_mmap(td, &bsd_args); #ifdef DEBUG if (ldebug(mmap)) printf("-> %s() return: 0x%x (0x%08x)\n", __func__, error, (u_int)td->td_retval[0]); #endif return (error); } int linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) { struct mprotect_args bsd_args; bsd_args.addr = uap->addr; bsd_args.len = uap->len; bsd_args.prot = uap->prot; if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) bsd_args.prot |= PROT_READ | PROT_EXEC; return (sys_mprotect(td, &bsd_args)); } int linux_iopl(struct thread *td, struct linux_iopl_args *args) { int error; if (args->level < 0 || args->level > 3) return (EINVAL); if ((error = priv_check(td, PRIV_IO)) != 0) return (error); if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | (args->level * (PSL_IOPL / 3)); return (0); } int linux_sigaction(struct thread *td, struct linux_sigaction_args *args) { l_osigaction_t osa; l_sigaction_t act, oact; int error; #ifdef DEBUG if (ldebug(sigaction)) printf(ARGS(sigaction, "%d, %p, %p"), args->sig, (void *)args->nsa, (void *)args->osa); #endif if (args->nsa != NULL) { error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); if (error) return (error); act.lsa_handler = osa.lsa_handler; act.lsa_flags = osa.lsa_flags; act.lsa_restorer = osa.lsa_restorer; LINUX_SIGEMPTYSET(act.lsa_mask); act.lsa_mask.__bits[0] = osa.lsa_mask; } error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, args->osa ? &oact : NULL); if (args->osa != NULL && !error) { osa.lsa_handler = oact.lsa_handler; osa.lsa_flags = oact.lsa_flags; osa.lsa_restorer = oact.lsa_restorer; osa.lsa_mask = oact.lsa_mask.__bits[0]; error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); } return (error); } /* * Linux has two extra args, restart and oldmask. We don't use these, * but it seems that "restart" is actually a context pointer that * enables the signal to happen with a different register set. */ int linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) { sigset_t sigmask; l_sigset_t mask; #ifdef DEBUG if (ldebug(sigsuspend)) printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); #endif LINUX_SIGEMPTYSET(mask); mask.__bits[0] = args->mask; linux_to_bsd_sigset(&mask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) { l_sigset_t lmask; sigset_t sigmask; int error; #ifdef DEBUG if (ldebug(rt_sigsuspend)) printf(ARGS(rt_sigsuspend, "%p, %d"), (void *)uap->newset, uap->sigsetsize); #endif if (uap->sigsetsize != sizeof(l_sigset_t)) return (EINVAL); error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); if (error) return (error); linux_to_bsd_sigset(&lmask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_pause(struct thread *td, struct linux_pause_args *args) { struct proc *p = td->td_proc; sigset_t sigmask; #ifdef DEBUG if (ldebug(pause)) printf(ARGS(pause, "")); #endif PROC_LOCK(p); sigmask = td->td_sigmask; PROC_UNLOCK(p); return (kern_sigsuspend(td, sigmask)); } int linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) { stack_t ss, oss; l_stack_t lss; int error; #ifdef DEBUG if (ldebug(sigaltstack)) printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); #endif if (uap->uss != NULL) { error = copyin(uap->uss, &lss, sizeof(l_stack_t)); if (error) return (error); ss.ss_sp = PTRIN(lss.ss_sp); ss.ss_size = lss.ss_size; ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); } error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, (uap->uoss != NULL) ? &oss : NULL); if (!error && uap->uoss != NULL) { lss.ss_sp = PTROUT(oss.ss_sp); lss.ss_size = oss.ss_size; lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); } return (error); } int linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) { struct ftruncate_args sa; #ifdef DEBUG if (ldebug(ftruncate64)) printf(ARGS(ftruncate64, "%u, %jd"), args->fd, (intmax_t)args->length); #endif sa.fd = args->fd; sa.length = args->length; return sys_ftruncate(td, &sa); } int linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) { struct timeval atv; l_timeval atv32; struct timezone rtz; int error = 0; if (uap->tp) { microtime(&atv); atv32.tv_sec = atv.tv_sec; atv32.tv_usec = atv.tv_usec; error = copyout(&atv32, uap->tp, sizeof(atv32)); } if (error == 0 && uap->tzp != NULL) { rtz.tz_minuteswest = tz_minuteswest; rtz.tz_dsttime = tz_dsttime; error = copyout(&rtz, uap->tzp, sizeof(rtz)); } return (error); } int linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap) { l_timeval atv32; struct timeval atv, *tvp; struct timezone atz, *tzp; int error; if (uap->tp) { error = copyin(uap->tp, &atv32, sizeof(atv32)); if (error) return (error); atv.tv_sec = atv32.tv_sec; atv.tv_usec = atv32.tv_usec; tvp = &atv; } else tvp = NULL; if (uap->tzp) { error = copyin(uap->tzp, &atz, sizeof(atz)); if (error) return (error); tzp = &atz; } else tzp = NULL; return (kern_settimeofday(td, tvp, tzp)); } int linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) { struct l_rusage s32; struct rusage s; int error; error = kern_getrusage(td, uap->who, &s); if (error != 0) return (error); if (uap->rusage != NULL) { bsd_to_linux_rusage(&s, &s32); error = copyout(&s32, uap->rusage, sizeof(s32)); } return (error); } int linux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) { struct l_user_desc info; struct user_segment_descriptor sd; struct pcb *pcb; int a[2]; int error; error = copyin(args->desc, &info, sizeof(struct l_user_desc)); if (error) return (error); #ifdef DEBUG if (ldebug(set_thread_area)) printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, " "%i, %i, %i"), info.entry_number, info.base_addr, info.limit, info.seg_32bit, info.contents, info.read_exec_only, info.limit_in_pages, info.seg_not_present, info.useable); #endif /* * Semantics of Linux version: every thread in the system has array * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. * This syscall loads one of the selected TLS decriptors with a value * and also loads GDT descriptors 6, 7 and 8 with the content of * the per-thread descriptors. * * Semantics of FreeBSD version: I think we can ignore that Linux has * three per-thread descriptors and use just the first one. * The tls_array[] is used only in [gs]et_thread_area() syscalls and * for loading the GDT descriptors. We use just one GDT descriptor * for TLS, so we will load just one. * * XXX: This doesn't work when a user space process tries to use more * than one TLS segment. Comment in the Linux source says wine might * do this. */ /* * GLIBC reads current %gs and call set_thread_area() with it. * We should let GUDATA_SEL and GUGS32_SEL proceed as well because * we use these segments. */ switch (info.entry_number) { case GUGS32_SEL: case GUDATA_SEL: case 6: case -1: info.entry_number = GUGS32_SEL; break; default: return (EINVAL); } /* * We have to copy out the GDT entry we use. * * XXX: What if a user space program does not check the return value * and tries to use 6, 7 or 8? */ error = copyout(&info, args->desc, sizeof(struct l_user_desc)); if (error) return (error); if (LINUX_LDT_empty(&info)) { a[0] = 0; a[1] = 0; } else { a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); } memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(set_thread_area)) printf("Segment created in set_thread_area: " "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, " "type: %i, dpl: %i, p: %i, xx: %i, long: %i, " "def32: %i, gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_long, sd.sd_def32, sd.sd_gran); #endif pcb = td->td_pcb; pcb->pcb_gsbase = (register_t)info.base_addr; set_pcb_flags(pcb, PCB_32BIT | PCB_GS32BIT); update_gdt_gsbase(td, info.base_addr); return (0); } int linux_wait4(struct thread *td, struct linux_wait4_args *args) { int error, options; struct rusage ru, *rup; struct l_rusage lru; #ifdef DEBUG if (ldebug(wait4)) printf(ARGS(wait4, "%d, %p, %d, %p"), args->pid, (void *)args->status, args->options, (void *)args->rusage); #endif options = (args->options & (WNOHANG | WUNTRACED)); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) options |= WLINUXCLONE; if (args->rusage != NULL) rup = &ru; else rup = NULL; error = linux_common_wait(td, args->pid, args->status, options, rup); if (error) return (error); if (args->rusage != NULL) { bsd_to_linux_rusage(rup, &lru); error = copyout(&lru, args->rusage, sizeof(lru)); } return (error); } + +int +linux_waitid(struct thread *td, struct linux_waitid_args *args) +{ + int status, options, sig; + struct __wrusage wru; + struct l_rusage lru; + siginfo_t siginfo; + l_siginfo_t lsi; + idtype_t idtype; + int error; + + options = 0; + linux_to_bsd_waitopts(args->options, &options); + + if (options & ~(WNOHANG | WNOWAIT | WEXITED | WUNTRACED | WCONTINUED)) + return (EINVAL); + if (!(options & (WEXITED | WUNTRACED | WCONTINUED))) + return (EINVAL); + + switch (args->idtype) { + case LINUX_P_ALL: + idtype = P_ALL; + break; + case LINUX_P_PID: + if (args->id <= 0) + return (EINVAL); + idtype = P_PID; + break; + case LINUX_P_PGID: + if (args->id <= 0) + return (EINVAL); + idtype = P_PGID; + break; + default: + return (EINVAL); + } + + error = kern_wait6(td, idtype, args->id, &status, options, + &wru, &siginfo); + if (error) + return (error); + td->td_retval[0] = 0; + + if (args->rusage != NULL) { + bsd_to_linux_rusage(&wru.wru_children, &lru); + error = copyout(&lru, args->rusage, sizeof(lru)); + if (error) + return (error); + } + + if (args->info != NULL) { + sig = siginfo.si_signo; + if (siginfo.si_signo <= td->td_proc->p_sysent->sv_sigsize) + sig = td->td_proc->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + siginfo_to_lsiginfo(&siginfo, &lsi, sig); + error = copyout(&lsi, args->info, sizeof(lsi)); + } + + return (error); +} Index: user/dchagin/lemul/sys/amd64/linux32/syscalls.master =================================================================== --- user/dchagin/lemul/sys/amd64/linux32/syscalls.master (revision 247218) +++ user/dchagin/lemul/sys/amd64/linux32/syscalls.master (revision 247219) @@ -1,560 +1,561 @@ $FreeBSD$ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 ; System call name/number master file (or rather, slave, from LINUX). ; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h. ; Columns: number audit type nargs name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; audit the audit event associated with the system call ; A value of AUE_NULL means no auditing, but it also means that ; there is no audit event for the call at this time. For the ; case where the event exists, but we don't want auditing, the ; event should be #defined to AUE_NULL in audit_kevents.h. ; type one of STD, OBSOL, UNIMPL ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; STD always included ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only #include "opt_compat.h" #include #include #include #include #include #include ; Isn't pretty, but there seems to be no other way to trap nosys #define nosys linux_nosys ; #ifdef's, etc. may be included, and are copied to the output files. 0 AUE_NULL UNIMPL setup 1 AUE_EXIT STD { void linux_exit(int rval); } 2 AUE_FORK STD { int linux_fork(void); } 3 AUE_NULL NOPROTO { int read(int fd, char *buf, \ u_int nbyte); } 4 AUE_NULL NOPROTO { int write(int fd, char *buf, \ u_int nbyte); } 5 AUE_OPEN_RWTC STD { int linux_open(char *path, l_int flags, \ l_int mode); } 6 AUE_CLOSE NOPROTO { int close(int fd); } 7 AUE_WAIT4 STD { int linux_waitpid(l_pid_t pid, \ l_int *status, l_int options); } 8 AUE_CREAT STD { int linux_creat(char *path, \ l_int mode); } 9 AUE_LINK STD { int linux_link(char *path, char *to); } 10 AUE_UNLINK STD { int linux_unlink(char *path); } 11 AUE_EXECVE STD { int linux_execve(char *path, uint32_t *argp, \ uint32_t *envp); } 12 AUE_CHDIR STD { int linux_chdir(char *path); } 13 AUE_NULL STD { int linux_time(l_time_t *tm); } 14 AUE_MKNOD STD { int linux_mknod(char *path, l_int mode, \ l_dev_t dev); } 15 AUE_CHMOD STD { int linux_chmod(char *path, \ l_mode_t mode); } 16 AUE_LCHOWN STD { int linux_lchown16(char *path, \ l_uid16_t uid, l_gid16_t gid); } 17 AUE_NULL UNIMPL break 18 AUE_STAT STD { int linux_stat(char *path, \ struct linux_stat *up); } 19 AUE_LSEEK STD { int linux_lseek(l_uint fdes, l_off_t off, \ l_int whence); } 20 AUE_GETPID STD { int linux_getpid(void); } 21 AUE_MOUNT STD { int linux_mount(char *specialfile, \ char *dir, char *filesystemtype, \ l_ulong rwflag, void *data); } 22 AUE_UMOUNT STD { int linux_oldumount(char *path); } 23 AUE_SETUID STD { int linux_setuid16(l_uid16_t uid); } 24 AUE_GETUID STD { int linux_getuid16(void); } 25 AUE_SETTIMEOFDAY STD { int linux_stime(void); } 26 AUE_PTRACE STD { int linux_ptrace(l_long req, l_long pid, \ l_long addr, l_long data); } 27 AUE_NULL STD { int linux_alarm(l_uint secs); } 28 AUE_FSTAT UNIMPL fstat 29 AUE_NULL STD { int linux_pause(void); } 30 AUE_UTIME STD { int linux_utime(char *fname, \ struct l_utimbuf *times); } 31 AUE_NULL UNIMPL stty 32 AUE_NULL UNIMPL gtty 33 AUE_ACCESS STD { int linux_access(char *path, l_int amode); } 34 AUE_NICE STD { int linux_nice(l_int inc); } 35 AUE_NULL UNIMPL ftime 36 AUE_SYNC NOPROTO { int sync(void); } 37 AUE_KILL STD { int linux_kill(l_int pid, l_int signum); } 38 AUE_RENAME STD { int linux_rename(char *from, char *to); } 39 AUE_MKDIR STD { int linux_mkdir(char *path, l_int mode); } 40 AUE_RMDIR STD { int linux_rmdir(char *path); } 41 AUE_DUP NOPROTO { int dup(u_int fd); } 42 AUE_PIPE STD { int linux_pipe(l_int *pipefds); } 43 AUE_NULL STD { int linux_times(struct l_times_argv *buf); } 44 AUE_NULL UNIMPL prof 45 AUE_NULL STD { int linux_brk(l_ulong dsend); } 46 AUE_SETGID STD { int linux_setgid16(l_gid16_t gid); } 47 AUE_GETGID STD { int linux_getgid16(void); } 48 AUE_NULL STD { int linux_signal(l_int sig, \ l_handler_t handler); } 49 AUE_GETEUID STD { int linux_geteuid16(void); } 50 AUE_GETEGID STD { int linux_getegid16(void); } 51 AUE_ACCT NOPROTO { int acct(char *path); } 52 AUE_UMOUNT STD { int linux_umount(char *path, l_int flags); } 53 AUE_NULL UNIMPL lock 54 AUE_IOCTL STD { int linux_ioctl(l_uint fd, l_uint cmd, \ uintptr_t arg); } 55 AUE_FCNTL STD { int linux_fcntl(l_uint fd, l_uint cmd, \ uintptr_t arg); } 56 AUE_NULL UNIMPL mpx 57 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); } 58 AUE_NULL UNIMPL ulimit 59 AUE_NULL STD { int linux_olduname(void); } 60 AUE_UMASK NOPROTO { int umask(int newmask); } 61 AUE_CHROOT NOPROTO { int chroot(char *path); } 62 AUE_NULL STD { int linux_ustat(l_dev_t dev, \ struct l_ustat *ubuf); } 63 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); } 64 AUE_GETPPID STD { int linux_getppid(void); } 65 AUE_GETPGRP NOPROTO { int getpgrp(void); } 66 AUE_SETSID NOPROTO { int setsid(void); } 67 AUE_NULL STD { int linux_sigaction(l_int sig, \ l_osigaction_t *nsa, \ l_osigaction_t *osa); } 68 AUE_NULL STD { int linux_sgetmask(void); } 69 AUE_NULL STD { int linux_ssetmask(l_osigset_t mask); } 70 AUE_SETREUID STD { int linux_setreuid16(l_uid16_t ruid, \ l_uid16_t euid); } 71 AUE_SETREGID STD { int linux_setregid16(l_gid16_t rgid, \ l_gid16_t egid); } 72 AUE_NULL STD { int linux_sigsuspend(l_int hist0, \ l_int hist1, l_osigset_t mask); } 73 AUE_NULL STD { int linux_sigpending(l_osigset_t *mask); } 74 AUE_SYSCTL STD { int linux_sethostname(char *hostname, \ u_int len); } 75 AUE_SETRLIMIT STD { int linux_setrlimit(l_uint resource, \ struct l_rlimit *rlim); } 76 AUE_GETRLIMIT STD { int linux_old_getrlimit(l_uint resource, \ struct l_rlimit *rlim); } 77 AUE_GETRUSAGE STD { int linux_getrusage(int who, \ struct l_rusage *rusage); } 78 AUE_NULL STD { int linux_gettimeofday( \ struct l_timeval *tp, \ struct timezone *tzp); } 79 AUE_SETTIMEOFDAY STD { int linux_settimeofday( \ struct l_timeval *tp, \ struct timezone *tzp); } 80 AUE_GETGROUPS STD { int linux_getgroups16(l_uint gidsetsize, \ l_gid16_t *gidset); } 81 AUE_SETGROUPS STD { int linux_setgroups16(l_uint gidsetsize, \ l_gid16_t *gidset); } 82 AUE_SELECT STD { int linux_old_select( \ struct l_old_select_argv *ptr); } 83 AUE_SYMLINK STD { int linux_symlink(char *path, char *to); } ; 84: oldlstat 84 AUE_LSTAT STD { int linux_lstat(char *path, struct linux_lstat *up); } 85 AUE_READLINK STD { int linux_readlink(char *name, char *buf, \ l_int count); } 86 AUE_USELIB UNIMPL linux_uselib 87 AUE_SWAPON NOPROTO { int swapon(char *name); } 88 AUE_REBOOT STD { int linux_reboot(l_int magic1, \ l_int magic2, l_uint cmd, void *arg); } ; 89: old_readdir 89 AUE_GETDIRENTRIES STD { int linux_readdir(l_uint fd, \ struct l_dirent *dent, l_uint count); } ; 90: old_mmap 90 AUE_MMAP STD { int linux_mmap(struct l_mmap_argv *ptr); } 91 AUE_MUNMAP NOPROTO { int munmap(caddr_t addr, int len); } 92 AUE_TRUNCATE STD { int linux_truncate(char *path, \ l_ulong length); } 93 AUE_FTRUNCATE STD { int linux_ftruncate(int fd, long length); } 94 AUE_FCHMOD NOPROTO { int fchmod(int fd, int mode); } 95 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); } 96 AUE_GETPRIORITY STD { int linux_getpriority(int which, int who); } 97 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \ int prio); } 98 AUE_PROFILE UNIMPL profil 99 AUE_STATFS STD { int linux_statfs(char *path, \ struct l_statfs_buf *buf); } 100 AUE_FSTATFS STD { int linux_fstatfs(l_uint fd, \ struct l_statfs_buf *buf); } 101 AUE_NULL UNIMPL ioperm 102 AUE_NULL STD { int linux_socketcall(l_int what, \ l_ulong args); } 103 AUE_NULL STD { int linux_syslog(l_int type, char *buf, \ l_int len); } 104 AUE_SETITIMER STD { int linux_setitimer(l_int which, \ struct l_itimerval *itv, \ struct l_itimerval *oitv); } 105 AUE_GETITIMER STD { int linux_getitimer(l_int which, \ struct l_itimerval *itv); } 106 AUE_STAT STD { int linux_newstat(char *path, \ struct l_newstat *buf); } 107 AUE_LSTAT STD { int linux_newlstat(char *path, \ struct l_newstat *buf); } 108 AUE_FSTAT STD { int linux_newfstat(l_uint fd, \ struct l_newstat *buf); } ; 109: olduname 109 AUE_NULL STD { int linux_uname(void); } 110 AUE_NULL STD { int linux_iopl(l_int level); } 111 AUE_NULL STD { int linux_vhangup(void); } 112 AUE_NULL UNIMPL idle 113 AUE_NULL UNIMPL vm86old 114 AUE_WAIT4 STD { int linux_wait4(l_pid_t pid, \ l_uint *status, l_int options, \ struct l_rusage *rusage); } 115 AUE_SWAPOFF STD { int linux_swapoff(void); } 116 AUE_NULL STD { int linux_sysinfo(struct l_sysinfo *info); } 117 AUE_NULL STD { int linux_ipc(l_uint what, l_int arg1, \ l_int arg2, l_int arg3, void *ptr, \ l_long arg5); } 118 AUE_FSYNC NOPROTO { int fsync(int fd); } 119 AUE_SIGRETURN STD { int linux_sigreturn( \ struct l_sigframe *sfp); } 120 AUE_RFORK STD { int linux_clone(l_int flags, void *stack, \ void *parent_tidptr, void *tls, void * child_tidptr); } 121 AUE_SYSCTL STD { int linux_setdomainname(char *name, \ int len); } 122 AUE_NULL STD { int linux_newuname( \ struct l_new_utsname *buf); } 123 AUE_NULL UNIMPL modify_ldt 124 AUE_ADJTIME STD { int linux_adjtimex(void); } 125 AUE_MPROTECT STD { int linux_mprotect(caddr_t addr, int len, \ int prot); } 126 AUE_SIGPROCMASK STD { int linux_sigprocmask(l_int how, \ l_osigset_t *mask, l_osigset_t *omask); } 127 AUE_NULL STD { int linux_create_module(void); } 128 AUE_NULL STD { int linux_init_module(void); } 129 AUE_NULL STD { int linux_delete_module(void); } 130 AUE_NULL STD { int linux_get_kernel_syms(void); } 131 AUE_QUOTACTL STD { int linux_quotactl(void); } 132 AUE_GETPGID NOPROTO { int getpgid(int pid); } 133 AUE_FCHDIR NOPROTO { int fchdir(int fd); } 134 AUE_BDFLUSH STD { int linux_bdflush(void); } 135 AUE_NULL STD { int linux_sysfs(l_int option, \ l_ulong arg1, l_ulong arg2); } 136 AUE_PERSONALITY STD { int linux_personality(l_ulong per); } 137 AUE_NULL UNIMPL afs_syscall 138 AUE_SETFSUID STD { int linux_setfsuid16(l_uid16_t uid); } 139 AUE_SETFSGID STD { int linux_setfsgid16(l_gid16_t gid); } 140 AUE_LSEEK STD { int linux_llseek(l_int fd, l_ulong ohigh, \ l_ulong olow, l_loff_t *res, \ l_uint whence); } 141 AUE_GETDIRENTRIES STD { int linux_getdents(l_uint fd, void *dent, \ l_uint count); } ; 142: newselect 142 AUE_SELECT STD { int linux_select(l_int nfds, \ l_fd_set *readfds, l_fd_set *writefds, \ l_fd_set *exceptfds, \ struct l_timeval *timeout); } 143 AUE_FLOCK NOPROTO { int flock(int fd, int how); } 144 AUE_MSYNC STD { int linux_msync(l_ulong addr, \ l_size_t len, l_int fl); } 145 AUE_READV STD { int linux_readv(l_ulong fd, struct l_iovec32 *iovp, \ l_ulong iovcnt); } 146 AUE_WRITEV STD { int linux_writev(l_ulong fd, struct l_iovec32 *iovp, \ l_ulong iovcnt); } 147 AUE_GETSID STD { int linux_getsid(l_pid_t pid); } 148 AUE_NULL STD { int linux_fdatasync(l_uint fd); } 149 AUE_SYSCTL STD { int linux_sysctl( \ struct l___sysctl_args *args); } 150 AUE_MLOCK NOPROTO { int mlock(const void *addr, size_t len); } 151 AUE_MUNLOCK NOPROTO { int munlock(const void *addr, size_t len); } 152 AUE_MLOCKALL NOPROTO { int mlockall(int how); } 153 AUE_MUNLOCKALL NOPROTO { int munlockall(void); } 154 AUE_SCHED_SETPARAM STD { int linux_sched_setparam(l_pid_t pid, \ struct l_sched_param *param); } 155 AUE_SCHED_GETPARAM STD { int linux_sched_getparam(l_pid_t pid, \ struct l_sched_param *param); } 156 AUE_SCHED_SETSCHEDULER STD { int linux_sched_setscheduler( \ l_pid_t pid, l_int policy, \ struct l_sched_param *param); } 157 AUE_SCHED_GETSCHEDULER STD { int linux_sched_getscheduler( \ l_pid_t pid); } 158 AUE_NULL NOPROTO { int sched_yield(void); } 159 AUE_SCHED_GET_PRIORITY_MAX STD { int linux_sched_get_priority_max( \ l_int policy); } 160 AUE_SCHED_GET_PRIORITY_MIN STD { int linux_sched_get_priority_min( \ l_int policy); } 161 AUE_SCHED_RR_GET_INTERVAL STD { int linux_sched_rr_get_interval(l_pid_t pid, \ struct l_timespec *interval); } 162 AUE_NULL STD { int linux_nanosleep( \ const struct l_timespec *rqtp, \ struct l_timespec *rmtp); } 163 AUE_NULL STD { int linux_mremap(l_ulong addr, \ l_ulong old_len, l_ulong new_len, \ l_ulong flags, l_ulong new_addr); } 164 AUE_SETRESUID STD { int linux_setresuid16(l_uid16_t ruid, \ l_uid16_t euid, l_uid16_t suid); } 165 AUE_GETRESUID STD { int linux_getresuid16(l_uid16_t *ruid, \ l_uid16_t *euid, l_uid16_t *suid); } 166 AUE_NULL UNIMPL vm86 167 AUE_NULL STD { int linux_query_module(void); } 168 AUE_POLL NOPROTO { int poll(struct pollfd *fds, \ unsigned int nfds, int timeout); } 169 AUE_NULL STD { int linux_nfsservctl(void); } 170 AUE_SETRESGID STD { int linux_setresgid16(l_gid16_t rgid, \ l_gid16_t egid, l_gid16_t sgid); } 171 AUE_GETRESGID STD { int linux_getresgid16(l_gid16_t *rgid, \ l_gid16_t *egid, l_gid16_t *sgid); } 172 AUE_PRCTL STD { int linux_prctl(l_int option, l_int arg2, l_int arg3, \ l_int arg4, l_int arg5); } 173 AUE_NULL STD { int linux_rt_sigreturn( \ struct l_ucontext *ucp); } 174 AUE_NULL STD { int linux_rt_sigaction(l_int sig, \ l_sigaction_t *act, l_sigaction_t *oact, \ l_size_t sigsetsize); } 175 AUE_NULL STD { int linux_rt_sigprocmask(l_int how, \ l_sigset_t *mask, l_sigset_t *omask, \ l_size_t sigsetsize); } 176 AUE_NULL STD { int linux_rt_sigpending(l_sigset_t *set, \ l_size_t sigsetsize); } 177 AUE_NULL STD { int linux_rt_sigtimedwait(l_sigset_t *mask, \ l_siginfo_t *ptr, \ struct l_timeval *timeout, \ l_size_t sigsetsize); } 178 AUE_NULL STD { int linux_rt_sigqueueinfo(void); } 179 AUE_NULL STD { int linux_rt_sigsuspend( \ l_sigset_t *newset, \ l_size_t sigsetsize); } 180 AUE_PREAD STD { int linux_pread(l_uint fd, char *buf, \ l_size_t nbyte, l_loff_t offset); } 181 AUE_PWRITE STD { int linux_pwrite(l_uint fd, char *buf, \ l_size_t nbyte, l_loff_t offset); } 182 AUE_CHOWN STD { int linux_chown16(char *path, \ l_uid16_t uid, l_gid16_t gid); } 183 AUE_GETCWD STD { int linux_getcwd(char *buf, \ l_ulong bufsize); } 184 AUE_CAPGET STD { int linux_capget(struct l_user_cap_header *hdrp, \ struct l_user_cap_data *datap); } 185 AUE_CAPSET STD { int linux_capset(struct l_user_cap_header *hdrp, \ struct l_user_cap_data *datap); } 186 AUE_NULL STD { int linux_sigaltstack(l_stack_t *uss, \ l_stack_t *uoss); } 187 AUE_SENDFILE STD { int linux_sendfile(void); } 188 AUE_GETPMSG UNIMPL getpmsg 189 AUE_PUTPMSG UNIMPL putpmsg 190 AUE_VFORK STD { int linux_vfork(void); } ; 191: ugetrlimit 191 AUE_GETRLIMIT STD { int linux_getrlimit(l_uint resource, \ struct l_rlimit *rlim); } 192 AUE_MMAP STD { int linux_mmap2(l_ulong addr, l_ulong len, \ l_ulong prot, l_ulong flags, l_ulong fd, \ l_ulong pgoff); } 193 AUE_TRUNCATE STD { int linux_truncate64(char *path, \ l_loff_t length); } 194 AUE_FTRUNCATE STD { int linux_ftruncate64(l_uint fd, \ l_loff_t length); } 195 AUE_STAT STD { int linux_stat64(const char *filename, \ struct l_stat64 *statbuf); } 196 AUE_LSTAT STD { int linux_lstat64(const char *filename, \ struct l_stat64 *statbuf); } 197 AUE_FSTAT STD { int linux_fstat64(l_int fd, \ struct l_stat64 *statbuf); } 198 AUE_LCHOWN STD { int linux_lchown(char *path, l_uid_t uid, \ l_gid_t gid); } 199 AUE_GETUID STD { int linux_getuid(void); } 200 AUE_GETGID STD { int linux_getgid(void); } 201 AUE_GETEUID NOPROTO { int geteuid(void); } 202 AUE_GETEGID NOPROTO { int getegid(void); } 203 AUE_SETREUID NOPROTO { int setreuid(uid_t ruid, uid_t euid); } 204 AUE_SETREGID NOPROTO { int setregid(gid_t rgid, gid_t egid); } 205 AUE_GETGROUPS STD { int linux_getgroups(l_int gidsetsize, \ l_gid_t *grouplist); } 206 AUE_SETGROUPS STD { int linux_setgroups(l_int gidsetsize, \ l_gid_t *grouplist); } 207 AUE_FCHOWN NODEF fchown fchown fchown_args int 208 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \ uid_t suid); } 209 AUE_GETRESUID NOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \ uid_t *suid); } 210 AUE_SETRESGID NOPROTO { int setresgid(gid_t rgid, gid_t egid, \ gid_t sgid); } 211 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \ gid_t *sgid); } 212 AUE_CHOWN STD { int linux_chown(char *path, l_uid_t uid, \ l_gid_t gid); } 213 AUE_SETUID NOPROTO { int setuid(uid_t uid); } 214 AUE_SETGID NOPROTO { int setgid(gid_t gid); } 215 AUE_SETFSUID STD { int linux_setfsuid(l_uid_t uid); } 216 AUE_SETFSGID STD { int linux_setfsgid(l_gid_t gid); } 217 AUE_PIVOT_ROOT STD { int linux_pivot_root(char *new_root, \ char *put_old); } 218 AUE_MINCORE STD { int linux_mincore(l_ulong start, \ l_size_t len, u_char *vec); } 219 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \ int behav); } 220 AUE_GETDIRENTRIES STD { int linux_getdents64(l_uint fd, \ void *dirent, l_uint count); } 221 AUE_FCNTL STD { int linux_fcntl64(l_uint fd, l_uint cmd, \ uintptr_t arg); } 222 AUE_NULL UNIMPL 223 AUE_NULL UNIMPL 224 AUE_NULL STD { long linux_gettid(void); } 225 AUE_NULL UNIMPL linux_readahead 226 AUE_NULL STD { int linux_setxattr(void); } 227 AUE_NULL STD { int linux_lsetxattr(void); } 228 AUE_NULL STD { int linux_fsetxattr(void); } 229 AUE_NULL STD { int linux_getxattr(void); } 230 AUE_NULL STD { int linux_lgetxattr(void); } 231 AUE_NULL STD { int linux_fgetxattr(void); } 232 AUE_NULL STD { int linux_listxattr(void); } 233 AUE_NULL STD { int linux_llistxattr(void); } 234 AUE_NULL STD { int linux_flistxattr(void); } 235 AUE_NULL STD { int linux_removexattr(void); } 236 AUE_NULL STD { int linux_lremovexattr(void); } 237 AUE_NULL STD { int linux_fremovexattr(void); } 238 AUE_NULL STD { int linux_tkill(int tid, int sig); } 239 AUE_SENDFILE UNIMPL linux_sendfile64 240 AUE_NULL STD { int linux_sys_futex(void *uaddr, int op, uint32_t val, \ struct l_timespec *timeout, uint32_t *uaddr2, uint32_t val3); } 241 AUE_NULL STD { int linux_sched_setaffinity(l_pid_t pid, l_uint len, \ l_ulong *user_mask_ptr); } 242 AUE_NULL STD { int linux_sched_getaffinity(l_pid_t pid, l_uint len, \ l_ulong *user_mask_ptr); } 243 AUE_NULL STD { int linux_set_thread_area(struct l_user_desc *desc); } 244 AUE_NULL UNIMPL linux_get_thread_area 245 AUE_NULL UNIMPL linux_io_setup 246 AUE_NULL UNIMPL linux_io_destroy 247 AUE_NULL UNIMPL linux_io_getevents 248 AUE_NULL UNIMPL linux_io_submit 249 AUE_NULL UNIMPL linux_io_cancel 250 AUE_NULL STD { int linux_fadvise64(int fd, l_loff_t offset, \ l_size_t len, int advice); } 251 AUE_NULL UNIMPL 252 AUE_EXIT STD { int linux_exit_group(int error_code); } 253 AUE_NULL STD { int linux_lookup_dcookie(void); } 254 AUE_NULL STD { int linux_epoll_create(void); } 255 AUE_NULL STD { int linux_epoll_ctl(void); } 256 AUE_NULL STD { int linux_epoll_wait(void); } 257 AUE_NULL STD { int linux_remap_file_pages(void); } 258 AUE_NULL STD { int linux_set_tid_address(int *tidptr); } 259 AUE_NULL STD { int linux_timer_create(void); } 260 AUE_NULL STD { int linux_timer_settime(void); } 261 AUE_NULL STD { int linux_timer_gettime(void); } 262 AUE_NULL STD { int linux_timer_getoverrun(void); } 263 AUE_NULL STD { int linux_timer_delete(void); } 264 AUE_CLOCK_SETTIME STD { int linux_clock_settime(clockid_t which, struct l_timespec *tp); } 265 AUE_NULL STD { int linux_clock_gettime(clockid_t which, struct l_timespec *tp); } 266 AUE_NULL STD { int linux_clock_getres(clockid_t which, struct l_timespec *tp); } 267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \ struct l_timespec *rqtp, struct l_timespec *rmtp); } 268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); } 269 AUE_FSTATFS STD { int linux_fstatfs64(void); } 270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); } 271 AUE_UTIMES STD { int linux_utimes(char *fname, \ struct l_timeval *tptr); } 272 AUE_NULL STD { int linux_fadvise64_64(int fd, \ l_loff_t offset, l_loff_t len, \ int advice); } 273 AUE_NULL UNIMPL vserver 274 AUE_NULL STD { int linux_mbind(void); } 275 AUE_NULL STD { int linux_get_mempolicy(void); } 276 AUE_NULL STD { int linux_set_mempolicy(void); } ; linux 2.6.6: 277 AUE_NULL STD { int linux_mq_open(void); } 278 AUE_NULL STD { int linux_mq_unlink(void); } 279 AUE_NULL STD { int linux_mq_timedsend(void); } 280 AUE_NULL STD { int linux_mq_timedreceive(void); } 281 AUE_NULL STD { int linux_mq_notify(void); } 282 AUE_NULL STD { int linux_mq_getsetattr(void); } 283 AUE_NULL STD { int linux_kexec_load(void); } -284 AUE_NULL STD { int linux_waitid(void); } +284 AUE_WAIT6 STD { int linux_waitid(int idtype, l_pid_t id, l_siginfo_t *info, \ + int options, struct l_rusage *rusage); } 285 AUE_NULL UNIMPL ; linux 2.6.11: 286 AUE_NULL STD { int linux_add_key(void); } 287 AUE_NULL STD { int linux_request_key(void); } 288 AUE_NULL STD { int linux_keyctl(void); } ; linux 2.6.13: 289 AUE_NULL STD { int linux_ioprio_set(void); } 290 AUE_NULL STD { int linux_ioprio_get(void); } 291 AUE_NULL STD { int linux_inotify_init(void); } 292 AUE_NULL STD { int linux_inotify_add_watch(void); } 293 AUE_NULL STD { int linux_inotify_rm_watch(void); } ; linux 2.6.16: 294 AUE_NULL STD { int linux_migrate_pages(void); } 295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, const char *filename, \ l_int flags, l_int mode); } 296 AUE_MKDIRAT STD { int linux_mkdirat(l_int dfd, const char *pathname, \ l_int mode); } 297 AUE_MKNODAT STD { int linux_mknodat(l_int dfd, const char *filename, \ l_int mode, l_uint dev); } 298 AUE_FCHOWNAT STD { int linux_fchownat(l_int dfd, const char *filename, \ l_uid16_t uid, l_gid16_t gid, l_int flag); } 299 AUE_FUTIMESAT STD { int linux_futimesat(l_int dfd, char *filename, \ struct l_timeval *utimes); } 300 AUE_FSTATAT STD { int linux_fstatat64(l_int dfd, char *pathname, \ struct l_stat64 *statbuf, l_int flag); } 301 AUE_UNLINKAT STD { int linux_unlinkat(l_int dfd, const char *pathname, \ l_int flag); } 302 AUE_RENAMEAT STD { int linux_renameat(l_int olddfd, const char *oldname, \ l_int newdfd, const char *newname); } 303 AUE_LINKAT STD { int linux_linkat(l_int olddfd, const char *oldname, \ l_int newdfd, const char *newname, l_int flag); } 304 AUE_SYMLINKAT STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ const char *newname); } 305 AUE_READLINKAT STD { int linux_readlinkat(l_int dfd, const char *path, \ char *buf, l_int bufsiz); } 306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ l_mode_t mode); } 307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int amode, int flag); } 308 AUE_NULL STD { int linux_pselect6(void); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } ; linux 2.6.17: 311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \ l_size_t len); } 312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \ l_size_t *len); } 313 AUE_NULL STD { int linux_splice(void); } 314 AUE_NULL STD { int linux_sync_file_range(void); } 315 AUE_NULL STD { int linux_tee(void); } 316 AUE_NULL STD { int linux_vmsplice(void); } ; linux 2.6.18: 317 AUE_NULL STD { int linux_move_pages(void); } ; linux 2.6.19: 318 AUE_NULL STD { int linux_getcpu(void); } 319 AUE_NULL STD { int linux_epoll_pwait(void); } ; linux 2.6.22: 320 AUE_NULL STD { int linux_utimensat(void); } 321 AUE_NULL STD { int linux_signalfd(void); } 322 AUE_NULL STD { int linux_timerfd_create(void); } 323 AUE_NULL STD { int linux_eventfd(void); } ; linux 2.6.23: 324 AUE_NULL STD { int linux_fallocate(void); } ; linux 2.6.25: 325 AUE_NULL STD { int linux_timerfd_settime(void); } 326 AUE_NULL STD { int linux_timerfd_gettime(void); } ; linux 2.6.27: 327 AUE_NULL STD { int linux_signalfd4(void); } 328 AUE_NULL STD { int linux_eventfd2(void); } 329 AUE_NULL STD { int linux_epoll_create1(void); } 330 AUE_NULL STD { int linux_dup3(void); } 331 AUE_NULL STD { int linux_pipe2(l_int *pipefds, l_int flags); } 332 AUE_NULL STD { int linux_inotify_init1(void); } ; linux 2.6.30: 333 AUE_NULL STD { int linux_preadv(void); } 334 AUE_NULL STD { int linux_pwritev(void); } ; linux 2.6.31: 335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); } 336 AUE_NULL STD { int linux_perf_event_open(void); } ; linux 2.6.33: 337 AUE_NULL STD { int linux_recvmmsg(void); } 338 AUE_NULL STD { int linux_fanotify_init(void); } 339 AUE_NULL STD { int linux_fanotify_mark(void); } ; linux 2.6.36: 340 AUE_NULL STD { int linux_prlimit64(void); } ; later: 341 AUE_NULL STD { int linux_name_to_handle_at(void); } 342 AUE_NULL STD { int linux_open_by_handle_at(void); } 343 AUE_NULL STD { int linux_clock_adjtime(void); } 344 AUE_NULL STD { int linux_syncfs(void); } 345 AUE_NULL STD { int linux_sendmmsg(void); } 346 AUE_NULL STD { int linux_setns(void); } 347 AUE_NULL STD { int linux_process_vm_readv(void); } 348 AUE_NULL STD { int linux_process_vm_writev(void); } Index: user/dchagin/lemul/sys/compat/linux/linux_misc.h =================================================================== --- user/dchagin/lemul/sys/compat/linux/linux_misc.h (revision 247218) +++ user/dchagin/lemul/sys/compat/linux/linux_misc.h (revision 247219) @@ -1,132 +1,138 @@ /*- * Copyright (c) 2006 Roman Divacky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _LINUX_MISC_H_ #define _LINUX_MISC_H_ /* * Miscellaneous */ #define LINUX_NAME_MAX 255 #define LINUX_MAX_UTSNAME 65 #define LINUX_CTL_MAXNAME 10 /* defines for prctl */ #define LINUX_PR_SET_PDEATHSIG 1 /* Second arg is a signal. */ #define LINUX_PR_GET_PDEATHSIG 2 /* * Second arg is a ptr to return the * signal. */ #define LINUX_PR_GET_KEEPCAPS 7 /* Get drop capabilities on setuid */ #define LINUX_PR_SET_KEEPCAPS 8 /* Set drop capabilities on setuid */ #define LINUX_PR_SET_NAME 15 /* Set process name. */ #define LINUX_PR_GET_NAME 16 /* Get process name. */ #define LINUX_MAX_COMM_LEN 16 /* Maximum length of the process name. */ #define LINUX_MREMAP_MAYMOVE 1 #define LINUX_MREMAP_FIXED 2 extern const char *linux_platform; /* * Non-standard aux entry types used in Linux ELF binaries. */ #define LINUX_AT_PLATFORM 15 /* String identifying CPU */ #define LINUX_AT_HWCAP 16 /* CPU capabilities */ #define LINUX_AT_CLKTCK 17 /* frequency at which times() increments */ #define LINUX_AT_SECURE 23 /* secure mode boolean */ #define LINUX_AT_BASE_PLATFORM 24 /* string identifying real platform, may * differ from AT_PLATFORM. */ #define LINUX_AT_EXECFN 31 /* filename of program */ /* Linux sets the i387 to extended precision. */ #if defined(__i386__) || defined(__amd64__) #define __LINUX_NPXCW__ 0x37f #endif #define LINUX_CLONE_VM 0x00000100 #define LINUX_CLONE_FS 0x00000200 #define LINUX_CLONE_FILES 0x00000400 #define LINUX_CLONE_SIGHAND 0x00000800 #define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */ #define LINUX_CLONE_VFORK 0x00004000 #define LINUX_CLONE_PARENT 0x00008000 #define LINUX_CLONE_THREAD 0x00010000 #define LINUX_CLONE_SETTLS 0x00080000 #define LINUX_CLONE_PARENT_SETTID 0x00100000 #define LINUX_CLONE_CHILD_CLEARTID 0x00200000 #define LINUX_CLONE_CHILD_SETTID 0x01000000 /* Scheduling policies */ #define LINUX_SCHED_OTHER 0 #define LINUX_SCHED_FIFO 1 #define LINUX_SCHED_RR 2 struct l_new_utsname { char sysname[LINUX_MAX_UTSNAME]; char nodename[LINUX_MAX_UTSNAME]; char release[LINUX_MAX_UTSNAME]; char version[LINUX_MAX_UTSNAME]; char machine[LINUX_MAX_UTSNAME]; char domainname[LINUX_MAX_UTSNAME]; }; #define LINUX_CLOCK_REALTIME 0 #define LINUX_CLOCK_MONOTONIC 1 #define LINUX_CLOCK_PROCESS_CPUTIME_ID 2 #define LINUX_CLOCK_THREAD_CPUTIME_ID 3 #define LINUX_CLOCK_REALTIME_HR 4 #define LINUX_CLOCK_MONOTONIC_HR 5 extern int stclohz; #define LINUX_WNOHANG 0x00000001 #define LINUX_WUNTRACED 0x00000002 #define LINUX_WSTOPPED LINUX_WUNTRACED #define LINUX_WEXITED 0x00000004 #define LINUX_WCONTINUED 0x00000008 #define LINUX_WNOWAIT 0x01000000 #define __WNOTHREAD 0x20000000 #define __WALL 0x40000000 #define __WCLONE 0x80000000 +/* Linux waitid idtype */ +#define LINUX_P_ALL 0 +#define LINUX_P_PID 1 +#define LINUX_P_PGID 2 + + int linux_common_wait(struct thread *td, int pid, int *status, int options, struct rusage *ru); void linux_to_bsd_waitopts(int options, int *bsdopts); int linux_set_upcall_kse(struct thread *td, register_t stack); int linux_set_cloned_tls(struct thread *td, void *desc); struct thread *linux_tdfind(struct thread *, lwpid_t, pid_t); #endif /* _LINUX_MISC_H_ */ Index: user/dchagin/lemul/sys/i386/linux/linux_dummy.c =================================================================== --- user/dchagin/lemul/sys/i386/linux/linux_dummy.c (revision 247218) +++ user/dchagin/lemul/sys/i386/linux/linux_dummy.c (revision 247219) @@ -1,167 +1,166 @@ /*- * Copyright (c) 1994-1995 Søren Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_kdtrace.h" #include #include #include #include #include #include #include #include #include /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); DUMMY(stime); DUMMY(fstat); DUMMY(olduname); DUMMY(syslog); DUMMY(uname); DUMMY(vhangup); DUMMY(vm86old); DUMMY(swapoff); DUMMY(adjtimex); DUMMY(create_module); DUMMY(init_module); DUMMY(delete_module); DUMMY(get_kernel_syms); DUMMY(quotactl); DUMMY(bdflush); DUMMY(sysfs); DUMMY(vm86); DUMMY(query_module); DUMMY(nfsservctl); DUMMY(rt_sigqueueinfo); DUMMY(sendfile); /* different semantics */ DUMMY(setfsuid); DUMMY(setfsgid); DUMMY(pivot_root); DUMMY(mincore); DUMMY(lookup_dcookie); DUMMY(epoll_create); DUMMY(epoll_ctl); DUMMY(epoll_wait); DUMMY(remap_file_pages); DUMMY(fstatfs64); DUMMY(mbind); DUMMY(get_mempolicy); DUMMY(set_mempolicy); DUMMY(kexec_load); -DUMMY(waitid); /* linux 2.6.11: */ DUMMY(add_key); DUMMY(request_key); DUMMY(keyctl); /* linux 2.6.13: */ DUMMY(ioprio_set); DUMMY(ioprio_get); DUMMY(inotify_init); DUMMY(inotify_add_watch); DUMMY(inotify_rm_watch); /* linux 2.6.16: */ DUMMY(migrate_pages); DUMMY(pselect6); DUMMY(ppoll); DUMMY(unshare); /* linux 2.6.17: */ DUMMY(splice); DUMMY(sync_file_range); DUMMY(tee); DUMMY(vmsplice); /* linux 2.6.18: */ DUMMY(move_pages); /* linux 2.6.19: */ DUMMY(getcpu); DUMMY(epoll_pwait); /* linux 2.6.22: */ DUMMY(utimensat); DUMMY(signalfd); DUMMY(timerfd_create); DUMMY(eventfd); /* linux 2.6.23: */ DUMMY(fallocate); /* linux 2.6.25: */ DUMMY(timerfd_settime); DUMMY(timerfd_gettime); /* linux 2.6.27: */ DUMMY(signalfd4); DUMMY(eventfd2); DUMMY(epoll_create1); DUMMY(dup3); DUMMY(inotify_init1); /* linux 2.6.30: */ DUMMY(preadv); DUMMY(pwritev); /* linux 2.6.31 */ DUMMY(rt_tsigqueueinfo); DUMMY(perf_event_open); /* linux 2.6.33: */ DUMMY(recvmmsg); DUMMY(fanotify_init); DUMMY(fanotify_mark); /* linux 2.6.36: */ DUMMY(prlimit64); /* later: */ DUMMY(name_to_handle_at); DUMMY(open_by_handle_at); DUMMY(clock_adjtime); DUMMY(syncfs); DUMMY(sendmmsg); DUMMY(setns); DUMMY(process_vm_readv); DUMMY(process_vm_writev); #define DUMMY_XATTR(s) \ int \ linux_ ## s ## xattr( \ struct thread *td, struct linux_ ## s ## xattr_args *arg) \ { \ \ return (ENOATTR); \ } DUMMY_XATTR(set); DUMMY_XATTR(lset); DUMMY_XATTR(fset); DUMMY_XATTR(get); DUMMY_XATTR(lget); DUMMY_XATTR(fget); DUMMY_XATTR(list); DUMMY_XATTR(llist); DUMMY_XATTR(flist); DUMMY_XATTR(remove); DUMMY_XATTR(lremove); DUMMY_XATTR(fremove); Index: user/dchagin/lemul/sys/i386/linux/linux_machdep.c =================================================================== --- user/dchagin/lemul/sys/i386/linux/linux_machdep.c (revision 247218) +++ user/dchagin/lemul/sys/i386/linux/linux_machdep.c (revision 247219) @@ -1,1099 +1,1159 @@ /*- * Copyright (c) 2000 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* needed for pcb definition in linux_set_thread_area */ #include "opt_posix.h" extern struct sysentvec elf32_freebsd_sysvec; /* defined in i386/i386/elf_machdep.c */ struct l_descriptor { l_uint entry_number; l_ulong base_addr; l_uint limit; l_uint seg_32bit:1; l_uint contents:2; l_uint read_exec_only:1; l_uint limit_in_pages:1; l_uint seg_not_present:1; l_uint useable:1; }; struct l_old_select_argv { l_int nfds; l_fd_set *readfds; l_fd_set *writefds; l_fd_set *exceptfds; struct l_timeval *timeout; }; static int linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, l_int flags, l_int fd, l_loff_t pos); int linux_to_bsd_sigaltstack(int lsa) { int bsa = 0; if (lsa & LINUX_SS_DISABLE) bsa |= SS_DISABLE; if (lsa & LINUX_SS_ONSTACK) bsa |= SS_ONSTACK; return (bsa); } int bsd_to_linux_sigaltstack(int bsa) { int lsa = 0; if (bsa & SS_DISABLE) lsa |= LINUX_SS_DISABLE; if (bsa & SS_ONSTACK) lsa |= LINUX_SS_ONSTACK; return (lsa); } int linux_execve(struct thread *td, struct linux_execve_args *args) { int error; char *newpath; struct image_args eargs; LCONVPATHEXIST(td, args->path, &newpath); #ifdef DEBUG if (ldebug(execve)) printf(ARGS(execve, "%s"), newpath); #endif error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE, args->argp, args->envp); free(newpath, M_TEMP); if (error == 0) error = kern_execve(td, &eargs, NULL); return (error); } struct l_ipc_kludge { struct l_msgbuf *msgp; l_long msgtyp; }; int linux_ipc(struct thread *td, struct linux_ipc_args *args) { switch (args->what & 0xFFFF) { case LINUX_SEMOP: { struct linux_semop_args a; a.semid = args->arg1; a.tsops = args->ptr; a.nsops = args->arg2; return (linux_semop(td, &a)); } case LINUX_SEMGET: { struct linux_semget_args a; a.key = args->arg1; a.nsems = args->arg2; a.semflg = args->arg3; return (linux_semget(td, &a)); } case LINUX_SEMCTL: { struct linux_semctl_args a; int error; a.semid = args->arg1; a.semnum = args->arg2; a.cmd = args->arg3; error = copyin(args->ptr, &a.arg, sizeof(a.arg)); if (error) return (error); return (linux_semctl(td, &a)); } case LINUX_MSGSND: { struct linux_msgsnd_args a; a.msqid = args->arg1; a.msgp = args->ptr; a.msgsz = args->arg2; a.msgflg = args->arg3; return (linux_msgsnd(td, &a)); } case LINUX_MSGRCV: { struct linux_msgrcv_args a; a.msqid = args->arg1; a.msgsz = args->arg2; a.msgflg = args->arg3; if ((args->what >> 16) == 0) { struct l_ipc_kludge tmp; int error; if (args->ptr == NULL) return (EINVAL); error = copyin(args->ptr, &tmp, sizeof(tmp)); if (error) return (error); a.msgp = tmp.msgp; a.msgtyp = tmp.msgtyp; } else { a.msgp = args->ptr; a.msgtyp = args->arg5; } return (linux_msgrcv(td, &a)); } case LINUX_MSGGET: { struct linux_msgget_args a; a.key = args->arg1; a.msgflg = args->arg2; return (linux_msgget(td, &a)); } case LINUX_MSGCTL: { struct linux_msgctl_args a; a.msqid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_msgctl(td, &a)); } case LINUX_SHMAT: { struct linux_shmat_args a; a.shmid = args->arg1; a.shmaddr = args->ptr; a.shmflg = args->arg2; a.raddr = (l_ulong *)args->arg3; return (linux_shmat(td, &a)); } case LINUX_SHMDT: { struct linux_shmdt_args a; a.shmaddr = args->ptr; return (linux_shmdt(td, &a)); } case LINUX_SHMGET: { struct linux_shmget_args a; a.key = args->arg1; a.size = args->arg2; a.shmflg = args->arg3; return (linux_shmget(td, &a)); } case LINUX_SHMCTL: { struct linux_shmctl_args a; a.shmid = args->arg1; a.cmd = args->arg2; a.buf = args->ptr; return (linux_shmctl(td, &a)); } default: break; } return (EINVAL); } int linux_old_select(struct thread *td, struct linux_old_select_args *args) { struct l_old_select_argv linux_args; struct linux_select_args newsel; int error; #ifdef DEBUG if (ldebug(old_select)) printf(ARGS(old_select, "%p"), args->ptr); #endif error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); newsel.nfds = linux_args.nfds; newsel.readfds = linux_args.readfds; newsel.writefds = linux_args.writefds; newsel.exceptfds = linux_args.exceptfds; newsel.timeout = linux_args.timeout; return (linux_select(td, &newsel)); } int linux_set_cloned_tls(struct thread *td, void *desc) { struct segment_descriptor sd; struct l_user_desc info; int idx, error; int a[2]; error = copyin(desc, &info, sizeof(struct l_user_desc)); if (error) { printf(LMSG("copyin failed!")); } else { idx = info.entry_number; /* * looks like we're getting the idx we returned * in the set_thread_area() syscall */ if (idx != 6 && idx != 3) { printf(LMSG("resetting idx!")); idx = 3; } /* this doesnt happen in practice */ if (idx == 6) { /* we might copy out the entry_number as 3 */ info.entry_number = 3; error = copyout(&info, desc, sizeof(struct l_user_desc)); if (error) printf(LMSG("copyout failed!")); } a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(clone)) printf("Segment created in clone with " "CLONE_SETTLS: lobase: %x, hibase: %x, " "lolimit: %x, hilimit: %x, type: %i, " "dpl: %i, p: %i, xx: %i, def32: %i, " "gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_def32, sd.sd_gran); #endif /* set %gs */ td->td_pcb->pcb_gsd = sd; td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); } return (error); } int linux_set_upcall_kse(struct thread *td, register_t stack) { if (stack) td->td_frame->tf_esp = stack; /* * The newly created Linux thread returns * to the user space by the same path that a parent do. */ td->td_frame->tf_eax = 0; return (0); } #define STACK_SIZE (2 * 1024 * 1024) #define GUARD_SIZE (4 * PAGE_SIZE) int linux_mmap2(struct thread *td, struct linux_mmap2_args *args) { #ifdef DEBUG if (ldebug(mmap2)) printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"), (void *)args->addr, args->len, args->prot, args->flags, args->fd, args->pgoff); #endif return (linux_mmap_common(td, args->addr, args->len, args->prot, args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * PAGE_SIZE)); } int linux_mmap(struct thread *td, struct linux_mmap_args *args) { int error; struct l_mmap_argv linux_args; error = copyin(args->ptr, &linux_args, sizeof(linux_args)); if (error) return (error); #ifdef DEBUG if (ldebug(mmap)) printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"), (void *)linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pgoff); #endif return (linux_mmap_common(td, linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, (uint32_t)linux_args.pgoff)); } static int linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, l_int flags, l_int fd, l_loff_t pos) { struct proc *p = td->td_proc; struct mmap_args /* { caddr_t addr; size_t len; int prot; int flags; int fd; long pad; off_t pos; } */ bsd_args; int error; struct file *fp; error = 0; bsd_args.flags = 0; fp = NULL; /* * Linux mmap(2): * You must specify exactly one of MAP_SHARED and MAP_PRIVATE */ if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE))) return (EINVAL); if (flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; if (flags & LINUX_MAP_FIXED) bsd_args.flags |= MAP_FIXED; if (flags & LINUX_MAP_ANON) { /* Enforce pos to be on page boundary, then ignore. */ if ((pos & PAGE_MASK) != 0) return (EINVAL); pos = 0; bsd_args.flags |= MAP_ANON; } else bsd_args.flags |= MAP_NOSYNC; if (flags & LINUX_MAP_GROWSDOWN) bsd_args.flags |= MAP_STACK; /* * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC * on Linux/i386. We do this to ensure maximum compatibility. * Linux/ia64 does the same in i386 emulation mode. */ bsd_args.prot = prot; if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) bsd_args.prot |= PROT_READ | PROT_EXEC; /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */ bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd; if (bsd_args.fd != -1) { /* * Linux follows Solaris mmap(2) description: * The file descriptor fildes is opened with * read permission, regardless of the * protection options specified. * * Checking just CAP_MMAP is fine here, since the real work * is done in the FreeBSD mmap(). */ if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) return (error); if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); return (EINVAL); } /* Linux mmap() just fails for O_WRONLY files */ if (!(fp->f_flag & FREAD)) { fdrop(fp, td); return (EACCES); } fdrop(fp, td); } if (flags & LINUX_MAP_GROWSDOWN) { /* * The Linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option * takes as addr the inital BOS, and as len, the initial * region size. It can then grow down from addr without * limit. However, linux threads has an implicit internal * limit to stack size of STACK_SIZE. Its just not * enforced explicitly in linux. But, here we impose * a limit of (STACK_SIZE - GUARD_SIZE) on the stack * region, since we can do this with our mmap. * * Our mmap with MAP_STACK takes addr as the maximum * downsize limit on BOS, and as len the max size of * the region. It them maps the top SGROWSIZ bytes, * and auto grows the region down, up to the limit * in addr. * * If we don't use the MAP_STACK option, the effect * of this code is to allocate a stack region of a * fixed size of (STACK_SIZE - GUARD_SIZE). */ if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) { /* * Some linux apps will attempt to mmap * thread stacks near the top of their * address space. If their TOS is greater * than vm_maxsaddr, vm_map_growstack() * will confuse the thread stack with the * process stack and deliver a SEGV if they * attempt to grow the thread stack past their * current stacksize rlimit. To avoid this, * adjust vm_maxsaddr upwards to reflect * the current stacksize rlimit rather * than the maximum possible stacksize. * It would be better to adjust the * mmap'ed region, but some apps do not check * mmap's return value. */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - lim_cur(p, RLIMIT_STACK); PROC_UNLOCK(p); } /* * This gives us our maximum stack size and a new BOS. * If we're using VM_STACK, then mmap will just map * the top SGROWSIZ bytes, and let the stack grow down * to the limit at BOS. If we're not using VM_STACK * we map the full stack, since we don't have a way * to autogrow it. */ if (len > STACK_SIZE - GUARD_SIZE) { bsd_args.addr = (caddr_t)PTRIN(addr); bsd_args.len = len; } else { bsd_args.addr = (caddr_t)PTRIN(addr) - (STACK_SIZE - GUARD_SIZE - len); bsd_args.len = STACK_SIZE - GUARD_SIZE; } } else { bsd_args.addr = (caddr_t)PTRIN(addr); bsd_args.len = len; } bsd_args.pos = pos; #ifdef DEBUG if (ldebug(mmap)) printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", __func__, (void *)bsd_args.addr, bsd_args.len, bsd_args.prot, bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); #endif error = sys_mmap(td, &bsd_args); #ifdef DEBUG if (ldebug(mmap)) printf("-> %s() return: 0x%x (0x%08x)\n", __func__, error, (u_int)td->td_retval[0]); #endif return (error); } int linux_mprotect(struct thread *td, struct linux_mprotect_args *uap) { struct mprotect_args bsd_args; bsd_args.addr = uap->addr; bsd_args.len = uap->len; bsd_args.prot = uap->prot; if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) bsd_args.prot |= PROT_READ | PROT_EXEC; return (sys_mprotect(td, &bsd_args)); } int linux_ioperm(struct thread *td, struct linux_ioperm_args *args) { int error; struct i386_ioperm_args iia; iia.start = args->start; iia.length = args->length; iia.enable = args->enable; error = i386_set_ioperm(td, &iia); return (error); } int linux_iopl(struct thread *td, struct linux_iopl_args *args) { int error; if (args->level < 0 || args->level > 3) return (EINVAL); if ((error = priv_check(td, PRIV_IO)) != 0) return (error); if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) | (args->level * (PSL_IOPL / 3)); return (0); } int linux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap) { int error; struct i386_ldt_args ldt; struct l_descriptor ld; union descriptor desc; int size, written; switch (uap->func) { case 0x00: /* read_ldt */ ldt.start = 0; ldt.descs = uap->ptr; ldt.num = uap->bytecount / sizeof(union descriptor); error = i386_get_ldt(td, &ldt); td->td_retval[0] *= sizeof(union descriptor); break; case 0x02: /* read_default_ldt = 0 */ size = 5*sizeof(struct l_desc_struct); if (size > uap->bytecount) size = uap->bytecount; for (written = error = 0; written < size && error == 0; written++) error = subyte((char *)uap->ptr + written, 0); td->td_retval[0] = written; break; case 0x01: /* write_ldt */ case 0x11: /* write_ldt */ if (uap->bytecount != sizeof(ld)) return (EINVAL); error = copyin(uap->ptr, &ld, sizeof(ld)); if (error) return (error); ldt.start = ld.entry_number; ldt.descs = &desc; ldt.num = 1; desc.sd.sd_lolimit = (ld.limit & 0x0000ffff); desc.sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; desc.sd.sd_lobase = (ld.base_addr & 0x00ffffff); desc.sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; desc.sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | (ld.contents << 2); desc.sd.sd_dpl = 3; desc.sd.sd_p = (ld.seg_not_present ^ 1); desc.sd.sd_xx = 0; desc.sd.sd_def32 = ld.seg_32bit; desc.sd.sd_gran = ld.limit_in_pages; error = i386_set_ldt(td, &ldt, &desc); break; default: error = ENOSYS; break; } if (error == EOPNOTSUPP) { printf("linux: modify_ldt needs kernel option USER_LDT\n"); error = ENOSYS; } return (error); } int linux_sigaction(struct thread *td, struct linux_sigaction_args *args) { l_osigaction_t osa; l_sigaction_t act, oact; int error; #ifdef DEBUG if (ldebug(sigaction)) printf(ARGS(sigaction, "%d, %p, %p"), args->sig, (void *)args->nsa, (void *)args->osa); #endif if (args->nsa != NULL) { error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); if (error) return (error); act.lsa_handler = osa.lsa_handler; act.lsa_flags = osa.lsa_flags; act.lsa_restorer = osa.lsa_restorer; LINUX_SIGEMPTYSET(act.lsa_mask); act.lsa_mask.__bits[0] = osa.lsa_mask; } error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, args->osa ? &oact : NULL); if (args->osa != NULL && !error) { osa.lsa_handler = oact.lsa_handler; osa.lsa_flags = oact.lsa_flags; osa.lsa_restorer = oact.lsa_restorer; osa.lsa_mask = oact.lsa_mask.__bits[0]; error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); } return (error); } /* * Linux has two extra args, restart and oldmask. We dont use these, * but it seems that "restart" is actually a context pointer that * enables the signal to happen with a different register set. */ int linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) { sigset_t sigmask; l_sigset_t mask; #ifdef DEBUG if (ldebug(sigsuspend)) printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); #endif LINUX_SIGEMPTYSET(mask); mask.__bits[0] = args->mask; linux_to_bsd_sigset(&mask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) { l_sigset_t lmask; sigset_t sigmask; int error; #ifdef DEBUG if (ldebug(rt_sigsuspend)) printf(ARGS(rt_sigsuspend, "%p, %d"), (void *)uap->newset, uap->sigsetsize); #endif if (uap->sigsetsize != sizeof(l_sigset_t)) return (EINVAL); error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); if (error) return (error); linux_to_bsd_sigset(&lmask, &sigmask); return (kern_sigsuspend(td, sigmask)); } int linux_pause(struct thread *td, struct linux_pause_args *args) { struct proc *p = td->td_proc; sigset_t sigmask; #ifdef DEBUG if (ldebug(pause)) printf(ARGS(pause, "")); #endif PROC_LOCK(p); sigmask = td->td_sigmask; PROC_UNLOCK(p); return (kern_sigsuspend(td, sigmask)); } int linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) { stack_t ss, oss; l_stack_t lss; int error; #ifdef DEBUG if (ldebug(sigaltstack)) printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); #endif if (uap->uss != NULL) { error = copyin(uap->uss, &lss, sizeof(l_stack_t)); if (error) return (error); ss.ss_sp = lss.ss_sp; ss.ss_size = lss.ss_size; ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); } error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, (uap->uoss != NULL) ? &oss : NULL); if (!error && uap->uoss != NULL) { lss.ss_sp = oss.ss_sp; lss.ss_size = oss.ss_size; lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); } return (error); } int linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) { struct ftruncate_args sa; #ifdef DEBUG if (ldebug(ftruncate64)) printf(ARGS(ftruncate64, "%u, %jd"), args->fd, (intmax_t)args->length); #endif sa.fd = args->fd; sa.length = args->length; return sys_ftruncate(td, &sa); } int linux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) { struct l_user_desc info; int error; int idx; int a[2]; struct segment_descriptor sd; error = copyin(args->desc, &info, sizeof(struct l_user_desc)); if (error) return (error); #ifdef DEBUG if (ldebug(set_thread_area)) printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, %i, %i, %i\n"), info.entry_number, info.base_addr, info.limit, info.seg_32bit, info.contents, info.read_exec_only, info.limit_in_pages, info.seg_not_present, info.useable); #endif idx = info.entry_number; /* * Semantics of linux version: every thread in the system has array of * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This * syscall loads one of the selected tls decriptors with a value and * also loads GDT descriptors 6, 7 and 8 with the content of the * per-thread descriptors. * * Semantics of fbsd version: I think we can ignore that linux has 3 * per-thread descriptors and use just the 1st one. The tls_array[] * is used only in set/get-thread_area() syscalls and for loading the * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so * we will load just one. * * XXX: this doesn't work when a user space process tries to use more * than 1 TLS segment. Comment in the linux sources says wine might do * this. */ /* * we support just GLIBC TLS now * we should let 3 proceed as well because we use this segment so * if code does two subsequent calls it should succeed */ if (idx != 6 && idx != -1 && idx != 3) return (EINVAL); /* * we have to copy out the GDT entry we use * FreeBSD uses GDT entry #3 for storing %gs so load that * * XXX: what if a user space program doesn't check this value and tries * to use 6, 7 or 8? */ idx = info.entry_number = 3; error = copyout(&info, args->desc, sizeof(struct l_user_desc)); if (error) return (error); if (LINUX_LDT_empty(&info)) { a[0] = 0; a[1] = 0; } else { a[0] = LINUX_LDT_entry_a(&info); a[1] = LINUX_LDT_entry_b(&info); } memcpy(&sd, &a, sizeof(a)); #ifdef DEBUG if (ldebug(set_thread_area)) 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, sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, sd.sd_def32, sd.sd_gran); #endif /* this is taken from i386 version of cpu_set_user_tls() */ critical_enter(); /* set %gs */ td->td_pcb->pcb_gsd = sd; PCPU_GET(fsgs_gdt)[1] = sd; load_gs(GSEL(GUGS_SEL, SEL_UPL)); critical_exit(); return (0); } int linux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args) { struct l_user_desc info; int error; int idx; struct l_desc_struct desc; struct segment_descriptor sd; #ifdef DEBUG if (ldebug(get_thread_area)) printf(ARGS(get_thread_area, "%p"), args->desc); #endif error = copyin(args->desc, &info, sizeof(struct l_user_desc)); if (error) return (error); idx = info.entry_number; /* XXX: I am not sure if we want 3 to be allowed too. */ if (idx != 6 && idx != 3) return (EINVAL); idx = 3; memset(&info, 0, sizeof(info)); sd = PCPU_GET(fsgs_gdt)[1]; memcpy(&desc, &sd, sizeof(desc)); info.entry_number = idx; info.base_addr = LINUX_GET_BASE(&desc); info.limit = LINUX_GET_LIMIT(&desc); info.seg_32bit = LINUX_GET_32BIT(&desc); info.contents = LINUX_GET_CONTENTS(&desc); info.read_exec_only = !LINUX_GET_WRITABLE(&desc); info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); info.seg_not_present = !LINUX_GET_PRESENT(&desc); info.useable = LINUX_GET_USEABLE(&desc); error = copyout(&info, args->desc, sizeof(struct l_user_desc)); if (error) return (EFAULT); return (0); } /* copied from kern/kern_time.c */ int linux_timer_create(struct thread *td, struct linux_timer_create_args *args) { return sys_ktimer_create(td, (struct ktimer_create_args *) args); } int linux_timer_settime(struct thread *td, struct linux_timer_settime_args *args) { return sys_ktimer_settime(td, (struct ktimer_settime_args *) args); } int linux_timer_gettime(struct thread *td, struct linux_timer_gettime_args *args) { return sys_ktimer_gettime(td, (struct ktimer_gettime_args *) args); } int linux_timer_getoverrun(struct thread *td, struct linux_timer_getoverrun_args *args) { return sys_ktimer_getoverrun(td, (struct ktimer_getoverrun_args *) args); } int linux_timer_delete(struct thread *td, struct linux_timer_delete_args *args) { return sys_ktimer_delete(td, (struct ktimer_delete_args *) args); } /* XXX: this wont work with module - convert it */ int linux_mq_open(struct thread *td, struct linux_mq_open_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_open(td, (struct kmq_open_args *) args); #else return (ENOSYS); #endif } int linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_unlink(td, (struct kmq_unlink_args *) args); #else return (ENOSYS); #endif } int linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_timedsend(td, (struct kmq_timedsend_args *) args); #else return (ENOSYS); #endif } int linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *) args); #else return (ENOSYS); #endif } int linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_notify(td, (struct kmq_notify_args *) args); #else return (ENOSYS); #endif } int linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args) { #ifdef P1003_1B_MQUEUE return sys_kmq_setattr(td, (struct kmq_setattr_args *) args); #else return (ENOSYS); #endif } int linux_wait4(struct thread *td, struct linux_wait4_args *args) { int error, options; struct rusage ru, *rup; #ifdef DEBUG if (ldebug(wait4)) printf(ARGS(wait4, "%d, %p, %d, %p"), args->pid, (void *)args->status, args->options, (void *)args->rusage); #endif options = (args->options & (WNOHANG | WUNTRACED)); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) options |= WLINUXCLONE; if (args->rusage != NULL) rup = &ru; else rup = NULL; error = linux_common_wait(td, args->pid, args->status, options, rup); if (error) return (error); if (args->rusage != NULL) error = copyout(&ru, args->rusage, sizeof(ru)); return (error); } + +int +linux_waitid(struct thread *td, struct linux_waitid_args *args) +{ + int status, options, sig; + struct __wrusage wru; + siginfo_t siginfo; + l_siginfo_t lsi; + idtype_t idtype; + int error; + + options = 0; + linux_to_bsd_waitopts(args->options, &options); + + if (options & ~(WNOHANG | WNOWAIT | WEXITED | WUNTRACED | WCONTINUED)) + return (EINVAL); + if (!(options & (WEXITED | WUNTRACED | WCONTINUED))) + return (EINVAL); + + switch (args->idtype) { + case LINUX_P_ALL: + idtype = P_ALL; + break; + case LINUX_P_PID: + if (args->id <= 0) + return (EINVAL); + idtype = P_PID; + break; + case LINUX_P_PGID: + if (args->id <= 0) + return (EINVAL); + idtype = P_PGID; + break; + default: + return (EINVAL); + } + + error = kern_wait6(td, idtype, args->id, &status, options, + &wru, &siginfo); + if (error) + return (error); + td->td_retval[0] = 0; + + if (args->rusage != NULL) { + error = copyout(&wru.wru_children, args->rusage, + sizeof(wru.wru_children)); + if (error) + return (error); + } + + if (args->info != NULL) { + sig = siginfo.si_signo; + if (siginfo.si_signo <= td->td_proc->p_sysent->sv_sigsize) + sig = td->td_proc->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + siginfo_to_lsiginfo(&siginfo, &lsi, sig); + error = copyout(&lsi, args->info, sizeof(lsi)); + } + + return (error); +} Index: user/dchagin/lemul/sys/i386/linux/syscalls.master =================================================================== --- user/dchagin/lemul/sys/i386/linux/syscalls.master (revision 247218) +++ user/dchagin/lemul/sys/i386/linux/syscalls.master (revision 247219) @@ -1,570 +1,571 @@ $FreeBSD$ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 ; System call name/number master file (or rather, slave, from LINUX). ; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h. ; Columns: number audit type nargs name alt{name,tag,rtyp}/comments ; number system call number, must be in order ; audit the audit event associated with the system call ; A value of AUE_NULL means no auditing, but it also means that ; there is no audit event for the call at this time. For the ; case where the event exists, but we don't want auditing, the ; event should be #defined to AUE_NULL in audit_kevents.h. ; type one of STD, OBSOL, UNIMPL ; name psuedo-prototype of syscall routine ; If one of the following alts is different, then all appear: ; altname name of system call if different ; alttag name of args struct tag if different from [o]`name'"_args" ; altrtyp return type if not int (bogus - syscalls always return int) ; for UNIMPL/OBSOL, name continues with comments ; types: ; STD always included ; OBSOL obsolete, not included in system, only specifies name ; UNIMPL not implemented, placeholder only #include #include #include #include #include #include ; Isn't pretty, but there seems to be no other way to trap nosys #define nosys linux_nosys ; #ifdef's, etc. may be included, and are copied to the output files. 0 AUE_NULL UNIMPL setup 1 AUE_EXIT STD { void linux_exit(int rval); } 2 AUE_FORK STD { int linux_fork(void); } 3 AUE_NULL NOPROTO { int read(int fd, char *buf, \ u_int nbyte); } 4 AUE_NULL NOPROTO { int write(int fd, char *buf, \ u_int nbyte); } 5 AUE_OPEN_RWTC STD { int linux_open(char *path, l_int flags, \ l_int mode); } 6 AUE_CLOSE NOPROTO { int close(int fd); } 7 AUE_WAIT4 STD { int linux_waitpid(l_pid_t pid, \ l_int *status, l_int options); } 8 AUE_CREAT STD { int linux_creat(char *path, \ l_int mode); } 9 AUE_LINK STD { int linux_link(char *path, char *to); } 10 AUE_UNLINK STD { int linux_unlink(char *path); } 11 AUE_EXECVE STD { int linux_execve(char *path, char **argp, \ char **envp); } 12 AUE_CHDIR STD { int linux_chdir(char *path); } 13 AUE_NULL STD { int linux_time(l_time_t *tm); } 14 AUE_MKNOD STD { int linux_mknod(char *path, l_int mode, \ l_dev_t dev); } 15 AUE_CHMOD STD { int linux_chmod(char *path, \ l_mode_t mode); } 16 AUE_LCHOWN STD { int linux_lchown16(char *path, \ l_uid16_t uid, l_gid16_t gid); } 17 AUE_NULL UNIMPL break 18 AUE_STAT STD { int linux_stat(char *path, \ struct linux_stat *up); } 19 AUE_LSEEK STD { int linux_lseek(l_uint fdes, l_off_t off, \ l_int whence); } 20 AUE_GETPID STD { int linux_getpid(void); } 21 AUE_MOUNT STD { int linux_mount(char *specialfile, \ char *dir, char *filesystemtype, \ l_ulong rwflag, void *data); } 22 AUE_UMOUNT STD { int linux_oldumount(char *path); } 23 AUE_SETUID STD { int linux_setuid16(l_uid16_t uid); } 24 AUE_GETUID STD { int linux_getuid16(void); } 25 AUE_SETTIMEOFDAY STD { int linux_stime(void); } 26 AUE_PTRACE STD { int linux_ptrace(l_long req, l_long pid, \ l_long addr, l_long data); } 27 AUE_NULL STD { int linux_alarm(l_uint secs); } 28 AUE_FSTAT STD { int linux_fstat(l_uint fd, \ struct linux_stat *up); } 29 AUE_NULL STD { int linux_pause(void); } 30 AUE_UTIME STD { int linux_utime(char *fname, \ struct l_utimbuf *times); } 31 AUE_NULL UNIMPL stty 32 AUE_NULL UNIMPL gtty 33 AUE_ACCESS STD { int linux_access(char *path, l_int amode); } 34 AUE_NICE STD { int linux_nice(l_int inc); } 35 AUE_NULL UNIMPL ftime 36 AUE_SYNC NOPROTO { int sync(void); } 37 AUE_KILL STD { int linux_kill(l_int pid, l_int signum); } 38 AUE_RENAME STD { int linux_rename(char *from, char *to); } 39 AUE_MKDIR STD { int linux_mkdir(char *path, l_int mode); } 40 AUE_RMDIR STD { int linux_rmdir(char *path); } 41 AUE_DUP NOPROTO { int dup(u_int fd); } 42 AUE_PIPE STD { int linux_pipe(l_int *pipefds); } 43 AUE_NULL STD { int linux_times(struct l_times_argv *buf); } 44 AUE_NULL UNIMPL prof 45 AUE_NULL STD { int linux_brk(l_ulong dsend); } 46 AUE_SETGID STD { int linux_setgid16(l_gid16_t gid); } 47 AUE_GETGID STD { int linux_getgid16(void); } 48 AUE_NULL STD { int linux_signal(l_int sig, \ void *handler); } 49 AUE_GETEUID STD { int linux_geteuid16(void); } 50 AUE_GETEGID STD { int linux_getegid16(void); } 51 AUE_ACCT NOPROTO { int acct(char *path); } 52 AUE_UMOUNT STD { int linux_umount(char *path, l_int flags); } 53 AUE_NULL UNIMPL lock 54 AUE_IOCTL STD { int linux_ioctl(l_uint fd, l_uint cmd, \ l_ulong arg); } 55 AUE_FCNTL STD { int linux_fcntl(l_uint fd, l_uint cmd, \ l_ulong arg); } 56 AUE_NULL UNIMPL mpx 57 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); } 58 AUE_NULL UNIMPL ulimit 59 AUE_NULL STD { int linux_olduname(void); } 60 AUE_UMASK NOPROTO { int umask(int newmask); } 61 AUE_CHROOT NOPROTO { int chroot(char *path); } 62 AUE_NULL STD { int linux_ustat(l_dev_t dev, \ struct l_ustat *ubuf); } 63 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); } 64 AUE_GETPPID STD { int linux_getppid(void); } 65 AUE_GETPGRP NOPROTO { int getpgrp(void); } 66 AUE_SETSID NOPROTO { int setsid(void); } 67 AUE_NULL STD { int linux_sigaction(l_int sig, \ l_osigaction_t *nsa, \ l_osigaction_t *osa); } 68 AUE_NULL STD { int linux_sgetmask(void); } 69 AUE_NULL STD { int linux_ssetmask(l_osigset_t mask); } 70 AUE_SETREUID STD { int linux_setreuid16(l_uid16_t ruid, \ l_uid16_t euid); } 71 AUE_SETREGID STD { int linux_setregid16(l_gid16_t rgid, \ l_gid16_t egid); } 72 AUE_NULL STD { int linux_sigsuspend(l_int hist0, \ l_int hist1, l_osigset_t mask); } 73 AUE_NULL STD { int linux_sigpending(l_osigset_t *mask); } 74 AUE_SYSCTL STD { int linux_sethostname(char *hostname, \ u_int len); } 75 AUE_SETRLIMIT STD { int linux_setrlimit(l_uint resource, \ struct l_rlimit *rlim); } 76 AUE_GETRLIMIT STD { int linux_old_getrlimit(l_uint resource, \ struct l_rlimit *rlim); } 77 AUE_GETRUSAGE NOPROTO { int getrusage(int who, \ struct rusage *rusage); } 78 AUE_NULL NOPROTO { int gettimeofday( \ struct timeval *tp, \ struct timezone *tzp); } 79 AUE_SETTIMEOFDAY NOPROTO { int settimeofday( \ struct timeval *tv, \ struct timezone *tzp); } 80 AUE_GETGROUPS STD { int linux_getgroups16(l_uint gidsetsize, \ l_gid16_t *gidset); } 81 AUE_SETGROUPS STD { int linux_setgroups16(l_uint gidsetsize, \ l_gid16_t *gidset); } 82 AUE_SELECT STD { int linux_old_select( \ struct l_old_select_argv *ptr); } 83 AUE_SYMLINK STD { int linux_symlink(char *path, char *to); } ; 84: oldlstat 84 AUE_LSTAT STD { int linux_lstat(char *path, struct l_stat *up); } 85 AUE_READLINK STD { int linux_readlink(char *name, char *buf, \ l_int count); } 86 AUE_USELIB STD { int linux_uselib(char *library); } 87 AUE_SWAPON NOPROTO { int swapon(char *name); } 88 AUE_REBOOT STD { int linux_reboot(l_int magic1, \ l_int magic2, l_uint cmd, void *arg); } ; 89: old_readdir 89 AUE_GETDIRENTRIES STD { int linux_readdir(l_uint fd, \ struct l_dirent *dent, l_uint count); } ; 90: old_mmap 90 AUE_MMAP STD { int linux_mmap(struct l_mmap_argv *ptr); } 91 AUE_MUNMAP NOPROTO { int munmap(caddr_t addr, int len); } 92 AUE_TRUNCATE STD { int linux_truncate(char *path, \ l_ulong length); } 93 AUE_FTRUNCATE STD { int linux_ftruncate(int fd, long length); } 94 AUE_FCHMOD NOPROTO { int fchmod(int fd, int mode); } 95 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); } 96 AUE_GETPRIORITY STD { int linux_getpriority(int which, int who); } 97 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \ int prio); } 98 AUE_PROFILE UNIMPL profil 99 AUE_STATFS STD { int linux_statfs(char *path, \ struct l_statfs_buf *buf); } 100 AUE_FSTATFS STD { int linux_fstatfs(l_uint fd, \ struct l_statfs_buf *buf); } 101 AUE_NULL STD { int linux_ioperm(l_ulong start, \ l_ulong length, l_int enable); } 102 AUE_NULL STD { int linux_socketcall(l_int what, \ l_ulong args); } 103 AUE_NULL STD { int linux_syslog(l_int type, char *buf, \ l_int len); } 104 AUE_SETITIMER STD { int linux_setitimer(l_int which, \ struct l_itimerval *itv, \ struct l_itimerval *oitv); } 105 AUE_GETITIMER STD { int linux_getitimer(l_int which, \ struct l_itimerval *itv); } 106 AUE_STAT STD { int linux_newstat(char *path, \ struct l_newstat *buf); } 107 AUE_LSTAT STD { int linux_newlstat(char *path, \ struct l_newstat *buf); } 108 AUE_FSTAT STD { int linux_newfstat(l_uint fd, \ struct l_newstat *buf); } ; 109: olduname 109 AUE_NULL STD { int linux_uname(void); } 110 AUE_NULL STD { int linux_iopl(l_int level); } 111 AUE_NULL STD { int linux_vhangup(void); } 112 AUE_NULL UNIMPL idle 113 AUE_NULL STD { int linux_vm86old(void); } 114 AUE_WAIT4 STD { int linux_wait4(l_pid_t pid, \ l_uint *status, l_int options, \ struct l_rusage *rusage); } 115 AUE_SWAPOFF STD { int linux_swapoff(void); } 116 AUE_NULL STD { int linux_sysinfo(struct l_sysinfo *info); } 117 AUE_NULL STD { int linux_ipc(l_uint what, l_int arg1, \ l_int arg2, l_int arg3, void *ptr, \ l_long arg5); } 118 AUE_FSYNC NOPROTO { int fsync(int fd); } 119 AUE_SIGRETURN STD { int linux_sigreturn( \ struct l_sigframe *sfp); } 120 AUE_RFORK STD { int linux_clone(l_int flags, void *stack, \ void *parent_tidptr, void *tls, void * child_tidptr); } 121 AUE_SYSCTL STD { int linux_setdomainname(char *name, \ int len); } 122 AUE_NULL STD { int linux_newuname( \ struct l_new_utsname *buf); } 123 AUE_NULL STD { int linux_modify_ldt(l_int func, \ void *ptr, l_ulong bytecount); } 124 AUE_ADJTIME STD { int linux_adjtimex(void); } 125 AUE_MPROTECT STD { int linux_mprotect(caddr_t addr, int len, \ int prot); } 126 AUE_SIGPROCMASK STD { int linux_sigprocmask(l_int how, \ l_osigset_t *mask, l_osigset_t *omask); } 127 AUE_NULL STD { int linux_create_module(void); } 128 AUE_NULL STD { int linux_init_module(void); } 129 AUE_NULL STD { int linux_delete_module(void); } 130 AUE_NULL STD { int linux_get_kernel_syms(void); } 131 AUE_QUOTACTL STD { int linux_quotactl(void); } 132 AUE_GETPGID NOPROTO { int getpgid(int pid); } 133 AUE_FCHDIR NOPROTO { int fchdir(int fd); } 134 AUE_BDFLUSH STD { int linux_bdflush(void); } 135 AUE_NULL STD { int linux_sysfs(l_int option, \ l_ulong arg1, l_ulong arg2); } 136 AUE_PERSONALITY STD { int linux_personality(l_ulong per); } 137 AUE_NULL UNIMPL afs_syscall 138 AUE_SETFSUID STD { int linux_setfsuid16(l_uid16_t uid); } 139 AUE_SETFSGID STD { int linux_setfsgid16(l_gid16_t gid); } 140 AUE_LSEEK STD { int linux_llseek(l_int fd, l_ulong ohigh, \ l_ulong olow, l_loff_t *res, \ l_uint whence); } 141 AUE_GETDIRENTRIES STD { int linux_getdents(l_uint fd, \ void *dent, l_uint count); } ; 142: newselect 142 AUE_SELECT STD { int linux_select(l_int nfds, \ l_fd_set *readfds, l_fd_set *writefds, \ l_fd_set *exceptfds, \ struct l_timeval *timeout); } 143 AUE_FLOCK NOPROTO { int flock(int fd, int how); } 144 AUE_MSYNC STD { int linux_msync(l_ulong addr, \ l_size_t len, l_int fl); } 145 AUE_READV NOPROTO { int readv(int fd, struct iovec *iovp, \ u_int iovcnt); } 146 AUE_WRITEV NOPROTO { int writev(int fd, struct iovec *iovp, \ u_int iovcnt); } 147 AUE_GETSID STD { int linux_getsid(l_pid_t pid); } 148 AUE_NULL STD { int linux_fdatasync(l_uint fd); } 149 AUE_SYSCTL STD { int linux_sysctl( \ struct l___sysctl_args *args); } 150 AUE_MLOCK NOPROTO { int mlock(const void *addr, size_t len); } 151 AUE_MUNLOCK NOPROTO { int munlock(const void *addr, size_t len); } 152 AUE_MLOCKALL NOPROTO { int mlockall(int how); } 153 AUE_MUNLOCKALL NOPROTO { int munlockall(void); } 154 AUE_SCHED_SETPARAM STD { int linux_sched_setparam(l_pid_t pid, \ struct l_sched_param *param); } 155 AUE_SCHED_GETPARAM STD { int linux_sched_getparam(l_pid_t pid, \ struct l_sched_param *param); } 156 AUE_SCHED_SETSCHEDULER STD { int linux_sched_setscheduler( \ l_pid_t pid, l_int policy, \ struct l_sched_param *param); } 157 AUE_SCHED_GETSCHEDULER STD { int linux_sched_getscheduler( \ l_pid_t pid); } 158 AUE_NULL NOPROTO { int sched_yield(void); } 159 AUE_SCHED_GET_PRIORITY_MAX STD { int linux_sched_get_priority_max( \ l_int policy); } 160 AUE_SCHED_GET_PRIORITY_MIN STD { int linux_sched_get_priority_min( \ l_int policy); } 161 AUE_SCHED_RR_GET_INTERVAL STD { int linux_sched_rr_get_interval( \ l_pid_t pid, struct l_timespec *interval); } 162 AUE_NULL STD { int linux_nanosleep( \ const struct l_timespec *rqtp, \ struct l_timespec *rmtp); } 163 AUE_NULL STD { int linux_mremap(l_ulong addr, \ l_ulong old_len, l_ulong new_len, \ l_ulong flags, l_ulong new_addr); } 164 AUE_SETRESUID STD { int linux_setresuid16(l_uid16_t ruid, \ l_uid16_t euid, l_uid16_t suid); } 165 AUE_GETRESUID STD { int linux_getresuid16(l_uid16_t *ruid, \ l_uid16_t *euid, l_uid16_t *suid); } 166 AUE_NULL STD { int linux_vm86(void); } 167 AUE_NULL STD { int linux_query_module(void); } 168 AUE_POLL NOPROTO { int poll(struct pollfd* fds, \ unsigned int nfds, long timeout); } 169 AUE_NULL STD { int linux_nfsservctl(void); } 170 AUE_SETRESGID STD { int linux_setresgid16(l_gid16_t rgid, \ l_gid16_t egid, l_gid16_t sgid); } 171 AUE_GETRESGID STD { int linux_getresgid16(l_gid16_t *rgid, \ l_gid16_t *egid, l_gid16_t *sgid); } 172 AUE_PRCTL STD { int linux_prctl(l_int option, l_int arg2, l_int arg3, \ l_int arg4, l_int arg5); } 173 AUE_NULL STD { int linux_rt_sigreturn( \ struct l_ucontext *ucp); } 174 AUE_NULL STD { int linux_rt_sigaction(l_int sig, \ l_sigaction_t *act, l_sigaction_t *oact, \ l_size_t sigsetsize); } 175 AUE_NULL STD { int linux_rt_sigprocmask(l_int how, \ l_sigset_t *mask, l_sigset_t *omask, \ l_size_t sigsetsize); } 176 AUE_NULL STD { int linux_rt_sigpending(l_sigset_t *set, \ l_size_t sigsetsize); } 177 AUE_NULL STD { int linux_rt_sigtimedwait(l_sigset_t *mask, \ l_siginfo_t *ptr, \ struct l_timeval *timeout, \ l_size_t sigsetsize); } 178 AUE_NULL STD { int linux_rt_sigqueueinfo(void); } 179 AUE_NULL STD { int linux_rt_sigsuspend( \ l_sigset_t *newset, \ l_size_t sigsetsize); } 180 AUE_PREAD STD { int linux_pread(l_uint fd, char *buf, \ l_size_t nbyte, l_loff_t offset); } 181 AUE_PWRITE STD { int linux_pwrite(l_uint fd, char *buf, \ l_size_t nbyte, l_loff_t offset); } 182 AUE_CHOWN STD { int linux_chown16(char *path, \ l_uid16_t uid, l_gid16_t gid); } 183 AUE_GETCWD STD { int linux_getcwd(char *buf, \ l_ulong bufsize); } 184 AUE_CAPGET STD { int linux_capget(struct l_user_cap_header *hdrp, \ struct l_user_cap_data *datap); } 185 AUE_CAPSET STD { int linux_capset(struct l_user_cap_header *hdrp, \ struct l_user_cap_data *datap); } 186 AUE_NULL STD { int linux_sigaltstack(l_stack_t *uss, \ l_stack_t *uoss); } 187 AUE_SENDFILE STD { int linux_sendfile(void); } 188 AUE_GETPMSG UNIMPL getpmsg 189 AUE_PUTPMSG UNIMPL putpmsg 190 AUE_VFORK STD { int linux_vfork(void); } ; 191: ugetrlimit 191 AUE_GETRLIMIT STD { int linux_getrlimit(l_uint resource, \ struct l_rlimit *rlim); } 192 AUE_MMAP STD { int linux_mmap2(l_ulong addr, l_ulong len, \ l_ulong prot, l_ulong flags, l_ulong fd, \ l_ulong pgoff); } 193 AUE_TRUNCATE STD { int linux_truncate64(char *path, \ l_loff_t length); } 194 AUE_FTRUNCATE STD { int linux_ftruncate64(l_uint fd, \ l_loff_t length); } 195 AUE_STAT STD { int linux_stat64(const char *filename, \ struct l_stat64 *statbuf); } 196 AUE_LSTAT STD { int linux_lstat64(const char *filename, \ struct l_stat64 *statbuf); } 197 AUE_FSTAT STD { int linux_fstat64(l_int fd, \ struct l_stat64 *statbuf); } 198 AUE_LCHOWN STD { int linux_lchown(char *path, l_uid_t uid, \ l_gid_t gid); } 199 AUE_GETUID STD { int linux_getuid(void); } 200 AUE_GETGID STD { int linux_getgid(void); } 201 AUE_GETEUID NOPROTO { int geteuid(void); } 202 AUE_GETEGID NOPROTO { int getegid(void); } 203 AUE_SETREUID NOPROTO { int setreuid(uid_t ruid, uid_t euid); } 204 AUE_SETREGID NOPROTO { int setregid(gid_t rgid, gid_t egid); } 205 AUE_GETGROUPS STD { int linux_getgroups(l_int gidsetsize, \ l_gid_t *grouplist); } 206 AUE_SETGROUPS STD { int linux_setgroups(l_int gidsetsize, \ l_gid_t *grouplist); } 207 AUE_FCHOWN NODEF fchown fchown fchown_args int 208 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \ uid_t suid); } 209 AUE_GETRESUID NOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \ uid_t *suid); } 210 AUE_SETRESGID NOPROTO { int setresgid(gid_t rgid, gid_t egid, \ gid_t sgid); } 211 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \ gid_t *sgid); } 212 AUE_CHOWN STD { int linux_chown(char *path, l_uid_t uid, \ l_gid_t gid); } 213 AUE_SETUID NOPROTO { int setuid(uid_t uid); } 214 AUE_SETGID NOPROTO { int setgid(gid_t gid); } 215 AUE_SETFSUID STD { int linux_setfsuid(l_uid_t uid); } 216 AUE_SETFSGID STD { int linux_setfsgid(l_gid_t gid); } 217 AUE_PIVOT_ROOT STD { int linux_pivot_root(char *new_root, \ char *put_old); } 218 AUE_MINCORE STD { int linux_mincore(l_ulong start, \ l_size_t len, u_char *vec); } 219 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \ int behav); } 220 AUE_GETDIRENTRIES STD { int linux_getdents64(l_uint fd, \ void *dirent, l_uint count); } 221 AUE_FCNTL STD { int linux_fcntl64(l_uint fd, l_uint cmd, \ l_ulong arg); } 222 AUE_NULL UNIMPL 223 AUE_NULL UNIMPL 224 AUE_NULL STD { long linux_gettid(void); } 225 AUE_NULL UNIMPL linux_readahead 226 AUE_NULL STD { int linux_setxattr(void); } 227 AUE_NULL STD { int linux_lsetxattr(void); } 228 AUE_NULL STD { int linux_fsetxattr(void); } 229 AUE_NULL STD { int linux_getxattr(void); } 230 AUE_NULL STD { int linux_lgetxattr(void); } 231 AUE_NULL STD { int linux_fgetxattr(void); } 232 AUE_NULL STD { int linux_listxattr(void); } 233 AUE_NULL STD { int linux_llistxattr(void); } 234 AUE_NULL STD { int linux_flistxattr(void); } 235 AUE_NULL STD { int linux_removexattr(void); } 236 AUE_NULL STD { int linux_lremovexattr(void); } 237 AUE_NULL STD { int linux_fremovexattr(void); } 238 AUE_NULL STD { int linux_tkill(int tid, int sig); } 239 AUE_SENDFILE UNIMPL linux_sendfile64 240 AUE_NULL STD { int linux_sys_futex(void *uaddr, int op, uint32_t val, \ struct l_timespec *timeout, uint32_t *uaddr2, uint32_t val3); } 241 AUE_NULL STD { int linux_sched_setaffinity(l_pid_t pid, l_uint len, \ l_ulong *user_mask_ptr); } 242 AUE_NULL STD { int linux_sched_getaffinity(l_pid_t pid, l_uint len, \ l_ulong *user_mask_ptr); } 243 AUE_NULL STD { int linux_set_thread_area(struct l_user_desc *desc); } 244 AUE_NULL STD { int linux_get_thread_area(struct l_user_desc *desc); } 245 AUE_NULL UNIMPL linux_io_setup 246 AUE_NULL UNIMPL linux_io_destroy 247 AUE_NULL UNIMPL linux_io_getevents 248 AUE_NULL UNIMPL linux_io_submit 249 AUE_NULL UNIMPL linux_io_cancel 250 AUE_NULL STD { int linux_fadvise64(int fd, l_loff_t offset, \ l_size_t len, int advice); } 251 AUE_NULL UNIMPL 252 AUE_EXIT STD { int linux_exit_group(int error_code); } 253 AUE_NULL STD { int linux_lookup_dcookie(void); } 254 AUE_NULL STD { int linux_epoll_create(void); } 255 AUE_NULL STD { int linux_epoll_ctl(void); } 256 AUE_NULL STD { int linux_epoll_wait(void); } 257 AUE_NULL STD { int linux_remap_file_pages(void); } 258 AUE_NULL STD { int linux_set_tid_address(int *tidptr); } 259 AUE_NULL STD { int linux_timer_create(clockid_t clock_id, \ struct sigevent *evp, l_timer_t *timerid); } 260 AUE_NULL STD { int linux_timer_settime(l_timer_t timerid, \ const struct itimerspec *new, struct itimerspec *old); } 261 AUE_NULL STD { int linux_timer_gettime(l_timer_t timerid, struct itimerspec *setting); } 262 AUE_NULL STD { int linux_timer_getoverrun(l_timer_t timerid); } 263 AUE_NULL STD { int linux_timer_delete(l_timer_t timerid); } 264 AUE_CLOCK_SETTIME STD { int linux_clock_settime(clockid_t which, struct l_timespec *tp); } 265 AUE_NULL STD { int linux_clock_gettime(clockid_t which, struct l_timespec *tp); } 266 AUE_NULL STD { int linux_clock_getres(clockid_t which, struct l_timespec *tp); } 267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \ struct l_timespec *rqtp, struct l_timespec *rmtp); } 268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); } 269 AUE_FSTATFS STD { int linux_fstatfs64(void); } 270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); } 271 AUE_UTIMES STD { int linux_utimes(char *fname, \ struct l_timeval *tptr); } 272 AUE_NULL STD { int linux_fadvise64_64(int fd, \ l_loff_t offset, l_loff_t len, \ int advice); } 273 AUE_NULL UNIMPL vserver 274 AUE_NULL STD { int linux_mbind(void); } 275 AUE_NULL STD { int linux_get_mempolicy(void); } 276 AUE_NULL STD { int linux_set_mempolicy(void); } ; linux 2.6.6: 277 AUE_NULL STD { int linux_mq_open(const char *name, int oflag, mode_t mode, \ struct mq_attr *attr); } 278 AUE_NULL STD { int linux_mq_unlink(const char *name); } 279 AUE_NULL STD { int linux_mq_timedsend(l_mqd_t mqd, const char *msg_ptr, \ size_t msg_len, unsigned int msg_prio, const struct \ l_timespec *abs_timeout); } 280 AUE_NULL STD { int linux_mq_timedreceive(l_mqd_t mqd, char *msg_ptr, \ size_t msg_len, unsigned int msg_prio, const struct \ l_timespec *abs_timeout); } 281 AUE_NULL STD { int linux_mq_notify(l_mqd_t mqd, const struct l_timespec *abs_timeout); } 282 AUE_NULL STD { int linux_mq_getsetattr(l_mqd_t mqd, const struct mq_attr *attr, \ struct mq_attr *oattr); } 283 AUE_NULL STD { int linux_kexec_load(void); } -284 AUE_NULL STD { int linux_waitid(void); } +284 AUE_WAIT6 STD { int linux_waitid(int idtype, l_pid_t id, l_siginfo_t *info, \ + int options, struct l_rusage *rusage); } 285 AUE_NULL UNIMPL ; linux 2.6.11: 286 AUE_NULL STD { int linux_add_key(void); } 287 AUE_NULL STD { int linux_request_key(void); } 288 AUE_NULL STD { int linux_keyctl(void); } ; linux 2.6.13: 289 AUE_NULL STD { int linux_ioprio_set(void); } 290 AUE_NULL STD { int linux_ioprio_get(void); } 291 AUE_NULL STD { int linux_inotify_init(void); } 292 AUE_NULL STD { int linux_inotify_add_watch(void); } 293 AUE_NULL STD { int linux_inotify_rm_watch(void); } ; linux 2.6.16: 294 AUE_NULL STD { int linux_migrate_pages(void); } 295 AUE_OPEN_RWTC STD { int linux_openat(l_int dfd, const char *filename, \ l_int flags, l_int mode); } 296 AUE_MKDIRAT STD { int linux_mkdirat(l_int dfd, const char *pathname, \ l_int mode); } 297 AUE_MKNODAT STD { int linux_mknodat(l_int dfd, const char *filename, \ l_int mode, l_uint dev); } 298 AUE_FCHOWNAT STD { int linux_fchownat(l_int dfd, const char *filename, \ l_uid16_t uid, l_gid16_t gid, l_int flag); } 299 AUE_FUTIMESAT STD { int linux_futimesat(l_int dfd, char *filename, \ struct l_timeval *utimes); } 300 AUE_FSTATAT STD { int linux_fstatat64(l_int dfd, char *pathname, \ struct l_stat64 *statbuf, l_int flag); } 301 AUE_UNLINKAT STD { int linux_unlinkat(l_int dfd, const char *pathname, \ l_int flag); } 302 AUE_RENAMEAT STD { int linux_renameat(l_int olddfd, const char *oldname, \ l_int newdfd, const char *newname); } 303 AUE_LINKAT STD { int linux_linkat(l_int olddfd, const char *oldname, \ l_int newdfd, const char *newname, l_int flag); } 304 AUE_SYMLINKAT STD { int linux_symlinkat(const char *oldname, l_int newdfd, \ const char *newname); } 305 AUE_READLINKAT STD { int linux_readlinkat(l_int dfd, const char *path, \ char *buf, l_int bufsiz); } 306 AUE_FCHMODAT STD { int linux_fchmodat(l_int dfd, const char *filename, \ l_mode_t mode); } 307 AUE_FACCESSAT STD { int linux_faccessat(l_int dfd, const char *filename, l_int amode, l_int flag); } 308 AUE_NULL STD { int linux_pselect6(void); } 309 AUE_NULL STD { int linux_ppoll(void); } 310 AUE_NULL STD { int linux_unshare(void); } ; linux 2.6.17: 311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \ l_size_t len); } 312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head **head, \ l_size_t *len); } 313 AUE_NULL STD { int linux_splice(void); } 314 AUE_NULL STD { int linux_sync_file_range(void); } 315 AUE_NULL STD { int linux_tee(void); } 316 AUE_NULL STD { int linux_vmsplice(void); } ; linux 2.6.18: 317 AUE_NULL STD { int linux_move_pages(void); } ; linux 2.6.19: 318 AUE_NULL STD { int linux_getcpu(void); } 319 AUE_NULL STD { int linux_epoll_pwait(void); } ; linux 2.6.22: 320 AUE_NULL STD { int linux_utimensat(void); } 321 AUE_NULL STD { int linux_signalfd(void); } 322 AUE_NULL STD { int linux_timerfd_create(void); } 323 AUE_NULL STD { int linux_eventfd(void); } ; linux 2.6.23: 324 AUE_NULL STD { int linux_fallocate(void); } ; linux 2.6.25: 325 AUE_NULL STD { int linux_timerfd_settime(void); } 326 AUE_NULL STD { int linux_timerfd_gettime(void); } ; linux 2.6.27: 327 AUE_NULL STD { int linux_signalfd4(void); } 328 AUE_NULL STD { int linux_eventfd2(void); } 329 AUE_NULL STD { int linux_epoll_create1(void); } 330 AUE_NULL STD { int linux_dup3(void); } 331 AUE_NULL STD { int linux_pipe2(l_int *pipefds, l_int flags); } 332 AUE_NULL STD { int linux_inotify_init1(void); } ; linux 2.6.30: 333 AUE_NULL STD { int linux_preadv(void); } 334 AUE_NULL STD { int linux_pwritev(void); } ; linux 2.6.31: 335 AUE_NULL STD { int linux_rt_tsigqueueinfo(void); } 336 AUE_NULL STD { int linux_perf_event_open(void); } ; linux 2.6.33: 337 AUE_NULL STD { int linux_recvmmsg(void); } 338 AUE_NULL STD { int linux_fanotify_init(void); } 339 AUE_NULL STD { int linux_fanotify_mark(void); } ; linux 2.6.36: 340 AUE_NULL STD { int linux_prlimit64(void); } ; later: 341 AUE_NULL STD { int linux_name_to_handle_at(void); } 342 AUE_NULL STD { int linux_open_by_handle_at(void); } 343 AUE_NULL STD { int linux_clock_adjtime(void); } 344 AUE_NULL STD { int linux_syncfs(void); } 345 AUE_NULL STD { int linux_sendmmsg(void); } 346 AUE_NULL STD { int linux_setns(void); } 347 AUE_NULL STD { int linux_process_vm_readv(void); } 348 AUE_NULL STD { int linux_process_vm_writev(void); }