Kernel/LibC: Replace SYS_{GET,SET}_TLS with SYS_{SET,GET}_{FS,GS}BASE

This allows userspace to use both registers
This commit is contained in:
2025-11-10 21:48:38 +02:00
parent 7a68ce7e94
commit 89c0ff1a9d
17 changed files with 165 additions and 46 deletions

View File

@@ -29,7 +29,8 @@ namespace Kernel
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
#if ARCH(i686)
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
gdt->write_entry(0x30, 0x00000000, 0x00000, 0x00, 0x0); // tls
gdt->write_entry(0x30, 0x00000000, 0x00000, 0x00, 0x0); // fsbase
gdt->write_entry(0x38, 0x00000000, 0x00000, 0x00, 0x0); // gsbase
#endif
gdt->write_tss();
@@ -37,10 +38,14 @@ namespace Kernel
}
#if ARCH(i686)
void GDT::set_tls(uintptr_t addr)
void GDT::set_fsbase(uintptr_t addr)
{
write_entry(0x30, addr, 0xFFFF, 0xF2, 0xC);
}
void GDT::set_gsbase(uintptr_t addr)
{
write_entry(0x38, addr, 0xFFFF, 0xF2, 0xC);
}
#endif
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)

View File

@@ -173,7 +173,15 @@ namespace Kernel
auxiliary_vector.span()
));
if (tls_addr.has_value())
thread->set_tls(*tls_addr);
{
#if ARCH(x86_64)
thread->set_fsbase(*tls_addr);
#elif ARCH(i686)
thread->set_gsbase(*tls_addr);
#else
#error
#endif
}
process->add_thread(thread);
process->register_to_scheduler();
@@ -730,7 +738,13 @@ namespace Kernel
{
auto tls_result = TRY(initialize_thread_local_storage(*new_page_table, *executable.master_tls));
TRY(new_mapped_regions.emplace_back(BAN::move(tls_result.region)));
new_thread->set_tls(tls_result.addr);
#if ARCH(x86_64)
new_thread->set_fsbase(tls_result.addr);
#elif ARCH(i686)
new_thread->set_gsbase(tls_result.addr);
#else
#error
#endif
}
// NOTE: this is done before disabling interrupts and moving the threads as
@@ -3016,16 +3030,28 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_set_tls(void* addr)
BAN::ErrorOr<long> Process::sys_set_fsbase(void* addr)
{
Thread::current().set_tls(reinterpret_cast<vaddr_t>(addr));
Processor::load_tls();
Thread::current().set_fsbase(reinterpret_cast<vaddr_t>(addr));
Processor::load_fsbase();
return 0;
}
BAN::ErrorOr<long> Process::sys_get_tls()
BAN::ErrorOr<long> Process::sys_get_fsbase()
{
return Thread::current().get_tls();
return Thread::current().get_fsbase();
}
BAN::ErrorOr<long> Process::sys_set_gsbase(void* addr)
{
Thread::current().set_gsbase(reinterpret_cast<vaddr_t>(addr));
Processor::load_gsbase();
return 0;
}
BAN::ErrorOr<long> Process::sys_get_gsbase()
{
return Thread::current().get_gsbase();
}
BAN::ErrorOr<long> Process::sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg)

View File

@@ -12,6 +12,7 @@ namespace Kernel
#if ARCH(x86_64)
static constexpr uint32_t MSR_IA32_FS_BASE = 0xC0000100;
static constexpr uint32_t MSR_IA32_GS_BASE = 0xC0000101;
static constexpr uint32_t MSR_IA32_KERNEL_GS_BASE = 0xC0000102;
#endif
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
@@ -265,15 +266,52 @@ namespace Kernel
set_interrupt_state(state);
}
void Processor::load_tls()
void Processor::load_segments()
{
const auto addr = scheduler().current_thread().get_tls();
{
const auto addr = scheduler().current_thread().get_fsbase();
#if ARCH(x86_64)
uint32_t ptr_hi = addr >> 32;
uint32_t ptr_lo = addr & 0xFFFFFFFF;
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
#elif ARCH(i686)
gdt().set_fsbase(addr);
#endif
}
{
const auto addr = scheduler().current_thread().get_gsbase();
#if ARCH(x86_64)
uint32_t ptr_hi = addr >> 32;
uint32_t ptr_lo = addr & 0xFFFFFFFF;
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
#elif ARCH(i686)
gdt().set_gsbase(addr);
#endif
}
}
void Processor::load_fsbase()
{
const auto addr = scheduler().current_thread().get_fsbase();
#if ARCH(x86_64)
uint32_t ptr_hi = addr >> 32;
uint32_t ptr_lo = addr & 0xFFFFFFFF;
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_FS_BASE));
#elif ARCH(i686)
gdt().set_tls(addr);
gdt().set_fsbase(addr);
#endif
}
void Processor::load_gsbase()
{
const auto addr = scheduler().current_thread().get_gsbase();
#if ARCH(x86_64)
uint32_t ptr_hi = addr >> 32;
uint32_t ptr_lo = addr & 0xFFFFFFFF;
asm volatile("wrmsr" :: "d"(ptr_hi), "a"(ptr_lo), "c"(MSR_IA32_KERNEL_GS_BASE));
#elif ARCH(i686)
gdt().set_gsbase(addr);
#endif
}

View File

@@ -282,7 +282,8 @@ namespace Kernel
}
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
Processor::load_tls();
if (thread->is_userspace())
Processor::load_segments();
*interrupt_stack = thread->interrupt_stack();
*interrupt_registers = thread->interrupt_registers();

View File

@@ -328,7 +328,8 @@ namespace Kernel
thread->m_kernel_stack = TRY(m_kernel_stack->clone(new_process->page_table()));
thread->m_userspace_stack = TRY(m_userspace_stack->clone(new_process->page_table()));
thread->m_tls = m_tls;
thread->m_fsbase = m_fsbase;
thread->m_gsbase = m_gsbase;
thread->m_state = State::NotStarted;