From ed2c0a35680e38546467d05db6da41c5eb53a86d Mon Sep 17 00:00:00 2001 From: Nathan Singer Date: Fri, 13 Jun 2025 14:37:22 -0400 Subject: [PATCH] cleans up gdt code --- kernel/arch/gdt/gdt.s | 8 +-- kernel/arch/gdt/gdt_entry.c | 87 +++++++++++++++++++++++++++++++-- kernel/include/kernel/x86/gdt.h | 53 -------------------- 3 files changed, 86 insertions(+), 62 deletions(-) diff --git a/kernel/arch/gdt/gdt.s b/kernel/arch/gdt/gdt.s index 86db7f4..5527c3e 100644 --- a/kernel/arch/gdt/gdt.s +++ b/kernel/arch/gdt/gdt.s @@ -1,8 +1,8 @@ gdtr DW 0 ; limit store DD 0 ; base storage -global setGdt -setGdt: +global set_gdt +set_gdt: mov ax, [esp + 4] mov [gdtr], ax mov eax, [esp + 8] @@ -10,8 +10,8 @@ setGdt: lgdt [gdtr] ret -global reloadSegments -reloadSegments: +global reload_segments +reload_segments: jmp 0x08:.reload_CS ; 0x08 is a stand in for the code segment .reload_CS: mov ax, 0x10 ; stand in for the data segment diff --git a/kernel/arch/gdt/gdt_entry.c b/kernel/arch/gdt/gdt_entry.c index 2e858a8..51ce263 100644 --- a/kernel/arch/gdt/gdt_entry.c +++ b/kernel/arch/gdt/gdt_entry.c @@ -26,8 +26,58 @@ * etc, by going through the CPU permission system (RING 0 - 3) */ +#define GDT_SIZE 5 + +// Each define here is for a specific flag in the descriptor. +// Refer to the intel documentation for a description of what each one does. +#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data) +#define SEG_PRES(x) ((x) << 0x07) // Present +#define SEG_SAVL(x) ((x) << 0x0C) // Available for system use +#define SEG_LONG(x) ((x) << 0x0D) // Long mode +#define SEG_SIZE(x) ((x) << 0x0E) // Size (0 for 16-bit, 1 for 32) +#define SEG_GRAN(x) ((x) << 0x0F) // Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) +#define SEG_PRIV(x) (((x) & 0x03) << 0x05) // Set privilege level (0 - 3) + +#define SEG_DATA_RD 0x00 // Read-Only +#define SEG_DATA_RDA 0x01 // Read-Only, accessed +#define SEG_DATA_RDWR 0x02 // Read/Write +#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed +#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down +#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed +#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down +#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed +#define SEG_CODE_EX 0x08 // Execute-Only +#define SEG_CODE_EXA 0x09 // Execute-Only, accessed +#define SEG_CODE_EXRD 0x0A // Execute/Read +#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed +#define SEG_CODE_EXC 0x0C // Execute-Only, conforming +#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed +#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming +#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed + +#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(0) | SEG_CODE_EXRD + +#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(0) | SEG_DATA_RDWR + +#define GDT_CODE_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(3) | SEG_CODE_EXRD + +#define GDT_DATA_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ + SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ + SEG_PRIV(3) | SEG_DATA_RDWR + + + uint64_t gdt[GDT_SIZE]; +void set_gdt(unsigned short limit, uint64_t* base); +void reload_segments(void); + uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag) { uint64_t descriptor; @@ -63,11 +113,11 @@ void gdt_init(void) gdt[0] = create_descriptor(0, 0, 0); // null gdt[1] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL0)); // kernel code gdt[2] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL0)); // kernel data - //gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3)); // user code - //gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3)); // user data + gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3)); // user code + gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3)); // user data - setGdt((sizeof(uint64_t) * GDT_SIZE) - 1, &(gdt[0])); // limit, base - reloadSegments(); + set_gdt((sizeof(uint64_t) * GDT_SIZE) - 1, &(gdt[0])); // limit, base + reload_segments(); #ifdef __TESTING__ kinfo("Initialized the GDT"); #endif @@ -76,4 +126,31 @@ void gdt_init(void) #endif } - +#undef SEG_DESCTYPE +#undef SEG_PRES +#undef SEG_SAVL +#undef SEG_LONG +#undef SEG_SIZE +#undef SEG_GRAN +#undef SEG_PRIV +#undef SEG_DATA_RD +#undef SEG_DATA_RDA +#undef SEG_DATA_RDWR +#undef SEG_DATA_RDWRA +#undef SEG_DATA_RDEXPD +#undef SEG_DATA_RDEXPDA +#undef SEG_DATA_RDWREXPD +#undef SEG_DATA_RDWREXPDA +#undef SEG_CODE_EX +#undef SEG_CODE_EXA +#undef SEG_CODE_EXRD +#undef SEG_CODE_EXRDA +#undef SEG_CODE_EXC +#undef SEG_CODE_EXCA +#undef SEG_CODE_EXRDC +#undef SEG_CODE_EXRDCA +#undef GDT_CODE_PL0 +#undef GDT_DATA_PL0 +#undef GDT_CODE_PL3 +#undef GDT_DATA_PL3 +#undef GDT_SIZE diff --git a/kernel/include/kernel/x86/gdt.h b/kernel/include/kernel/x86/gdt.h index 4f89d76..d463038 100644 --- a/kernel/include/kernel/x86/gdt.h +++ b/kernel/include/kernel/x86/gdt.h @@ -3,59 +3,6 @@ #ifndef ARCH_I386_GDT_H #define ARCH_I386_GDT_H -// Each define here is for a specific flag in the descriptor. -// Refer to the intel documentation for a description of what each one does. -#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data) -#define SEG_PRES(x) ((x) << 0x07) // Present -#define SEG_SAVL(x) ((x) << 0x0C) // Available for system use -#define SEG_LONG(x) ((x) << 0x0D) // Long mode -#define SEG_SIZE(x) ((x) << 0x0E) // Size (0 for 16-bit, 1 for 32) -#define SEG_GRAN(x) ((x) << 0x0F) // Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) -#define SEG_PRIV(x) (((x) & 0x03) << 0x05) // Set privilege level (0 - 3) - -#define SEG_DATA_RD 0x00 // Read-Only -#define SEG_DATA_RDA 0x01 // Read-Only, accessed -#define SEG_DATA_RDWR 0x02 // Read/Write -#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed -#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down -#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed -#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down -#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed -#define SEG_CODE_EX 0x08 // Execute-Only -#define SEG_CODE_EXA 0x09 // Execute-Only, accessed -#define SEG_CODE_EXRD 0x0A // Execute/Read -#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed -#define SEG_CODE_EXC 0x0C // Execute-Only, conforming -#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed -#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming -#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed - -#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(0) | SEG_CODE_EXRD - -#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(0) | SEG_DATA_RDWR - -#define GDT_CODE_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(3) | SEG_CODE_EXRD - -#define GDT_DATA_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(3) | SEG_DATA_RDWR - - -#define GDT_SIZE 3 - - -void setGdt(unsigned short limit, uint64_t* base); - -void reloadSegments(); - -uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag); - void gdt_init(void); #endif