Kernel: Only save/load sse state when it is used
There is no need to save and load sse state on every interrupt. Instead we can use CR0.TS to make threads trigger an interrupt when they use sse instructions. This can be used to only save and load sse state when needed. Processor now keeps track of its current "sse thread" and the scheduler either enabled or disabled sse based on which thread it is starting up. When a thread dies, it checks if it was the current sse thread to avoid use after free bugs. When load balancing, processor has to save the thread's sse state before sending it to a new processor (if it was the current sse thread). This ensures thread's sse state will be correct when the new processor ends up loading it.
This commit is contained in:
@@ -120,6 +120,9 @@ namespace Kernel
|
||||
static void update_tsc();
|
||||
static uint64_t ns_since_boot_tsc();
|
||||
|
||||
static Thread* get_current_sse_thread() { return read_gs_sized<Thread*>(offsetof(Processor, m_sse_thread)); };
|
||||
static void set_current_sse_thread(Thread* thread) { write_gs_sized<Thread*>(offsetof(Processor, m_sse_thread), thread); };
|
||||
|
||||
static paddr_t shared_page_paddr() { return s_shared_page_paddr; }
|
||||
static volatile API::SharedPage& shared_page() { return *reinterpret_cast<API::SharedPage*>(s_shared_page_vaddr); }
|
||||
|
||||
@@ -133,6 +136,21 @@ namespace Kernel
|
||||
static void load_fsbase();
|
||||
static void load_gsbase();
|
||||
|
||||
static void disable_sse()
|
||||
{
|
||||
uintptr_t dummy;
|
||||
#if ARCH(x86_64)
|
||||
asm volatile("movq %%cr0, %0; orq $0x08, %0; movq %0, %%cr0" : "=r"(dummy));
|
||||
#elif ARCH(i686)
|
||||
asm volatile("movl %%cr0, %0; orl $0x08, %0; movl %0, %%cr0" : "=r"(dummy));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void enable_sse()
|
||||
{
|
||||
asm volatile("clts");
|
||||
}
|
||||
|
||||
private:
|
||||
Processor() = default;
|
||||
~Processor() { ASSERT_NOT_REACHED(); }
|
||||
@@ -194,6 +212,8 @@ namespace Kernel
|
||||
|
||||
vaddr_t m_thread_syscall_stack;
|
||||
|
||||
Thread* m_sse_thread { nullptr };
|
||||
|
||||
static constexpr size_t s_stack_size { 4096 };
|
||||
void* m_stack { nullptr };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user