banan-os/kernel/kernel/Processor.cpp

77 lines
1.6 KiB
C++

#include <kernel/Memory/kmalloc.h>
#include <kernel/Processor.h>
#include <kernel/Thread.h>
namespace Kernel
{
static constexpr uint32_t MSR_IA32_GS_BASE = 0xC0000101;
ProcessorID Processor::s_bsb_id { PROCESSOR_NONE };
static BAN::Array<Processor, 0xFF> s_processors;
static ProcessorID read_processor_id()
{
uint8_t id;
asm volatile(
"movl $1, %%eax;"
"cpuid;"
"shrl $24, %%ebx;"
"movb %%bl, %0;"
: "=rm"(id)
:: "eax", "ebx", "ecx", "edx"
);
return id;
}
Processor& Processor::create(ProcessorID id)
{
// bsb is the first processor
if (s_bsb_id == PROCESSOR_NONE)
s_bsb_id = id = read_processor_id();
auto& processor = s_processors[id];
ASSERT(processor.m_id == PROCESSOR_NONE);
processor.m_id = id;
processor.m_stack = kmalloc(s_stack_size, 4096, true);
ASSERT(processor.m_stack);
processor.m_gdt = GDT::create();
ASSERT(processor.m_gdt);
processor.m_idt = IDT::create();
ASSERT(processor.m_idt);
return processor;
}
Processor& Processor::initialize()
{
auto id = read_processor_id();
auto& processor = s_processors[id];
// set gs base to pointer to this processor
uint64_t ptr = reinterpret_cast<uint64_t>(&processor);
asm volatile("wrmsr" :: "d"(ptr >> 32), "a"(ptr), "c"(MSR_IA32_GS_BASE));
ASSERT(processor.m_gdt);
processor.gdt().load();
ASSERT(processor.m_idt);
processor.idt().load();
return processor;
}
void Processor::allocate_idle_thread()
{
ASSERT(idle_thread() == nullptr);
auto* idle_thread = MUST(Thread::create_kernel([](void*) { for (;;) asm volatile("hlt"); }, nullptr, nullptr));
write_gs_ptr(offsetof(Processor, m_idle_thread), idle_thread);
}
}