Kernel: Move GDT to Processor
This commit is contained in:
@@ -1,68 +1,35 @@
|
||||
#include <BAN/Array.h>
|
||||
#include <kernel/GDT.h>
|
||||
#include <kernel/Debug.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace Kernel::GDT
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
struct TaskStateSegment
|
||||
GDT* GDT::create()
|
||||
{
|
||||
uint32_t reserved1;
|
||||
uint64_t rsp0;
|
||||
uint64_t rsp1;
|
||||
uint64_t rsp2;
|
||||
uint64_t reserved2;
|
||||
uint64_t ist1;
|
||||
uint64_t ist2;
|
||||
uint64_t ist3;
|
||||
uint64_t ist4;
|
||||
uint64_t ist5;
|
||||
uint64_t ist6;
|
||||
uint64_t ist7;
|
||||
uint64_t reserved3;
|
||||
uint16_t reserved4;
|
||||
uint16_t iopb;
|
||||
} __attribute__((packed));
|
||||
auto* gdt = new GDT();
|
||||
ASSERT(gdt);
|
||||
|
||||
union SegmentDescriptor
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t limit1;
|
||||
uint16_t base1;
|
||||
uint8_t base2;
|
||||
uint8_t access;
|
||||
uint8_t limit2 : 4;
|
||||
uint8_t flags : 4;
|
||||
uint8_t base3;
|
||||
} __attribute__((packed));
|
||||
gdt->write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
gdt->write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||
gdt->write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||
gdt->write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xA); // user code
|
||||
gdt->write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||
gdt->write_tss();
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
} __attribute__((packed));
|
||||
gdt->flush_gdt();
|
||||
gdt->flush_tss();
|
||||
|
||||
} __attribute__((packed));
|
||||
return gdt;
|
||||
}
|
||||
|
||||
struct GDTR
|
||||
{
|
||||
uint16_t size;
|
||||
uint64_t address;
|
||||
} __attribute__((packed));
|
||||
|
||||
static constexpr uint16_t s_tss_offset = 0x28;
|
||||
|
||||
static TaskStateSegment s_tss;
|
||||
static BAN::Array<SegmentDescriptor, 7> s_gdt; // null, kernel code, kernel data, user code, user data, tss low, tss high
|
||||
static GDTR s_gdtr;
|
||||
|
||||
static void 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);
|
||||
uint8_t idx = offset / sizeof(SegmentDescriptor);
|
||||
|
||||
SegmentDescriptor& desc = s_gdt[offset / sizeof(SegmentDescriptor)];
|
||||
auto& desc = m_gdt[idx];
|
||||
desc.base1 = (base >> 0) & 0xFFFF;
|
||||
desc.base2 = (base >> 16) & 0xFF;
|
||||
desc.base3 = (base >> 24) & 0xFF;
|
||||
@@ -75,49 +42,18 @@ namespace Kernel::GDT
|
||||
desc.flags = flags & 0x0F;
|
||||
}
|
||||
|
||||
static void write_tss()
|
||||
void GDT::write_tss()
|
||||
{
|
||||
memset(&s_tss, 0x00, sizeof(TaskStateSegment));
|
||||
s_tss.iopb = sizeof(TaskStateSegment);
|
||||
memset(&m_tss, 0x00, sizeof(TaskStateSegment));
|
||||
m_tss.iopb = sizeof(TaskStateSegment);
|
||||
|
||||
uint64_t base = (uint64_t)&s_tss;
|
||||
uint64_t base = reinterpret_cast<uint64_t>(&m_tss);
|
||||
|
||||
write_entry(s_tss_offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||
write_entry(0x28, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||
|
||||
SegmentDescriptor& desc = s_gdt[s_tss_offset / sizeof(SegmentDescriptor) + 1];
|
||||
auto& desc = m_gdt[0x30 / sizeof(SegmentDescriptor)];
|
||||
desc.low = base >> 32;
|
||||
desc.high = 0;
|
||||
}
|
||||
|
||||
void set_tss_stack(uintptr_t rsp)
|
||||
{
|
||||
s_tss.rsp0 = rsp;
|
||||
}
|
||||
|
||||
static void flush_gdt()
|
||||
{
|
||||
asm volatile("lgdt %0" :: "m"(s_gdtr));
|
||||
}
|
||||
|
||||
static void flush_tss()
|
||||
{
|
||||
asm volatile("ltr %0" :: "m"(s_tss_offset));
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
s_gdtr.address = (uint64_t)&s_gdt;
|
||||
s_gdtr.size = s_gdt.size() * sizeof(SegmentDescriptor) - 1;
|
||||
|
||||
write_entry(0x00, 0x00000000, 0x00000, 0x00, 0x0); // null
|
||||
write_entry(0x08, 0x00000000, 0xFFFFF, 0x9A, 0xA); // kernel code
|
||||
write_entry(0x10, 0x00000000, 0xFFFFF, 0x92, 0xC); // kernel data
|
||||
write_entry(0x18, 0x00000000, 0xFFFFF, 0xFA, 0xA); // user code
|
||||
write_entry(0x20, 0x00000000, 0xFFFFF, 0xF2, 0xC); // user data
|
||||
write_tss();
|
||||
|
||||
flush_gdt();
|
||||
flush_tss();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user