kernel/x86: add ability to set GS segment base from userland
Needed for Wine. Co-authored-by: Jérôme Duval <[email protected]> Change-Id: I13f6a5802fce04fd2ebb4cc01ecd2f12c90830db Reviewed-on: https://review.haiku-os.org/c/haiku/+/4839 Reviewed-by: Jérôme Duval <[email protected]> Reviewed-by: X512 <[email protected]> Reviewed-by: Fredrik Holmqvist <[email protected]> Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
co-authored by
Jérôme Duval
parent
397102c17d
commit
b19f5c839b
@@ -48,6 +48,8 @@ struct arch_thread {
|
|||||||
|
|
||||||
uintptr_t* current_stack;
|
uintptr_t* current_stack;
|
||||||
uintptr_t instruction_pointer;
|
uintptr_t instruction_pointer;
|
||||||
|
|
||||||
|
uint64 user_gs_base;
|
||||||
#else
|
#else
|
||||||
struct farcall current_stack;
|
struct farcall current_stack;
|
||||||
struct farcall interrupt_stack;
|
struct farcall interrupt_stack;
|
||||||
|
|||||||
@@ -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 */
|
||||||
@@ -13,9 +13,11 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arch_thread_defs.h>
|
||||||
#include <commpage.h>
|
#include <commpage.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <generic_syscall.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <ksignal.h>
|
#include <ksignal.h>
|
||||||
#include <int.h>
|
#include <int.h>
|
||||||
@@ -96,6 +98,7 @@ x86_set_tls_context(Thread* thread)
|
|||||||
{
|
{
|
||||||
// Set FS segment base address to the TLS segment.
|
// 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_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 -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -172,6 +201,9 @@ arch_thread_init(kernel_args* args)
|
|||||||
"fxsaveq %0"
|
"fxsaveq %0"
|
||||||
:: "m" (sInitialState.fpu_state));
|
:: "m" (sInitialState.fpu_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register_generic_syscall(THREAD_SYSCALLS, arch_thread_control, 1, 0);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ SubDirHdrs $(SUBDIR) timers ;
|
|||||||
|
|
||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
UsePrivateHeaders [ FDirName system arch x86 ] ;
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) paging ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) paging ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ;
|
||||||
|
|||||||
Reference in New Issue
Block a user