linux32_machdep.c revision 224778
1133819Stjr/*- 2133819Stjr * Copyright (c) 2004 Tim J. Robbins 3133819Stjr * Copyright (c) 2002 Doug Rabson 4133819Stjr * Copyright (c) 2000 Marcel Moolenaar 5133819Stjr * All rights reserved. 6133819Stjr * 7133819Stjr * Redistribution and use in source and binary forms, with or without 8133819Stjr * modification, are permitted provided that the following conditions 9133819Stjr * are met: 10133819Stjr * 1. Redistributions of source code must retain the above copyright 11133819Stjr * notice, this list of conditions and the following disclaimer 12133819Stjr * in this position and unchanged. 13133819Stjr * 2. Redistributions in binary form must reproduce the above copyright 14133819Stjr * notice, this list of conditions and the following disclaimer in the 15133819Stjr * documentation and/or other materials provided with the distribution. 16133819Stjr * 3. The name of the author may not be used to endorse or promote products 17133819Stjr * derived from this software without specific prior written permission. 18133819Stjr * 19133819Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20133819Stjr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21133819Stjr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22133819Stjr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23133819Stjr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24133819Stjr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25133819Stjr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26133819Stjr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27133819Stjr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28133819Stjr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29133819Stjr */ 30133819Stjr 31133819Stjr#include <sys/cdefs.h> 32133819Stjr__FBSDID("$FreeBSD: head/sys/amd64/linux32/linux32_machdep.c 224778 2011-08-11 12:30:23Z rwatson $"); 33133819Stjr 34133819Stjr#include <sys/param.h> 35133819Stjr#include <sys/kernel.h> 36133819Stjr#include <sys/systm.h> 37224778Srwatson#include <sys/capability.h> 38165832Snetchild#include <sys/file.h> 39165832Snetchild#include <sys/fcntl.h> 40162954Sphk#include <sys/clock.h> 41142057Sjhb#include <sys/imgact.h> 42161310Snetchild#include <sys/limits.h> 43133819Stjr#include <sys/lock.h> 44133819Stjr#include <sys/malloc.h> 45133819Stjr#include <sys/mman.h> 46133819Stjr#include <sys/mutex.h> 47166729Sjkim#include <sys/priv.h> 48133819Stjr#include <sys/proc.h> 49133819Stjr#include <sys/resource.h> 50133819Stjr#include <sys/resourcevar.h> 51166188Sjeff#include <sys/sched.h> 52133819Stjr#include <sys/syscallsubr.h> 53133819Stjr#include <sys/sysproto.h> 54133819Stjr#include <sys/unistd.h> 55218030Sdchagin#include <sys/wait.h> 56133819Stjr 57133819Stjr#include <machine/frame.h> 58168035Sjkim#include <machine/pcb.h> 59166729Sjkim#include <machine/psl.h> 60168035Sjkim#include <machine/segments.h> 61168035Sjkim#include <machine/specialreg.h> 62133819Stjr 63133819Stjr#include <vm/vm.h> 64133819Stjr#include <vm/pmap.h> 65133819Stjr#include <vm/vm_map.h> 66133819Stjr 67210431Skib#include <compat/freebsd32/freebsd32_util.h> 68133819Stjr#include <amd64/linux32/linux.h> 69133819Stjr#include <amd64/linux32/linux32_proto.h> 70133819Stjr#include <compat/linux/linux_ipc.h> 71218030Sdchagin#include <compat/linux/linux_misc.h> 72133819Stjr#include <compat/linux/linux_signal.h> 73133819Stjr#include <compat/linux/linux_util.h> 74161474Snetchild#include <compat/linux/linux_emul.h> 75133819Stjr 76133819Stjrstruct l_old_select_argv { 77133819Stjr l_int nfds; 78133819Stjr l_uintptr_t readfds; 79133819Stjr l_uintptr_t writefds; 80133819Stjr l_uintptr_t exceptfds; 81133819Stjr l_uintptr_t timeout; 82133819Stjr} __packed; 83133819Stjr 84133819Stjrint 85133819Stjrlinux_to_bsd_sigaltstack(int lsa) 86133819Stjr{ 87133819Stjr int bsa = 0; 88133819Stjr 89133819Stjr if (lsa & LINUX_SS_DISABLE) 90133819Stjr bsa |= SS_DISABLE; 91133819Stjr if (lsa & LINUX_SS_ONSTACK) 92133819Stjr bsa |= SS_ONSTACK; 93133819Stjr return (bsa); 94133819Stjr} 95133819Stjr 96198554Sjhbstatic int linux_mmap_common(struct thread *td, l_uintptr_t addr, 97198554Sjhb l_size_t len, l_int prot, l_int flags, l_int fd, 98198554Sjhb l_loff_t pos); 99198554Sjhb 100133819Stjrint 101133819Stjrbsd_to_linux_sigaltstack(int bsa) 102133819Stjr{ 103133819Stjr int lsa = 0; 104133819Stjr 105133819Stjr if (bsa & SS_DISABLE) 106133819Stjr lsa |= LINUX_SS_DISABLE; 107133819Stjr if (bsa & SS_ONSTACK) 108133819Stjr lsa |= LINUX_SS_ONSTACK; 109133819Stjr return (lsa); 110133819Stjr} 111133819Stjr 112218059Sdchaginstatic void 113218059Sdchaginbsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru) 114218028Sdchagin{ 115218059Sdchagin 116218028Sdchagin lru->ru_utime.tv_sec = ru->ru_utime.tv_sec; 117218028Sdchagin lru->ru_utime.tv_usec = ru->ru_utime.tv_usec; 118218028Sdchagin lru->ru_stime.tv_sec = ru->ru_stime.tv_sec; 119218028Sdchagin lru->ru_stime.tv_usec = ru->ru_stime.tv_usec; 120218028Sdchagin lru->ru_maxrss = ru->ru_maxrss; 121218028Sdchagin lru->ru_ixrss = ru->ru_ixrss; 122218028Sdchagin lru->ru_idrss = ru->ru_idrss; 123218028Sdchagin lru->ru_isrss = ru->ru_isrss; 124218028Sdchagin lru->ru_minflt = ru->ru_minflt; 125218028Sdchagin lru->ru_majflt = ru->ru_majflt; 126218028Sdchagin lru->ru_nswap = ru->ru_nswap; 127218028Sdchagin lru->ru_inblock = ru->ru_inblock; 128218028Sdchagin lru->ru_oublock = ru->ru_oublock; 129218028Sdchagin lru->ru_msgsnd = ru->ru_msgsnd; 130218028Sdchagin lru->ru_msgrcv = ru->ru_msgrcv; 131218028Sdchagin lru->ru_nsignals = ru->ru_nsignals; 132218028Sdchagin lru->ru_nvcsw = ru->ru_nvcsw; 133218028Sdchagin lru->ru_nivcsw = ru->ru_nivcsw; 134218028Sdchagin} 135218028Sdchagin 136142057Sjhbint 137142057Sjhblinux_execve(struct thread *td, struct linux_execve_args *args) 138142057Sjhb{ 139142057Sjhb struct image_args eargs; 140142057Sjhb char *path; 141142057Sjhb int error; 142142057Sjhb 143142057Sjhb LCONVPATHEXIST(td, args->path, &path); 144142057Sjhb 145142057Sjhb#ifdef DEBUG 146142057Sjhb if (ldebug(execve)) 147142057Sjhb printf(ARGS(execve, "%s"), path); 148142057Sjhb#endif 149142057Sjhb 150210431Skib error = freebsd32_exec_copyin_args(&eargs, path, UIO_SYSSPACE, 151210431Skib args->argp, args->envp); 152142057Sjhb free(path, M_TEMP); 153142057Sjhb if (error == 0) 154142057Sjhb error = kern_execve(td, &eargs, NULL); 155161474Snetchild if (error == 0) 156168063Sjkim /* Linux process can execute FreeBSD one, do not attempt 157161474Snetchild * to create emuldata for such process using 158161474Snetchild * linux_proc_init, this leads to a panic on KASSERT 159168063Sjkim * because such process has p->p_emuldata == NULL. 160161474Snetchild */ 161217896Sdchagin if (SV_PROC_ABI(td->td_proc) == SV_ABI_LINUX) 162168063Sjkim error = linux_proc_init(td, 0, 0); 163142057Sjhb return (error); 164142057Sjhb} 165142057Sjhb 166185438SkibCTASSERT(sizeof(struct l_iovec32) == 8); 167133819Stjr 168144449Sjhbstatic int 169185438Skiblinux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop) 170133819Stjr{ 171185438Skib struct l_iovec32 iov32; 172144449Sjhb struct iovec *iov; 173144449Sjhb struct uio *uio; 174185438Skib uint32_t iovlen; 175144449Sjhb int error, i; 176133819Stjr 177144449Sjhb *uiop = NULL; 178144449Sjhb if (iovcnt > UIO_MAXIOV) 179133819Stjr return (EINVAL); 180144449Sjhb iovlen = iovcnt * sizeof(struct iovec); 181168844Sjkim uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK); 182144449Sjhb iov = (struct iovec *)(uio + 1); 183144449Sjhb for (i = 0; i < iovcnt; i++) { 184185438Skib error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32)); 185144449Sjhb if (error) { 186144449Sjhb free(uio, M_IOV); 187144449Sjhb return (error); 188144449Sjhb } 189144449Sjhb iov[i].iov_base = PTRIN(iov32.iov_base); 190144449Sjhb iov[i].iov_len = iov32.iov_len; 191133819Stjr } 192144449Sjhb uio->uio_iov = iov; 193144449Sjhb uio->uio_iovcnt = iovcnt; 194144449Sjhb uio->uio_segflg = UIO_USERSPACE; 195144449Sjhb uio->uio_offset = -1; 196144449Sjhb uio->uio_resid = 0; 197144449Sjhb for (i = 0; i < iovcnt; i++) { 198144449Sjhb if (iov->iov_len > INT_MAX - uio->uio_resid) { 199144449Sjhb free(uio, M_IOV); 200144449Sjhb return (EINVAL); 201144449Sjhb } 202144449Sjhb uio->uio_resid += iov->iov_len; 203144449Sjhb iov++; 204144449Sjhb } 205144449Sjhb *uiop = uio; 206144449Sjhb return (0); 207144449Sjhb} 208133819Stjr 209144449Sjhbint 210185438Skiblinux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp, 211185438Skib int error) 212185438Skib{ 213185438Skib struct l_iovec32 iov32; 214185438Skib struct iovec *iov; 215185438Skib uint32_t iovlen; 216185438Skib int i; 217185438Skib 218185438Skib *iovp = NULL; 219185438Skib if (iovcnt > UIO_MAXIOV) 220185438Skib return (error); 221185438Skib iovlen = iovcnt * sizeof(struct iovec); 222185438Skib iov = malloc(iovlen, M_IOV, M_WAITOK); 223185438Skib for (i = 0; i < iovcnt; i++) { 224185438Skib error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32)); 225185438Skib if (error) { 226185438Skib free(iov, M_IOV); 227185438Skib return (error); 228185438Skib } 229185438Skib iov[i].iov_base = PTRIN(iov32.iov_base); 230185438Skib iov[i].iov_len = iov32.iov_len; 231185438Skib } 232185438Skib *iovp = iov; 233185438Skib return(0); 234185438Skib 235185438Skib} 236185438Skib 237185438Skibint 238144449Sjhblinux_readv(struct thread *td, struct linux_readv_args *uap) 239144449Sjhb{ 240144449Sjhb struct uio *auio; 241144449Sjhb int error; 242133819Stjr 243144449Sjhb error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 244144449Sjhb if (error) 245144449Sjhb return (error); 246144449Sjhb error = kern_readv(td, uap->fd, auio); 247144449Sjhb free(auio, M_IOV); 248133819Stjr return (error); 249133819Stjr} 250133819Stjr 251133819Stjrint 252133819Stjrlinux_writev(struct thread *td, struct linux_writev_args *uap) 253133819Stjr{ 254144449Sjhb struct uio *auio; 255144449Sjhb int error; 256133819Stjr 257144449Sjhb error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio); 258144449Sjhb if (error) 259144449Sjhb return (error); 260144449Sjhb error = kern_writev(td, uap->fd, auio); 261144449Sjhb free(auio, M_IOV); 262133819Stjr return (error); 263133819Stjr} 264133819Stjr 265133819Stjrstruct l_ipc_kludge { 266133819Stjr l_uintptr_t msgp; 267133819Stjr l_long msgtyp; 268133819Stjr} __packed; 269133819Stjr 270133819Stjrint 271133819Stjrlinux_ipc(struct thread *td, struct linux_ipc_args *args) 272133819Stjr{ 273133819Stjr 274133819Stjr switch (args->what & 0xFFFF) { 275133819Stjr case LINUX_SEMOP: { 276133819Stjr struct linux_semop_args a; 277133819Stjr 278133819Stjr a.semid = args->arg1; 279133819Stjr a.tsops = args->ptr; 280133819Stjr a.nsops = args->arg2; 281133819Stjr return (linux_semop(td, &a)); 282133819Stjr } 283133819Stjr case LINUX_SEMGET: { 284133819Stjr struct linux_semget_args a; 285133819Stjr 286133819Stjr a.key = args->arg1; 287133819Stjr a.nsems = args->arg2; 288133819Stjr a.semflg = args->arg3; 289133819Stjr return (linux_semget(td, &a)); 290133819Stjr } 291133819Stjr case LINUX_SEMCTL: { 292133819Stjr struct linux_semctl_args a; 293133819Stjr int error; 294133819Stjr 295133819Stjr a.semid = args->arg1; 296133819Stjr a.semnum = args->arg2; 297133819Stjr a.cmd = args->arg3; 298133819Stjr error = copyin(args->ptr, &a.arg, sizeof(a.arg)); 299133819Stjr if (error) 300133819Stjr return (error); 301133819Stjr return (linux_semctl(td, &a)); 302133819Stjr } 303133819Stjr case LINUX_MSGSND: { 304133819Stjr struct linux_msgsnd_args a; 305133819Stjr 306133819Stjr a.msqid = args->arg1; 307133819Stjr a.msgp = args->ptr; 308133819Stjr a.msgsz = args->arg2; 309133819Stjr a.msgflg = args->arg3; 310133819Stjr return (linux_msgsnd(td, &a)); 311133819Stjr } 312133819Stjr case LINUX_MSGRCV: { 313133819Stjr struct linux_msgrcv_args a; 314133819Stjr 315133819Stjr a.msqid = args->arg1; 316133819Stjr a.msgsz = args->arg2; 317133819Stjr a.msgflg = args->arg3; 318133819Stjr if ((args->what >> 16) == 0) { 319133819Stjr struct l_ipc_kludge tmp; 320133819Stjr int error; 321133819Stjr 322133819Stjr if (args->ptr == 0) 323133819Stjr return (EINVAL); 324133819Stjr error = copyin(args->ptr, &tmp, sizeof(tmp)); 325133819Stjr if (error) 326133819Stjr return (error); 327133819Stjr a.msgp = PTRIN(tmp.msgp); 328133819Stjr a.msgtyp = tmp.msgtyp; 329133819Stjr } else { 330133819Stjr a.msgp = args->ptr; 331133819Stjr a.msgtyp = args->arg5; 332133819Stjr } 333133819Stjr return (linux_msgrcv(td, &a)); 334133819Stjr } 335133819Stjr case LINUX_MSGGET: { 336133819Stjr struct linux_msgget_args a; 337133819Stjr 338133819Stjr a.key = args->arg1; 339133819Stjr a.msgflg = args->arg2; 340133819Stjr return (linux_msgget(td, &a)); 341133819Stjr } 342133819Stjr case LINUX_MSGCTL: { 343133819Stjr struct linux_msgctl_args a; 344133819Stjr 345133819Stjr a.msqid = args->arg1; 346133819Stjr a.cmd = args->arg2; 347133819Stjr a.buf = args->ptr; 348133819Stjr return (linux_msgctl(td, &a)); 349133819Stjr } 350133819Stjr case LINUX_SHMAT: { 351133819Stjr struct linux_shmat_args a; 352133819Stjr 353133819Stjr a.shmid = args->arg1; 354133819Stjr a.shmaddr = args->ptr; 355133819Stjr a.shmflg = args->arg2; 356144441Sjhb a.raddr = PTRIN((l_uint)args->arg3); 357133819Stjr return (linux_shmat(td, &a)); 358133819Stjr } 359133819Stjr case LINUX_SHMDT: { 360133819Stjr struct linux_shmdt_args a; 361133819Stjr 362133819Stjr a.shmaddr = args->ptr; 363133819Stjr return (linux_shmdt(td, &a)); 364133819Stjr } 365133819Stjr case LINUX_SHMGET: { 366133819Stjr struct linux_shmget_args a; 367133819Stjr 368133819Stjr a.key = args->arg1; 369133819Stjr a.size = args->arg2; 370133819Stjr a.shmflg = args->arg3; 371133819Stjr return (linux_shmget(td, &a)); 372133819Stjr } 373133819Stjr case LINUX_SHMCTL: { 374133819Stjr struct linux_shmctl_args a; 375133819Stjr 376133819Stjr a.shmid = args->arg1; 377133819Stjr a.cmd = args->arg2; 378133819Stjr a.buf = args->ptr; 379133819Stjr return (linux_shmctl(td, &a)); 380133819Stjr } 381133819Stjr default: 382133819Stjr break; 383133819Stjr } 384133819Stjr 385133819Stjr return (EINVAL); 386133819Stjr} 387133819Stjr 388133819Stjrint 389133819Stjrlinux_old_select(struct thread *td, struct linux_old_select_args *args) 390133819Stjr{ 391133819Stjr struct l_old_select_argv linux_args; 392133819Stjr struct linux_select_args newsel; 393133819Stjr int error; 394133819Stjr 395133819Stjr#ifdef DEBUG 396133819Stjr if (ldebug(old_select)) 397133819Stjr printf(ARGS(old_select, "%p"), args->ptr); 398133819Stjr#endif 399133819Stjr 400133819Stjr error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 401133819Stjr if (error) 402133819Stjr return (error); 403133819Stjr 404133819Stjr newsel.nfds = linux_args.nfds; 405133819Stjr newsel.readfds = PTRIN(linux_args.readfds); 406133819Stjr newsel.writefds = PTRIN(linux_args.writefds); 407133819Stjr newsel.exceptfds = PTRIN(linux_args.exceptfds); 408133819Stjr newsel.timeout = PTRIN(linux_args.timeout); 409133819Stjr return (linux_select(td, &newsel)); 410133819Stjr} 411133819Stjr 412133819Stjrint 413218612Sdchaginlinux_set_cloned_tls(struct thread *td, void *desc) 414218612Sdchagin{ 415218612Sdchagin struct user_segment_descriptor sd; 416218612Sdchagin struct l_user_desc info; 417218612Sdchagin struct pcb *pcb; 418218612Sdchagin int error; 419218612Sdchagin int a[2]; 420218612Sdchagin 421218612Sdchagin error = copyin(desc, &info, sizeof(struct l_user_desc)); 422218612Sdchagin if (error) { 423218612Sdchagin printf(LMSG("copyin failed!")); 424218612Sdchagin } else { 425218612Sdchagin /* We might copy out the entry_number as GUGS32_SEL. */ 426218612Sdchagin info.entry_number = GUGS32_SEL; 427218612Sdchagin error = copyout(&info, desc, sizeof(struct l_user_desc)); 428218612Sdchagin if (error) 429218612Sdchagin printf(LMSG("copyout failed!")); 430218612Sdchagin 431218612Sdchagin a[0] = LINUX_LDT_entry_a(&info); 432218612Sdchagin a[1] = LINUX_LDT_entry_b(&info); 433218612Sdchagin 434218612Sdchagin memcpy(&sd, &a, sizeof(a)); 435218612Sdchagin#ifdef DEBUG 436218612Sdchagin if (ldebug(clone)) 437218612Sdchagin printf("Segment created in clone with " 438218612Sdchagin "CLONE_SETTLS: lobase: %x, hibase: %x, " 439218612Sdchagin "lolimit: %x, hilimit: %x, type: %i, " 440218612Sdchagin "dpl: %i, p: %i, xx: %i, long: %i, " 441218612Sdchagin "def32: %i, gran: %i\n", sd.sd_lobase, 442218612Sdchagin sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, 443218612Sdchagin sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, 444218612Sdchagin sd.sd_long, sd.sd_def32, sd.sd_gran); 445218612Sdchagin#endif 446218612Sdchagin pcb = td->td_pcb; 447218612Sdchagin pcb->pcb_gsbase = (register_t)info.base_addr; 448218612Sdchagin/* XXXKIB pcb->pcb_gs32sd = sd; */ 449218612Sdchagin td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); 450218612Sdchagin set_pcb_flags(pcb, PCB_GS32BIT | PCB_32BIT); 451218612Sdchagin } 452218612Sdchagin 453218612Sdchagin return (error); 454218612Sdchagin} 455218612Sdchagin 456133819Stjrint 457218613Sdchaginlinux_set_upcall_kse(struct thread *td, register_t stack) 458218613Sdchagin{ 459218613Sdchagin 460218613Sdchagin td->td_frame->tf_rsp = stack; 461218613Sdchagin 462218613Sdchagin return (0); 463218613Sdchagin} 464218613Sdchagin 465133819Stjr#define STACK_SIZE (2 * 1024 * 1024) 466133819Stjr#define GUARD_SIZE (4 * PAGE_SIZE) 467133819Stjr 468133819Stjrint 469133819Stjrlinux_mmap2(struct thread *td, struct linux_mmap2_args *args) 470133819Stjr{ 471133819Stjr 472133819Stjr#ifdef DEBUG 473133819Stjr if (ldebug(mmap2)) 474168063Sjkim printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"), 475168063Sjkim args->addr, args->len, args->prot, 476133819Stjr args->flags, args->fd, args->pgoff); 477133819Stjr#endif 478133819Stjr 479198554Sjhb return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot, 480198554Sjhb args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff * 481198554Sjhb PAGE_SIZE)); 482133819Stjr} 483133819Stjr 484133819Stjrint 485133819Stjrlinux_mmap(struct thread *td, struct linux_mmap_args *args) 486133819Stjr{ 487133819Stjr int error; 488133819Stjr struct l_mmap_argv linux_args; 489133819Stjr 490133819Stjr error = copyin(args->ptr, &linux_args, sizeof(linux_args)); 491133819Stjr if (error) 492133819Stjr return (error); 493133819Stjr 494133819Stjr#ifdef DEBUG 495133819Stjr if (ldebug(mmap)) 496168063Sjkim printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"), 497168063Sjkim linux_args.addr, linux_args.len, linux_args.prot, 498168063Sjkim linux_args.flags, linux_args.fd, linux_args.pgoff); 499133819Stjr#endif 500133819Stjr 501198554Sjhb return (linux_mmap_common(td, linux_args.addr, linux_args.len, 502198554Sjhb linux_args.prot, linux_args.flags, linux_args.fd, 503198554Sjhb (uint32_t)linux_args.pgoff)); 504133819Stjr} 505133819Stjr 506133819Stjrstatic int 507198554Sjhblinux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, 508198554Sjhb l_int flags, l_int fd, l_loff_t pos) 509133819Stjr{ 510133819Stjr struct proc *p = td->td_proc; 511133819Stjr struct mmap_args /* { 512133819Stjr caddr_t addr; 513133819Stjr size_t len; 514133819Stjr int prot; 515133819Stjr int flags; 516133819Stjr int fd; 517133819Stjr long pad; 518133819Stjr off_t pos; 519133819Stjr } */ bsd_args; 520133819Stjr int error; 521165832Snetchild struct file *fp; 522133819Stjr 523133819Stjr error = 0; 524133819Stjr bsd_args.flags = 0; 525165832Snetchild fp = NULL; 526165832Snetchild 527165832Snetchild /* 528165832Snetchild * Linux mmap(2): 529165832Snetchild * You must specify exactly one of MAP_SHARED and MAP_PRIVATE 530165832Snetchild */ 531198554Sjhb if (!((flags & LINUX_MAP_SHARED) ^ (flags & LINUX_MAP_PRIVATE))) 532165832Snetchild return (EINVAL); 533165832Snetchild 534198554Sjhb if (flags & LINUX_MAP_SHARED) 535133819Stjr bsd_args.flags |= MAP_SHARED; 536198554Sjhb if (flags & LINUX_MAP_PRIVATE) 537133819Stjr bsd_args.flags |= MAP_PRIVATE; 538198554Sjhb if (flags & LINUX_MAP_FIXED) 539133819Stjr bsd_args.flags |= MAP_FIXED; 540208994Skan if (flags & LINUX_MAP_ANON) { 541208994Skan /* Enforce pos to be on page boundary, then ignore. */ 542208994Skan if ((pos & PAGE_MASK) != 0) 543208994Skan return (EINVAL); 544208994Skan pos = 0; 545133819Stjr bsd_args.flags |= MAP_ANON; 546208994Skan } else 547133819Stjr bsd_args.flags |= MAP_NOSYNC; 548198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) 549133819Stjr bsd_args.flags |= MAP_STACK; 550133819Stjr 551166727Sjkim /* 552166727Sjkim * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC 553166727Sjkim * on Linux/i386. We do this to ensure maximum compatibility. 554166727Sjkim * Linux/ia64 does the same in i386 emulation mode. 555166727Sjkim */ 556198554Sjhb bsd_args.prot = prot; 557166727Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 558166727Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 559166727Sjkim 560167048Sjkim /* Linux does not check file descriptor when MAP_ANONYMOUS is set. */ 561198554Sjhb bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : fd; 562167048Sjkim if (bsd_args.fd != -1) { 563166727Sjkim /* 564166727Sjkim * Linux follows Solaris mmap(2) description: 565166727Sjkim * The file descriptor fildes is opened with 566166727Sjkim * read permission, regardless of the 567166727Sjkim * protection options specified. 568166727Sjkim */ 569166727Sjkim 570224778Srwatson if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0) 571166727Sjkim return (error); 572166727Sjkim if (fp->f_type != DTYPE_VNODE) { 573166727Sjkim fdrop(fp, td); 574166727Sjkim return (EINVAL); 575166727Sjkim } 576166727Sjkim 577166727Sjkim /* Linux mmap() just fails for O_WRONLY files */ 578166727Sjkim if (!(fp->f_flag & FREAD)) { 579166727Sjkim fdrop(fp, td); 580166727Sjkim return (EACCES); 581166727Sjkim } 582166727Sjkim 583166727Sjkim fdrop(fp, td); 584166727Sjkim } 585166727Sjkim 586198554Sjhb if (flags & LINUX_MAP_GROWSDOWN) { 587168063Sjkim /* 588168063Sjkim * The Linux MAP_GROWSDOWN option does not limit auto 589133819Stjr * growth of the region. Linux mmap with this option 590133819Stjr * takes as addr the inital BOS, and as len, the initial 591133819Stjr * region size. It can then grow down from addr without 592168063Sjkim * limit. However, Linux threads has an implicit internal 593133819Stjr * limit to stack size of STACK_SIZE. Its just not 594168063Sjkim * enforced explicitly in Linux. But, here we impose 595133819Stjr * a limit of (STACK_SIZE - GUARD_SIZE) on the stack 596133819Stjr * region, since we can do this with our mmap. 597133819Stjr * 598133819Stjr * Our mmap with MAP_STACK takes addr as the maximum 599133819Stjr * downsize limit on BOS, and as len the max size of 600168848Sjkim * the region. It then maps the top SGROWSIZ bytes, 601166944Snetchild * and auto grows the region down, up to the limit 602133819Stjr * in addr. 603133819Stjr * 604133819Stjr * If we don't use the MAP_STACK option, the effect 605133819Stjr * of this code is to allocate a stack region of a 606133819Stjr * fixed size of (STACK_SIZE - GUARD_SIZE). 607133819Stjr */ 608133819Stjr 609198554Sjhb if ((caddr_t)PTRIN(addr) + len > p->p_vmspace->vm_maxsaddr) { 610168063Sjkim /* 611168063Sjkim * Some Linux apps will attempt to mmap 612133819Stjr * thread stacks near the top of their 613133819Stjr * address space. If their TOS is greater 614133819Stjr * than vm_maxsaddr, vm_map_growstack() 615133819Stjr * will confuse the thread stack with the 616133819Stjr * process stack and deliver a SEGV if they 617133819Stjr * attempt to grow the thread stack past their 618133819Stjr * current stacksize rlimit. To avoid this, 619133819Stjr * adjust vm_maxsaddr upwards to reflect 620133819Stjr * the current stacksize rlimit rather 621133819Stjr * than the maximum possible stacksize. 622133819Stjr * It would be better to adjust the 623133819Stjr * mmap'ed region, but some apps do not check 624133819Stjr * mmap's return value. 625133819Stjr */ 626133819Stjr PROC_LOCK(p); 627166727Sjkim p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK - 628133819Stjr lim_cur(p, RLIMIT_STACK); 629133819Stjr PROC_UNLOCK(p); 630133819Stjr } 631133819Stjr 632168063Sjkim /* 633176193Sjkim * This gives us our maximum stack size and a new BOS. 634176193Sjkim * If we're using VM_STACK, then mmap will just map 635176193Sjkim * the top SGROWSIZ bytes, and let the stack grow down 636176193Sjkim * to the limit at BOS. If we're not using VM_STACK 637176193Sjkim * we map the full stack, since we don't have a way 638176193Sjkim * to autogrow it. 639133819Stjr */ 640198554Sjhb if (len > STACK_SIZE - GUARD_SIZE) { 641198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 642198554Sjhb bsd_args.len = len; 643176193Sjkim } else { 644198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr) - 645198554Sjhb (STACK_SIZE - GUARD_SIZE - len); 646176193Sjkim bsd_args.len = STACK_SIZE - GUARD_SIZE; 647176193Sjkim } 648133819Stjr } else { 649198554Sjhb bsd_args.addr = (caddr_t)PTRIN(addr); 650198554Sjhb bsd_args.len = len; 651133819Stjr } 652198554Sjhb bsd_args.pos = pos; 653133819Stjr 654133819Stjr#ifdef DEBUG 655133819Stjr if (ldebug(mmap)) 656133819Stjr printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n", 657133819Stjr __func__, 658133843Sobrien (void *)bsd_args.addr, (int)bsd_args.len, bsd_args.prot, 659133819Stjr bsd_args.flags, bsd_args.fd, (int)bsd_args.pos); 660133819Stjr#endif 661133819Stjr error = mmap(td, &bsd_args); 662133819Stjr#ifdef DEBUG 663133819Stjr if (ldebug(mmap)) 664133819Stjr printf("-> %s() return: 0x%x (0x%08x)\n", 665133819Stjr __func__, error, (u_int)td->td_retval[0]); 666133819Stjr#endif 667133819Stjr return (error); 668133819Stjr} 669133819Stjr 670133819Stjrint 671168035Sjkimlinux_mprotect(struct thread *td, struct linux_mprotect_args *uap) 672168035Sjkim{ 673168035Sjkim struct mprotect_args bsd_args; 674168035Sjkim 675168035Sjkim bsd_args.addr = uap->addr; 676168035Sjkim bsd_args.len = uap->len; 677168035Sjkim bsd_args.prot = uap->prot; 678168035Sjkim if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC)) 679168035Sjkim bsd_args.prot |= PROT_READ | PROT_EXEC; 680168035Sjkim return (mprotect(td, &bsd_args)); 681168035Sjkim} 682168035Sjkim 683168035Sjkimint 684166729Sjkimlinux_iopl(struct thread *td, struct linux_iopl_args *args) 685166729Sjkim{ 686166729Sjkim int error; 687166729Sjkim 688166729Sjkim if (args->level < 0 || args->level > 3) 689166729Sjkim return (EINVAL); 690166729Sjkim if ((error = priv_check(td, PRIV_IO)) != 0) 691166729Sjkim return (error); 692166729Sjkim if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 693166729Sjkim return (error); 694166729Sjkim td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) | 695166729Sjkim (args->level * (PSL_IOPL / 3)); 696166729Sjkim 697166729Sjkim return (0); 698166729Sjkim} 699166729Sjkim 700166729Sjkimint 701133819Stjrlinux_pipe(struct thread *td, struct linux_pipe_args *args) 702133819Stjr{ 703133819Stjr int error; 704184849Sed int fildes[2]; 705133819Stjr 706133819Stjr#ifdef DEBUG 707133819Stjr if (ldebug(pipe)) 708133819Stjr printf(ARGS(pipe, "*")); 709133819Stjr#endif 710133819Stjr 711184849Sed error = kern_pipe(td, fildes); 712184849Sed if (error) 713133819Stjr return (error); 714133819Stjr 715184849Sed /* XXX: Close descriptors on error. */ 716184849Sed return (copyout(fildes, args->pipefds, sizeof fildes)); 717133819Stjr} 718166731Sjkim 719133819Stjrint 720133819Stjrlinux_sigaction(struct thread *td, struct linux_sigaction_args *args) 721133819Stjr{ 722133819Stjr l_osigaction_t osa; 723133819Stjr l_sigaction_t act, oact; 724133819Stjr int error; 725133819Stjr 726133819Stjr#ifdef DEBUG 727133819Stjr if (ldebug(sigaction)) 728133819Stjr printf(ARGS(sigaction, "%d, %p, %p"), 729133819Stjr args->sig, (void *)args->nsa, (void *)args->osa); 730133819Stjr#endif 731133819Stjr 732133819Stjr if (args->nsa != NULL) { 733133819Stjr error = copyin(args->nsa, &osa, sizeof(l_osigaction_t)); 734133819Stjr if (error) 735133819Stjr return (error); 736133819Stjr act.lsa_handler = osa.lsa_handler; 737133819Stjr act.lsa_flags = osa.lsa_flags; 738133819Stjr act.lsa_restorer = osa.lsa_restorer; 739133819Stjr LINUX_SIGEMPTYSET(act.lsa_mask); 740133819Stjr act.lsa_mask.__bits[0] = osa.lsa_mask; 741133819Stjr } 742133819Stjr 743133819Stjr error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL, 744133819Stjr args->osa ? &oact : NULL); 745133819Stjr 746133819Stjr if (args->osa != NULL && !error) { 747133819Stjr osa.lsa_handler = oact.lsa_handler; 748133819Stjr osa.lsa_flags = oact.lsa_flags; 749133819Stjr osa.lsa_restorer = oact.lsa_restorer; 750133819Stjr osa.lsa_mask = oact.lsa_mask.__bits[0]; 751133819Stjr error = copyout(&osa, args->osa, sizeof(l_osigaction_t)); 752133819Stjr } 753133819Stjr 754133819Stjr return (error); 755133819Stjr} 756133819Stjr 757133819Stjr/* 758168063Sjkim * Linux has two extra args, restart and oldmask. We don't use these, 759133819Stjr * but it seems that "restart" is actually a context pointer that 760133819Stjr * enables the signal to happen with a different register set. 761133819Stjr */ 762133819Stjrint 763133819Stjrlinux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args) 764133819Stjr{ 765133819Stjr sigset_t sigmask; 766133819Stjr l_sigset_t mask; 767133819Stjr 768133819Stjr#ifdef DEBUG 769133819Stjr if (ldebug(sigsuspend)) 770133819Stjr printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask); 771133819Stjr#endif 772133819Stjr 773133819Stjr LINUX_SIGEMPTYSET(mask); 774133819Stjr mask.__bits[0] = args->mask; 775133819Stjr linux_to_bsd_sigset(&mask, &sigmask); 776133819Stjr return (kern_sigsuspend(td, sigmask)); 777133819Stjr} 778133819Stjr 779133819Stjrint 780133819Stjrlinux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap) 781133819Stjr{ 782133819Stjr l_sigset_t lmask; 783133819Stjr sigset_t sigmask; 784133819Stjr int error; 785133819Stjr 786133819Stjr#ifdef DEBUG 787133819Stjr if (ldebug(rt_sigsuspend)) 788133819Stjr printf(ARGS(rt_sigsuspend, "%p, %d"), 789133819Stjr (void *)uap->newset, uap->sigsetsize); 790133819Stjr#endif 791133819Stjr 792133819Stjr if (uap->sigsetsize != sizeof(l_sigset_t)) 793133819Stjr return (EINVAL); 794133819Stjr 795133819Stjr error = copyin(uap->newset, &lmask, sizeof(l_sigset_t)); 796133819Stjr if (error) 797133819Stjr return (error); 798133819Stjr 799133819Stjr linux_to_bsd_sigset(&lmask, &sigmask); 800133819Stjr return (kern_sigsuspend(td, sigmask)); 801133819Stjr} 802133819Stjr 803133819Stjrint 804133819Stjrlinux_pause(struct thread *td, struct linux_pause_args *args) 805133819Stjr{ 806133819Stjr struct proc *p = td->td_proc; 807133819Stjr sigset_t sigmask; 808133819Stjr 809133819Stjr#ifdef DEBUG 810133819Stjr if (ldebug(pause)) 811133819Stjr printf(ARGS(pause, "")); 812133819Stjr#endif 813133819Stjr 814133819Stjr PROC_LOCK(p); 815133819Stjr sigmask = td->td_sigmask; 816133819Stjr PROC_UNLOCK(p); 817133819Stjr return (kern_sigsuspend(td, sigmask)); 818133819Stjr} 819133819Stjr 820133819Stjrint 821133819Stjrlinux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap) 822133819Stjr{ 823133819Stjr stack_t ss, oss; 824133819Stjr l_stack_t lss; 825133819Stjr int error; 826133819Stjr 827133819Stjr#ifdef DEBUG 828133819Stjr if (ldebug(sigaltstack)) 829133819Stjr printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss); 830133819Stjr#endif 831133819Stjr 832133819Stjr if (uap->uss != NULL) { 833133819Stjr error = copyin(uap->uss, &lss, sizeof(l_stack_t)); 834133819Stjr if (error) 835133819Stjr return (error); 836133819Stjr 837133819Stjr ss.ss_sp = PTRIN(lss.ss_sp); 838133819Stjr ss.ss_size = lss.ss_size; 839133819Stjr ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags); 840133819Stjr } 841134269Sjhb error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL, 842134269Sjhb (uap->uoss != NULL) ? &oss : NULL); 843133819Stjr if (!error && uap->uoss != NULL) { 844133819Stjr lss.ss_sp = PTROUT(oss.ss_sp); 845133819Stjr lss.ss_size = oss.ss_size; 846133819Stjr lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags); 847133819Stjr error = copyout(&lss, uap->uoss, sizeof(l_stack_t)); 848133819Stjr } 849133819Stjr 850133819Stjr return (error); 851133819Stjr} 852133819Stjr 853133819Stjrint 854133819Stjrlinux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args) 855133819Stjr{ 856133819Stjr struct ftruncate_args sa; 857133819Stjr 858133819Stjr#ifdef DEBUG 859133819Stjr if (ldebug(ftruncate64)) 860133819Stjr printf(ARGS(ftruncate64, "%u, %jd"), args->fd, 861133819Stjr (intmax_t)args->length); 862133819Stjr#endif 863133819Stjr 864133819Stjr sa.fd = args->fd; 865133819Stjr sa.length = args->length; 866133819Stjr return ftruncate(td, &sa); 867133819Stjr} 868133819Stjr 869133819Stjrint 870133819Stjrlinux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap) 871133819Stjr{ 872133819Stjr struct timeval atv; 873133819Stjr l_timeval atv32; 874133819Stjr struct timezone rtz; 875133819Stjr int error = 0; 876133819Stjr 877133819Stjr if (uap->tp) { 878133819Stjr microtime(&atv); 879133819Stjr atv32.tv_sec = atv.tv_sec; 880133819Stjr atv32.tv_usec = atv.tv_usec; 881168844Sjkim error = copyout(&atv32, uap->tp, sizeof(atv32)); 882133819Stjr } 883133819Stjr if (error == 0 && uap->tzp != NULL) { 884133819Stjr rtz.tz_minuteswest = tz_minuteswest; 885133819Stjr rtz.tz_dsttime = tz_dsttime; 886168844Sjkim error = copyout(&rtz, uap->tzp, sizeof(rtz)); 887133819Stjr } 888133819Stjr return (error); 889133819Stjr} 890133819Stjr 891133819Stjrint 892168843Sjkimlinux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap) 893168843Sjkim{ 894168843Sjkim l_timeval atv32; 895168843Sjkim struct timeval atv, *tvp; 896168843Sjkim struct timezone atz, *tzp; 897168843Sjkim int error; 898168843Sjkim 899168843Sjkim if (uap->tp) { 900168843Sjkim error = copyin(uap->tp, &atv32, sizeof(atv32)); 901168843Sjkim if (error) 902168843Sjkim return (error); 903168843Sjkim atv.tv_sec = atv32.tv_sec; 904168843Sjkim atv.tv_usec = atv32.tv_usec; 905168843Sjkim tvp = &atv; 906168843Sjkim } else 907168843Sjkim tvp = NULL; 908168843Sjkim if (uap->tzp) { 909168843Sjkim error = copyin(uap->tzp, &atz, sizeof(atz)); 910168843Sjkim if (error) 911168843Sjkim return (error); 912168843Sjkim tzp = &atz; 913168843Sjkim } else 914168843Sjkim tzp = NULL; 915168843Sjkim return (kern_settimeofday(td, tvp, tzp)); 916168843Sjkim} 917168843Sjkim 918168843Sjkimint 919133819Stjrlinux_getrusage(struct thread *td, struct linux_getrusage_args *uap) 920133819Stjr{ 921136152Sjhb struct l_rusage s32; 922136152Sjhb struct rusage s; 923133819Stjr int error; 924133819Stjr 925136152Sjhb error = kern_getrusage(td, uap->who, &s); 926133819Stjr if (error != 0) 927133819Stjr return (error); 928136152Sjhb if (uap->rusage != NULL) { 929218028Sdchagin bsd_to_linux_rusage(&s, &s32); 930136152Sjhb error = copyout(&s32, uap->rusage, sizeof(s32)); 931133819Stjr } 932133819Stjr return (error); 933133819Stjr} 934133819Stjr 935133819Stjrint 936133819Stjrlinux_sched_rr_get_interval(struct thread *td, 937133819Stjr struct linux_sched_rr_get_interval_args *uap) 938133819Stjr{ 939133819Stjr struct timespec ts; 940133819Stjr struct l_timespec ts32; 941133819Stjr int error; 942133819Stjr 943144449Sjhb error = kern_sched_rr_get_interval(td, uap->pid, &ts); 944133819Stjr if (error != 0) 945133819Stjr return (error); 946133819Stjr ts32.tv_sec = ts.tv_sec; 947133819Stjr ts32.tv_nsec = ts.tv_nsec; 948133819Stjr return (copyout(&ts32, uap->interval, sizeof(ts32))); 949133819Stjr} 950133819Stjr 951133819Stjrint 952168035Sjkimlinux_set_thread_area(struct thread *td, 953168035Sjkim struct linux_set_thread_area_args *args) 954133819Stjr{ 955168035Sjkim struct l_user_desc info; 956168035Sjkim struct user_segment_descriptor sd; 957216634Sjkim struct pcb *pcb; 958168035Sjkim int a[2]; 959168035Sjkim int error; 960133819Stjr 961168035Sjkim error = copyin(args->desc, &info, sizeof(struct l_user_desc)); 962168035Sjkim if (error) 963168035Sjkim return (error); 964168035Sjkim 965168035Sjkim#ifdef DEBUG 966168035Sjkim if (ldebug(set_thread_area)) 967168848Sjkim printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, " 968168035Sjkim "%i, %i, %i"), info.entry_number, info.base_addr, 969168035Sjkim info.limit, info.seg_32bit, info.contents, 970168035Sjkim info.read_exec_only, info.limit_in_pages, 971168035Sjkim info.seg_not_present, info.useable); 972168035Sjkim#endif 973168035Sjkim 974168035Sjkim /* 975168035Sjkim * Semantics of Linux version: every thread in the system has array 976168035Sjkim * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. 977168035Sjkim * This syscall loads one of the selected TLS decriptors with a value 978168035Sjkim * and also loads GDT descriptors 6, 7 and 8 with the content of 979168035Sjkim * the per-thread descriptors. 980168035Sjkim * 981168035Sjkim * Semantics of FreeBSD version: I think we can ignore that Linux has 982168035Sjkim * three per-thread descriptors and use just the first one. 983168035Sjkim * The tls_array[] is used only in [gs]et_thread_area() syscalls and 984168035Sjkim * for loading the GDT descriptors. We use just one GDT descriptor 985168035Sjkim * for TLS, so we will load just one. 986168848Sjkim * 987168848Sjkim * XXX: This doesn't work when a user space process tries to use more 988168035Sjkim * than one TLS segment. Comment in the Linux source says wine might 989168848Sjkim * do this. 990168035Sjkim */ 991168035Sjkim 992168035Sjkim /* 993168035Sjkim * GLIBC reads current %gs and call set_thread_area() with it. 994168035Sjkim * We should let GUDATA_SEL and GUGS32_SEL proceed as well because 995168035Sjkim * we use these segments. 996168035Sjkim */ 997168035Sjkim switch (info.entry_number) { 998168035Sjkim case GUGS32_SEL: 999168035Sjkim case GUDATA_SEL: 1000168035Sjkim case 6: 1001168035Sjkim case -1: 1002168035Sjkim info.entry_number = GUGS32_SEL; 1003168035Sjkim break; 1004168035Sjkim default: 1005168035Sjkim return (EINVAL); 1006168035Sjkim } 1007168035Sjkim 1008168035Sjkim /* 1009168035Sjkim * We have to copy out the GDT entry we use. 1010168848Sjkim * 1011168848Sjkim * XXX: What if a user space program does not check the return value 1012168848Sjkim * and tries to use 6, 7 or 8? 1013168035Sjkim */ 1014168035Sjkim error = copyout(&info, args->desc, sizeof(struct l_user_desc)); 1015168035Sjkim if (error) 1016168035Sjkim return (error); 1017168035Sjkim 1018168035Sjkim if (LINUX_LDT_empty(&info)) { 1019168035Sjkim a[0] = 0; 1020168035Sjkim a[1] = 0; 1021168035Sjkim } else { 1022168035Sjkim a[0] = LINUX_LDT_entry_a(&info); 1023168035Sjkim a[1] = LINUX_LDT_entry_b(&info); 1024168035Sjkim } 1025168035Sjkim 1026168035Sjkim memcpy(&sd, &a, sizeof(a)); 1027168035Sjkim#ifdef DEBUG 1028168035Sjkim if (ldebug(set_thread_area)) 1029168035Sjkim printf("Segment created in set_thread_area: " 1030168035Sjkim "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, " 1031168035Sjkim "type: %i, dpl: %i, p: %i, xx: %i, long: %i, " 1032168035Sjkim "def32: %i, gran: %i\n", 1033168035Sjkim sd.sd_lobase, 1034168035Sjkim sd.sd_hibase, 1035168035Sjkim sd.sd_lolimit, 1036168035Sjkim sd.sd_hilimit, 1037168035Sjkim sd.sd_type, 1038168035Sjkim sd.sd_dpl, 1039168035Sjkim sd.sd_p, 1040168035Sjkim sd.sd_xx, 1041168035Sjkim sd.sd_long, 1042168035Sjkim sd.sd_def32, 1043168035Sjkim sd.sd_gran); 1044168035Sjkim#endif 1045168035Sjkim 1046216634Sjkim pcb = td->td_pcb; 1047216634Sjkim pcb->pcb_gsbase = (register_t)info.base_addr; 1048216634Sjkim set_pcb_flags(pcb, PCB_32BIT | PCB_GS32BIT); 1049190620Skib update_gdt_gsbase(td, info.base_addr); 1050168035Sjkim 1051168035Sjkim return (0); 1052133819Stjr} 1053218030Sdchagin 1054218030Sdchaginint 1055218030Sdchaginlinux_wait4(struct thread *td, struct linux_wait4_args *args) 1056218030Sdchagin{ 1057218030Sdchagin int error, options; 1058218030Sdchagin struct rusage ru, *rup; 1059218030Sdchagin struct l_rusage lru; 1060218030Sdchagin 1061218030Sdchagin#ifdef DEBUG 1062218030Sdchagin if (ldebug(wait4)) 1063218030Sdchagin printf(ARGS(wait4, "%d, %p, %d, %p"), 1064218030Sdchagin args->pid, (void *)args->status, args->options, 1065218030Sdchagin (void *)args->rusage); 1066218030Sdchagin#endif 1067218030Sdchagin 1068218030Sdchagin options = (args->options & (WNOHANG | WUNTRACED)); 1069218030Sdchagin /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ 1070218030Sdchagin if (args->options & __WCLONE) 1071218030Sdchagin options |= WLINUXCLONE; 1072218030Sdchagin 1073218030Sdchagin if (args->rusage != NULL) 1074218030Sdchagin rup = &ru; 1075218030Sdchagin else 1076218030Sdchagin rup = NULL; 1077218030Sdchagin error = linux_common_wait(td, args->pid, args->status, options, rup); 1078218030Sdchagin if (error) 1079218030Sdchagin return (error); 1080218030Sdchagin if (args->rusage != NULL) { 1081218030Sdchagin bsd_to_linux_rusage(rup, &lru); 1082218030Sdchagin error = copyout(&lru, args->rusage, sizeof(lru)); 1083218030Sdchagin } 1084218030Sdchagin 1085218030Sdchagin return (error); 1086218030Sdchagin} 1087