Kernel: Initialize GDT in kernel code
We dont use the boot GDT only while booting
This commit is contained in:
122
kernel/arch/x86_64/GDT.cpp
Normal file
122
kernel/arch/x86_64/GDT.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <BAN/Assert.h>
|
||||
#include <kernel/GDT.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern "C" uintptr_t g_boot_stack_top[0];
|
||||
|
||||
namespace Kernel::GDT
|
||||
{
|
||||
|
||||
struct TaskStateSegment
|
||||
{
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
} __attribute__((packed));
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct GDTR
|
||||
{
|
||||
uint16_t size;
|
||||
uint64_t address;
|
||||
} __attribute__((packed));
|
||||
|
||||
static TaskStateSegment* s_tss = nullptr;
|
||||
static SegmentDescriptor* s_gdt = nullptr;
|
||||
static GDTR s_gdtr;
|
||||
|
||||
static void write_entry(uint8_t offset, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags)
|
||||
{
|
||||
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset);
|
||||
desc.base1 = base;
|
||||
desc.base2 = base >> 16;
|
||||
desc.base3 = base >> 24;
|
||||
|
||||
desc.limit1 = limit;
|
||||
desc.limit2 = limit >> 16;
|
||||
|
||||
desc.access = access;
|
||||
|
||||
desc.flags = flags;
|
||||
}
|
||||
|
||||
static void write_tss(uint8_t offset)
|
||||
{
|
||||
s_tss = new TaskStateSegment();
|
||||
ASSERT(s_tss);
|
||||
|
||||
memset(s_tss, 0x00, sizeof(TaskStateSegment));
|
||||
s_tss->rsp0 = (uintptr_t)g_boot_stack_top;
|
||||
|
||||
uintptr_t base = (uintptr_t)s_tss;
|
||||
|
||||
write_entry(offset, (uint32_t)base, sizeof(TaskStateSegment), 0x89, 0x0);
|
||||
SegmentDescriptor& desc = *(SegmentDescriptor*)((uintptr_t)s_gdt + offset + 0x08);
|
||||
desc.low = base >> 32;
|
||||
desc.high = 0;
|
||||
}
|
||||
|
||||
static void flush_gdt()
|
||||
{
|
||||
asm volatile("lgdt %0" :: "m"(s_gdtr));
|
||||
}
|
||||
|
||||
extern "C" void flush_tss(uint16_t offset)
|
||||
{
|
||||
asm volatile("ltr %0" :: "m"(offset));
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
constexpr uint32_t descriptor_count = 6 + 1; // tss takes 2
|
||||
s_gdt = new SegmentDescriptor[descriptor_count];
|
||||
ASSERT(s_gdt);
|
||||
|
||||
s_gdtr.address = (uint64_t)s_gdt;
|
||||
s_gdtr.size = descriptor_count * 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(0x28);
|
||||
|
||||
flush_gdt();
|
||||
flush_tss(0x28);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
# 0 MiB -> 1 MiB: bootloader stuff
|
||||
# 1 MiB -> 2 MiB: kernel
|
||||
# 2 MiB -> 3 MiB: kmalloc
|
||||
# 3 MiB -> 4 MiB: kmalloc_eternal
|
||||
# 3 MiB -> 4 MiB: kmalloc_fixed
|
||||
.align 4096
|
||||
boot_pml4:
|
||||
.skip 512 * 8
|
||||
@@ -52,8 +52,6 @@
|
||||
boot_pd1:
|
||||
.skip 512 * 8
|
||||
|
||||
.section .text, "a"
|
||||
|
||||
.global g_multiboot_info
|
||||
g_multiboot_info:
|
||||
.skip 8
|
||||
@@ -61,6 +59,8 @@ g_multiboot_info:
|
||||
g_multiboot_magic:
|
||||
.skip 8
|
||||
|
||||
.section .text, "a"
|
||||
|
||||
boot_gdt:
|
||||
.quad 0x0000000000000000 # null descriptor
|
||||
.quad 0x00AF9A000000FFFF # kernel code
|
||||
|
||||
@@ -7,6 +7,7 @@ ELF_FORMAT=elf64-x86-64
|
||||
|
||||
KERNEL_ARCH_OBJS= \
|
||||
$(ARCHDIR)/boot.o \
|
||||
$(ARCHDIR)/GDT.o \
|
||||
$(ARCHDIR)/IDT.o \
|
||||
$(ARCHDIR)/interrupts.o \
|
||||
$(ARCHDIR)/MMU.o \
|
||||
|
||||
Reference in New Issue
Block a user