#include #include #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)); }