Kernel: Start working on TLS, add SYS_{SET,GET}_TLS
This commit is contained in:
parent
254fd80088
commit
4bcd3ed86f
|
@ -41,11 +41,15 @@ start_userspace_thread:
|
||||||
call get_thread_start_sp
|
call get_thread_start_sp
|
||||||
movl %eax, %esp
|
movl %eax, %esp
|
||||||
|
|
||||||
|
# ds, es = user data
|
||||||
movw $(0x20 | 3), %bx
|
movw $(0x20 | 3), %bx
|
||||||
movw %bx, %ds
|
movw %bx, %ds
|
||||||
movw %bx, %es
|
movw %bx, %es
|
||||||
movw %bx, %fs
|
# gs = thread local
|
||||||
|
movw $(0x30 | 3), %bx
|
||||||
movw %bx, %gs
|
movw %bx, %gs
|
||||||
|
# fs = 0
|
||||||
xorw %bx, %bx
|
xorw %bx, %bx
|
||||||
|
movw %bx, %fs
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
|
@ -128,6 +128,10 @@ namespace Kernel
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ARCH(i686)
|
||||||
|
void set_tls(uintptr_t addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GDT() = default;
|
GDT() = default;
|
||||||
|
|
||||||
|
@ -149,8 +153,8 @@ namespace Kernel
|
||||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||||
static constexpr uint16_t m_tss_offset = 0x28;
|
static constexpr uint16_t m_tss_offset = 0x28;
|
||||||
#elif ARCH(i686)
|
#elif ARCH(i686)
|
||||||
BAN::Array<SegmentDescriptor, 7> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tss
|
BAN::Array<SegmentDescriptor, 8> m_gdt; // null, kernel code, kernel data, user code, user data, processor data, tls, tss
|
||||||
static constexpr uint16_t m_tss_offset = 0x30;
|
static constexpr uint16_t m_tss_offset = 0x38;
|
||||||
#endif
|
#endif
|
||||||
TaskStateSegment m_tss;
|
TaskStateSegment m_tss;
|
||||||
const GDTR m_gdtr {
|
const GDTR m_gdtr {
|
||||||
|
|
|
@ -174,6 +174,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_yield();
|
BAN::ErrorOr<long> sys_yield();
|
||||||
|
BAN::ErrorOr<long> sys_set_tls(void*);
|
||||||
|
BAN::ErrorOr<long> sys_get_tls();
|
||||||
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
BAN::ErrorOr<long> sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg);
|
||||||
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
BAN::ErrorOr<long> sys_pthread_exit(void* value);
|
||||||
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
|
||||||
|
|
|
@ -110,6 +110,8 @@ namespace Kernel
|
||||||
static void send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true);
|
static void send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true);
|
||||||
static void broadcast_smp_message(const SMPMessage&);
|
static void broadcast_smp_message(const SMPMessage&);
|
||||||
|
|
||||||
|
static void load_tls();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Processor() = default;
|
Processor() = default;
|
||||||
~Processor() { ASSERT_NOT_REACHED(); }
|
~Processor() { ASSERT_NOT_REACHED(); }
|
||||||
|
|
|
@ -88,6 +88,9 @@ namespace Kernel
|
||||||
|
|
||||||
bool is_userspace() const { return m_is_userspace; }
|
bool is_userspace() const { return m_is_userspace; }
|
||||||
|
|
||||||
|
void set_tls(vaddr_t tls) { m_tls = tls; }
|
||||||
|
vaddr_t get_tls() const { return m_tls; }
|
||||||
|
|
||||||
size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); }
|
size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); }
|
||||||
size_t physical_page_count() const { return virtual_page_count(); }
|
size_t physical_page_count() const { return virtual_page_count(); }
|
||||||
|
|
||||||
|
@ -121,6 +124,8 @@ namespace Kernel
|
||||||
bool m_is_userspace { false };
|
bool m_is_userspace { false };
|
||||||
bool m_delete_process { false };
|
bool m_delete_process { false };
|
||||||
|
|
||||||
|
vaddr_t m_tls { 0 };
|
||||||
|
|
||||||
SchedulerQueue::Node* m_scheduler_node { nullptr };
|
SchedulerQueue::Node* m_scheduler_node { nullptr };
|
||||||
|
|
||||||
InterruptStack m_interrupt_stack { };
|
InterruptStack m_interrupt_stack { };
|
||||||
|
|
|
@ -26,12 +26,20 @@ namespace Kernel
|
||||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
|
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, data_flags); // user data
|
||||||
#if ARCH(i686)
|
#if ARCH(i686)
|
||||||
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
gdt->write_entry(0x28, reinterpret_cast<uint32_t>(processor), sizeof(Processor), 0x92, 0x4); // processor data
|
||||||
|
gdt->write_entry(0x30, 0x00000000, 0x00000, 0x00, 0x0); // tls
|
||||||
#endif
|
#endif
|
||||||
gdt->write_tss();
|
gdt->write_tss();
|
||||||
|
|
||||||
return gdt;
|
return gdt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ARCH(i686)
|
||||||
|
void GDT::set_tls(uintptr_t addr)
|
||||||
|
{
|
||||||
|
write_entry(0x30, addr, 0xFFFF, 0xF2, 0xC);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
void GDT::write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||||
{
|
{
|
||||||
ASSERT(offset % sizeof(SegmentDescriptor) == 0);
|
ASSERT(offset % sizeof(SegmentDescriptor) == 0);
|
||||||
|
|
|
@ -2037,6 +2037,18 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_set_tls(void* addr)
|
||||||
|
{
|
||||||
|
Thread::current().set_tls(reinterpret_cast<vaddr_t>(addr));
|
||||||
|
Processor::load_tls();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_get_tls()
|
||||||
|
{
|
||||||
|
return Thread::current().get_tls();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg)
|
BAN::ErrorOr<long> Process::sys_pthread_create(const pthread_attr_t* attr, void (*entry)(void*), void* arg)
|
||||||
{
|
{
|
||||||
if (attr != nullptr)
|
if (attr != nullptr)
|
||||||
|
|
|
@ -10,7 +10,10 @@ extern Kernel::TerminalDriver* g_terminal_driver;
|
||||||
namespace Kernel
|
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_GS_BASE = 0xC0000101;
|
||||||
|
#endif
|
||||||
|
|
||||||
ProcessorID Processor::s_bsb_id { PROCESSOR_NONE };
|
ProcessorID Processor::s_bsb_id { PROCESSOR_NONE };
|
||||||
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
||||||
|
@ -260,6 +263,18 @@ namespace Kernel
|
||||||
set_interrupt_state(state);
|
set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Processor::load_tls()
|
||||||
|
{
|
||||||
|
const auto addr = scheduler().current_thread().get_tls();
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi)
|
void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi)
|
||||||
{
|
{
|
||||||
ASSERT(processor_id != current_id());
|
ASSERT(processor_id != current_id());
|
||||||
|
|
|
@ -278,6 +278,7 @@ namespace Kernel
|
||||||
thread->m_state = Thread::State::Executing;
|
thread->m_state = Thread::State::Executing;
|
||||||
|
|
||||||
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
Processor::gdt().set_tss_stack(thread->kernel_stack_top());
|
||||||
|
Processor::load_tls();
|
||||||
*interrupt_stack = thread->interrupt_stack();
|
*interrupt_stack = thread->interrupt_stack();
|
||||||
*interrupt_registers = thread->interrupt_registers();
|
*interrupt_registers = thread->interrupt_registers();
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,8 @@ namespace Kernel
|
||||||
thread->m_kernel_stack = TRY(m_kernel_stack->clone(new_process->page_table()));
|
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_userspace_stack = TRY(m_userspace_stack->clone(new_process->page_table()));
|
||||||
|
|
||||||
|
thread->m_tls = m_tls;
|
||||||
|
|
||||||
thread->m_state = State::NotStarted;
|
thread->m_state = State::NotStarted;
|
||||||
|
|
||||||
thread->m_interrupt_stack.ip = ip;
|
thread->m_interrupt_stack.ip = ip;
|
||||||
|
|
|
@ -91,6 +91,8 @@ __BEGIN_DECLS
|
||||||
O(SYS_SYMLINKAT, symlinkat) \
|
O(SYS_SYMLINKAT, symlinkat) \
|
||||||
O(SYS_HARDLINKAT, hardlinkat) \
|
O(SYS_HARDLINKAT, hardlinkat) \
|
||||||
O(SYS_YIELD, yield) \
|
O(SYS_YIELD, yield) \
|
||||||
|
O(SYS_SET_TLS, set_tls) \
|
||||||
|
O(SYS_GET_TLS, get_tls) \
|
||||||
O(SYS_PTHREAD_CREATE, pthread_create) \
|
O(SYS_PTHREAD_CREATE, pthread_create) \
|
||||||
O(SYS_PTHREAD_EXIT, pthread_exit) \
|
O(SYS_PTHREAD_EXIT, pthread_exit) \
|
||||||
O(SYS_PTHREAD_JOIN, pthread_join) \
|
O(SYS_PTHREAD_JOIN, pthread_join) \
|
||||||
|
|
Loading…
Reference in New Issue