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
This commit is contained in:
dchagin 2016-01-09 20:18:53 +00:00
parent f7b2f01ed0
commit e706df7b9a
19 changed files with 77 additions and 1 deletions

View File

@ -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);

View File

@ -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)

View File

@ -129,6 +129,7 @@ static void linux_set_syscall_retval(struct thread *td, int error);
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_params *imgp)
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

View File

@ -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

View File

@ -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);

View File

@ -87,6 +87,8 @@ static struct sysentvec elf64_freebsd_sysvec = {
.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);

View File

@ -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);

View File

@ -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";

View File

@ -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);

View File

@ -90,6 +90,7 @@ struct sysentvec ibcs2_svr3_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
static int

View File

@ -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

View File

@ -97,6 +97,7 @@ struct sysentvec aout_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
#elif defined(__amd64__)

View File

@ -414,6 +414,7 @@ struct sysentvec null_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
/*

View File

@ -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 = {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -85,6 +85,7 @@ static struct sysentvec elf64_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
static Elf64_Brandinfo freebsd_brand_info = {

View File

@ -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. */