kernel/x86_64: add a compatibility syscalls table.

* install syscall handlers in compatibility mode.
* copy the syscall entry in the compatibility commpage, ATM only for Intel
SYSENTER.
* copy the thread exit handler in the compatibility commpage.

Change-Id: Ic350799938815194377d8a4560cb106fe7366cc6
This commit is contained in:
Jérôme Duval
2018-06-05 17:13:08 +00:00
parent 0d1e94a465
commit bdd7dae89c
3 changed files with 170 additions and 16 deletions
@@ -9,7 +9,13 @@
#include <KernelExport.h>
#ifdef _COMPAT_MODE
# include <commpage_compat.h>
#endif
#include <cpu.h>
#ifdef _COMPAT_MODE
# include <elf.h>
#endif
#include <smp.h>
@@ -17,6 +23,30 @@
extern "C" void x86_64_syscall_entry(void);
#ifdef _COMPAT_MODE
// SYSCALL/SYSENTER handlers (in entry_compat.S).
extern "C" {
void x86_64_syscall32_entry(void);
void x86_64_sysenter32_entry(void);
}
void (*gX86SetSyscallStack)(addr_t stackTop) = NULL;
// user syscall assembly stubs
extern "C" void x86_user_syscall_sysenter(void);
extern unsigned int x86_user_syscall_sysenter_end;
extern "C" void x86_user_syscall_syscall(void);
extern unsigned int x86_user_syscall_syscall_end;
extern "C" void x86_sysenter32_userspace_thread_exit(void);
extern unsigned int x86_sysenter32_userspace_thread_exit_end;
#endif // _COMPAT_MODE
static void
init_syscall_registers(void* dummy, int cpuNum)
{
@@ -32,6 +62,11 @@ init_syscall_registers(void* dummy, int cpuNum)
// Entry point address.
x86_write_msr(IA32_MSR_LSTAR, (addr_t)x86_64_syscall_entry);
#ifdef _COMPAT_MODE
// Syscall compat entry point address.
x86_write_msr(IA32_MSR_CSTAR, (addr_t)x86_64_syscall32_entry);
#endif
// Segments that will be set upon entry and return. This is very strange
// and requires a specific ordering of segments in the GDT. Upon entry:
// - CS is set to IA32_STAR[47:32]
@@ -59,3 +94,58 @@ x86_initialize_syscall(void)
// need to use the commpage. Tell all CPUs to initialize the SYSCALL MSRs.
call_all_cpus_sync(&init_syscall_registers, NULL);
}
#ifdef _COMPAT_MODE
static void
set_intel_syscall_stack(addr_t stackTop)
{
x86_write_msr(IA32_MSR_SYSENTER_ESP, stackTop);
}
static void
init_intel_syscall_registers(void* dummy, int cpuNum)
{
x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SELECTOR);
x86_write_msr(IA32_MSR_SYSENTER_ESP, 0);
x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_64_sysenter32_entry);
gX86SetSyscallStack = &set_intel_syscall_stack;
}
void
x86_compat_initialize_syscall(void)
{
// for 32-bit syscalls, fill the commpage with the right mechanism
call_all_cpus_sync(&init_intel_syscall_registers, NULL);
void* syscallCode = (void *)&x86_user_syscall_sysenter;
void* syscallCodeEnd = &x86_user_syscall_sysenter_end;
// TODO check AMD for sysenter
// fill in the table entry
size_t len = (size_t)((addr_t)syscallCodeEnd - (addr_t)syscallCode);
addr_t position = fill_commpage_compat_entry(COMMPAGE_ENTRY_X86_SYSCALL,
syscallCode, len);
image_id image = get_commpage_compat_image();
elf_add_memory_image_symbol(image, "commpage_compat_syscall", position,
len, B_SYMBOL_TYPE_TEXT);
void* threadExitCode = (void *)&x86_sysenter32_userspace_thread_exit;
void* threadExitCodeEnd = &x86_sysenter32_userspace_thread_exit_end;
len = (size_t)((addr_t)threadExitCodeEnd - (addr_t)threadExitCode);
position = fill_commpage_compat_entry(COMMPAGE_ENTRY_X86_THREAD_EXIT,
threadExitCode, len);
elf_add_memory_image_symbol(image, "commpage_compat_thread_exit",
position, len, B_SYMBOL_TYPE_TEXT);
}
#endif // _COMPAT_MODE
@@ -0,0 +1,73 @@
/*
* Copyright 2018, Jérôme Duval, [email protected].
* Copyright 2008, Ingo Weinhold, [email protected].
* Copyright 2004-2010, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
/*! Big case statement for dispatching syscalls, as well as the generic
syscall interface.
*/
#include <syscalls.h>
#include <arch_config.h>
#include <arch/system_info.h>
#include <cpu.h>
#include <debug.h>
#include <disk_device_manager/ddm_userland_interface.h>
#include <elf.h>
#include <frame_buffer_console.h>
#include <fs/fd.h>
#include <fs/node_monitor.h>
#include <generic_syscall.h>
#include <int.h>
#include <kernel.h>
#include <kimage.h>
#include <ksignal.h>
#include <ksyscalls.h>
#include <ksystem_info.h>
#include <messaging.h>
#include <port.h>
#include <posix/realtime_sem.h>
#include <posix/xsi_message_queue.h>
#include <posix/xsi_semaphore.h>
#include <real_time_clock.h>
#include <safemode.h>
#include <sem.h>
#include <sys/resource.h>
#include <system_profiler.h>
#include <thread.h>
#include <tracing.h>
#include <user_atomic.h>
#include <user_mutex.h>
#include <usergroup.h>
#include <UserTimer.h>
#include <util/AutoLock.h>
#include <vfs.h>
#include <vm/vm.h>
#include <wait_for_objects.h>
status_t _user_generic_syscall(const char* userSubsystem, uint32 function,
void* buffer, size_t bufferSize);
int _user_is_computer_on(void);
#include "syscall_numbers.h"
#define kSyscallCount kSyscallCompatCount
#define kSyscallInfos kSyscallCompatInfos
#define kExtendedSyscallInfos kExtendedSyscallCompatInfos
extern const int kSyscallCount;
extern const syscall_info kSyscallInfos[];
extern const extended_syscall_info kExtendedSyscallInfos[];
/*
* kSyscallCount and kSyscallInfos here
*/
// generated by gensyscalls
#include "syscall_table.h"
+7 -16
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2018, Jérôme Duval, [email protected].
* Copyright 2010, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -10,20 +11,9 @@
void x86_initialize_syscall();
#ifdef __x86_64__
static inline void
x86_set_syscall_stack(addr_t stackTop)
{
// Nothing to do here, the thread's stack pointer is always accessible
// via the GS segment.
}
#else
#if defined(__x86_64__) && defined(_COMPAT_MODE)
void x86_compat_initialize_syscall();
#endif
extern void (*gX86SetSyscallStack)(addr_t stackTop);
@@ -32,11 +22,12 @@ extern void (*gX86SetSyscallStack)(addr_t stackTop);
static inline void
x86_set_syscall_stack(addr_t stackTop)
{
#if !defined(__x86_64__) || defined(_COMPAT_MODE)
// TODO on x86_64, only necessary for 32-bit threads
if (gX86SetSyscallStack != NULL)
gX86SetSyscallStack(stackTop);
#endif
}
#endif // __x86_64__
#endif // _KERNEL_ARCH_X86_SYSCALLS_H