aboutsummaryrefslogtreecommitdiff
path: root/kernel/drivers
diff options
context:
space:
mode:
authorMarvin Borner2021-04-29 14:36:40 +0200
committerMarvin Borner2021-04-29 14:36:40 +0200
commitf8e47b6b0c0578c52d82c0e243620361b87a4abe (patch)
treee42d898d299b7aa10c8f266d347b4fda5a5967f3 /kernel/drivers
parent04104fc051d44f4f9b3328f29b4be91fa4060f34 (diff)
Multiboot/Grub progress
Diffstat (limited to 'kernel/drivers')
-rw-r--r--kernel/drivers/cpu.c15
-rw-r--r--kernel/drivers/gdt.c96
2 files changed, 96 insertions, 15 deletions
diff --git a/kernel/drivers/cpu.c b/kernel/drivers/cpu.c
index 2c86008..5d53bef 100644
--- a/kernel/drivers/cpu.c
+++ b/kernel/drivers/cpu.c
@@ -91,21 +91,6 @@ void fpu_restore(void)
__asm__ volatile("fxrstor (%0)" ::"r"(fpu_state));
}
-void tss_set_stack(u32 ss, u32 esp)
-{
- UNUSED(ss);
- UNUSED(esp);
- return;
- /* assert(tss_entry && ss && esp); */
- /* struct { */
- /* u32 prev; */
- /* u32 esp0; */
- /* u32 ss0; */
- /* } *tss = (void *)tss_entry; */
- /* tss->esp0 = esp; */
- /* tss->ss0 = ss; */
-}
-
CLEAR static struct cpuid cpuid(u32 code)
{
u32 a, b, c, d;
diff --git a/kernel/drivers/gdt.c b/kernel/drivers/gdt.c
new file mode 100644
index 0000000..73db111
--- /dev/null
+++ b/kernel/drivers/gdt.c
@@ -0,0 +1,96 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <assert.h>
+#include <def.h>
+#include <gdt.h>
+#include <mem.h>
+
+static struct gdt_entry gdt[6] = { 0 };
+static struct tss_entry tss = { 0 };
+
+PROTECTED static struct gdt_ptr gp = { 0 };
+
+CLEAR static void gdt_set_gate(u32 num, u32 base, u32 limit, u8 access, u8 gran)
+{
+ // Set descriptor base address
+ gdt[num].base_low = (u16)(base & 0xffff);
+ gdt[num].base_middle = (u8)((base >> 16) & 0xff);
+ gdt[num].base_high = (u8)((base >> 24) & 0xff);
+ gdt[num].limit_low = (u16)(limit & 0xffff);
+
+ // Set granularity and access flags
+ gdt[num].granularity = (u8)((limit >> 16) & 0x0f);
+ gdt[num].granularity |= (gran & 0xf0);
+ gdt[num].access = access;
+}
+
+CLEAR static void tss_write(u32 num, u16 ss0, u32 esp0)
+{
+ u32 base = (u32)&tss;
+ u32 limit = base + sizeof(tss);
+
+ gdt_set_gate(num, base, limit, 0xe9, 0x00);
+
+ memset(&tss, 0, sizeof(tss));
+
+ tss.ss0 = ss0;
+ tss.esp0 = esp0;
+ tss.cs = 0x0b;
+ tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;
+}
+
+CLEAR static void tss_flush(void)
+{
+ __asm__ volatile("ltr %0" ::"r"((u16)0x2b));
+}
+
+CLEAR static void gdt_flush(void)
+{
+ __asm__ volatile("lgdt %0" ::"m"(gp) : "memory");
+}
+
+void tss_set_stack(u32 ss, u32 esp)
+{
+ assert(ss && esp);
+ tss.esp0 = esp;
+ tss.ss0 = ss;
+}
+
+CLEAR void gdt_install(void)
+{
+ // Set GDT pointer and limit
+ gp.limit = (sizeof(struct gdt_entry) * 6) - 1;
+ gp.base = &gdt;
+
+ // NULL descriptor
+ gdt_set_gate(0, 0, 0, 0, 0);
+
+ // Code segment
+ gdt_set_gate(1, 0, 0xffffffff, 0x9a, 0xcf);
+
+ // Data segment
+ gdt_set_gate(2, 0, 0xffffffff, 0x92, 0xcf);
+
+ // User mode code segment
+ gdt_set_gate(3, 0, 0xffffffff, 0xfa, 0xcf);
+
+ // User mode data segment
+ gdt_set_gate(4, 0, 0xffffffff, 0xf2, 0xcf);
+
+ // Write TSS
+ tss_write(5, GDT_SUPER_DATA_OFFSET, STACK_START);
+
+ // Remove old GDT and install the new changes!
+ gdt_flush();
+ tss_flush();
+
+ __asm__ volatile("mov %%ax, %%ds\n"
+ "mov %%ax, %%es\n"
+ "mov %%ax, %%fs\n"
+ "mov %%ax, %%gs\n"
+ "mov %%ax, %%ss\n" ::"a"(GDT_SUPER_DATA_OFFSET)
+ : "memory");
+
+ __asm__ volatile("ljmpl $" STRINGIFY(GDT_SUPER_CODE_OFFSET) ", $code\n"
+ "code:\n");
+}