From 15386c43baca7bcc7f547ee94d675473f6d33970 Mon Sep 17 00:00:00 2001 From: Arnau478 Date: Sat, 18 Jun 2022 01:53:28 +0200 Subject: [PATCH] Implemented GDT --- src/kernel/arch/i686/gdt.asm | 31 ++++++++++++ src/kernel/arch/i686/gdt.c | 91 ++++++++++++++++++++++++++++++++++++ src/kernel/arch/i686/gdt.h | 6 +++ src/kernel/hal/hal.c | 2 + 4 files changed, 130 insertions(+) create mode 100644 src/kernel/arch/i686/gdt.asm create mode 100644 src/kernel/arch/i686/gdt.c create mode 100644 src/kernel/arch/i686/gdt.h diff --git a/src/kernel/arch/i686/gdt.asm b/src/kernel/arch/i686/gdt.asm new file mode 100644 index 0000000..0071e50 --- /dev/null +++ b/src/kernel/arch/i686/gdt.asm @@ -0,0 +1,31 @@ +[bits 32] + +global i686_gdt_load +i686_gdt_load: + ; New call frame + push ebp + mov ebp, esp + + ; Load GDT + mov eax, [ebp + 8] + lgdt [eax] + + ; Reload code segment + mov eax, [ebp + 12] + push eax + push .reload_cs + retf + +.reload_cs: + ; Reload data segments + mov ax, [ebp + 16] + mov dx, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; Restore old call frame + mov esp, ebp + push ebp + ret diff --git a/src/kernel/arch/i686/gdt.c b/src/kernel/arch/i686/gdt.c new file mode 100644 index 0000000..c1603e7 --- /dev/null +++ b/src/kernel/arch/i686/gdt.c @@ -0,0 +1,91 @@ +#include +#include "gdt.h" + +typedef struct{ + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t flags_limit_high; + uint8_t base_high; +} __attribute__((packed)) gdt_entry; + +typedef struct{ + uint16_t limit; + gdt_entry *ptr; +} __attribute__((packed)) gdt_descriptor; + +typedef enum{ + GDT_ACCESS_CODE_READABLE = 0x02, + GDT_ACCESS_DATA_WRITEABLE = 0x02, + + GDT_ACCESS_CODE_CONFORMING = 0x04, + GDT_ACCESS_DATA_DIRECTION_NORMAL = 0x00, + GDT_ACCESS_DATA_DIRECTION_DOWN = 0x04, + + GDT_ACCESS_DATA_SEGMENT = 0x10, + GDT_ACCESS_CODE_SEGMENT = 0x18, + + GDT_ACCESS_DESCRIPTOR_TSS = 0x00, + + GDT_ACCESS_RING0 = 0x00, + GDT_ACCESS_RING1 = 0x20, + GDT_ACCESS_RING2 = 0x40, + GDT_ACCESS_RING3 = 0x60, + + GDT_ACCESS_PRESENT = 0x80, +} GDT_ACCESS; + +typedef enum{ + GDT_FLAG_64BIT = 0x20, + GDT_FLAG_32BIT = 0x40, + GDT_FLAG_16BIT = 0x00, + + GDT_FLAG_GRANULARITY_1B = 0x00, + GDT_FLAG_GRANULARITY_4K = 0x80, +} GDT_FLAGS; + +// Helpful macros +#define GDT_LIMIT_LOW(limit) ((limit) & 0xFFFF) +#define GDT_BASE_LOW(base) ((base) & 0xFFFF) +#define GDT_BASE_MIDDLE(base) (((base) >> 16) & 0xFF) +#define GDT_FLAGS_LIMIT_HIGH(limit, flags) ((((limit) >> 16) & 0xF) | ((flags) & 0xF0)) +#define GDT_BASE_HIGH(base) (((base) >> 24) & 0xFF) + +#define GDT_ENTRY(base, limit, access, flags) { \ + GDT_LIMIT_LOW(limit), \ + GDT_BASE_LOW(base), \ + GDT_BASE_MIDDLE(base), \ + access, \ + GDT_FLAGS_LIMIT_HIGH(limit, flags), \ + GDT_BASE_HIGH(base), \ +} + +static gdt_entry g_gdt[] = { + // Null descriptor + GDT_ENTRY(0, 0, 0, 0), + + // Kernel 32-bit code segment + GDT_ENTRY( + 0, + 0xFFFF, + GDT_ACCESS_PRESENT | GDT_ACCESS_RING0 | GDT_ACCESS_CODE_SEGMENT | GDT_ACCESS_CODE_READABLE, + GDT_FLAG_32BIT | GDT_FLAG_GRANULARITY_4K + ), + + // Kernel 32-bit data segment + GDT_ENTRY( + 0, + 0xFFFF, + GDT_ACCESS_PRESENT | GDT_ACCESS_RING0 | GDT_ACCESS_DATA_SEGMENT | GDT_ACCESS_DATA_WRITEABLE, + GDT_FLAG_32BIT | GDT_FLAG_GRANULARITY_4K + ), +}; + +static gdt_descriptor g_gdt_descriptor = {sizeof(g_gdt) - 1, g_gdt}; + +void __attribute__((cdecl)) i686_gdt_load(gdt_descriptor *descriptor, uint16_t code_segment, int16_t data_segment); + +void i686_gdt_initialize(){ + i686_gdt_load(&g_gdt_descriptor, i686_GDT_CODE_SEGMENT, i686_GDT_DATA_SEGMENT); +} diff --git a/src/kernel/arch/i686/gdt.h b/src/kernel/arch/i686/gdt.h new file mode 100644 index 0000000..1ea9b51 --- /dev/null +++ b/src/kernel/arch/i686/gdt.h @@ -0,0 +1,6 @@ +#pragma once + +#define i686_GDT_CODE_SEGMENT 0x08 +#define i686_GDT_DATA_SEGMENT 0x10 + +void i686_gdt_initialize(); diff --git a/src/kernel/hal/hal.c b/src/kernel/hal/hal.c index ab8602c..e995c42 100644 --- a/src/kernel/hal/hal.c +++ b/src/kernel/hal/hal.c @@ -1,6 +1,8 @@ #include "hal.h" +#include "../arch/i686/gdt.h" #include "../arch/i686/idt.h" void hal_initialize(){ + i686_gdt_initialize(); i686_idt_initialize(); }