Skip site navigation (1)Skip section navigation (2)
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>