[haiku-commits] haiku: hrev51988 - in src/system/kernel/arch/x86/64: . src/system/kernel/arch/x86

  • From: Jérôme Duval <jerome.duval@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 5 Jun 2018 13:13:11 -0400 (EDT)

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


Other related posts:

  • » [haiku-commits] haiku: hrev51988 - in src/system/kernel/arch/x86/64: . src/system/kernel/arch/x86 - Jérôme Duval