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:
@@ -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"
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user