Files
Sylva/kernel/interrupt/gdt.cpp
T
2026-06-06 10:37:51 +08:00

73 lines
2.1 KiB
C++

#include <interrupt/gdt.h>
#include <common.h>
#include <string_utils.h>
#include <serial.h>
static gdt_entry g_gdt[7]; // 5 segments + TSS (2 entries)
static gdt_ptr g_gdt_ptr;
static tss g_tss;
extern "C" void lgdt_and_reload(void* gdt_ptr);
extern "C" void tss_load(UINT16 selector);
static void gdt_set_entry(UINT32 index, UINT32 base, UINT32 limit,
UINT8 access, UINT8 granularity) {
g_gdt[index].limit_low = limit & 0xFFFF;
g_gdt[index].base_low = base & 0xFFFF;
g_gdt[index].base_mid = (base >> 16) & 0xFF;
g_gdt[index].access = access;
g_gdt[index].granularity = granularity | ((limit >> 16) & 0x0F);
g_gdt[index].base_high = (base >> 24) & 0xFF;
}
static void tss_set_descriptor(UINT32 index) {
UINT64 base = (UINT64)&g_tss;
UINT32 limit = sizeof(tss) - 1;
g_gdt[index].limit_low = limit & 0xFFFF;
g_gdt[index].base_low = base & 0xFFFF;
g_gdt[index].base_mid = (base >> 16) & 0xFF;
g_gdt[index].access = 0x89;
g_gdt[index].granularity = 0x00;
g_gdt[index].base_high = (base >> 24) & 0xFF;
g_gdt[index + 1].limit_low = (limit >> 16) & 0xFFFF;
g_gdt[index + 1].base_low = (base >> 32) & 0xFFFF;
g_gdt[index + 1].base_mid = (base >> 48) & 0xFF;
g_gdt[index + 1].access = 0;
g_gdt[index + 1].granularity = 0;
g_gdt[index + 1].base_high = 0;
}
void gdt_init(void) {
serial_write("GDT: initializing\n");
for (SSINT32 i = 0; i < 7; i++) {
g_gdt[i] = {0};
}
gdt_set_entry(0, 0, 0, 0, 0);
gdt_set_entry(1, 0, 0xFFFFF, 0x9A, 0xA0);
gdt_set_entry(2, 0, 0xFFFFF, 0x92, 0xC0);
gdt_set_entry(3, 0, 0xFFFFF, 0xFA, 0xA0);
gdt_set_entry(4, 0, 0xFFFFF, 0xF2, 0xC0);
tss_set_descriptor(5);
g_tss = {};
g_tss.iopb_offset = sizeof(tss);
g_gdt_ptr.limit = sizeof(g_gdt) - 1;
g_gdt_ptr.base = (UINT64)&g_gdt[0];
serial_write("GDT: loading GDT + reloading segments\n");
lgdt_and_reload(&g_gdt_ptr);
serial_write("GDT: loading TSS\n");
tss_load(GDT_TSS);
serial_write("GDT: done\n");
}
void gdt_set_kernel_stack(UINT64 stack) {
g_tss.rsp0 = stack;
}