Files
my-os-project2/kernel/hal/x86_64/gdt.c
2025-08-10 21:30:23 +02:00

95 lines
2.0 KiB
C

#include <stdint.h>
#include <stddef.h>
#include "compiler/attr.h"
#include "hal/hal.h"
#define GDT_SIZE 5
typedef struct {
uint16_t limitlow;
uint16_t baselow;
uint8_t basemid;
uint8_t access;
uint8_t gran;
uint8_t basehigh;
} PACKED GdtEntry;
typedef struct {
uint16_t limit;
uint64_t base;
} PACKED GdtPtr;
typedef struct {
GdtEntry old[5];
GdtEntry tsslow;
GdtEntry tsshigh;
} PACKED ExtendedGdt;
typedef struct {
uint32_t resv0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} PACKED Tss;
static Tss tss = {0};
static ExtendedGdt *curgdt = NULL;
#define KCODE 0x08
#define KDATA 0x10
#define UCODE 0x18
#define UDATA 0x20
#define TSS 0x28
#define GDT_PRESENT 0x80
#define GDT_TSS 0x89
static uint64_t gdt_curretbase(void) {
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
return gdtr.base;
}
void gdt_setenty(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
entry->baselow = base & 0xffff;
entry->basemid = (base >> 16) & 0xff;
entry->basehigh = (base >> 24) & 0xff;
entry->limitlow = limit & 0xffff;
entry->gran = (limit >> 16) & 0x0f | (gran & 0xf0);
entry->access = access;
}
void gdt_init(void) {
uint64_t base = gdt_curretbase();
curgdt = (ExtendedGdt *)base;
HAL_MEMSET(&tss, 0, sizeof(tss));
tss.iopb_off = sizeof(tss);
uint64_t tss_base = (uint64_t)&tss;
uint32_t tss_limit = sizeof(tss) - 1;
gdt_setenty(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
GdtEntry *tsshigh = &curgdt->tsshigh;
tsshigh->baselow = (tss_base >> 32) & 0xffff;
tsshigh->basemid = (tss_base >> 48) & 0xff;
tsshigh->basehigh = (tss_base >> 56) & 0xff;
tsshigh->access = 0;
tsshigh->gran = 0;
tsshigh->limitlow = 0;
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
gdtr.limit = sizeof(ExtendedGdt) - 1;
asm volatile("lgdt %0" :: "m"(gdtr));
asm volatile("ltr %0" :: "r"((uint16_t)0x28));
}