68 lines
2.0 KiB
C
68 lines
2.0 KiB
C
#include "src/kernel/gdt.h"
|
|
#include "src/kernel/tss.h"
|
|
|
|
typedef struct {
|
|
uint16_t limit_low;
|
|
uint16_t base_low;
|
|
uint8_t base_mid;
|
|
uint8_t access;
|
|
uint8_t flags_limit_high;
|
|
uint8_t base_high;
|
|
} __attribute__((packed)) gdt_entry_t;
|
|
|
|
typedef struct {
|
|
gdt_entry_t base;
|
|
uint32_t base_upper;
|
|
uint32_t reserved;
|
|
} __attribute__((packed)) gdt_system_entry_t;
|
|
|
|
typedef struct {
|
|
gdt_entry_t gdt[6];
|
|
gdt_system_entry_t tss_entry;
|
|
} __attribute__((packed)) gdt_table_t;
|
|
|
|
typedef struct {
|
|
uint16_t limit;
|
|
uint64_t offset;
|
|
} __attribute__((packed)) gdt_descriptor_t;
|
|
|
|
static gdt_table_t gdt;
|
|
static gdt_descriptor_t desc;
|
|
|
|
static void set_entry(gdt_entry_t *e, uint8_t access, uint8_t flags) {
|
|
e->limit_low = 0xFFFF;
|
|
e->base_low = 0;
|
|
e->base_mid = 0;
|
|
e->access = access;
|
|
e->flags_limit_high = flags | 0x0F;
|
|
e->base_high = 0;
|
|
}
|
|
|
|
static void set_tss_entry(void *base) {
|
|
uint64_t ibase = (uint64_t)base;
|
|
gdt.tss_entry.base.limit_low = sizeof(tss_t) - 1;
|
|
gdt.tss_entry.base.base_low = ibase & 0xFFFF;
|
|
gdt.tss_entry.base.base_mid = (ibase >> 16) & 0xFF;
|
|
gdt.tss_entry.base.access = 0x89; // present, type=TSS available
|
|
gdt.tss_entry.base.flags_limit_high = 0x00;
|
|
gdt.tss_entry.base.base_high = (ibase >> 24) & 0xFF;
|
|
gdt.tss_entry.base_upper = ibase >> 32;
|
|
gdt.tss_entry.reserved = 0;
|
|
}
|
|
|
|
void gdt_init() {
|
|
gdt.gdt[0] = (gdt_entry_t){0};
|
|
set_entry(&gdt.gdt[1], 0x9A, 0xCF); // present, ring 0, code, executable, readable, 32-bit, 4KB granularity
|
|
set_entry(&gdt.gdt[2], 0x9A, 0xA0); // present, ring 0, code, executable, readable, 64-bit
|
|
set_entry(&gdt.gdt[3], 0x92, 0x00); // present, ring 0, data, writable
|
|
set_entry(&gdt.gdt[4], 0xF2, 0x00); // present, ring 3, data, writable
|
|
set_entry(&gdt.gdt[5], 0xFA, 0xA0); // present, ring 3, code, executable, readable, 64-bit
|
|
set_tss_entry(&tss);
|
|
|
|
desc.limit = sizeof(gdt) - 1;
|
|
desc.offset = (uint64_t)&gdt;
|
|
|
|
__asm__ volatile("lgdt %0" : : "m"(desc));
|
|
__asm__ volatile("ltr %0" : : "r"((uint16_t)TSS_SEL));
|
|
}
|