hrev51988 adds 1 changeset to branch 'master'
old head: 0d1e94a465bc2a8c40a82395327eaae4649dbc72
new head: bdd7dae89c36aa55ab8eeaff6b442d0c4406664b
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=bdd7dae89c36+%5E0d1e94a465bc
----------------------------------------------------------------------------
bdd7dae89c36: 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
[ Jérôme Duval <jerome.duval@xxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev51988
Commit: bdd7dae89c36aa55ab8eeaff6b442d0c4406664b
URL: https://git.haiku-os.org/haiku/commit/?id=bdd7dae89c36
Author: Jérôme Duval <jerome.duval@xxxxxxxxx>
Date: Tue May 15 16:59:13 2018 UTC
----------------------------------------------------------------------------
3 files changed, 170 insertions(+), 16 deletions(-)
src/system/kernel/arch/x86/64/syscalls.cpp | 90 ++++++++++++++++++++++
src/system/kernel/arch/x86/syscalls_compat.cpp | 73 ++++++++++++++++++
src/system/kernel/arch/x86/x86_syscalls.h | 23 ++----
----------------------------------------------------------------------------
diff --git a/src/system/kernel/arch/x86/64/syscalls.cpp
b/src/system/kernel/arch/x86/64/syscalls.cpp
index 907dd4989d..f71e7ad7f5 100644
--- a/src/system/kernel/arch/x86/64/syscalls.cpp
+++ b/src/system/kernel/arch/x86/64/syscalls.cpp
@@ -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
+
diff --git a/src/system/kernel/arch/x86/syscalls_compat.cpp
b/src/system/kernel/arch/x86/syscalls_compat.cpp
new file mode 100644
index 0000000000..f4d751a5d7
--- /dev/null
+++ b/src/system/kernel/arch/x86/syscalls_compat.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
+ * Copyright 2008, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * 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"
diff --git a/src/system/kernel/arch/x86/x86_syscalls.h
b/src/system/kernel/arch/x86/x86_syscalls.h
index 85ae6d7878..049aacd6ce 100644
--- a/src/system/kernel/arch/x86/x86_syscalls.h
+++ b/src/system/kernel/arch/x86/x86_syscalls.h
@@ -1,4 +1,5 @@
/*
+ * Copyright 2018, Jérôme Duval, jerome.duval@xxxxxxxxx.
* Copyright 2010, Ingo Weinhold, ingo_weinhold@xxxxxx.
* 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