diff options
Diffstat (limited to 'sys/amd64/linux/linux_sysvec.c')
-rw-r--r-- | sys/amd64/linux/linux_sysvec.c | 505 |
1 files changed, 226 insertions, 279 deletions
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c index 25fc8b10e903..9c3d7e6405c1 100644 --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -31,63 +31,49 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #define __ELF_WORD_SIZE 64 #include <sys/param.h> -#include <sys/systm.h> #include <sys/exec.h> -#include <sys/fcntl.h> #include <sys/imgact.h> #include <sys/imgact_elf.h> #include <sys/kernel.h> #include <sys/ktr.h> #include <sys/lock.h> -#include <sys/malloc.h> #include <sys/module.h> #include <sys/mutex.h> #include <sys/proc.h> -#include <sys/resourcevar.h> #include <sys/stddef.h> -#include <sys/signalvar.h> #include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/sysent.h> -#include <sys/sysproto.h> -#include <sys/vnode.h> -#include <sys/eventhandler.h> -#include <vm/vm.h> #include <vm/pmap.h> -#include <vm/vm_extern.h> -#include <vm/vm_map.h> -#include <vm/vm_object.h> -#include <vm/vm_page.h> +#include <vm/vm.h> #include <vm/vm_param.h> -#include <machine/cpu.h> #include <machine/md_var.h> -#include <machine/pcb.h> -#include <machine/specialreg.h> #include <machine/trap.h> #include <x86/linux/linux_x86.h> #include <amd64/linux/linux.h> #include <amd64/linux/linux_proto.h> +#include <compat/linux/linux_elf.h> #include <compat/linux/linux_emul.h> #include <compat/linux/linux_fork.h> #include <compat/linux/linux_ioctl.h> #include <compat/linux/linux_mib.h> #include <compat/linux/linux_misc.h> #include <compat/linux/linux_signal.h> -#include <compat/linux/linux_sysproto.h> #include <compat/linux/linux_util.h> #include <compat/linux/linux_vdso.h> #include <x86/linux/linux_x86_sigframe.h> +_Static_assert(sizeof(struct l_fpstate) == + sizeof(__typeof(((mcontext_t *)0)->mc_fpstate)), + "fxsave area size incorrect"); + MODULE_VERSION(linux64, 1); #define LINUX_VDSOPAGE_SIZE PAGE_SIZE * 2 @@ -110,14 +96,10 @@ extern char _binary_linux_vdso_so_o_end; static vm_offset_t linux_vdso_base; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; +extern const char *linux_syscallnames[]; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); -static int linux_copyout_strings(struct image_params *imgp, - uintptr_t *stack_base); -static int linux_fixup_elf(uintptr_t *stack_base, - struct image_params *iparams); -static bool linux_trans_osrel(const Elf_Note *note, int32_t *osrel); static void linux_vdso_install(const void *param); static void linux_vdso_deinstall(const void *param); static void linux_vdso_reloc(char *mapping, Elf_Addr offset); @@ -137,6 +119,23 @@ LINUX_VDSO_SYM_INTPTR(kern_timekeep_base); LINUX_VDSO_SYM_INTPTR(kern_tsc_selector); LINUX_VDSO_SYM_INTPTR(kern_cpu_selector); +/* + * According to the Intel x86 ISA 64-bit syscall + * saves %rip to %rcx and rflags to %r11. Registers on syscall entry: + * %rax system call number + * %rcx return address + * %r11 saved rflags + * %rdi arg1 + * %rsi arg2 + * %rdx arg3 + * %r10 arg4 + * %r8 arg5 + * %r9 arg6 + * + * Then FreeBSD fast_syscall() move registers: + * %rcx -> trapframe.tf_rip + * %r10 -> trapframe.tf_rcx + */ static int linux_fetch_syscall_args(struct thread *td) { @@ -159,10 +158,15 @@ linux_fetch_syscall_args(struct thread *td) if (sa->code >= p->p_sysent->sv_size) /* nosys */ - sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1]; + sa->callp = &nosys_sysent; else sa->callp = &p->p_sysent->sv_table[sa->code]; + /* Restore r10 earlier to avoid doing this multiply times. */ + frame->tf_r10 = frame->tf_rcx; + /* Restore %rcx for machine context. */ + frame->tf_rcx = frame->tf_rip; + td->td_retval[0] = 0; return (0); } @@ -177,7 +181,6 @@ linux_set_syscall_retval(struct thread *td, int error) switch (error) { case 0: frame->tf_rax = td->td_retval[0]; - frame->tf_r10 = frame->tf_rcx; break; case ERESTART: @@ -188,7 +191,6 @@ linux_set_syscall_retval(struct thread *td, int error) * */ frame->tf_rip -= frame->tf_err; - frame->tf_r10 = frame->tf_rcx; break; case EJUSTRETURN: @@ -196,7 +198,6 @@ linux_set_syscall_retval(struct thread *td, int error) default: frame->tf_rax = bsd_to_linux_errno(error); - frame->tf_r10 = frame->tf_rcx; break; } @@ -205,9 +206,6 @@ linux_set_syscall_retval(struct thread *td, int error) * and %r11 values are not preserved across the syscall. * Require full context restore to get all registers except * those two restored at return to usermode. - * - * XXX: Would be great to be able to avoid PCB_FULL_IRET - * for the error == 0 case. */ set_pcb_flags(td->td_pcb, PCB_FULL_IRET); } @@ -220,192 +218,14 @@ linux_set_fork_retval(struct thread *td) frame->tf_rax = 0; } -static int -linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) -{ - Elf_Auxargs *args; - Elf_Auxinfo *argarray, *pos; - struct proc *p; - int error, issetugid; - - p = imgp->proc; - args = (Elf64_Auxargs *)imgp->auxargs; - argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, - M_WAITOK | M_ZERO); - - issetugid = p->p_flag & P_SUGID ? 1 : 0; - AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base); - AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); - AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); - AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); - AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); - AUXARGS_ENTRY(pos, AT_PHENT, args->phent); - AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); - AUXARGS_ENTRY(pos, AT_BASE, args->base); - AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); - AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); - AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); - AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); - AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary); - AUXARGS_ENTRY(pos, LINUX_AT_HWCAP2, 0); - if (imgp->execpathp != 0) - AUXARGS_ENTRY_PTR(pos, LINUX_AT_EXECFN, imgp->execpathp); - if (args->execfd != -1) - AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); - AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); - AUXARGS_ENTRY(pos, AT_NULL, 0); - - free(imgp->auxargs, M_TEMP); - imgp->auxargs = NULL; - KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - - error = copyout(argarray, (void *)base, - sizeof(*argarray) * LINUX_AT_COUNT); - free(argarray, M_TEMP); - return (error); -} - -static int -linux_fixup_elf(uintptr_t *stack_base, struct image_params *imgp) -{ - Elf_Addr *base; - - base = (Elf64_Addr *)*stack_base; - base--; - if (suword(base, (uint64_t)imgp->args->argc) == -1) - return (EFAULT); - - *stack_base = (uintptr_t)base; - return (0); -} - -/* - * Copy strings out to the new process address space, constructing new arg - * and env vector tables. Return a pointer to the base so that it can be used - * as the initial stack pointer. - */ -static int -linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base) +void +linux64_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos) { - int argc, envc, error; - char **vectp; - char *stringp; - uintptr_t destp, ustringp; - struct ps_strings *arginfo; - char canary[LINUX_AT_RANDOM_LEN]; - size_t execpath_len; - struct proc *p; - - p = imgp->proc; - arginfo = (struct ps_strings *)PROC_PS_STRINGS(p); - destp = (uintptr_t)arginfo; - - if (imgp->execpath != NULL && imgp->auxargs != NULL) { - execpath_len = strlen(imgp->execpath) + 1; - destp -= execpath_len; - destp = rounddown2(destp, sizeof(void *)); - imgp->execpathp = (void *)destp; - error = copyout(imgp->execpath, imgp->execpathp, execpath_len); - if (error != 0) - return (error); - } - - /* Prepare the canary for SSP. */ - arc4rand(canary, sizeof(canary), 0); - destp -= roundup(sizeof(canary), sizeof(void *)); - imgp->canary = (void *)destp; - error = copyout(canary, imgp->canary, sizeof(canary)); - if (error != 0) - return (error); - - /* Allocate room for the argument and environment strings. */ - destp -= ARG_MAX - imgp->args->stringspace; - destp = rounddown2(destp, sizeof(void *)); - ustringp = destp; - - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has LINUX_AT_COUNT entries. - */ - destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo); - destp = rounddown2(destp, sizeof(void *)); - } - - vectp = (char **)destp; - - /* - * Allocate room for the argv[] and env vectors including the - * terminating NULL pointers. - */ - vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; - - /* - * Starting with 2.24, glibc depends on a 16-byte stack alignment. - * One "long argc" will be prepended later. - */ - vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8); - - /* vectp also becomes our initial stack base. */ - *stack_base = (uintptr_t)vectp; - - stringp = imgp->args->begin_argv; - argc = imgp->args->argc; - envc = imgp->args->envc; - - /* Copy out strings - arguments and environment. */ - error = copyout(stringp, (void *)ustringp, - ARG_MAX - imgp->args->stringspace); - if (error != 0) - return (error); - - /* Fill in "ps_strings" struct for ps, w, etc. */ - if (suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp) != 0 || - suword(&arginfo->ps_nargvstr, argc) != 0) - return (EFAULT); - - /* Fill in argument portion of vector table. */ - for (; argc > 0; --argc) { - if (suword(vectp++, ustringp) != 0) - return (EFAULT); - while (*stringp++ != 0) - ustringp++; - ustringp++; - } - - /* A null vector table pointer separates the argp's from the envp's. */ - if (suword(vectp++, 0) != 0) - return (EFAULT); - - if (suword(&arginfo->ps_envstr, (long)(intptr_t)vectp) != 0 || - suword(&arginfo->ps_nenvstr, envc) != 0) - return (EFAULT); - - /* Fill in environment portion of vector table. */ - for (; envc > 0; --envc) { - if (suword(vectp++, ustringp) != 0) - return (EFAULT); - while (*stringp++ != 0) - ustringp++; - ustringp++; - } - - /* The end of the vector table is a null pointer. */ - if (suword(vectp, 0) != 0) - return (EFAULT); - if (imgp->auxargs) { - vectp++; - error = imgp->sysent->sv_copyout_auxargs(imgp, - (uintptr_t)vectp); - if (error != 0) - return (error); - } - - return (0); + AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base); + AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, cpu_feature); + AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP2, linux_x86_elf_hwcap2()); + AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform)); } /* @@ -453,16 +273,90 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp, fpstate_drop(td); } +static int +linux_fxrstor(struct thread *td, mcontext_t *mcp, struct l_sigcontext *sc) +{ + struct savefpu *fp = (struct savefpu *)&mcp->mc_fpstate[0]; + int error; + + error = copyin(PTRIN(sc->sc_fpstate), fp, sizeof(mcp->mc_fpstate)); + if (error != 0) + return (error); + bzero(&fp->sv_pad[0], sizeof(fp->sv_pad)); + return (set_fpcontext(td, mcp, NULL, 0)); +} + +static int +linux_xrstor(struct thread *td, mcontext_t *mcp, struct l_sigcontext *sc) +{ + struct savefpu *fp = (struct savefpu *)&mcp->mc_fpstate[0]; + char *xfpustate; + struct proc *p; + uint32_t magic2; + int error; + + p = td->td_proc; + mcp->mc_xfpustate_len = cpu_max_ext_state_size - sizeof(struct savefpu); + + /* Legacy region of an xsave area. */ + error = copyin(PTRIN(sc->sc_fpstate), fp, sizeof(mcp->mc_fpstate)); + if (error != 0) + return (error); + bzero(&fp->sv_pad[0], sizeof(fp->sv_pad)); + + /* Extended region of an xsave area. */ + sc->sc_fpstate += sizeof(mcp->mc_fpstate); + xfpustate = (char *)fpu_save_area_alloc(); + error = copyin(PTRIN(sc->sc_fpstate), xfpustate, mcp->mc_xfpustate_len); + if (error != 0) { + fpu_save_area_free((struct savefpu *)xfpustate); + uprintf("pid %d (%s): linux xrstor failed\n", p->p_pid, + td->td_name); + return (error); + } + + /* Linux specific end of xsave area marker. */ + sc->sc_fpstate += mcp->mc_xfpustate_len; + error = copyin(PTRIN(sc->sc_fpstate), &magic2, LINUX_FP_XSTATE_MAGIC2_SIZE); + if (error != 0 || magic2 != LINUX_FP_XSTATE_MAGIC2) { + fpu_save_area_free((struct savefpu *)xfpustate); + uprintf("pid %d (%s): sigreturn magic2 0x%x error %d\n", + p->p_pid, td->td_name, magic2, error); + return (error); + } + + error = set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); + fpu_save_area_free((struct savefpu *)xfpustate); + if (error != 0) { + uprintf("pid %d (%s): sigreturn set_fpcontext error %d\n", + p->p_pid, td->td_name, error); + } + return (error); +} + +static int +linux_copyin_fpstate(struct thread *td, struct l_ucontext *uc) +{ + mcontext_t mc; + + bzero(&mc, sizeof(mc)); + mc.mc_ownedfp = _MC_FPOWNED_FPU; + mc.mc_fpformat = _MC_FPFMT_XMM; + + if ((uc->uc_flags & LINUX_UC_FP_XSTATE) != 0) + return (linux_xrstor(td, &mc, &uc->uc_mcontext)); + else + return (linux_fxrstor(td, &mc, &uc->uc_mcontext)); +} + /* * Copied from amd64/amd64/machdep.c - * - * XXX fpu state need? don't think so */ int linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) { struct proc *p; - struct l_ucontext uc; + struct l_rt_sigframe sf; struct l_sigcontext *context; struct trapframe *regs; unsigned long rflags; @@ -471,12 +365,12 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) ksiginfo_t ksi; regs = td->td_frame; - error = copyin((void *)regs->tf_rbx, &uc, sizeof(uc)); + error = copyin((void *)regs->tf_rbx, &sf, sizeof(sf)); if (error != 0) return (error); p = td->td_proc; - context = &uc.uc_mcontext; + context = &sf.sf_uc.uc_mcontext; rflags = context->sc_rflags; /* @@ -515,7 +409,7 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) return (EINVAL); } - linux_to_bsd_sigset(&uc.uc_sigmask, &bmask); + linux_to_bsd_sigset(&sf.sf_uc.uc_sigmask, &bmask); kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0); regs->tf_rdi = context->sc_rdi; @@ -539,10 +433,82 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) regs->tf_err = context->sc_err; regs->tf_rflags = rflags; + error = linux_copyin_fpstate(td, &sf.sf_uc); + if (error != 0) { + uprintf("pid %d comm %s linux can't restore fpu state %d\n", + p->p_pid, p->p_comm, error); + return (error); + } + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); return (EJUSTRETURN); } +static int +linux_fxsave(mcontext_t *mcp, void *ufp) +{ + struct l_fpstate *fx = (struct l_fpstate *)&mcp->mc_fpstate[0]; + + bzero(&fx->reserved2[0], sizeof(fx->reserved2)); + return (copyout(fx, ufp, sizeof(*fx))); +} + +static int +linux_xsave(mcontext_t *mcp, char *xfpusave, char *ufp) +{ + struct l_fpstate *fx = (struct l_fpstate *)&mcp->mc_fpstate[0]; + uint32_t magic2; + int error; + + /* Legacy region of an xsave area. */ + fx->sw_reserved.magic1 = LINUX_FP_XSTATE_MAGIC1; + fx->sw_reserved.xstate_size = mcp->mc_xfpustate_len + sizeof(*fx); + fx->sw_reserved.extended_size = fx->sw_reserved.xstate_size + + LINUX_FP_XSTATE_MAGIC2_SIZE; + fx->sw_reserved.xfeatures = xsave_mask; + + error = copyout(fx, ufp, sizeof(*fx)); + if (error != 0) + return (error); + ufp += sizeof(*fx); + + /* Extended region of an xsave area. */ + error = copyout(xfpusave, ufp, mcp->mc_xfpustate_len); + if (error != 0) + return (error); + + /* Linux specific end of xsave area marker. */ + ufp += mcp->mc_xfpustate_len; + magic2 = LINUX_FP_XSTATE_MAGIC2; + return (copyout(&magic2, ufp, LINUX_FP_XSTATE_MAGIC2_SIZE)); +} + +static int +linux_copyout_fpstate(struct thread *td, struct l_ucontext *uc, char **sp) +{ + size_t xfpusave_len; + char *xfpusave; + mcontext_t mc; + char *ufp = *sp; + + get_fpcontext(td, &mc, &xfpusave, &xfpusave_len); + KASSERT(mc.mc_fpformat != _MC_FPFMT_NODEV, ("fpu not present")); + + /* Room for fxsave area. */ + ufp -= sizeof(struct l_fpstate); + if (xfpusave != NULL) { + /* Room for xsave area. */ + ufp -= (xfpusave_len + LINUX_FP_XSTATE_MAGIC2_SIZE); + uc->uc_flags |= LINUX_UC_FP_XSTATE; + } + *sp = ufp = (char *)((unsigned long)ufp & ~0x3Ful); + + if (xfpusave != NULL) + return (linux_xsave(&mc, xfpusave, ufp)); + else + return (linux_fxsave(&mc, ufp)); +} + /* * copied from amd64/amd64/machdep.c * @@ -555,7 +521,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) struct proc *p; struct thread *td; struct sigacts *psp; - caddr_t sp; + char *sp; struct trapframe *regs; int sig, code; int oonstack, issiginfo; @@ -574,16 +540,37 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) LINUX_CTR4(rt_sendsig, "%p, %d, %p, %u", catcher, sig, mask, code); - /* Save user context. */ bzero(&sf, sizeof(sf)); - bsd_to_linux_sigset(mask, &sf.sf_uc.uc_sigmask); - sf.sf_uc.uc_mcontext.sc_mask = sf.sf_uc.uc_sigmask; - sf.sf_uc.uc_stack.ss_sp = PTROUT(td->td_sigstk.ss_sp); sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE; + /* Allocate space for the signal handler context. */ + if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; + } else + sp = (char *)regs->tf_rsp - 128; + + mtx_unlock(&psp->ps_mtx); + PROC_UNLOCK(p); + + if (linux_copyout_fpstate(td, &sf.sf_uc, &sp) != 0) { + uprintf("pid %d comm %s linux can't save fpu state, killing\n", + p->p_pid, p->p_comm); + PROC_LOCK(p); + sigexit(td, SIGILL); + } + sf.sf_uc.uc_mcontext.sc_fpstate = (register_t)sp; + + /* Make room, keeping the stack aligned. */ + sp -= sizeof(struct l_rt_sigframe); + sfp = (struct l_rt_sigframe *)((unsigned long)sp & ~0xFul); + + /* Save user context. */ + bsd_to_linux_sigset(mask, &sf.sf_uc.uc_sigmask); + sf.sf_uc.uc_mcontext.sc_mask = sf.sf_uc.uc_sigmask; sf.sf_uc.uc_mcontext.sc_rdi = regs->tf_rdi; sf.sf_uc.uc_mcontext.sc_rsi = regs->tf_rsi; sf.sf_uc.uc_mcontext.sc_rdx = regs->tf_rdx; @@ -607,19 +594,6 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) sf.sf_uc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); sf.sf_uc.uc_mcontext.sc_cr2 = (register_t)ksi->ksi_addr; - /* Allocate space for the signal handler context. */ - if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - sp = (caddr_t)td->td_sigstk.ss_sp + td->td_sigstk.ss_size; - } else - sp = (caddr_t)regs->tf_rsp - 128; - sp -= sizeof(struct l_rt_sigframe); - /* Align to 16 bytes. */ - sfp = (struct l_rt_sigframe *)((unsigned long)sp & ~0xFul); - - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(p); - /* Translate the signal. */ sig = bsd_to_linux_signal(sig); /* Fill in POSIX parts. */ @@ -633,6 +607,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) sigexit(td, SIGILL); } + fpstate_drop(td); /* Build the argument list for the signal handler. */ regs->tf_rdi = sig; /* arg 1 in %rdi */ regs->tf_rax = 0; @@ -703,7 +678,7 @@ linux_vsyscall(struct thread *td) struct sysentvec elf_linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, - .sv_fixup = linux_fixup_elf, + .sv_fixup = __elfN(freebsd_fixup), .sv_sendsig = linux_rt_sendsig, .sv_sigcode = &_binary_linux_vdso_so_o_start, .sv_szsigcode = &linux_szsigcode, @@ -712,7 +687,6 @@ struct sysentvec elf_linux_sysvec = { .sv_elf_core_osabi = ELFOSABI_NONE, .sv_elf_core_abi_vendor = LINUX_ABI_VENDOR, .sv_elf_core_prepare_notes = linux64_prepare_notes, - .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS_LA48, @@ -720,8 +694,8 @@ struct sysentvec elf_linux_sysvec = { .sv_psstrings = LINUX_PS_STRINGS_LA48, .sv_psstringssz = sizeof(struct ps_strings), .sv_stackprot = VM_PROT_ALL, - .sv_copyout_auxargs = linux_copyout_auxargs, - .sv_copyout_strings = linux_copyout_strings, + .sv_copyout_auxargs = __linuxN(copyout_auxargs), + .sv_copyout_strings = __linuxN(copyout_strings), .sv_setregs = linux_exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, @@ -729,12 +703,14 @@ struct sysentvec elf_linux_sysvec = { SV_SIG_WAITNDQ | SV_TIMEKEEP, .sv_set_syscall_retval = linux_set_syscall_retval, .sv_fetch_syscall_args = linux_fetch_syscall_args, - .sv_syscallnames = NULL, + .sv_syscallnames = linux_syscallnames, .sv_shared_page_base = LINUX_SHAREDPAGE_LA48, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, .sv_trap = linux_vsyscall, + .sv_hwcap = NULL, + .sv_hwcap2 = NULL, .sv_onexec = linux_on_exec_vmspace, .sv_onexit = linux_on_exit, .sv_ontdexit = linux_thread_dtor, @@ -750,7 +726,7 @@ linux_on_exec_vmspace(struct proc *p, struct image_params *imgp) error = linux_map_vdso(p, linux_vdso_obj, linux_vdso_base, LINUX_VDSOPAGE_SIZE, imgp); if (error == 0) - linux_on_exec(p, imgp); + error = linux_on_exec(p, imgp); return (error); } @@ -772,7 +748,7 @@ linux_exec_sysvec_init(void *param) tkoff = kern_timekeep_base - linux_vdso_base; ktimekeep_base = (l_uintptr_t *)(linux_vdso_mapping + tkoff); - *ktimekeep_base = sv->sv_timekeep_base; + *ktimekeep_base = sv->sv_shared_page_base + sv->sv_timekeep_offset; tkoff = kern_tsc_selector - linux_vdso_base; ktsc_selector = (l_uintptr_t *)(linux_vdso_mapping + tkoff); @@ -879,37 +855,11 @@ linux_vdso_reloc(char *mapping, Elf_Addr offset) } } -static char GNULINUX_ABI_VENDOR[] = "GNU"; -static int GNULINUX_ABI_DESC = 0; - -static bool -linux_trans_osrel(const Elf_Note *note, int32_t *osrel) -{ - const Elf32_Word *desc; - uintptr_t p; - - p = (uintptr_t)(note + 1); - p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); - - desc = (const Elf32_Word *)p; - if (desc[0] != GNULINUX_ABI_DESC) - return (false); - - /* - * For Linux we encode osrel using the Linux convention of - * (version << 16) | (major << 8) | (minor) - * See macro in linux_mib.h - */ - *osrel = LINUX_KERNVER(desc[1], desc[2], desc[3]); - - return (true); -} - static Elf_Brandnote linux64_brandnote = { - .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR), + .hdr.n_namesz = sizeof(GNU_ABI_VENDOR), .hdr.n_descsz = 16, .hdr.n_type = 1, - .vendor = GNULINUX_ABI_VENDOR, + .vendor = GNU_ABI_VENDOR, .flags = BN_TRANSLATE_OSREL, .trans_osrel = linux_trans_osrel }; @@ -918,7 +868,6 @@ static Elf64_Brandinfo linux_glibc2brand = { .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib64/ld-linux-x86-64.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -930,7 +879,6 @@ static Elf64_Brandinfo linux_glibc2brandshort = { .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib64/ld-linux.so.2", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -942,7 +890,6 @@ static Elf64_Brandinfo linux_muslbrand = { .brand = ELFOSABI_LINUX, .machine = EM_X86_64, .compat_3_brand = "Linux", - .emul_path = linux_emul_path, .interp_path = "/lib/ld-musl-x86_64.so.1", .sysvec = &elf_linux_sysvec, .interp_newpath = NULL, @@ -951,7 +898,7 @@ static Elf64_Brandinfo linux_muslbrand = { LINUX_BI_FUTEX_REQUEUE }; -Elf64_Brandinfo *linux_brandlist[] = { +static Elf64_Brandinfo *linux_brandlist[] = { &linux_glibc2brand, &linux_glibc2brandshort, &linux_muslbrand, |