summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/gdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/gdt.c')
-rw-r--r--arch/x86_64/gdt.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/x86_64/gdt.c b/arch/x86_64/gdt.c
new file mode 100644
index 0000000..e8ca912
--- /dev/null
+++ b/arch/x86_64/gdt.c
@@ -0,0 +1,111 @@
+#include "arch/x86_64/tables.h"
+#include "arch/x86_64/processor.h"
+#include "string.h"
+
+static segment_descriptor_t s_gdt[] = {
+ { 0 }, //Kernel NULL
+ { //Kernel Code
+ .limit_0_15 = 0xFFFF,
+ .base_0_15 = 0x0,
+ .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE,
+ .s = 1,
+ .dpl = 0,
+ .p = 1,
+ .limit_16_19 = 0xF,
+ .avl = 0,
+ .l = 1,
+ .d_b = 0,
+ .g = 1,
+ .base_24_31 = 0x0
+ },
+ { //Kernel Data
+ .limit_0_15 = 0xFFFF,
+ .base_0_15 = 0x0,
+ .type = CD_SEGMENT_TYPE_WRITEABLE,
+ .s = 1,
+ .dpl = 0,
+ .p = 1,
+ .limit_16_19 = 0xF,
+ .avl = 0,
+ .l = 0,
+ .d_b = 1,
+ .g = 1,
+ .base_24_31 = 0x0
+ },
+ { 0 }, //User NULL
+ { //User Data
+ .limit_0_15 = 0xFFFF,
+ .base_0_15 = 0x0,
+ .type = CD_SEGMENT_TYPE_WRITEABLE,
+ .s = 1,
+ .dpl = 3,
+ .p = 1,
+ .limit_16_19 = 0xF,
+ .avl = 0,
+ .l = 0,
+ .d_b = 1,
+ .g = 1,
+ .base_24_31 = 0x0
+ },
+ { //User Code
+ .limit_0_15 = 0xFFFF,
+ .base_0_15 = 0x0,
+ .type = CD_SEGMENT_TYPE_CODE | CD_SEGMENT_TYPE_WRITEABLE,
+ .s = 1,
+ .dpl = 3,
+ .p = 1,
+ .limit_16_19 = 0xF,
+ .avl = 0,
+ .l = 1,
+ .d_b = 0,
+ .g = 1,
+ .base_24_31 = 0x0
+ },
+ { //TSS Low
+ .limit_0_15 = 0,
+ .base_0_15 = 0,
+ .base_16_23 = 0,
+ .type = S_SEGMENT_TYPE_TSS_AVAIL,
+ .avl = 0,
+ .s = 0,
+ .dpl = 0,
+ .p = 1,
+ .limit_16_19 = 0,
+ .l = 0,
+ .d_b = 0,
+ .g = 0,
+ .base_24_31 = 0
+ },
+ { 0 } //TSS High
+};
+
+void
+gdt_setup(processor_t *processor)
+{
+ memcpy(processor->gdt, s_gdt, sizeof(s_gdt));
+
+ processor->gdtr.base = (uintptr_t)&s_gdt;
+ processor->gdtr.length = sizeof(s_gdt) - 1;
+
+ segment_descriptor_t *tss_lo = &processor->gdt[GDT_ENTRY_TSS_LOW];
+ segment_descriptor_t *tss_hi = &processor->gdt[GDT_ENTRY_TSS_HIGH];
+
+ uintptr_t tssb = (uintptr_t)&processor->tss;
+ tss_lo->base_0_15 = tssb & 0xFFFF;
+ tss_lo->base_16_23 = (tssb >> 16) & 0xFF;
+ tss_lo->base_24_31 = (tssb >> 24) & 0xFF;
+ tss_hi->limit_0_15 = (tssb >> 32) & 0xFFFF;
+ tss_hi->base_0_15 = (tssb >> 48) & 0xFFFF;
+
+ size_t tssl = sizeof(tss_t);
+ tss_lo->limit_0_15 = tssl & 0xFFFF;
+ tss_lo->limit_16_19 = (tssl >> 16) & 0xF;
+
+ processor->tss.iopb = tssl;
+
+ extern void gdt_load(void*);
+ gdt_load(&processor->gdtr);
+
+ extern void tss_flush(uint16_t);
+ tss_flush(GDT_ENTRY_TSS_LOW * sizeof(segment_descriptor_t));
+}