73 lines
2.1 KiB
C++
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;
|
|
}
|