From b19f5c839b2fb834ab15d9432bd3b7a09f9223da Mon Sep 17 00:00:00 2001 From: X512 Date: Fri, 31 Dec 2021 01:22:08 +0900 Subject: [PATCH] kernel/x86: add ability to set GS segment base from userland MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for Wine. Co-authored-by: Jérôme Duval Change-Id: I13f6a5802fce04fd2ebb4cc01ecd2f12c90830db Reviewed-on: https://review.haiku-os.org/c/haiku/+/4839 Reviewed-by: Jérôme Duval Reviewed-by: X512 Reviewed-by: Fredrik Holmqvist Reviewed-by: waddlesplash Tested-by: Commit checker robot --- .../kernel/arch/x86/arch_thread_types.h | 2 ++ .../system/arch/x86/arch_thread_defs.h | 13 ++++++++ src/system/kernel/arch/x86/64/thread.cpp | 32 +++++++++++++++++++ src/system/kernel/arch/x86/Jamfile | 1 + 4 files changed, 48 insertions(+) create mode 100644 headers/private/system/arch/x86/arch_thread_defs.h diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 5f124bd99e..8da03e8e65 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -48,6 +48,8 @@ struct arch_thread { uintptr_t* current_stack; uintptr_t instruction_pointer; + + uint64 user_gs_base; #else struct farcall current_stack; struct farcall interrupt_stack; diff --git a/headers/private/system/arch/x86/arch_thread_defs.h b/headers/private/system/arch/x86/arch_thread_defs.h new file mode 100644 index 0000000000..2975b0e274 --- /dev/null +++ b/headers/private/system/arch/x86/arch_thread_defs.h @@ -0,0 +1,13 @@ +/* + * Copyright 2022, The Haiku Team. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _X86_THREAD_DEFS_H +#define _X86_THREAD_DEFS_H + + +#define THREAD_SYSCALLS "thread" +#define THREAD_SET_GS_BASE 1 + + +#endif /* _X86_THREAD_DEFS_H */ diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 25df19b8ac..7a35c88427 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -13,9 +13,11 @@ #include +#include #include #include #include +#include #include #include #include @@ -96,6 +98,7 @@ x86_set_tls_context(Thread* thread) { // Set FS segment base address to the TLS segment. x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); + x86_write_msr(IA32_MSR_KERNEL_GS_BASE, thread->arch_info.user_gs_base); } @@ -135,6 +138,32 @@ get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action, } +static status_t +arch_thread_control(const char* subsystem, uint32 function, void* buffer, + size_t bufferSize) +{ + switch (function) { + case THREAD_SET_GS_BASE: + { + uint64 base; + if (bufferSize != sizeof(base)) + return B_BAD_VALUE; + + if (!IS_USER_ADDRESS(buffer) + || user_memcpy(&base, buffer, sizeof(base)) < B_OK) { + return B_BAD_ADDRESS; + } + + Thread* thread = thread_get_current_thread(); + thread->arch_info.user_gs_base = base; + x86_write_msr(IA32_MSR_KERNEL_GS_BASE, base); + return B_OK; + } + } + return B_BAD_HANDLER; +} + + // #pragma mark - @@ -172,6 +201,9 @@ arch_thread_init(kernel_args* args) "fxsaveq %0" :: "m" (sInitialState.fpu_state)); } + + register_generic_syscall(THREAD_SYSCALLS, arch_thread_control, 1, 0); + return B_OK; } diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 4858ec18c2..08a40cc045 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -11,6 +11,7 @@ SubDirHdrs $(SUBDIR) timers ; UsePrivateKernelHeaders ; UsePrivateHeaders shared ; +UsePrivateHeaders [ FDirName system arch x86 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) paging ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ;