aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarvin Borner2019-09-30 22:41:39 +0200
committerMarvin Borner2019-09-30 22:42:02 +0200
commit682c47a98844ffec3f3129160e9cdb98ba129989 (patch)
treee673ace5ef65c83907cbd6575ec3a1a7e49b0fd6 /src
parent2fb0965a68dd232a70d1616bfbd7281fc65c2b0a (diff)
Added paging and fixed several bugs
Diffstat (limited to 'src')
-rw-r--r--src/kernel/graphics/vesa.c21
-rw-r--r--src/kernel/graphics/vesa.h4
-rw-r--r--src/kernel/kernel.c13
-rw-r--r--src/kernel/paging/kheap.c168
-rw-r--r--src/kernel/paging/kheap.h51
-rw-r--r--src/kernel/paging/paging.c167
-rw-r--r--src/kernel/paging/paging.h59
-rw-r--r--src/kernel/system.h20
8 files changed, 459 insertions, 44 deletions
diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index f6bdba0..32bc0e9 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -2,6 +2,7 @@
#include "graphics.h"
#include "../input/input.h"
#include "../system.h"
+#include "../paging/kheap.h"
void switch_to_vga() {
regs16_t regs;
@@ -56,15 +57,11 @@ struct vbe_mode_info *vbe_set_mode(unsigned short mode) {
}
void set_optimal_resolution() {
- init();
- terminal_write_string("SUCCESS!\n");
- keyboard_install();
-
struct vbe_info *info;
struct vbe_mode_info *mode_info;
- // info = lmalloc(sizeof(struct vbe_info));
- // mode_info = lmalloc(sizeof(struct vbe_mode_info));
+ info = kmalloc(sizeof(struct vbe_info));
+ mode_info = kmalloc(sizeof(struct vbe_mode_info));
info->signature[0] = 'V';
info->signature[1] = 'B';
@@ -83,7 +80,8 @@ void set_optimal_resolution() {
uint16_t *mode_ptr = get_ptr(info->video_modes);
uint16_t mode;
- struct vbe_mode_info *highest;
+ uint16_t highest = 0x11B;
+ uint16_t highest_height = 0;
while ((mode = *mode_ptr++) != 0xFFFF) {
mode &= 0x1FF;
regs16_t regs2;
@@ -94,12 +92,15 @@ void set_optimal_resolution() {
int32(0x10, &regs2);
if ((mode_info->attributes & 0x90) != 0x90) continue;
- if (mode_info->height >= highest->height) {
- highest = mode_info;
+ if (mode_info->height >= highest_height) {
+ highest = mode;
+ highest_height = mode_info->height;
}
}
- // lfree(info);
+ vbe_set_mode(0x11B);
+
+ kfree(info);
/*if (strcmp((const char *) info->version, (const char *) 0x300) == 0) {
init();
diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h
index 33272f8..eff74ea 100644
--- a/src/kernel/graphics/vesa.h
+++ b/src/kernel/graphics/vesa.h
@@ -11,9 +11,9 @@
struct vbe_info {
char signature[4];
uint32_t version;
- far_ptr_t oem;
+ struct far_ptr oem;
uint32_t capabilities;
- far_ptr_t video_modes;
+ struct far_ptr video_modes;
uint32_t video_memory;
uint32_t software_rev;
uint32_t vendor;
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 383966d..013f7d5 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -4,26 +4,29 @@
#include "interrupts/interrupts.h"
#include "input/input.h"
#include "timer/timer.h"
+#include "paging/paging.h"
+#include "paging/kheap.h"
void init() {
gdt_install();
idt_install();
isrs_install();
irq_install();
- asm volatile ("sti");
+ init_kheap();
+ page_init();
timer_install();
- terminal_initialize();
+ // terminal_initialize();
keyboard_install();
// mouse_install();
+ asm volatile ("sti");
}
void kernel_main(void) {
// vbe_set_mode(0x11B);
- // set_optimal_resolution();
+ set_optimal_resolution();
init();
- keyboard_install();
- terminal_write_string("Melvix loaded successfully!\n");
+ // terminal_write_string("Melvix loaded successfully!\n");
// __asm__ ("div %0" :: "r"(0)); // Exception testing x/0
for (;;);
diff --git a/src/kernel/paging/kheap.c b/src/kernel/paging/kheap.c
new file mode 100644
index 0000000..13f8ab2
--- /dev/null
+++ b/src/kernel/paging/kheap.c
@@ -0,0 +1,168 @@
+#include "kheap.h"
+#include "paging.h"
+#include "../lib/lib.h"
+#include "../system.h"
+
+unsigned int placement_address;
+
+heap_header_t *kheap = NULL;
+heap_header_t *uheap = NULL;
+
+void init_kheap() {
+ end = (unsigned int) &end;
+ placement_address = end;
+
+ kheap = (heap_header_t *) fmalloc(KHEAP_SIZE);
+ init_heap(kheap, KHEAP_SIZE);
+
+ uheap = (heap_header_t *) kmalloc_a(UHEAP_SIZE);
+ init_heap(uheap, UHEAP_SIZE);
+ vpage_map_user(root_vpage_dir, (unsigned int) &uheap, (unsigned int) &uheap);
+}
+
+void *fmalloc(unsigned int size) {
+ //assert(placement_address + size < MEM_END);
+ unsigned int hold = placement_address;
+ memory_set((void *) hold, 0, size);
+ placement_address += size;
+ return (void *) hold;
+}
+
+void *kmalloc_a(unsigned int size) {
+ //assert(((placement_address & 0xFFFFF000) + 0x1000) + size < MEM_END);
+ placement_address &= 0xFFFFF000;
+ placement_address += 0x1000;
+
+ unsigned int hold = placement_address;
+ placement_address += size;
+
+ return (void *) hold;
+}
+
+heap_header_t *find_sized_heap(heap_header_t *heap, size_t size) {
+ while ((heap->size < HEAP_FIND_SIZE + size) || (heap->free != 1)) {
+ assert(heap->magic == KHEAP_MAGIC);
+ assert(heap->magic2 == KHEAP_MAGIC2);
+ heap_footer_t *foot = (heap_footer_t *) ((unsigned int) heap + HEAP_S + heap->size);
+ assert(foot->magic == KHEAP_MAGIC);
+ assert(foot->magic2 == KHEAP_MAGIC2);
+
+ if (foot->size == KHEAP_END)
+ panic("out of heap space");
+
+ if (foot->size != heap->size)
+ panic("heap footer/header mismatch");
+
+ heap = (heap_header_t *) ((unsigned int) foot + sizeof(heap_footer_t));
+ }
+
+ return heap;
+}
+
+void split_heap(heap_header_t *heap, size_t size) {
+ heap_footer_t *foot = (heap_footer_t *) ((unsigned int) heap + HEAP_S + size);
+ foot->magic = KHEAP_MAGIC;
+ foot->magic2 = KHEAP_MAGIC2;
+ foot->size = size;
+
+ size_t new_size = heap->size - HEAP_TOTAL - size;
+ heap->size = size;
+
+ heap = (heap_header_t *) ((unsigned int) foot + sizeof(heap_footer_t));
+ heap->size = new_size;
+ heap->free = 1;
+ heap->magic = KHEAP_MAGIC;
+ heap->magic2 = KHEAP_MAGIC2;
+
+ foot = (heap_footer_t *) ((unsigned int) heap + HEAP_S + heap->size);
+ if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+ warn("invalid footer in split");
+ // dump_struct(foot, sizeof(heap_footer_t));
+ }
+
+ if (foot->size != KHEAP_END)
+ foot->size = new_size;
+}
+
+void free_internal(heap_header_t *heap, void *address) {
+ heap_header_t *head = (heap_header_t *) ((unsigned int) address - HEAP_S);
+ if (head == heap) {
+ warn("can't collapse top of heap");
+ head->free = 1;
+ return;
+ }
+
+ if ((head->magic != KHEAP_MAGIC) || (head->magic2 != KHEAP_MAGIC2)) {
+ //warn("invalid header in heap");
+ //dump_struct(head, sizeof(heap_header_t));
+ return;
+ }
+
+ heap_footer_t *foot = (heap_footer_t *) ((unsigned int) head + HEAP_S + head->size);
+ if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2))
+ panic("bad heap in free() call");
+
+ foot = (heap_footer_t *) ((unsigned int) head - sizeof(heap_footer_t));
+ if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+ //warn("invalid footer in heap");
+ return;
+ }
+
+ if (foot->size == KHEAP_END)
+ panic("impossible condition for heap");
+
+ heap = (heap_header_t *) ((unsigned int) foot - foot->size - HEAP_S);
+ if ((heap->magic != KHEAP_MAGIC) || (heap->magic2 != KHEAP_MAGIC2)) {
+ warn("invalid parent in heap");
+ return;
+ }
+
+ foot = (heap_footer_t *) ((unsigned int) heap + (heap->size + head->size + HEAP_TOTAL) + HEAP_S);
+ if ((foot->magic != KHEAP_MAGIC) || (foot->magic2 != KHEAP_MAGIC2)) {
+ return;
+ }
+
+ heap->size += head->size + HEAP_TOTAL;
+ foot->size = heap->size;
+}
+
+void *malloc_internal(heap_header_t *heap, size_t size) {
+ heap = find_sized_heap(heap, size + 8);
+ heap->free = 0;
+ split_heap(heap, size);
+ return (void *) ((unsigned int) heap + HEAP_S);
+}
+
+void init_heap(heap_header_t *heap, size_t size) {
+ heap->magic = KHEAP_MAGIC;
+ heap->magic2 = KHEAP_MAGIC2;
+ heap->free = 1;
+ heap->size = size - HEAP_TOTAL;
+
+ heap_footer_t *foot = (heap_footer_t *) ((unsigned int) heap + HEAP_S + heap->size);
+ foot->magic = KHEAP_MAGIC;
+ foot->magic2 = KHEAP_MAGIC2;
+ foot->size = KHEAP_END;
+}
+
+void *kmalloc(unsigned int size) {
+ if (kheap == NULL)
+ return fmalloc(size);
+
+ return malloc_internal(kheap, size);
+}
+
+void kfree(void *address) {
+ if (kheap == NULL)
+ return;
+
+ free_internal(kheap, address);
+}
+
+void *umalloc(size_t size) {
+ return malloc_internal(uheap, size);
+}
+
+void ufree(void *address) {
+ free_internal(uheap, address);
+} \ No newline at end of file
diff --git a/src/kernel/paging/kheap.h b/src/kernel/paging/kheap.h
new file mode 100644
index 0000000..7a92957
--- /dev/null
+++ b/src/kernel/paging/kheap.h
@@ -0,0 +1,51 @@
+#ifndef MELVIX_KHEAP_H
+#define MELVIX_KHEAP_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#define KHEAP_MAGIC 0x13374242
+#define KHEAP_MAGIC2 0xDEADBEEF
+#define KHEAP_END 0xFFFFDEAD
+#define MEM_END 0x8000000
+
+extern unsigned int end;
+
+typedef struct {
+ unsigned int magic;
+ bool free;
+ unsigned int size;
+ unsigned int magic2;
+} heap_header_t;
+
+typedef struct {
+ unsigned int magic;
+ unsigned int size;
+ unsigned int magic2;
+} heap_footer_t;
+
+#define HEAP_S (sizeof(heap_header_t))
+#define HEAP_TOTAL (sizeof(heap_footer_t) + HEAP_S)
+#define HEAP_MINIMUM 1
+#define HEAP_FIND_SIZE (HEAP_TOTAL + HEAP_MINIMUM)
+
+void init_kheap();
+
+void *fmalloc(unsigned int size);
+
+void *kmalloc(unsigned int size);
+
+void *kmalloc_a(unsigned int size);
+
+void kfree(void *ptr);
+
+void *umalloc(size_t size);
+
+void ufree(void *address);
+
+void init_heap(heap_header_t *heap, size_t size);
+
+#define KHEAP_SIZE 0xFFFFF
+#define UHEAP_SIZE 0xFFFFF
+
+#endif
diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c
index 164372e..6282953 100644
--- a/src/kernel/paging/paging.c
+++ b/src/kernel/paging/paging.c
@@ -1,22 +1,159 @@
-#include <stdint.h>
+#include <stddef.h>
+#include "paging.h"
+#include "kheap.h"
+#include "../lib/lib.h"
+#include "../graphics/graphics.h"
+#include "../interrupts/interrupts.h"
-uint64_t page_dir_ptr_tab[4] __attribute__((aligned(0x20)));
-uint64_t page_dir[512] __attribute__((aligned(0x1000)));
-uint64_t page_tab[512] __attribute__((aligned(0x1000)));
+vpage_dir_t *current_vpage_dir = NULL;
+vpage_dir_t *root_vpage_dir = NULL;
-void enable_paging() {
- page_dir_ptr_tab[0] = (uint64_t) &page_dir | 1;
- page_dir[0] = (uint64_t) &page_tab | 3;
+//Assembly abstraction for more maintainable code
+page_table_t *get_cr3() {
+ unsigned int cr3;
- unsigned int i, address = 0;
- for (i = 0; i < 512; i++) {
- page_tab[i] = address | 3;
- address = address + 0x1000;
+ asm volatile ("movl %%cr3, %%eax" : "=a" (cr3));
+ return (page_table_t *) cr3;
+}
+
+unsigned int get_cr0() {
+ unsigned int cr0;
+
+ asm volatile ("movl %%cr0, %%eax" : "=a" (cr0));
+ return cr0;
+}
+
+void set_cr3(vpage_dir_t *dir) {
+ asm volatile ("movl %%eax, %%cr3"::"a" ((unsigned int) &dir->tables[0]));
+}
+
+void set_cr0(unsigned int new_cr0) {
+ asm volatile ("movl %%eax, %%cr0"::"a" (new_cr0));
+}
+
+void switch_vpage_dir(vpage_dir_t *dir) {
+ set_cr3(dir);
+ set_cr0(get_cr0() | 0x80000000);
+}
+
+vpage_dir_t *mk_vpage_dir() {
+ vpage_dir_t *dir = (vpage_dir_t *) kmalloc_a(sizeof(vpage_dir_t));
+
+ int i;
+ for (i = 0; i < 1024; i++)
+ dir->tables[i] = EMPTY_TAB;
+
+ return dir;
+}
+
+page_table_t *mk_vpage_table() {
+ page_table_t *tab = (page_table_t *) kmalloc_a(sizeof(page_table_t));
+
+ int i;
+ for (i = 0; i < 1024; i++) {
+ tab->pages[i].present = 0;
+ tab->pages[i].rw = 1;
+ }
+
+ return tab;
+}
+
+void vpage_map(vpage_dir_t *dir, unsigned int phys, unsigned int virt) {
+ short id = virt >> 22;
+ page_table_t *tab = mk_vpage_table();
+
+ dir->tables[id] = ((page_table_t *) ((unsigned int) tab | 3));
+
+ int i;
+ for (i = 0; i < 1024; i++) {
+ tab->pages[i].frame = phys >> 12;
+ tab->pages[i].present = 1;
+ phys += 4096;
+ }
+}
+
+void vpage_map_user(vpage_dir_t *dir, unsigned int phys, unsigned int virt) {
+ short id = virt >> 22;
+ page_table_t *tab = mk_vpage_table();
+
+ dir->tables[id] = ((page_table_t *) ((unsigned int) tab | 3 | 4));
+
+ int i;
+ for (i = 0; i < 1024; i++) {
+ tab->pages[i].frame = phys >> 12;
+ tab->pages[i].present = 1;
+ tab->pages[i].user = 1;
+ phys += 4096;
}
+}
+void vpage_fault(struct regs *r) {
asm volatile ("cli");
- asm volatile ("movl %cr4, %eax; bts $5, %eax; movl %eax, %cr4"); // CRASH
- asm volatile ("movl %%eax, %%cr3"::"a" (&page_dir_ptr_tab));
- asm volatile ("movl %cr0, %eax; orl $0x80000000, %eax; movl %eax, %cr0;");
- asm volatile ("sti");
+
+ unsigned int no_page = r->err_code & 1;
+ unsigned int rw = r->err_code & 2;
+ unsigned int um = r->err_code & 4;
+ unsigned int re = r->err_code & 8;
+ unsigned int dc = r->err_code & 16;
+
+ if (dc) terminal_write_line(" (Instruction decode error) ");
+ if (!no_page) terminal_write_line(" (No page present) ");
+ if (um) terminal_write_line(" (in user mode) ");
+ if (rw) terminal_write_line(" (Write permissions) ");
+ if (re) terminal_write_line(" (RE) ");
+
+ terminal_write_line("\n");
+}
+
+void page_init() {
+ current_vpage_dir = mk_vpage_dir();
+ root_vpage_dir = current_vpage_dir;
+
+ unsigned int i;
+ for (i = 0; i < 0xF0000000; i += PAGE_S)
+ vpage_map(root_vpage_dir, i, i);
+
+ irq_install_handler(14, vpage_fault);
+ asm volatile ("cli");
+ switch_vpage_dir(root_vpage_dir);
+}
+
+void convert_vpage(vpage_dir_t *kdir) {
+ int i;
+ for (i = 0; i < 1024; i++) {
+ kdir->tables[i] = (page_table_t *) ((unsigned int) kdir->tables[i] | 4);
+
+ if (((unsigned int) kdir->tables[i]) & 1) {
+ int j;
+ for (j = 0; j < 1024; j++)
+ kdir->tables[i]->pages[j].user = 1;
+ }
+ }
+}
+
+void dump_page(vpage_dir_t *dir, unsigned int address) {
+ unsigned short id = address >> 22;
+ terminal_write_line(&"Index salt ="[(unsigned int) dir->tables[id]]);
+}
+
+vpage_dir_t *copy_user_dir(vpage_dir_t *dir) {
+ unsigned int i;
+
+ vpage_dir_t *copy = mk_vpage_dir();
+ memory_copy(copy, root_vpage_dir, sizeof(vpage_dir_t));
+
+ for (i = 0; i < 1024; i++) {
+ if (((unsigned int) dir->tables[i]) & 4) {
+ //vga_fmt("Found a user page at index %d\n", i);
+ page_table_t *tab = (page_table_t *) ((unsigned int) dir->tables[i] & 0xFFFFF000);
+ //vga_fmt("Table at address %X maps to %X\n", (unsigned int) tab, i << 22);
+ //vga_fmt("Virtually mapped from %X\n", tab->pages[0].frame << 12);
+
+ void *buffer = kmalloc_a(PAGE_S);
+ memory_copy(buffer, (void *) (tab->pages[0].frame << 12), PAGE_S);
+ vpage_map_user(copy, (unsigned int) buffer, (unsigned int) i << 22);
+ }
+ }
+
+ return copy;
} \ No newline at end of file
diff --git a/src/kernel/paging/paging.h b/src/kernel/paging/paging.h
index e8c3bf4..790dbee 100644
--- a/src/kernel/paging/paging.h
+++ b/src/kernel/paging/paging.h
@@ -1,6 +1,63 @@
#ifndef MELVIX_PAGING_H
#define MELVIX_PAGING_H
-void enable_paging();
+#define PAGE_S 0x400000
+
+extern unsigned int *current_dir;
+extern unsigned int *root_dir;
+
+typedef struct {
+ unsigned int present : 1;
+ unsigned int rw : 1;
+ unsigned int user : 1;
+ unsigned int accessed : 1;
+ unsigned int dirty : 1;
+ unsigned int unused : 7;
+ unsigned int frame : 20;
+} page_t;
+
+typedef struct {
+ page_t pages[1024];
+} page_table_t;
+
+typedef struct {
+ page_table_t *tables[1024];
+ unsigned int tables_physical[1024];
+ unsigned int physical_address;
+} page_directory_t;
+
+typedef struct {
+ page_table_t *tables[1024];
+} vpage_dir_t;
+
+extern vpage_dir_t *root_vpage_dir;
+
+#define EMPTY_TAB ((page_table_t*) 0x00000002)
+
+page_table_t *get_cr3();
+
+unsigned int get_cr0();
+
+void set_cr3(vpage_dir_t *dir);
+
+void set_cr0(unsigned int new_cr0);
+
+void switch_vpage_dir(vpage_dir_t *dir);
+
+vpage_dir_t *mk_vpage_dir();
+
+page_table_t *mk_vpage_table();
+
+void page_init();
+
+void vpage_map(vpage_dir_t *cr3, unsigned int virt, unsigned int phys);
+
+void vpage_map_user(vpage_dir_t *cr3, unsigned int virt, unsigned int phys);
+
+void convert_vpage(vpage_dir_t *kdir);
+
+void dump_page(vpage_dir_t *dir, unsigned int address);
+
+vpage_dir_t *copy_user_dir(vpage_dir_t *dir);
#endif
diff --git a/src/kernel/system.h b/src/kernel/system.h
index b310d5b..d41b7bc 100644
--- a/src/kernel/system.h
+++ b/src/kernel/system.h
@@ -1,7 +1,7 @@
#ifndef MELVIX_SYSTEM_H
#define MELVIX_SYSTEM_H
-#include "graphics/graphics.h"
+#include <stdint.h>
/**
* Initialize the basic features of the OS
@@ -35,19 +35,17 @@ struct far_ptr {
};
} __attribute__ ((packed));
-typedef struct far_ptr far_ptr_t;
-
/**
* Get offset from ASM segment:offset pointer
*/
-uint16_t get_offset(const volatile void *p) {
+static inline uint16_t get_offset(const volatile void *p) {
return (uint16_t) (uintptr_t) p & 0x000F;
}
/**
* Get segment from ASM segment:offset pointer
*/
-uint16_t get_segment(const volatile void *p) {
+static inline uint16_t get_segment(const volatile void *p) {
return (uint16_t) (((uintptr_t) p) >> 4);
}
@@ -56,8 +54,8 @@ uint16_t get_segment(const volatile void *p) {
* @param __ptr The ASM segment:offset pointer
* @return The new far pointer
*/
-far_ptr_t FAR_PTR(void *__ptr) {
- far_ptr_t __fptr;
+static inline struct far_ptr FAR_PTR(void *__ptr) {
+ struct far_ptr __fptr;
__fptr.offset = get_offset(__ptr);
__fptr.segment = get_segment(__ptr);
return __fptr;
@@ -68,7 +66,7 @@ far_ptr_t FAR_PTR(void *__ptr) {
* @param fptr The ASM far pointer
* @return The normalized pointer
*/
-void *get_ptr(far_ptr_t fptr) {
+static inline void *get_ptr(struct far_ptr fptr) {
return (void *) (unsigned long) ((fptr.segment << 4) + fptr.offset);
}
@@ -77,7 +75,7 @@ void *get_ptr(far_ptr_t fptr) {
* TODO: Add line number and file name
* @param msg The warning cause/reason
*/
-void warn(char *msg) {
+static inline void warn(char *msg) {
asm volatile ("cli");
terminal_set_color(6);
terminal_write_line("WARNING");
@@ -90,7 +88,7 @@ void warn(char *msg) {
* TODO: Add line number and file name
* @param msg The error cause/reason
*/
-void panic(char *msg) {
+static inline void panic(char *msg) {
asm volatile ("cli");
terminal_set_color(4);
terminal_write_line("PANIC");
@@ -105,7 +103,7 @@ void panic(char *msg) {
* TODO: Add line number and file name
* @param x The value
*/
-void assert(int x) {
+static inline void assert(int x) {
if (x == 0) {
panic("Assertion failed");
}