BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / c738dbb1e7e7a46a98436326234826eef71083e2 / kernel / gdt.c

// Related

Nucleus

Barry CPU specific segment c738dbb (3 years, 2 months ago)
diff --git a/kernel/gdt.c b/kernel/gdt.c
index bd083a6..b9cebb6 100644
--- a/kernel/gdt.c
+++ b/kernel/gdt.c
@@ -15,12 +15,26 @@
 #include <nucleus/cpu.h>
 #include "desc.h"
 
+/* GDT Entry Indicies */
+enum GDTIndex {
+	GDT_NULL,
+	GDT_KERN_CODE,
+	GDT_KERN_DATA,
+	GDT_USER_CODE,
+	GDT_USER_DATA,
+	GDT_FS,
+	GDT_GS,
+	GDT_TSS,
+};
+
 /* Structure for a GDT Entry */
 static struct GDTEntry {
 	uint16_t limitLower, baseLower;
 	uint8_t baseMiddle, access, gran, baseHigher;
 } __attribute__((packed)) *gdt[MAX_CPUS]; /* Per CPU */
 
+#define GDT_OFFSET(i) (i * sizeof(struct GDTEntry))
+
 /* Structure for a TSS Entry */
 static struct TSSEntry {
 	uint32_t prevTSS;
@@ -58,7 +72,8 @@ cpu_load_gdt(void)
 	 * an existing page, the new structures should be allocated in there.
 	 * Otherwise, a new page frame should be allocated.
 	 */
-	size_t size = (sizeof(struct GDTEntry) * 6) + sizeof(struct TSSEntry);
+	size_t size = (sizeof(struct GDTEntry) * (GDT_TSS + 1))
+	            + sizeof(struct TSSEntry);
 	off_t idx = CPUID % (PAGE_SIZE / size);
 	off_t block = (CPUID / (PAGE_SIZE / size)) * (PAGE_SIZE / size);
 	if (idx == 0)
@@ -68,29 +83,52 @@ cpu_load_gdt(void)
 
 	memset(gdt[CPUID], 0, size);
 
-	gdt_set_gate(0, 0x00000000, 0x00000000, 0x00, 0x00); /* Null */
-	/* Ring 0 */
-	gdt_set_gate(1, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF); /* Code */
-	gdt_set_gate(2, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF); /* Data */
-	/* Ring 3 */
-	gdt_set_gate(3, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF); /* Code */
-	gdt_set_gate(4, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF); /* Data */
+	gdt_set_gate(GDT_NULL,      0x00000000, 0x00000000, 0x00, 0x00);
+	gdt_set_gate(GDT_KERN_CODE, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF);
+	gdt_set_gate(GDT_KERN_DATA, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF);
+	gdt_set_gate(GDT_USER_CODE, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF);
+	gdt_set_gate(GDT_USER_DATA, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
+	gdt_set_gate(GDT_FS,        0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
+	gdt_set_gate(GDT_GS,        0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
 
-	uint32_t addr = (uint32_t) gdt[CPUID] + (sizeof(struct GDTEntry) * 6);
-	gdt_set_gate(5, addr, sizeof(struct TSSEntry) - 1, 0xE9, 0);
+	uint32_t addr = (uint32_t) (gdt[CPUID] + (GDT_TSS + 1));
+	gdt_set_gate(GDT_TSS, addr, sizeof(struct TSSEntry) - 1, 0xE9, 0);
 
 	tss[CPUID] = (void *) addr;
 	tss[CPUID]->ss0 = 0x10;
 	tss[CPUID]->esp0 = 0xF0800000 - sizeof(uintptr_t);
-	tss[CPUID]->cs = 0x08 | 0;
-	tss[CPUID]->ds = tss[CPUID]->es = tss[CPUID]->ss = 0x10 | 0;
-	tss[CPUID]->fs = tss[CPUID]->gs = 0x10 | 3;
+	tss[CPUID]->cs = GDT_OFFSET(GDT_KERN_CODE) | 0;
+	tss[CPUID]->ds = GDT_OFFSET(GDT_KERN_DATA) | 0;
+	tss[CPUID]->es = tss[CPUID]->ss = tss[CPUID]->ds;
+	tss[CPUID]->fs = tss[CPUID]->gs = GDT_OFFSET(GDT_FS) | 3;
 	tss[CPUID]->iomapBase = sizeof(struct TSSEntry);
 
 	struct DescRecord ptr = {
-		.limit = sizeof(struct GDTEntry) * 6,
+		.limit = sizeof(struct GDTEntry) * (GDT_TSS + 1),
 		.base = (uintptr_t) gdt[CPUID],
 	};
 	asm volatile("lgdt %0" :: "m" (ptr));
-	asm volatile("ltr %w0" :: "q" (0x28 | 3));
+	asm volatile("ltr %w0" :: "q" (GDT_OFFSET(GDT_TSS) | 3));
+}
+
+/* Set FS base */
+void
+set_fs_base(uintptr_t base)
+{
+	struct GDTEntry *fs = gdt[CPUID] + GDT_FS;
+	fs->baseLower = (base & 0xFFFF);
+	fs->baseMiddle = (base >> 16) & 0xFF;
+	fs->baseHigher = (base >> 24) & 0xFF;
+	asm volatile("mov %0, %%fs" :: "r" (GDT_OFFSET(GDT_FS) | 3));
+}
+
+/* Set FS base */
+void
+set_gs_base(uintptr_t base)
+{
+	struct GDTEntry *gs = gdt[CPUID] + GDT_GS;
+	gs->baseLower = (base & 0xFFFF);
+	gs->baseMiddle = (base >> 16) & 0xFF;
+	gs->baseHigher = (base >> 24) & 0xFF;
+	asm volatile("mov %0, %%gs" :: "r" (GDT_OFFSET(GDT_GS) | 3));
 }