summaryrefslogtreecommitdiff
path: root/src/gdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdt.c')
-rw-r--r--src/gdt.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/gdt.c b/src/gdt.c
new file mode 100644
index 0000000..22489ac
--- /dev/null
+++ b/src/gdt.c
@@ -0,0 +1,44 @@
+#include <gdt.h>
+
+struct gdt_entry {
+ uint16_t limit_low;
+ uint16_t base_low;
+ uint8_t base_middle_low;
+ uint8_t access;
+ uint8_t gran;
+ uint8_t base_middle_high;
+ uint32_t base_high;
+ uint32_t reseved;
+} __attribute__((packed));
+
+struct gdt {
+ uint16_t limit;
+ uint64_t base;
+} __attribute__((packed));
+
+struct gdt_entry gdt[3];
+struct gdt gdt_ptr;
+
+extern void gdt_flush();
+
+void gdt_set_gate(size_t num, uint64_t base, uint32_t limit, uint8_t access, uint8_t gran) {
+ gdt[num] = (struct gdt_entry) {
+ .base_low = base & 0xFFFF,
+ .base_middle_low = (base >> 16) & 0xFF,
+ .base_middle_high = (base >> 24) & 0xFF,
+ .base_high = (base >> 32) & 0xFFFFFFFF,
+ .limit_low = limit & 0xFFFF,
+ .gran = ((limit >> 16) & 0x0F) | (gran & 0xF0),
+ .access = access
+ };
+}
+
+void gdt_install() {
+ gdt_ptr.limit = (sizeof(struct gdt_entry) * 3) - 1;
+ gdt_ptr.base = (uint64_t) &gdt;
+
+ gdt_set_gate(0, 0, 0, 0, 0);
+ gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
+ gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+ gdt_flush();
+}