diff options
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/drivers/cpu.c | 15 | ||||
-rw-r--r-- | kernel/drivers/gdt.c | 96 | ||||
-rw-r--r-- | kernel/features/mm.c | 43 | ||||
-rw-r--r-- | kernel/features/proc.c | 1 | ||||
-rw-r--r-- | kernel/inc/cpu.h | 2 | ||||
-rw-r--r-- | kernel/inc/gdt.h | 60 | ||||
-rw-r--r-- | kernel/inc/mm.h | 3 | ||||
-rw-r--r-- | kernel/inc/multiboot.h | 9 | ||||
-rw-r--r-- | kernel/inc/proc.h | 5 | ||||
-rw-r--r-- | kernel/main.c | 7 | ||||
-rw-r--r-- | kernel/multiboot.c | 36 | ||||
-rw-r--r-- | libs/libc/inc/def.h | 3 |
13 files changed, 219 insertions, 62 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index e51469d..8296e02 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,6 +5,7 @@ COBJS = entry_asm.o \ multiboot.o \ drivers/interrupts.o \ drivers/interrupts_asm.o \ + drivers/gdt.o \ drivers/cpu.o \ drivers/serial.o \ drivers/pci.o \ 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"); +} diff --git a/kernel/features/mm.c b/kernel/features/mm.c index 39a6316..9dd425e 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -8,6 +8,7 @@ #include <fb.h> #include <mem.h> #include <mm.h> +#include <multiboot.h> #include <print.h> #include <rand.h> @@ -133,7 +134,12 @@ static void physical_page_set_free(u32 address) memory[page / 8] &= ~(1 << (page % 8)); } -static void physical_set_used(struct memory_range range) +CLEAR void physical_set_total(u32 total) +{ + memory_total = total; +} + +void physical_set_used(struct memory_range range) { assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); @@ -146,7 +152,7 @@ static void physical_set_used(struct memory_range range) } } -static void physical_set_free(struct memory_range range) +void physical_set_free(struct memory_range range) { assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); @@ -721,29 +727,7 @@ void memory_user_hook(void) CLEAR void memory_install(void) { - struct mem_info *mem_info = NULL; - struct vid_info *vid_info = NULL; - - for (struct mmap_boot *p = mem_info->start; (u32)(p - mem_info->start) < mem_info->size; - p++) { - if (p->hbase || !p->acpi || !p->type) - continue; - - u32 size = p->lsize; - if (p->hsize) - size = U32_MAX - p->lbase; - - /* printf("Memory region: %x-%x\n", p->lbase, p->lbase + size); */ - if (p->type == MEMORY_AVAILABLE) { - physical_set_free(memory_range_around(p->lbase, size)); - memory_total += size; - } else if (p->type == MEMORY_DEFECT) { - printf("Defect memory at 0x%x-0x%x!\n", p->lbase, p->lbase + size); - physical_set_used(memory_range_around(p->lbase, size)); - } else { - physical_set_used(memory_range_around(p->lbase, size)); - } - } + multiboot_mmap(); for (u32 i = 0; i < PAGE_KERNEL_COUNT; i++) { union page_dir_entry *dir_entry = &kernel_dir.entries[i]; @@ -757,7 +741,7 @@ CLEAR void memory_install(void) printf("Detected memory: %dKiB (%dMiB)\n", memory_total >> 10, memory_total >> 20); // Set first MiB 'used' (bootloader(s), VESA tables, memory maps, ...) - physical_set_used(memory_range(0, 0x00100000)); + //physical_set_used(memory_range(0, 0x00100000)); // Map kernel memory_map_identity(&kernel_dir, kernel_ro_memory_range(), MEMORY_READONLY); @@ -772,13 +756,10 @@ CLEAR void memory_install(void) memory_map_identity(&kernel_dir, memory_range(STACK_START, PAGE_SIZE), MEMORY_READONLY); // Map framebuffer - memory_map_identity(&kernel_dir, memory_range_around((u32)vid_info->vbe, 0x1000), - MEMORY_NONE); + /* memory_map_identity(&kernel_dir, memory_range_around((u32)vid_info->vbe, 0x1000), */ + /* MEMORY_NONE); */ /* fb_map_buffer(virtual_kernel_dir(), vid_info); */ - // Map TSS - //memory_map_identity(&kernel_dir, memory_range_around(boot->tss, 0x1000), MEMORY_NONE); - // Unmap NULL byte/page struct memory_range zero = memory_range(0, PAGE_SIZE); virtual_free(&kernel_dir, zero); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 70f2efc..6812c72 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -5,6 +5,7 @@ #include <cpu.h> #include <errno.h> #include <fs.h> +#include <gdt.h> #include <load.h> #include <mem.h> #include <mm.h> diff --git a/kernel/inc/cpu.h b/kernel/inc/cpu.h index 3d29e4f..7ac6074 100644 --- a/kernel/inc/cpu.h +++ b/kernel/inc/cpu.h @@ -32,8 +32,6 @@ void cr3_set(u32 cr3); u32 cr4_get(void); void cr4_set(u32 cr4); -void tss_set_stack(u32 ss, u32 esp); - void clac(void); void stac(void); diff --git a/kernel/inc/gdt.h b/kernel/inc/gdt.h new file mode 100644 index 0000000..06388a9 --- /dev/null +++ b/kernel/inc/gdt.h @@ -0,0 +1,60 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef GDT_H +#define GDT_H + +#include <def.h> + +#define GDT_SUPER_CODE_OFFSET 0x08 // Super (kernel) code segment offset in GDT +#define GDT_SUPER_DATA_OFFSET 0x10 // Super (kernel) data segment offset in GDT +#define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask) +#define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask) + +struct gdt_entry { + u16 limit_low; + u16 base_low; + u8 base_middle; + u8 access; + u8 granularity; + u8 base_high; +} PACKED; + +struct gdt_ptr { + u16 limit; + void *base; +} PACKED; + +struct tss_entry { + u32 prev_tss; + u32 esp0; + u32 ss0; + u32 esp1; + u32 ss1; + u32 esp2; + u32 ss2; + u32 cr3; + u32 eip; + u32 eflags; + u32 eax; + u32 ecx; + u32 edx; + u32 ebx; + u32 esp; + u32 ebp; + u32 esi; + u32 edi; + u32 es; + u32 cs; + u32 ss; + u32 ds; + u32 fs; + u32 gs; + u32 ldt; + u16 trap; + u16 iomap_base; +} PACKED; + +void gdt_install(void); +void tss_set_stack(u32 ss, u32 esp); + +#endif diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 1652695..a33d9d1 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -27,6 +27,9 @@ void page_fault_handler(struct regs *r) NONNULL; struct memory_range physical_alloc(u32 size); void physical_free(struct memory_range range); +void physical_set_used(struct memory_range range); +void physical_set_free(struct memory_range range); +void physical_set_total(u32 total); /** * Virtual diff --git a/kernel/inc/multiboot.h b/kernel/inc/multiboot.h index f9851fb..839ade7 100644 --- a/kernel/inc/multiboot.h +++ b/kernel/inc/multiboot.h @@ -104,9 +104,11 @@ struct multiboot_info { }; struct multiboot_mmap_entry { - u32 size; - u64 addr; - u64 len; + u32 struct_size; + u32 addr; + u32 addr_high; + u32 len; + u32 len_high; u32 type; } PACKED; @@ -119,6 +121,7 @@ struct multiboot_mod_list { u32 pad; }; +void multiboot_mmap(void); void multiboot_init(u32 magic, u32 addr); #endif diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 877e53e..e74286c 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -15,11 +15,6 @@ #define EFLAGS_ALWAYS 0x2 // Always one #define EFLAGS_INTERRUPTS 0x200 // Enable interrupts -#define GDT_SUPER_CODE_OFFSET 0x08 // Super (kernel) code segment offset in GDT -#define GDT_SUPER_DATA_OFFSET 0x10 // Super (kernel) data segment offset in GDT -#define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask) -#define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask) - #define RING(regs) ((regs->cs) & 3) enum proc_priv { PROC_PRIV_NONE, PROC_PRIV_ROOT, PROC_PRIV_KERNEL }; diff --git a/kernel/main.c b/kernel/main.c index e0e544b..37dd2da 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -3,6 +3,7 @@ #include <boot.h> #include <cpu.h> #include <fs.h> +#include <gdt.h> #include <ide.h> #include <interrupts.h> #include <io.h> @@ -26,11 +27,11 @@ int kernel_main(u32 magic, u32 addr) // Serial connection serial_install(); serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); - serial_print("Serial connected. LOOPING!\n"); + serial_print("Serial connected!\n"); + + gdt_install(); multiboot_init(magic, addr); - while (1) - ; memory_install(); memory_switch_dir(virtual_kernel_dir()); diff --git a/kernel/multiboot.c b/kernel/multiboot.c index eafe4c5..a9a0c75 100644 --- a/kernel/multiboot.c +++ b/kernel/multiboot.c @@ -2,16 +2,46 @@ #include <assert.h> #include <def.h> +#include <mm.h> #include <multiboot.h> -static struct multiboot_info *info = NULL; +PROTECTED static struct multiboot_info *info = NULL; -void multiboot_init(u32 magic, u32 addr) +CLEAR void multiboot_init(u32 magic, u32 addr) { assert(magic == MULTIBOOT_MAGIC); info = (void *)addr; if (info->flags & MULTIBOOT_INFO_CMDLINE) { - printf("CMDLINE: '%s'\n", info->cmdline); + // TODO: Do something useful with grub cmdline? + /* printf("CMDLINE: '%s'\n", info->cmdline); */ } } + +CLEAR void multiboot_mmap(void) +{ + assert(info->flags & MULTIBOOT_INFO_MEMORY); + + struct multiboot_mmap_entry *mmap = (void *)info->mmap_addr; + u32 length = info->mmap_length; + u32 count = length / sizeof(*mmap); + + u32 total = 0; + + for (u32 i = 0; i < count; i++) { + /* printf("Memory region 0x%x-0x%x\n", mmap->addr, mmap->addr + mmap->len); */ + if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) { + total += mmap->len; + physical_set_free(memory_range_around(mmap->addr, mmap->len)); + } else if (mmap->type == MULTIBOOT_MEMORY_BADRAM) { + printf("Defect memory at 0x%x-0x%x\n", mmap->addr, mmap->addr + mmap->len); + physical_set_used(memory_range_around(mmap->addr, mmap->len)); + } else { + physical_set_used(memory_range_around(mmap->addr, mmap->len)); + } + + mmap++; + } + + physical_set_total(total); +} diff --git a/libs/libc/inc/def.h b/libs/libc/inc/def.h index 134d8bb..cf49c63 100644 --- a/libs/libc/inc/def.h +++ b/libs/libc/inc/def.h @@ -30,6 +30,9 @@ typedef unsigned long long u64; #define ABS(a) ((u32)(((s32)(a) < 0) ? -(a) : (a))) +#define __STRINGIFY(a) #a +#define STRINGIFY(a) __STRINGIFY(a) + #define ATTR __attribute__ #define NORETURN ATTR((noreturn)) #define NOINLINE ATTR((noinline)) |