From 391ed256d21a6ae2e2456d1809f357e6e96e15d1 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Mon, 20 Jan 2020 23:12:54 +0100
Subject: Added pure awesomeness

Actually quite some days of work but ok
---
 src/kernel/memory/kheap.c         | 311 ++++++++++++++++++++++++++++++++++++++
 src/kernel/memory/kheap.h         |  52 +++++++
 src/kernel/memory/ordered_array.c |  68 +++++++++
 src/kernel/memory/ordered_array.h |  31 ++++
 src/kernel/memory/paging.c        | 203 +++++++++++++++++++++++++
 src/kernel/memory/paging.h        |  47 ++++++
 6 files changed, 712 insertions(+)
 create mode 100644 src/kernel/memory/kheap.c
 create mode 100644 src/kernel/memory/kheap.h
 create mode 100644 src/kernel/memory/ordered_array.c
 create mode 100644 src/kernel/memory/ordered_array.h
 create mode 100644 src/kernel/memory/paging.c
 create mode 100644 src/kernel/memory/paging.h

(limited to 'src/kernel/memory')

diff --git a/src/kernel/memory/kheap.c b/src/kernel/memory/kheap.c
new file mode 100644
index 0000000..def9ca2
--- /dev/null
+++ b/src/kernel/memory/kheap.c
@@ -0,0 +1,311 @@
+#include <stdint.h>
+#include <kernel/memory/kheap.h>
+#include <kernel/memory/paging.h>
+#include <kernel/system.h>
+
+uint32_t placement_address = (uint32_t) &ASM_KERNEL_END;
+extern page_directory_t *kernel_directory;
+heap_t *kheap = 0;
+
+uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys)
+{
+    if (kheap != 0) {
+        void *addr = alloc(sz, (uint8_t) align, kheap);
+        if (phys != 0) {
+            page_t *page = get_page((uint32_t) addr, 0, kernel_directory);
+            *phys = page->frame * 0x1000 + ((uint32_t) addr & 0xFFF);
+        }
+        return (uint32_t) addr;
+    } else {
+        if (align == 1 && (placement_address & 0xFFFFF000)) {
+            placement_address &= 0xFFFFF000;
+            placement_address += 0x1000;
+        }
+        if (phys) {
+            *phys = placement_address;
+        }
+        uint32_t tmp = placement_address;
+        placement_address += sz;
+        return tmp;
+    }
+}
+
+void kfree(void *p)
+{
+    free(p, kheap);
+}
+
+uint32_t kmalloc_a(uint32_t sz)
+{
+    return kmalloc_int(sz, 1, 0);
+}
+
+uint32_t kmalloc_p(uint32_t sz, uint32_t *phys)
+{
+    return kmalloc_int(sz, 0, phys);
+}
+
+uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys)
+{
+    return kmalloc_int(sz, 1, phys);
+}
+
+uint32_t kmalloc(uint32_t sz)
+{
+    return kmalloc_int(sz, 0, 0);
+}
+
+static void expand(uint32_t new_size, heap_t *heap)
+{
+    assert(new_size > heap->end_address - heap->start_address);
+
+    if ((new_size & 0xFFFFF000) != 0) {
+        new_size &= 0xFFFFF000;
+        new_size += 0x1000;
+    }
+
+    assert(heap->start_address + new_size <= heap->max_address);
+
+    uint32_t old_size = heap->end_address - heap->start_address;
+
+    uint32_t i = old_size;
+    while (i < new_size) {
+        alloc_frame(get_page(heap->start_address + i, 1, kernel_directory),
+                    (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
+        i += 0x1000;
+    }
+    heap->end_address = heap->start_address + new_size;
+}
+
+static uint32_t contract(uint32_t new_size, heap_t *heap)
+{
+    assert(new_size < heap->end_address - heap->start_address);
+
+    if (new_size & 0x1000) {
+        new_size &= 0x1000;
+        new_size += 0x1000;
+    }
+
+    if (new_size < HEAP_MIN_SIZE)
+        new_size = HEAP_MIN_SIZE;
+
+    uint32_t old_size = heap->end_address - heap->start_address;
+    uint32_t i = old_size - 0x1000;
+    while (new_size < i) {
+        free_frame(get_page(heap->start_address + i, 0, kernel_directory));
+        i -= 0x1000;
+    }
+
+    heap->end_address = heap->start_address + new_size;
+    return new_size;
+}
+
+static int32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap)
+{
+    uint32_t iterator = 0;
+    while (iterator < heap->index.size) {
+        header_t *header = (header_t *) lookup_ordered_array(iterator, &heap->index);
+        if (page_align > 0) {
+            uint32_t location = (uint32_t) header;
+            int32_t offset = 0;
+            if (((location + sizeof(header_t)) & 0xFFFFF000) != 0)
+                offset = 0x1000 - (location + sizeof(header_t)) % 0x1000;
+            int32_t hole_size = (int32_t) header->size - offset;
+            if (hole_size >= (int32_t) size)
+                break;
+        } else if (header->size >= size)
+            break;
+        iterator++;
+    }
+    if (iterator == heap->index.size)
+        return -1;
+    else
+        return iterator;
+}
+
+static int8_t header_t_less_than(void *a, void *b)
+{
+    return (int8_t) ((((header_t *) a)->size < ((header_t *) b)->size) ? 1 : 0);
+}
+
+heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly)
+{
+    heap_t *heap = (heap_t *) kmalloc(sizeof(heap_t));
+
+    assert(start % 0x1000 == 0);
+    assert(end_addr % 0x1000 == 0);
+
+    heap->index = place_ordered_array((void *) start, HEAP_INDEX_SIZE, &header_t_less_than);
+
+    start += sizeof(type_t) * HEAP_INDEX_SIZE;
+
+    if ((start & 0xFFFFF000) != 0) {
+        start &= 0xFFFFF000;
+        start += 0x1000;
+    }
+
+    heap->start_address = start;
+    heap->end_address = end_addr;
+    heap->max_address = max;
+    heap->supervisor = supervisor;
+    heap->readonly = readonly;
+
+    header_t *hole = (header_t *) start;
+    hole->size = end_addr - start;
+    hole->magic = HEAP_MAGIC;
+    hole->is_hole = 1;
+    insert_ordered_array((void *) hole, &heap->index);
+
+    return heap;
+}
+
+void *alloc(uint32_t size, uint8_t page_align, heap_t *heap)
+{
+    uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
+    int32_t iterator = find_smallest_hole(new_size, page_align, heap);
+
+    if (iterator == -1) {
+        uint32_t old_length = heap->end_address - heap->start_address;
+        uint32_t old_end_address = heap->end_address;
+
+        expand(old_length + new_size, heap);
+        uint32_t new_length = heap->end_address - heap->start_address;
+
+        iterator = 0;
+        uint32_t idx = (uint32_t) -1;
+        uint32_t value = 0x0;
+        while ((uint32_t) iterator < heap->index.size) {
+            uint32_t tmp = (uint32_t) lookup_ordered_array((uint32_t) iterator, &heap->index);
+            if (tmp > value) {
+                value = tmp;
+                idx = (uint32_t) iterator;
+            }
+            iterator++;
+        }
+
+        if ((int) idx == -1) {
+            header_t *header = (header_t *) old_end_address;
+            header->magic = HEAP_MAGIC;
+            header->size = new_length - old_length;
+            header->is_hole = 1;
+            footer_t *footer = (footer_t *) (old_end_address + header->size - sizeof(footer_t));
+            footer->magic = HEAP_MAGIC;
+            footer->header = header;
+            insert_ordered_array((void *) header, &heap->index);
+        } else {
+            header_t *header = lookup_ordered_array(idx, &heap->index);
+            header->size += new_length - old_length;
+            footer_t *footer = (footer_t *) ((uint32_t) header + header->size - sizeof(footer_t));
+            footer->header = header;
+            footer->magic = HEAP_MAGIC;
+        }
+        return alloc(size, page_align, heap);
+    }
+
+    header_t *orig_hole_header = (header_t *) lookup_ordered_array((uint32_t) iterator, &heap->index);
+    uint32_t orig_hole_pos = (uint32_t) orig_hole_header;
+    uint32_t orig_hole_size = orig_hole_header->size;
+    if (orig_hole_size - new_size < sizeof(header_t) + sizeof(footer_t)) {
+        size += orig_hole_size - new_size;
+        new_size = orig_hole_size;
+    }
+
+    if (page_align && orig_hole_pos & 0xFFFFF000) {
+        uint32_t new_location = orig_hole_pos + 0x1000 - (orig_hole_pos & 0xFFF) - sizeof(header_t);
+        header_t *hole_header = (header_t *) orig_hole_pos;
+        hole_header->size = 0x1000 - (orig_hole_pos & 0xFFF) - sizeof(header_t);
+        hole_header->magic = HEAP_MAGIC;
+        hole_header->is_hole = 1;
+        footer_t *hole_footer = (footer_t *) ((uint32_t) new_location - sizeof(footer_t));
+        hole_footer->magic = HEAP_MAGIC;
+        hole_footer->header = hole_header;
+        orig_hole_pos = new_location;
+        orig_hole_size = orig_hole_size - hole_header->size;
+    } else {
+        remove_ordered_array((uint32_t) iterator, &heap->index);
+    }
+
+    header_t *block_header = (header_t *) orig_hole_pos;
+    block_header->magic = HEAP_MAGIC;
+    block_header->is_hole = 0;
+    block_header->size = new_size;
+    footer_t *block_footer = (footer_t *) (orig_hole_pos + sizeof(header_t) + size);
+    block_footer->magic = HEAP_MAGIC;
+    block_footer->header = block_header;
+
+    if (orig_hole_size - new_size > 0) {
+        header_t *hole_header = (header_t *) (orig_hole_pos + sizeof(header_t) + size + sizeof(footer_t));
+        hole_header->magic = HEAP_MAGIC;
+        hole_header->is_hole = 1;
+        hole_header->size = orig_hole_size - new_size;
+        footer_t *hole_footer = (footer_t *) ((uint32_t) hole_header + orig_hole_size - new_size - sizeof(footer_t));
+        if ((uint32_t) hole_footer < heap->end_address) {
+            hole_footer->magic = HEAP_MAGIC;
+            hole_footer->header = hole_header;
+        }
+        insert_ordered_array((void *) hole_header, &heap->index);
+    }
+
+    return (void *) ((uint32_t) block_header + sizeof(header_t));
+}
+
+void free(void *p, heap_t *heap)
+{
+    if (p == 0)
+        return;
+
+    header_t *header = (header_t *) ((uint32_t) p - sizeof(header_t));
+    footer_t *footer = (footer_t *) ((uint32_t) header + header->size - sizeof(footer_t));
+
+    assert(header->magic == HEAP_MAGIC);
+    assert(footer->magic == HEAP_MAGIC);
+
+    header->is_hole = 1;
+
+    char do_add = 1;
+
+    footer_t *test_footer = (footer_t *) ((uint32_t) header - sizeof(footer_t));
+    if (test_footer->magic == HEAP_MAGIC &&
+        test_footer->header->is_hole == 1) {
+        uint32_t cache_size = header->size;
+        header = test_footer->header;
+        footer->header = header;
+        header->size += cache_size;
+        do_add = 0;
+    }
+
+    header_t *test_header = (header_t *) ((uint32_t) footer + sizeof(footer_t));
+    if (test_header->magic == HEAP_MAGIC &&
+        test_header->is_hole) {
+        header->size += test_header->size;
+        test_footer = (footer_t *) ((uint32_t) test_header + test_header->size - sizeof(footer_t));
+        footer = test_footer;
+        uint32_t iterator = 0;
+        while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void *) test_header))
+            iterator++;
+
+        assert(iterator < heap->index.size);
+        remove_ordered_array(iterator, &heap->index);
+    }
+
+    if ((uint32_t) footer + sizeof(footer_t) == heap->end_address) {
+        uint32_t old_length = heap->end_address - heap->start_address;
+        uint32_t new_length = contract((uint32_t) header - heap->start_address, heap);
+        if (header->size - (old_length - new_length) > 0) {
+            header->size -= old_length - new_length;
+            footer = (footer_t *) ((uint32_t) header + header->size - sizeof(footer_t));
+            footer->magic = HEAP_MAGIC;
+            footer->header = header;
+        } else {
+            uint32_t iterator = 0;
+            while ((iterator < heap->index.size) &&
+                   (lookup_ordered_array(iterator, &heap->index) != (void *) test_header))
+                iterator++;
+            if (iterator < heap->index.size)
+                remove_ordered_array(iterator, &heap->index);
+        }
+    }
+
+    if (do_add == 1)
+        insert_ordered_array((void *) header, &heap->index);
+}
\ No newline at end of file
diff --git a/src/kernel/memory/kheap.h b/src/kernel/memory/kheap.h
new file mode 100644
index 0000000..f31a2d3
--- /dev/null
+++ b/src/kernel/memory/kheap.h
@@ -0,0 +1,52 @@
+#ifndef MELVIX_KHEAP_H
+#define MELVIX_KHEAP_H
+
+#include <stdint.h>
+#include <kernel/memory/ordered_array.h>
+
+#define KHEAP_START         0xC0000000
+#define KHEAP_INITIAL_SIZE  0x100000
+
+#define HEAP_INDEX_SIZE   0x20000
+#define HEAP_MAGIC        0xabcdef42
+#define HEAP_MIN_SIZE     0x70000
+
+typedef struct {
+    uint32_t magic;
+    uint8_t is_hole;
+    uint32_t size;
+} header_t;
+
+typedef struct {
+    uint32_t magic;
+    header_t *header;
+} footer_t;
+
+typedef struct {
+    ordered_array_t index;
+    uint32_t start_address;
+    uint32_t end_address;
+    uint32_t max_address;
+    uint8_t supervisor;
+    uint8_t readonly;
+} heap_t;
+
+heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
+
+void *alloc(uint32_t size, uint8_t page_align, heap_t *heap);
+
+void free(void *p, heap_t *heap);
+
+uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys);
+
+uint32_t kmalloc_a(uint32_t sz);
+
+uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
+
+uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
+
+uint32_t kmalloc(uint32_t sz);
+
+void kfree(void *p);
+
+#endif
\ No newline at end of file
diff --git a/src/kernel/memory/ordered_array.c b/src/kernel/memory/ordered_array.c
new file mode 100644
index 0000000..5d94491
--- /dev/null
+++ b/src/kernel/memory/ordered_array.c
@@ -0,0 +1,68 @@
+#include <kernel/memory/ordered_array.h>
+#include <stdint.h>
+#include <kernel/lib/lib.h>
+#include <kernel/system.h>
+#include "kheap.h"
+
+int8_t standard_lessthan_predicate(type_t a, type_t b)
+{
+    return (int8_t) ((a < b) ? 1 : 0);
+}
+
+ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than)
+{
+    ordered_array_t to_ret;
+    to_ret.array = (void *) kmalloc(max_size * sizeof(type_t));
+    memset(to_ret.array, 0, max_size * sizeof(type_t));
+    to_ret.size = 0;
+    to_ret.max_size = max_size;
+    to_ret.less_than = less_than;
+    return to_ret;
+}
+
+ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than)
+{
+    ordered_array_t to_ret;
+    to_ret.array = (type_t *) addr;
+    memset(to_ret.array, 0, max_size * sizeof(type_t));
+    to_ret.size = 0;
+    to_ret.max_size = max_size;
+    to_ret.less_than = less_than;
+    return to_ret;
+}
+
+void insert_ordered_array(type_t item, ordered_array_t *array)
+{
+    assert((int) array->less_than);
+    uint32_t iterator = 0;
+    while (iterator < array->size && array->less_than(array->array[iterator], item))
+        iterator++;
+    if (iterator == array->size)
+        array->array[array->size++] = item;
+    else {
+        type_t tmp = array->array[iterator];
+        array->array[iterator] = item;
+        while (iterator < array->size) {
+            iterator++;
+            type_t tmp2 = array->array[iterator];
+            array->array[iterator] = tmp;
+            tmp = tmp2;
+        }
+        array->size++;
+    }
+}
+
+type_t lookup_ordered_array(uint32_t i, ordered_array_t *array)
+{
+    assert(i < array->size);
+    return array->array[i];
+}
+
+void remove_ordered_array(uint32_t i, ordered_array_t *array)
+{
+    while (i < array->size) {
+        array->array[i] = array->array[i + 1];
+        i++;
+    }
+    array->size--;
+}
\ No newline at end of file
diff --git a/src/kernel/memory/ordered_array.h b/src/kernel/memory/ordered_array.h
new file mode 100644
index 0000000..cf753e3
--- /dev/null
+++ b/src/kernel/memory/ordered_array.h
@@ -0,0 +1,31 @@
+#ifndef MELVIX_ORDERED_ARRAY_H
+#define MELVIX_ORDERED_ARRAY_H
+
+#include <stdint.h>
+
+typedef void *type_t;
+
+typedef int8_t (*lessthan_predicate_t)(type_t, type_t);
+
+typedef struct {
+    type_t *array;
+    uint32_t size;
+    uint32_t max_size;
+    lessthan_predicate_t less_than;
+} ordered_array_t;
+
+int8_t standard_lessthan_predicate(type_t a, type_t b);
+
+ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than);
+
+ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than);
+
+void destroy_ordered_array(ordered_array_t *array);
+
+void insert_ordered_array(type_t item, ordered_array_t *array);
+
+type_t lookup_ordered_array(uint32_t i, ordered_array_t *array);
+
+void remove_ordered_array(uint32_t i, ordered_array_t *array);
+
+#endif
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
new file mode 100644
index 0000000..e050861
--- /dev/null
+++ b/src/kernel/memory/paging.c
@@ -0,0 +1,203 @@
+#include <kernel/memory/paging.h>
+#include <kernel/memory/kheap.h>
+#include <kernel/lib/lib.h>
+#include <kernel/system.h>
+
+int paging_enabled = 0;
+
+page_directory_t *kernel_directory = 0;
+page_directory_t *current_directory = 0;
+
+uint32_t *frames;
+uint32_t nframes;
+
+extern uint32_t placement_address;
+extern heap_t *kheap;
+
+extern void copy_page_physical();
+
+#define INDEX_FROM_BIT(a) (a/(8*4))
+#define OFFSET_FROM_BIT(a) (a%(8*4))
+
+static void set_frame(uint32_t frame_addr)
+{
+    uint32_t frame = frame_addr / 0x1000;
+    uint32_t idx = INDEX_FROM_BIT(frame);
+    uint32_t off = OFFSET_FROM_BIT(frame);
+    frames[idx] |= (0x1 << off);
+}
+
+static void clear_frame(uint32_t frame_addr)
+{
+    uint32_t frame = frame_addr / 0x1000;
+    uint32_t idx = INDEX_FROM_BIT(frame);
+    uint32_t off = OFFSET_FROM_BIT(frame);
+    frames[idx] &= ~(0x1 << off);
+}
+
+static uint32_t first_frame()
+{
+    uint32_t i, j;
+    for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
+        if (frames[i] != 0xFFFFFFFF) {
+            for (j = 0; j < 32; j++) {
+                uint32_t toTest = (0x1 << j);
+                if (!(frames[i] & toTest)) {
+                    return i * 4 * 8 + j;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+void alloc_frame(page_t *page, int is_kernel, int is_writeable)
+{
+    if (page->frame != 0) {
+        return;
+    } else {
+        uint32_t idx = first_frame();
+        if (idx == (uint32_t) -1)
+            panic("No free frames!");
+        set_frame(idx * 0x1000);
+        page->present = 1;
+        page->rw = (is_writeable == 1) ? 1 : 0;
+        page->user = (is_kernel == 1) ? 0 : 1;
+        page->frame = idx;
+    }
+}
+
+void free_frame(page_t *page)
+{
+    uint32_t frame;
+    if (!(frame = page->frame)) {
+        return;
+    } else {
+        clear_frame(frame);
+        page->frame = 0x0;
+    }
+}
+
+void paging_install()
+{
+    uint32_t mem_end_page = memory_get_all() << 10;
+
+    nframes = mem_end_page / 0x1000;
+    frames = (uint32_t *) kmalloc(INDEX_FROM_BIT(nframes));
+    memset(frames, 0, INDEX_FROM_BIT(nframes));
+
+    kernel_directory = (page_directory_t *) kmalloc_a(sizeof(page_directory_t));
+    memset(kernel_directory, 0, sizeof(page_directory_t));
+    kernel_directory->physicalAddr = (uint32_t) kernel_directory->tablesPhysical;
+
+    for (uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
+        get_page((uint32_t) i, 1, kernel_directory);
+
+    int i = 0;
+    while (i < 0x400000) {
+        alloc_frame(get_page((uint32_t) i, 1, kernel_directory), 0, 0);
+        i += 0x1000;
+    }
+
+    for (i = KHEAP_START; i < (int) (KHEAP_START + KHEAP_INITIAL_SIZE); i += 0x1000)
+        alloc_frame(get_page((uint32_t) i, 1, kernel_directory), 0, 0);
+
+    switch_page_directory(kernel_directory);
+
+    kheap = create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
+
+    current_directory = clone_directory(kernel_directory);
+    switch_page_directory(current_directory);
+    vga_log("Installed Paging");
+}
+
+void switch_page_directory(page_directory_t *dir)
+{
+    current_directory = dir;
+    asm volatile("mov %0, %%cr3"::"r"(dir->physicalAddr));
+    uint32_t cr0;
+    asm volatile("mov %%cr0, %0": "=r"(cr0));
+    cr0 |= 0x80000000; // Enable paging!
+    asm volatile("mov %0, %%cr0"::"r"(cr0));
+}
+
+void paging_enable()
+{
+    switch_page_directory(kernel_directory);
+    paging_enabled = 1;
+}
+
+void paging_disable()
+{
+    uint32_t cr0;
+    asm ("mov %%cr0, %0": "=r"(cr0));
+    cr0 &= 0x7fffffff;
+    asm ("mov %0, %%cr0"::"r"(cr0));
+    paging_enabled = 0;
+}
+
+page_t *get_page(uint32_t address, int make, page_directory_t *dir)
+{
+    address /= 0x1000;
+    uint32_t table_idx = address / 1024;
+
+    if (dir->tables[table_idx]) {
+        return &dir->tables[table_idx]->pages[address % 1024];
+    } else if (make) {
+        uint32_t tmp;
+        dir->tables[table_idx] = (page_table_t *) kmalloc_ap(sizeof(page_table_t), &tmp);
+        memset(dir->tables[table_idx], 0, 0x1000);
+        dir->tablesPhysical[table_idx] = tmp | 0x7; // PRESENT, RW, US
+        return &dir->tables[table_idx]->pages[address % 1024];
+    } else {
+        return 0;
+    }
+}
+
+static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr)
+{
+    page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr);
+    memset(table, 0, sizeof(page_directory_t));
+
+    for (int i = 0; i < 1024; i++) {
+        if (!src->pages[i].frame)
+            continue;
+
+        alloc_frame(&table->pages[i], 0, 0);
+
+        if (src->pages[i].present) table->pages[i].present = 1;
+        if (src->pages[i].rw) table->pages[i].rw = 1;
+        if (src->pages[i].user) table->pages[i].user = 1;
+        if (src->pages[i].accessed)table->pages[i].accessed = 1;
+        if (src->pages[i].dirty) table->pages[i].dirty = 1;
+
+        copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000);
+    }
+    return table;
+}
+
+page_directory_t *clone_directory(page_directory_t *src)
+{
+    uint32_t phys;
+    page_directory_t *dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
+    memset(dir, 0, sizeof(page_directory_t));
+
+    uint32_t offset = (uint32_t) dir->tablesPhysical - (uint32_t) dir;
+
+    dir->physicalAddr = phys + offset;
+
+    for (int i = 0; i < 1024; i++) {
+        if (!src->tables[i])
+            continue;
+
+        if (kernel_directory->tables[i] == src->tables[i]) {
+            dir->tables[i] = src->tables[i];
+            dir->tablesPhysical[i] = src->tablesPhysical[i];
+        } else {
+            uint32_t phys;
+            dir->tables[i] = clone_table(src->tables[i], &phys);
+            dir->tablesPhysical[i] = phys | 0x07;
+        }
+    }
+    return dir;
+}
\ No newline at end of file
diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h
new file mode 100644
index 0000000..285cb6f
--- /dev/null
+++ b/src/kernel/memory/paging.h
@@ -0,0 +1,47 @@
+#ifndef MELVIX_PAGING_H
+#define MELVIX_PAGING_H
+
+#include <stdint.h>
+#include <kernel/interrupts/interrupts.h>
+
+typedef struct page {
+    uint32_t present: 1;
+    uint32_t rw: 1;
+    uint32_t user: 1;
+    uint32_t accessed: 1;
+    uint32_t dirty: 1;
+    uint32_t unused: 7;
+    uint32_t frame: 20;
+} page_t;
+
+typedef struct page_table {
+    page_t pages[1024];
+} page_table_t;
+
+typedef struct page_directory {
+    page_table_t *tables[1024];
+    uint32_t tablesPhysical[1024];
+    uint32_t physicalAddr;
+} page_directory_t;
+
+int paging_enabled;
+
+void alloc_frame(page_t *page, int is_kernel, int is_writeable);
+
+void free_frame(page_t *page);
+
+void paging_install();
+
+void switch_page_directory(page_directory_t *new);
+
+void paging_enable();
+
+void paging_disable();
+
+page_t *get_page(uint32_t address, int make, page_directory_t *dir);
+
+void page_fault(struct regs *regs);
+
+page_directory_t *clone_directory(page_directory_t *src);
+
+#endif
-- 
cgit v1.2.3


From 3fa449276364389137a7154a9971594816d86362 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Tue, 21 Jan 2020 22:10:16 +0100
Subject: Naming scheme and page fault improvements

---
 src/kernel/graphics/vesa.c  |  6 +++---
 src/kernel/interrupts/isr.c |  8 +++++++-
 src/kernel/memory/kheap.c   |  8 ++++----
 src/kernel/memory/paging.c  | 43 ++++++++++++++++++++++---------------------
 src/kernel/memory/paging.h  | 12 +++++-------
 5 files changed, 41 insertions(+), 36 deletions(-)

(limited to 'src/kernel/memory')

diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index d941413..15d953a 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -7,7 +7,7 @@
 #include <kernel/memory/kheap.h>
 #include <kernel/memory/paging.h>
 
-extern page_directory_t *kernel_directory;
+extern page_directory_t *current_directory;
 
 void switch_to_vga()
 {
@@ -184,9 +184,9 @@ void set_optimal_resolution()
     uint32_t fb_size = vbe_width * vbe_height * vbe_bpl;
     cursor_buffer = (unsigned char *) kmalloc(fb_size);
     for (uint32_t z = 0; z < fb_size; z += 0x1000) {
-        alloc_frame(get_page((uint32_t) fb + z, 1, kernel_directory), 0, 1);
-        alloc_frame(get_page((uint32_t) cursor_buffer + z, 1, kernel_directory), 0, 1);
+        paging_alloc_frame(paging_get_page((uint32_t) fb + z, 1, current_directory), 0, 1);
     }
+    serial_printf("0x%x", fb);
 
     if (vbe_height > 1440) vesa_set_font(32);
     else if (vbe_height > 720) vesa_set_font(24);
diff --git a/src/kernel/interrupts/isr.c b/src/kernel/interrupts/isr.c
index eb932b2..d89f581 100644
--- a/src/kernel/interrupts/isr.c
+++ b/src/kernel/interrupts/isr.c
@@ -3,6 +3,7 @@
 #include <kernel/system.h>
 #include <kernel/lib/string.h>
 #include <kernel/lib/stdio.h>
+#include <kernel/graphics/vesa.h>
 
 // Install ISRs in IDT
 void isrs_install()
@@ -119,6 +120,11 @@ void fault_handler(struct regs *r)
         // halt_loop(); // Idk loop?
         char *message = (char *) exception_messages[r->int_no];
         strcat(message, " Exception");
-        panic(message);
+
+        // Show message if there wasn't an error in video memory
+        if (faulting_address != (uint32_t) fb)
+            panic(message);
+        else
+            halt_loop();
     }
 }
\ No newline at end of file
diff --git a/src/kernel/memory/kheap.c b/src/kernel/memory/kheap.c
index def9ca2..40551bc 100644
--- a/src/kernel/memory/kheap.c
+++ b/src/kernel/memory/kheap.c
@@ -12,7 +12,7 @@ uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys)
     if (kheap != 0) {
         void *addr = alloc(sz, (uint8_t) align, kheap);
         if (phys != 0) {
-            page_t *page = get_page((uint32_t) addr, 0, kernel_directory);
+            page_t *page = paging_get_page((uint32_t) addr, 0, kernel_directory);
             *phys = page->frame * 0x1000 + ((uint32_t) addr & 0xFFF);
         }
         return (uint32_t) addr;
@@ -70,8 +70,8 @@ static void expand(uint32_t new_size, heap_t *heap)
 
     uint32_t i = old_size;
     while (i < new_size) {
-        alloc_frame(get_page(heap->start_address + i, 1, kernel_directory),
-                    (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
+        paging_alloc_frame(paging_get_page(heap->start_address + i, 1, kernel_directory),
+                           (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
         i += 0x1000;
     }
     heap->end_address = heap->start_address + new_size;
@@ -92,7 +92,7 @@ static uint32_t contract(uint32_t new_size, heap_t *heap)
     uint32_t old_size = heap->end_address - heap->start_address;
     uint32_t i = old_size - 0x1000;
     while (new_size < i) {
-        free_frame(get_page(heap->start_address + i, 0, kernel_directory));
+        paging_free_frame(paging_get_page(heap->start_address + i, 0, kernel_directory));
         i -= 0x1000;
     }
 
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
index e050861..ad19091 100644
--- a/src/kernel/memory/paging.c
+++ b/src/kernel/memory/paging.c
@@ -2,6 +2,7 @@
 #include <kernel/memory/kheap.h>
 #include <kernel/lib/lib.h>
 #include <kernel/system.h>
+#include <kernel/lib/stdio.h>
 
 int paging_enabled = 0;
 
@@ -19,7 +20,7 @@ extern void copy_page_physical();
 #define INDEX_FROM_BIT(a) (a/(8*4))
 #define OFFSET_FROM_BIT(a) (a%(8*4))
 
-static void set_frame(uint32_t frame_addr)
+static void paging_set_frame(uint32_t frame_addr)
 {
     uint32_t frame = frame_addr / 0x1000;
     uint32_t idx = INDEX_FROM_BIT(frame);
@@ -27,7 +28,7 @@ static void set_frame(uint32_t frame_addr)
     frames[idx] |= (0x1 << off);
 }
 
-static void clear_frame(uint32_t frame_addr)
+static void paging_clear_frame(uint32_t frame_addr)
 {
     uint32_t frame = frame_addr / 0x1000;
     uint32_t idx = INDEX_FROM_BIT(frame);
@@ -35,7 +36,7 @@ static void clear_frame(uint32_t frame_addr)
     frames[idx] &= ~(0x1 << off);
 }
 
-static uint32_t first_frame()
+static uint32_t paging_first_frame()
 {
     uint32_t i, j;
     for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
@@ -51,15 +52,15 @@ static uint32_t first_frame()
     return 0;
 }
 
-void alloc_frame(page_t *page, int is_kernel, int is_writeable)
+void paging_alloc_frame(page_t *page, int is_kernel, int is_writeable)
 {
     if (page->frame != 0) {
         return;
     } else {
-        uint32_t idx = first_frame();
+        uint32_t idx = paging_first_frame();
         if (idx == (uint32_t) -1)
             panic("No free frames!");
-        set_frame(idx * 0x1000);
+        paging_set_frame(idx * 0x1000);
         page->present = 1;
         page->rw = (is_writeable == 1) ? 1 : 0;
         page->user = (is_kernel == 1) ? 0 : 1;
@@ -67,13 +68,13 @@ void alloc_frame(page_t *page, int is_kernel, int is_writeable)
     }
 }
 
-void free_frame(page_t *page)
+void paging_free_frame(page_t *page)
 {
     uint32_t frame;
     if (!(frame = page->frame)) {
         return;
     } else {
-        clear_frame(frame);
+        paging_clear_frame(frame);
         page->frame = 0x0;
     }
 }
@@ -91,27 +92,27 @@ void paging_install()
     kernel_directory->physicalAddr = (uint32_t) kernel_directory->tablesPhysical;
 
     for (uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
-        get_page((uint32_t) i, 1, kernel_directory);
+        paging_get_page((uint32_t) i, 1, kernel_directory);
 
     int i = 0;
     while (i < 0x400000) {
-        alloc_frame(get_page((uint32_t) i, 1, kernel_directory), 0, 0);
+        paging_alloc_frame(paging_get_page((uint32_t) i, 1, kernel_directory), 0, 0);
         i += 0x1000;
     }
 
     for (i = KHEAP_START; i < (int) (KHEAP_START + KHEAP_INITIAL_SIZE); i += 0x1000)
-        alloc_frame(get_page((uint32_t) i, 1, kernel_directory), 0, 0);
+        paging_alloc_frame(paging_get_page((uint32_t) i, 1, kernel_directory), 0, 0);
 
-    switch_page_directory(kernel_directory);
+    paging_switch_directory(kernel_directory);
 
     kheap = create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
 
-    current_directory = clone_directory(kernel_directory);
-    switch_page_directory(current_directory);
+    current_directory = paging_clone_directory(kernel_directory);
+    paging_switch_directory(current_directory);
     vga_log("Installed Paging");
 }
 
-void switch_page_directory(page_directory_t *dir)
+void paging_switch_directory(page_directory_t *dir)
 {
     current_directory = dir;
     asm volatile("mov %0, %%cr3"::"r"(dir->physicalAddr));
@@ -123,7 +124,7 @@ void switch_page_directory(page_directory_t *dir)
 
 void paging_enable()
 {
-    switch_page_directory(kernel_directory);
+    paging_switch_directory(kernel_directory);
     paging_enabled = 1;
 }
 
@@ -136,7 +137,7 @@ void paging_disable()
     paging_enabled = 0;
 }
 
-page_t *get_page(uint32_t address, int make, page_directory_t *dir)
+page_t *paging_get_page(uint32_t address, int make, page_directory_t *dir)
 {
     address /= 0x1000;
     uint32_t table_idx = address / 1024;
@@ -154,7 +155,7 @@ page_t *get_page(uint32_t address, int make, page_directory_t *dir)
     }
 }
 
-static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr)
+static page_table_t *paging_clone_table(page_table_t *src, uint32_t *physAddr)
 {
     page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr);
     memset(table, 0, sizeof(page_directory_t));
@@ -163,7 +164,7 @@ static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr)
         if (!src->pages[i].frame)
             continue;
 
-        alloc_frame(&table->pages[i], 0, 0);
+        paging_alloc_frame(&table->pages[i], 0, 0);
 
         if (src->pages[i].present) table->pages[i].present = 1;
         if (src->pages[i].rw) table->pages[i].rw = 1;
@@ -176,7 +177,7 @@ static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr)
     return table;
 }
 
-page_directory_t *clone_directory(page_directory_t *src)
+page_directory_t *paging_clone_directory(page_directory_t *src)
 {
     uint32_t phys;
     page_directory_t *dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
@@ -195,7 +196,7 @@ page_directory_t *clone_directory(page_directory_t *src)
             dir->tablesPhysical[i] = src->tablesPhysical[i];
         } else {
             uint32_t phys;
-            dir->tables[i] = clone_table(src->tables[i], &phys);
+            dir->tables[i] = paging_clone_table(src->tables[i], &phys);
             dir->tablesPhysical[i] = phys | 0x07;
         }
     }
diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h
index 285cb6f..bb6ee4f 100644
--- a/src/kernel/memory/paging.h
+++ b/src/kernel/memory/paging.h
@@ -26,22 +26,20 @@ typedef struct page_directory {
 
 int paging_enabled;
 
-void alloc_frame(page_t *page, int is_kernel, int is_writeable);
+void paging_alloc_frame(page_t *page, int is_kernel, int is_writeable);
 
-void free_frame(page_t *page);
+void paging_free_frame(page_t *page);
 
 void paging_install();
 
-void switch_page_directory(page_directory_t *new);
+void paging_switch_directory(page_directory_t *dir);
 
 void paging_enable();
 
 void paging_disable();
 
-page_t *get_page(uint32_t address, int make, page_directory_t *dir);
+page_t *paging_get_page(uint32_t address, int make, page_directory_t *dir);
 
-void page_fault(struct regs *regs);
-
-page_directory_t *clone_directory(page_directory_t *src);
+page_directory_t *paging_clone_directory(page_directory_t *src);
 
 #endif
-- 
cgit v1.2.3


From b8630d78a15a69f50dac747e41e84b143dd99b08 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sat, 25 Jan 2020 23:39:17 +0100
Subject: Hehe fixed video bug :)

Took around 5 days.
---
 src/kernel/graphics/vesa.c | 11 +++++++++--
 src/kernel/memory/paging.c |  6 +++---
 src/kernel/memory/paging.h |  2 ++
 3 files changed, 14 insertions(+), 5 deletions(-)

(limited to 'src/kernel/memory')

diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c
index 15d953a..e2b0036 100644
--- a/src/kernel/graphics/vesa.c
+++ b/src/kernel/graphics/vesa.c
@@ -183,8 +183,15 @@ void set_optimal_resolution()
 
     uint32_t fb_size = vbe_width * vbe_height * vbe_bpl;
     cursor_buffer = (unsigned char *) kmalloc(fb_size);
-    for (uint32_t z = 0; z < fb_size; z += 0x1000) {
-        paging_alloc_frame(paging_get_page((uint32_t) fb + z, 1, current_directory), 0, 1);
+    uint32_t j = (uint32_t) fb;
+    while ((unsigned char *) j < fb + (vbe_width * vbe_height * 4)) {
+        paging_set_frame(j);
+        page_t *page = paging_get_page(j, 1, current_directory);
+        page->present = 1;
+        page->rw = 1;
+        page->user = 1;
+        page->frame = j / 0x1000;
+        j += 0x1000;
     }
     serial_printf("0x%x", fb);
 
diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c
index ad19091..861cdcb 100644
--- a/src/kernel/memory/paging.c
+++ b/src/kernel/memory/paging.c
@@ -20,7 +20,7 @@ extern void copy_page_physical();
 #define INDEX_FROM_BIT(a) (a/(8*4))
 #define OFFSET_FROM_BIT(a) (a%(8*4))
 
-static void paging_set_frame(uint32_t frame_addr)
+void paging_set_frame(uint32_t frame_addr)
 {
     uint32_t frame = frame_addr / 0x1000;
     uint32_t idx = INDEX_FROM_BIT(frame);
@@ -28,7 +28,7 @@ static void paging_set_frame(uint32_t frame_addr)
     frames[idx] |= (0x1 << off);
 }
 
-static void paging_clear_frame(uint32_t frame_addr)
+void paging_clear_frame(uint32_t frame_addr)
 {
     uint32_t frame = frame_addr / 0x1000;
     uint32_t idx = INDEX_FROM_BIT(frame);
@@ -36,7 +36,7 @@ static void paging_clear_frame(uint32_t frame_addr)
     frames[idx] &= ~(0x1 << off);
 }
 
-static uint32_t paging_first_frame()
+uint32_t paging_first_frame()
 {
     uint32_t i, j;
     for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h
index bb6ee4f..77258b7 100644
--- a/src/kernel/memory/paging.h
+++ b/src/kernel/memory/paging.h
@@ -26,6 +26,8 @@ typedef struct page_directory {
 
 int paging_enabled;
 
+void paging_set_frame(uint32_t frame_addr);
+
 void paging_alloc_frame(page_t *page, int is_kernel, int is_writeable);
 
 void paging_free_frame(page_t *page);
-- 
cgit v1.2.3