about summary refs log tree commit diff
path: root/src/pOS/arch/x86/kernel/interrupts/gdt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pOS/arch/x86/kernel/interrupts/gdt.cpp')
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/gdt.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/pOS/arch/x86/kernel/interrupts/gdt.cpp b/src/pOS/arch/x86/kernel/interrupts/gdt.cpp
new file mode 100644
index 0000000..0774421
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/gdt.cpp
@@ -0,0 +1,56 @@
+#include <kernel/interrupts/gdt.h>
+
+gdt_entry_t GDT::gdt_entries[GDT_NUM_DESCRIPTORS];
+gdt_ptr_t gdt_ptr;
+
+int GDT::init(void) {
+    memset(gdt_entries, 0, sizeof(gdt_entries));
+
+    gdt_ptr.limit = sizeof(gdt_entries) - 1;
+    gdt_ptr.base = (uint32_t)gdt_entries;
+
+    // NULL Segment
+    set_entry(0, 0, 0, 0, 0);
+    /* Kernel code, access(9A = 1 00 1 1 0 1 0)
+        1   present
+        00  ring 0
+        1   always 1
+        1   code segment
+        0   can be executed by ring lower or equal to DPL,
+        1   code segment is readable
+        0   access bit, always 0, cpu set this to 1 when accessing this sector*/
+
+    set_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
+    /* Kernel data, access(92 = 1 00 1 0 0 1 0)
+        Only differ at the fifth bit(counting from least insignificant bit), 0 means it's a data segment.*/
+
+    set_entry(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+    // User code and data segments, only differ in ring number(ring 3)
+    set_entry(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
+    set_entry(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
+
+    gdt_flush((uint32_t)(&gdt_ptr));
+
+    return 0;
+}
+
+int GDT::set_entry(int index, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
+    gdt_entry_t& entry = gdt_entries[index];
+
+    // Low 16 bits, middle 8 bits and high 8 bits of base
+    entry.base_low = base & 0xFFFF;
+    entry.base_middle = (base >> 16) & 0xFF;
+    entry.base_high = (base >> 24 & 0xFF);
+
+    /*  16 bits and high 4 bits of limit, since the high 4 bits of limits is between granularity and access, and we don't have 4 bit variable,
+    low 4 bits of granularity actually represents high 4 bits of limits. It's weird, I know.*/
+    entry.limit_low = limit & 0xFFFF;
+    entry.granularity = (limit >> 16) & 0x0F;
+
+    entry.access = access;
+
+    // Only need the high 4 bits of gran
+    entry.granularity = entry.granularity | (gran & 0xF0);
+
+    return 0;
+}