From d64412690132fc876cb86aaa8ed721c018df70ed Mon Sep 17 00:00:00 2001 From: xamidev Date: Wed, 1 Apr 2026 13:04:33 +0200 Subject: [PATCH] TSS setup --- include/arch/gdt.h | 15 ++++++++++++++- src/arch/x86/gdt.c | 23 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/arch/gdt.h b/include/arch/gdt.h index af85dac..f2297b9 100644 --- a/include/arch/gdt.h +++ b/include/arch/gdt.h @@ -13,19 +13,32 @@ // we'll only use this as a requirement for paging, not more. // This means base 0 and no limit (whole address space) -#define NUM_GDT_ENTRIES 5 +#define NUM_GDT_ENTRIES 7 #define NULL_SELECTOR 0x00 #define KERNEL_CODE_SEGMENT 0x08 #define KERNEL_DATA_SEGMENT 0x10 #define USER_CODE_SEGMENT 0x18 #define USER_DATA_SEGMENT 0x20 +#define TSS_SEGMENT 0x28 struct GDTR { uint16_t limit; uint64_t address; } __attribute__((packed)); +struct tss { + uint32_t reserved0; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved1; + uint64_t ist[7]; + uint64_t reserved2; + uint16_t reserved3; + uint16_t iopb; +} __attribute__((packed)); + void gdt_init(void); #endif \ No newline at end of file diff --git a/src/arch/x86/gdt.c b/src/arch/x86/gdt.c index 37edfd3..9f2100e 100644 --- a/src/arch/x86/gdt.c +++ b/src/arch/x86/gdt.c @@ -1,6 +1,6 @@ /* * @author xamidev - * @brief Global Descriptor Table (for legacy reasons) + * @brief Global Descriptor Table and Task State Segment setup * @license GPL-3.0-only */ @@ -14,6 +14,8 @@ uint64_t gdt_entries[NUM_GDT_ENTRIES]; struct GDTR gdtr; +struct tss tss = {0}; + /* * gdt_load - Loads Global Descriptor Table */ @@ -85,7 +87,22 @@ static void gdt_set_entry(int num, uint8_t flags, uint8_t access) */ static void gdt_set_tss(int num) { + uint64_t tss_base = (uint64_t)&tss; + uint64_t tss_limit = sizeof(struct tss) - 1; + tss.iopb = sizeof(struct tss); + + uint64_t tss_low = 0; + tss_low |= (tss_limit & 0xFFFFULL); + tss_low |= (tss_base & 0xFFFFFFULL) << 16; + tss_low |= 0x89ULL << 40; + tss_low |= ((tss_limit >> 16) & 0xFULL) << 48; + tss_low |= ((tss_base >> 24) & 0xFFULL) << 56; + + uint64_t tss_high = (tss_base >> 32) & 0xFFFFFFFFULL; + + gdt_entries[num] = tss_low; + gdt_entries[num + 1] = tss_high; } /* @@ -104,6 +121,7 @@ void gdt_init() gdt_set_entry(2, 0xC, 0x93); // Kernel data (0x10) gdt_set_entry(3, 0xA, 0xFB); // User code (0x18) gdt_set_entry(4, 0xC, 0xF3); // User data (0x20) + gdt_set_tss(5); // TSS (0x28) // The -1 subtraction is some wizardry explained in the OSDev wiki -> GDT gdtr.limit = NUM_GDT_ENTRIES * sizeof(uint64_t) - 1; @@ -113,7 +131,8 @@ void gdt_init() gdt_load(); gdt_flush(); - // Here we should load the task register with TSS selector + // Load task register with new TSS + asm volatile("ltr %%ax" : : "a"(TSS_SEGMENT) : "memory"); DEBUG("GDT initialized"); } \ No newline at end of file