Luna/kernel/src/gdt/GDT.cpp

97 lines
2.8 KiB
C++
Raw Normal View History

#define MODULE "gdt"
2022-09-05 14:13:51 +00:00
#include "gdt/GDT.h"
2022-09-17 15:40:35 +00:00
#include "assert.h"
#include "log/Log.h"
#include "memory/MemoryManager.h"
2022-09-17 15:40:35 +00:00
#include "std/string.h"
2022-09-05 14:13:51 +00:00
#include <stdint.h>
struct GDTR
{
uint16_t size;
uint64_t offset;
} __attribute__((packed));
struct GDTEntry
{
uint16_t limit0;
uint16_t base0;
uint8_t base1;
uint8_t access;
uint8_t limit1_flags;
uint8_t base2;
} __attribute__((packed));
2022-09-17 15:40:35 +00:00
struct HighGDTEntry
{
uint32_t base_high;
uint32_t reserved;
} __attribute__((packed));
struct TSS
{
uint32_t reserved0;
uint64_t rsp[3];
uint64_t reserved1;
uint64_t ist[7];
uint64_t reserved2;
uint16_t reserved3;
uint16_t iomap_base;
} __attribute__((packed));
2022-09-05 14:13:51 +00:00
struct InternalGDT
{
GDTEntry null;
GDTEntry kernel_code;
GDTEntry kernel_data;
GDTEntry user_code;
GDTEntry user_data;
2022-09-17 15:40:35 +00:00
GDTEntry tss;
HighGDTEntry tss2;
2022-09-05 14:13:51 +00:00
} __attribute__((packed)) __attribute((aligned(0x1000)));
2022-09-17 15:40:35 +00:00
__attribute__((aligned(0x1000))) static InternalGDT internal_gdt = {{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
{0xffff, 0x0000, 0x00, 0x9a, 0xaf, 0x00},
{0xffff, 0x0000, 0x00, 0x92, 0xcf, 0x00},
{0xffff, 0x0000, 0x00, 0xfa, 0xaf, 0x00},
{0xffff, 0x0000, 0x00, 0xf2, 0xcf, 0x00},
{0x0000, 0x0000, 0x00, 0xe9, 0x0f, 0x00},
2022-09-17 15:40:35 +00:00
{0x00000000, 0x00000000}};
static TSS main_tss;
2022-09-05 14:13:51 +00:00
extern "C" void load_gdt(GDTR* gdtr);
2022-09-17 15:40:35 +00:00
extern "C" void load_tr(int segment);
static void set_base(GDTEntry* entry, uint32_t base)
{
entry->base0 = (base & 0xFFFF);
entry->base1 = (base >> 16) & 0xFF;
2022-10-06 15:13:34 +00:00
entry->base2 = (uint8_t)((base >> 24) & 0xFF);
2022-09-17 15:40:35 +00:00
}
static void set_limit(GDTEntry* entry, uint32_t limit)
{
ASSERT(limit <= 0xFFFFF);
2022-10-06 15:13:34 +00:00
entry->limit0 = limit & 0xFFFF;
entry->limit1_flags = (entry->limit1_flags & 0xF0) | ((limit >> 16) & 0xF);
2022-09-17 15:40:35 +00:00
}
2022-09-05 14:13:51 +00:00
void GDT::load()
{
static GDTR gdtr;
gdtr.offset = (uint64_t)&internal_gdt;
gdtr.size = sizeof(InternalGDT);
2022-09-17 15:40:35 +00:00
memset(&main_tss, 0, sizeof(TSS));
main_tss.rsp[0] =
(uint64_t)MemoryManager::get_pages(4) + (PAGE_SIZE * 4) - 8; // allocate 16KB for the syscall stack
main_tss.iomap_base = sizeof(TSS);
2022-09-17 15:40:35 +00:00
set_base(&internal_gdt.tss, (uint64_t)&main_tss & 0xffffffff);
2022-10-06 15:13:34 +00:00
internal_gdt.tss2.base_high = (uint32_t)(((uint64_t)&main_tss >> 32) & 0xffffffff);
2022-09-17 15:40:35 +00:00
set_limit(&internal_gdt.tss, sizeof(TSS) - 1);
2022-09-08 15:03:17 +00:00
kdbgln("Loading GDT at offset %lx, size %d", gdtr.offset, gdtr.size);
2022-09-05 14:13:51 +00:00
load_gdt(&gdtr);
kdbgln("Loading TR (GDT entry 0x2b)");
load_tr(0x2b);
2022-09-05 14:13:51 +00:00
}