Date: Sat, 9 Jan 2016 20:18:54 +0000 (UTC) From: Dmitry Chagin <dchagin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r293613 - in head/sys: amd64/amd64 amd64/linux amd64/linux32 arm/arm arm64/arm64 compat/ia32 compat/svr4 i386/i386 i386/ibcs2 i386/linux kern mips/mips powerpc/powerpc sparc64/sparc64 sys Message-ID: <201601092018.u09KIsDd011149@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dchagin Date: Sat Jan 9 20:18:53 2016 New Revision: 293613 URL: https://svnweb.freebsd.org/changeset/base/293613 Log: Implement vsyscall hack. Prior to 2.13 glibc uses vsyscall instead of vdso. An upcoming linux_base-c6 needs it. Differential Revision: https://reviews.freebsd.org/D1090 Reviewed by: kib, trasz MFC after: 1 week Modified: head/sys/amd64/amd64/elf_machdep.c head/sys/amd64/amd64/trap.c head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/arm/arm/elf_machdep.c head/sys/arm64/arm64/elf_machdep.c head/sys/compat/ia32/ia32_sysvec.c head/sys/compat/svr4/svr4_sysvec.c head/sys/i386/i386/elf_machdep.c head/sys/i386/ibcs2/ibcs2_sysvec.c head/sys/i386/linux/linux_sysvec.c head/sys/kern/imgact_aout.c head/sys/kern/init_main.c head/sys/mips/mips/elf_machdep.c head/sys/mips/mips/freebsd32_machdep.c head/sys/powerpc/powerpc/elf32_machdep.c head/sys/powerpc/powerpc/elf64_machdep.c head/sys/sparc64/sparc64/elf_machdep.c head/sys/sys/sysent.h Modified: head/sys/amd64/amd64/elf_machdep.c ============================================================================== --- head/sys/amd64/amd64/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/amd64/amd64/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -80,6 +80,7 @@ struct sysentvec elf64_freebsd_sysvec = .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); Modified: head/sys/amd64/amd64/trap.c ============================================================================== --- head/sys/amd64/amd64/trap.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/amd64/amd64/trap.c Sat Jan 9 20:18:53 2016 (r293613) @@ -322,6 +322,13 @@ trap(struct trapframe *frame) break; case T_PAGEFLT: /* page fault */ + /* + * Emulator can take care about this trap? + */ + if (*p->p_sysent->sv_trap != NULL && + (*p->p_sysent->sv_trap)(td) == 0) + goto userout; + addr = frame->tf_addr; i = trap_pfault(frame, TRUE); if (i == -1) Modified: head/sys/amd64/linux/linux_sysvec.c ============================================================================== --- head/sys/amd64/linux/linux_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/amd64/linux/linux_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -129,6 +129,7 @@ static void linux_set_syscall_retval(str static int linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack); +static int linux_vsyscall(struct thread *td); /* * Linux syscalls return negative errno's, we do positive and map them @@ -746,6 +747,53 @@ exec_linux_imgact_try(struct image_param return(error); } +#define LINUX_VSYSCALL_START (-10UL << 20) +#define LINUX_VSYSCALL_SZ 1024 + +const unsigned long linux_vsyscall_vector[] = { + LINUX_SYS_gettimeofday, + LINUX_SYS_linux_time, + /* getcpu not implemented */ +}; + +static int +linux_vsyscall(struct thread *td) +{ + struct trapframe *frame; + uint64_t retqaddr; + int code, traced; + int error; + + frame = td->td_frame; + + /* Check %rip for vsyscall area */ + if (__predict_true(frame->tf_rip < LINUX_VSYSCALL_START)) + return (EINVAL); + if ((frame->tf_rip & (LINUX_VSYSCALL_SZ - 1)) != 0) + return (EINVAL); + code = (frame->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SZ; + if (code >= nitems(linux_vsyscall_vector)) + return (EINVAL); + + /* + * vsyscall called as callq *(%rax), so we must + * use return address from %rsp and also fixup %rsp + */ + error = copyin((void *)frame->tf_rsp, &retqaddr, sizeof(retqaddr)); + if (error) + return (error); + + frame->tf_rip = retqaddr; + frame->tf_rax = linux_vsyscall_vector[code]; + frame->tf_rsp += 8; + + traced = (frame->tf_flags & PSL_T); + + amd64_syscall(td, traced); + + return (0); +} + struct sysentvec elf_linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, @@ -778,7 +826,8 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_base = SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, - .sv_thread_detach = linux_thread_detach + .sv_thread_detach = linux_thread_detach, + .sv_trap = linux_vsyscall, }; static void Modified: head/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/amd64/linux32/linux32_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -1040,6 +1040,7 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; static void Modified: head/sys/arm/arm/elf_machdep.c ============================================================================== --- head/sys/arm/arm/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/arm/arm/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -86,6 +86,7 @@ struct sysentvec elf32_freebsd_sysvec = .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); Modified: head/sys/arm64/arm64/elf_machdep.c ============================================================================== --- head/sys/arm64/arm64/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/arm64/arm64/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -87,6 +87,8 @@ static struct sysentvec elf64_freebsd_sy .sv_shared_page_base = SHAREDPAGE, .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, + .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); Modified: head/sys/compat/ia32/ia32_sysvec.c ============================================================================== --- head/sys/compat/ia32/ia32_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/compat/ia32/ia32_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -134,6 +134,7 @@ struct sysentvec ia32_freebsd_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec); Modified: head/sys/compat/svr4/svr4_sysvec.c ============================================================================== --- head/sys/compat/svr4/svr4_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/compat/svr4/svr4_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -194,6 +194,7 @@ struct sysentvec svr4_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; const char svr4_emul_path[] = "/compat/svr4"; Modified: head/sys/i386/i386/elf_machdep.c ============================================================================== --- head/sys/i386/i386/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/i386/i386/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -87,6 +87,7 @@ struct sysentvec elf32_freebsd_sysvec = .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); Modified: head/sys/i386/ibcs2/ibcs2_sysvec.c ============================================================================== --- head/sys/i386/ibcs2/ibcs2_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/i386/ibcs2/ibcs2_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -90,6 +90,7 @@ struct sysentvec ibcs2_svr3_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static int Modified: head/sys/i386/linux/linux_sysvec.c ============================================================================== --- head/sys/i386/linux/linux_sysvec.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/i386/linux/linux_sysvec.c Sat Jan 9 20:18:53 2016 (r293613) @@ -985,6 +985,7 @@ struct sysentvec linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; INIT_SYSENTVEC(aout_sysvec, &linux_sysvec); @@ -1021,6 +1022,7 @@ struct sysentvec elf_linux_sysvec = { .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = linux_schedtail, .sv_thread_detach = linux_thread_detach, + .sv_trap = NULL, }; static void Modified: head/sys/kern/imgact_aout.c ============================================================================== --- head/sys/kern/imgact_aout.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/kern/imgact_aout.c Sat Jan 9 20:18:53 2016 (r293613) @@ -97,6 +97,7 @@ struct sysentvec aout_sysvec = { .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; #elif defined(__amd64__) Modified: head/sys/kern/init_main.c ============================================================================== --- head/sys/kern/init_main.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/kern/init_main.c Sat Jan 9 20:18:53 2016 (r293613) @@ -414,6 +414,7 @@ struct sysentvec null_sysvec = { .sv_syscallnames = NULL, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; /* Modified: head/sys/mips/mips/elf_machdep.c ============================================================================== --- head/sys/mips/mips/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/mips/mips/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -81,6 +81,7 @@ struct sysentvec elf64_freebsd_sysvec = .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf64_Brandinfo freebsd_brand_info = { @@ -135,6 +136,7 @@ struct sysentvec elf32_freebsd_sysvec = .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf32_Brandinfo freebsd_brand_info = { Modified: head/sys/mips/mips/freebsd32_machdep.c ============================================================================== --- head/sys/mips/mips/freebsd32_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/mips/mips/freebsd32_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -104,6 +104,7 @@ struct sysentvec elf32_freebsd_sysvec = .sv_syscallnames = freebsd32_syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); Modified: head/sys/powerpc/powerpc/elf32_machdep.c ============================================================================== --- head/sys/powerpc/powerpc/elf32_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/powerpc/powerpc/elf32_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -106,6 +106,7 @@ struct sysentvec elf32_freebsd_sysvec = .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); Modified: head/sys/powerpc/powerpc/elf64_machdep.c ============================================================================== --- head/sys/powerpc/powerpc/elf64_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/powerpc/powerpc/elf64_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -85,6 +85,7 @@ struct sysentvec elf64_freebsd_sysvec_v1 .sv_shared_page_len = PAGE_SIZE, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; INIT_SYSENTVEC(elf64_sysvec_v1, &elf64_freebsd_sysvec_v1); Modified: head/sys/sparc64/sparc64/elf_machdep.c ============================================================================== --- head/sys/sparc64/sparc64/elf_machdep.c Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/sparc64/sparc64/elf_machdep.c Sat Jan 9 20:18:53 2016 (r293613) @@ -85,6 +85,7 @@ static struct sysentvec elf64_freebsd_sy .sv_syscallnames = syscallnames, .sv_schedtail = NULL, .sv_thread_detach = NULL, + .sv_trap = NULL, }; static Elf64_Brandinfo freebsd_brand_info = { Modified: head/sys/sys/sysent.h ============================================================================== --- head/sys/sys/sysent.h Sat Jan 9 19:13:25 2016 (r293612) +++ head/sys/sys/sysent.h Sat Jan 9 20:18:53 2016 (r293613) @@ -129,6 +129,7 @@ struct sysentvec { void *sv_shared_page_obj; void (*sv_schedtail)(struct thread *); void (*sv_thread_detach)(struct thread *); + int (*sv_trap)(struct thread *); }; #define SV_ILP32 0x000100 /* 32-bit executable. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601092018.u09KIsDd011149>