diff options
author | Marvin Borner | 2021-04-29 14:36:40 +0200 |
---|---|---|
committer | Marvin Borner | 2021-04-29 14:36:40 +0200 |
commit | f8e47b6b0c0578c52d82c0e243620361b87a4abe (patch) | |
tree | e42d898d299b7aa10c8f266d347b4fda5a5967f3 /kernel/drivers | |
parent | 04104fc051d44f4f9b3328f29b4be91fa4060f34 (diff) |
Multiboot/Grub progress
Diffstat (limited to 'kernel/drivers')
-rw-r--r-- | kernel/drivers/cpu.c | 15 | ||||
-rw-r--r-- | kernel/drivers/gdt.c | 96 |
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"); +} |