BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / d41a53cbc7d055b1c00cf0a339dbed6925f4f02c / proc / gdt.c

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)
diff --git a/proc/gdt.c b/proc/gdt.c
new file mode 100644
index 0000000..6d9a7c7
--- /dev/null
+++ b/proc/gdt.c
@@ -0,0 +1,104 @@
+/*
+ * This file deals with the Global Descriptor Table.  It creates a simple GDT,
+ * suitable for use in the Kernel, and attaches a TSS to the end.  The TSS,
+ * which can be used to switch from ring 3 to ring 0, allows processes access to
+ * all IO ports.
+ */
+
+#include <stdint.h>
+#include "../mem/heap.h"
+#include "../mem/mem.h"
+#include "../mem/frame.h"
+#include "../proc/proc.h"
+#include "../screen.h"
+
+#define GDT_ENTRIES 6
+
+/* Structure for GDT entry */
+static struct GDTEntry {
+	uint16_t limitLower, baseLower;
+	uint8_t baseMiddle, access, gran, baseHigher;
+} __attribute__((packed)) *GDT;
+
+/* Structure for TSS entry */
+static struct TSSEntry {
+	uint32_t prevTSS;
+	uint32_t esp0, ss0;
+	uint32_t esp1, ss1;
+	uint32_t esp2, ss2;
+	uint32_t cr3, eip, eflags;
+	uint32_t eax, ecx, edx, ebx;
+	uint32_t esp, ebp, esi, edi;
+	uint32_t es, cs, ss, ds, fs, gs;
+	uint32_t ldt;
+	uint16_t trap, iomapBase;
+//	uint32_t iomap[2048];
+} __attribute__((packed)) *TSS; /* Per CPU */
+
+void load_gdt(uint32_t gdtPtr);
+void load_tss(void);
+
+/* Set a gate of the GDT */
+static void
+gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit,
+             uint8_t access, uint8_t gran)
+{
+	GDT[num].baseLower = (base & 0xFFFF);
+	GDT[num].baseMiddle = (base >> 16) & 0xFF;
+	GDT[num].baseHigher = (base >> 24) & 0xFF;
+	GDT[num].limitLower = (limit & 0xFFFF);
+	GDT[num].gran = (limit >> 16) & 0x0F;
+	GDT[num].gran |= gran & 0xF0;
+	GDT[num].access = access;
+}
+
+/* Create a TSS */
+static void
+write_tss(uint8_t num, uint32_t esp)
+{
+	uint32_t base = (uint32_t) TSS;
+	uint32_t limit = sizeof(struct TSSEntry) - 1;
+
+	gdt_set_gate(num, base, limit, 0xE9, 0x00);
+	num -= 5;
+	memset(&TSS[num], 0, sizeof(struct TSSEntry));
+	TSS[num].ss0 = 0x10;
+	TSS[num].esp0 = esp;
+	TSS[num].cs = 0x08 | 0;
+	TSS[num].ds = TSS[num].es = TSS[num].ss = 0x10 | 0;
+	TSS[num].fs = TSS[num].gs = 0x10 | 3;
+	TSS[num].iomapBase = 104;
+}
+
+/* Initialise the Kernel GDT */
+void
+init_gdt(void)
+{
+	GDT = (void *) alloc_frames(1);
+	TSS = (void *) (GDT + GDT_ENTRIES);
+	kprintf("Loaded GDT @ %#.8x, TSS @ %#.8x", GDT, TSS);
+}
+
+/* Load the Kernel GDT */
+void
+cpu_load_gdt(void)
+{
+	memset(GDT, 0, sizeof(GDT[0]) * GDT_ENTRIES);
+
+	gdt_set_gate(0, 0x00000000, 0x00000000, 0x00, 0x00); /* Null segment */
+	/* Ring 0 */
+	gdt_set_gate(1, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF); /* Code segment */
+	gdt_set_gate(2, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
+	/* Ring 3 */
+	gdt_set_gate(3, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF); /* Code segment */
+	gdt_set_gate(4, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF); /* Data segment */
+	/* TSS */
+	write_tss(5, 0xF0800000 - sizeof(uintptr_t));
+
+	uint16_t gdtPtr[3];
+	gdtPtr[0] = (sizeof(GDT[0]) * GDT_ENTRIES) - 1;
+	gdtPtr[1] = ((uint32_t) GDT) & 0xFFFF;
+	gdtPtr[2] = ((uint32_t) GDT) >> 16;
+	load_gdt((uint32_t) &gdtPtr);
+	load_tss();
+}