aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/paging
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/paging')
-rw-r--r--src/kernel/paging/kheap.c295
-rw-r--r--src/kernel/paging/kheap.h108
-rw-r--r--src/kernel/paging/ordered_array.c66
-rw-r--r--src/kernel/paging/ordered_array.h66
-rw-r--r--src/kernel/paging/paging.c274
-rw-r--r--src/kernel/paging/paging.h120
6 files changed, 170 insertions, 759 deletions
diff --git a/src/kernel/paging/kheap.c b/src/kernel/paging/kheap.c
deleted file mode 100644
index 9feae77..0000000
--- a/src/kernel/paging/kheap.c
+++ /dev/null
@@ -1,295 +0,0 @@
-#include <stdint.h>
-#include "kheap.h"
-#include "paging.h"
-#include "ordered_array.h"
-#include "../system.h"
-
-extern uint32_t end;
-extern page_directory_t *kernel_directory;
-uint32_t placement_address = (uint32_t) &end;
-heap_t *kheap = 0;
-
-uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys) {
- if (kheap != 0) {
- void *addr = alloc(sz, (unsigned char) 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 int find_smallest_hole(uint32_t size, unsigned char 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;
- int offset = 0;
- if (((location + sizeof(header_t)) & 0xFFFFF000) != 0)
- offset = 0x1000 - (location + sizeof(header_t)) % 0x1000;
- int hole_size = (int) header->size - offset;
-
- if (hole_size >= (int) size)
- break;
- } else if (header->size >= size)
- break;
- iterator++;
- }
-
- if (iterator == heap->index.size)
- return -1;
- else
- return iterator;
-}
-
-static char header_t_less_than(void *a, void *b) {
- return (((header_t *) a)->size < ((header_t *) b)->size) ? 1 : 0;
-}
-
-heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, unsigned char supervisor, unsigned char 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, unsigned char page_align, heap_t *heap) {
- uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
-
- int 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 = -1;
- uint32_t value = 0x0;
- while (iterator < (int) heap->index.size) {
- uint32_t tmp = (uint32_t) lookup_ordered_array(iterator, &heap->index);
- if (tmp > value) {
- value = tmp;
- idx = 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(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(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);
-}
diff --git a/src/kernel/paging/kheap.h b/src/kernel/paging/kheap.h
deleted file mode 100644
index a2254be..0000000
--- a/src/kernel/paging/kheap.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef MELVIX_KHEAP_H
-#define MELVIX_KHEAP_H
-
-#include "ordered_array.h"
-
-#define KHEAP_START 0xC0000000
-#define KHEAP_INITIAL_SIZE 0x100000
-
-#define HEAP_INDEX_SIZE 0x20000
-#define HEAP_MAGIC 0x03A93A90
-#define HEAP_MIN_SIZE 0x70000
-
-/**
- * Size information of holes/blocks
- */
-typedef struct {
- uint32_t magic;
- unsigned char is_hole; // 1 if 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;
- unsigned char supervisor;
- unsigned char readonly;
-} heap_t;
-
-/**
- * Create a new heap
- * @param start
- * @param end
- * @param max
- * @param supervisor
- * @param readonly
- * @return The heap pointer
- */
-heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, unsigned char supervisor, unsigned char readonly);
-
-/**
- * Allocate a region of memory
- * @param size The size of the memory
- * @param page_align Start the block on a page boundary
- * @param heap The Heap pointer
- * @return
- */
-void *alloc(uint32_t size, unsigned char page_align, heap_t *heap);
-
-/**
- * Release an allocated block
- * @param p The block
- * @param heap The heap
- */
-void free(void *p, heap_t *heap);
-
-/**
- * Release an allocated block using kheap
- * @param p The block
- */
-void kfree(void *p);
-
-/**
- * Allocate a chunk of memory
- * @param sz The size of the memory
- * @param align Start the block on a page boundary
- * @param phys Location of the memory if not 0
- * @return The memory address
- */
-uint32_t kmalloc_int(uint32_t sz, int align, uint32_t *phys);
-
-/**
- * Allocate a page-aligned chunk of memory
- * @param sz The size of the memory
- * @return The memory address
- */
-uint32_t kmalloc_a(uint32_t sz);
-
-/**
- * Allocate a chunk of memory in a physical address
- * @param sz The size of the memory
- * @param phys The physical address
- * @return The memory address
- */
-uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
-
-/**
- * Allocate a page-aligned chunk of memory in a physical address
- * @param sz The size of the memory
- * @param phys The physical address
- * @return The memory address
- */
-uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
-
-/**
- * Allocate a chunk of memory (non page-aligned and no physical address)
- * @param sz The size of the memory
- * @return The memory address
- */
-uint32_t kmalloc(uint32_t sz);
-
-#endif
diff --git a/src/kernel/paging/ordered_array.c b/src/kernel/paging/ordered_array.c
deleted file mode 100644
index 688ff8f..0000000
--- a/src/kernel/paging/ordered_array.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <stdint.h>
-#include "ordered_array.h"
-#include "kheap.h"
-#include "../lib/lib.h"
-#include "../system.h"
-
-char standard_lessthan_predicate(type_t a, type_t b) {
- return (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));
- memory_set(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;
- memory_set(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 destroy_ordered_array(ordered_array_t *array) {
- kfree(array->array);
-}
-
-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--;
-}
diff --git a/src/kernel/paging/ordered_array.h b/src/kernel/paging/ordered_array.h
deleted file mode 100644
index 223ea14..0000000
--- a/src/kernel/paging/ordered_array.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef MELVIX_ORDERED_ARRAY_H
-#define MELVIX_ORDERED_ARRAY_H
-
-#include <stdint.h>
-
-/**
- * The array can store anything - so a void pointer is used
- */
-typedef void *type_t;
-
-typedef char (*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;
-
-/**
- * A standard less-than predicate
- * @param a The first parameter
- * @param b The second parameter
- * @return Non-zero if the first parameter is bigger than the second
- */
-char standard_lessthan_predicate(type_t a, type_t b);
-
-/**
- * Create an ordered array
- * @param max_size Maximal size
- * @param less_than The less-than predicate
- * @return The newly created array
- */
-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);
-
-/**
- * Destroy an ordered array
- * @param array The ordered array
- */
-void destroy_ordered_array(ordered_array_t *array);
-
-/**
- * Add an item into the array
- * @param item The item
- * @param array The array
- */
-void insert_ordered_array(type_t item, ordered_array_t *array);
-
-/**
- * Lookup the item at a specific index
- * @param i The index
- * @param array The array
- * @return
- */
-type_t lookup_ordered_array(uint32_t i, ordered_array_t *array);
-
-/**
- * Delete an item at an index from an array
- * @param i The index
- * @param array The array
- */
-void remove_ordered_array(uint32_t i, ordered_array_t *array);
-
-#endif
diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c
index 0b7428e..f1dc340 100644
--- a/src/kernel/paging/paging.c
+++ b/src/kernel/paging/paging.c
@@ -1,187 +1,149 @@
+#include <stdint.h>
#include "paging.h"
-#include "kheap.h"
#include "../system.h"
-#include "../lib/lib.h"
-#include "../io/io.h"
-
-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;
-
-#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 test_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);
- return (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;
- }
- }
+
+extern void *end;
+
+uint32_t page_directory[1024] __attribute__((aligned(4096)));
+uint32_t page_tables[1024][1024] __attribute__((aligned(4096)));
+
+void paging_install() {
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ page_tables[i][j] = ((j * 0x1000) + (i * 0x400000)) | PT_RW;
}
}
- return -1;
-}
-
-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;
+ for (uint32_t i = 0; i < 1024; i++) {
+ page_directory[i] = ((uint32_t) page_tables[i]) | PD_RW | PD_PRESENT;
}
-}
-
-void initialise_paging() {
- uint32_t mem_end_page = 0x1000000;
- nframes = mem_end_page / 0x1000;
- frames = (uint32_t *) kmalloc(INDEX_FROM_BIT(nframes));
- memory_set(frames, 0, INDEX_FROM_BIT(nframes));
- kernel_directory = (page_directory_t *) kmalloc_a(sizeof(page_directory_t));
- memory_set(kernel_directory, 0, sizeof(page_directory_t));
- kernel_directory->physicalAddr = (uint32_t) kernel_directory->tablesPhysical;
+ // TODO: Calculate max memory
+ paging_set_present(0, 0x1000000);
- unsigned int i = 0;
- for (i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
- get_page(i, 1, kernel_directory);
+ paging_set_used(0, ((uint32_t) end >> 12) + 1);
- i = 0;
- while (i < 0x400000) {
- alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
- i += 0x1000;
- }
-
- for (i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
- alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
+ paging_enable();
+}
- 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);
- serial_write("Paging init successful!\n");
+int paging_enabled() {
+ uint32_t cr0;
+ asm volatile("mov %%cr0, %0": "=r"(cr0));
+ return (cr0 | 0x80000000) == cr0;
}
-void disable_paging() {
+void paging_disable() {
uint32_t cr0;
asm volatile("mov %%cr0, %0": "=r"(cr0));
cr0 &= 0x7fffffff;
asm volatile("mov %0, %%cr0"::"r"(cr0));
}
-void enable_paging() {
- switch_page_directory(kernel_directory);
- switch_page_directory(current_directory);
-}
-
-void switch_page_directory(page_directory_t *dir) {
- current_directory = dir;
- asm volatile("mov %0, %%cr3"::"r"(dir->physicalAddr));
+void paging_enable() {
+ asm volatile("mov %0, %%cr3"::"r"(page_directory));
uint32_t cr0;
asm volatile("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000;
asm volatile("mov %0, %%cr0"::"r"(cr0));
}
-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);
- memory_set(dir->tables[table_idx], 0, 0x1000);
- dir->tablesPhysical[table_idx] = tmp | 0x7;
- return &dir->tables[table_idx]->pages[address % 1024];
- } else {
- return 0;
+inline void invlpg(uint32_t addr) {
+ asm volatile("invlpg (%0)"::"r" (addr) : "memory");
+}
+
+void paging_map(uint32_t phy, uint32_t virt, uint16_t flags) {
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = virt >> 12 & 0x03FF;
+ page_tables[pdi][pti] = phy | flags;
+ invlpg(virt);
+}
+
+uint32_t paging_get_physical_addr(uint32_t virt) {
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = (virt >> 12) & 0x03FF;
+ return page_tables[pdi][pti] & 0xFFFFF000;
+}
+
+uint16_t paging_get_flags(uint32_t virt) {
+ uint32_t pdi = virt >> 22;
+ uint32_t pti = (virt >> 12) & 0x03FF;
+ return page_tables[pdi][pti] & 0xFFF;
+}
+
+void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag) {
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i++) {
+ page_tables[i / 1024][i % 1024] |= flag;
+ invlpg(i * 4096);
+ }
+}
+
+void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag) {
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i++) {
+ page_tables[i / 1024][i % 1024] &= ~flag;
+ invlpg(i * 4096);
+ }
+}
+
+void paging_set_present(uint32_t virt, uint32_t count) {
+ paging_set_flag_up(virt, count, PT_PRESENT);
+}
+
+void paging_set_absent(uint32_t virt, uint32_t count) {
+ paging_set_flag_down(virt, count, PT_PRESENT);
+}
+
+void paging_set_used(uint32_t virt, uint32_t count) {
+ paging_set_flag_up(virt, count, PT_USED);
+}
+
+void paging_set_free(uint32_t virt, uint32_t count) {
+ paging_set_flag_down(virt, count, PT_USED);
+}
+
+void paging_set_user(uint32_t virt, uint32_t count) {
+ uint32_t page_n = virt / 4096;
+ for (uint32_t i = page_n; i < page_n + count; i += 1024) {
+ page_directory[i / 1024] |= PD_ALL_PRIV;
}
+ paging_set_flag_up(virt, count, PT_ALL_PRIV);
}
-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);
- memory_set(table, 0, sizeof(page_directory_t));
-
- int i;
- for (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;
- extern void copy_page_physical(int a, int b);
- copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000);
+uint32_t paging_find_pages(uint32_t count) {
+ uint32_t continous = 0;
+ uint32_t startDir = 0;
+ uint32_t startPage = 0;
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ if (!(page_tables[i][j] & PT_PRESENT) || (page_tables[i][j] & PT_USED)) {
+ continous = 0;
+ startDir = i;
+ startPage = j + 1;
+ } else {
+ if (++continous == count)
+ return (startDir * 0x400000) + (startPage * 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);
- memory_set(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;
+
+ panic("Out of memory!");
+ return 0;
+}
+
+uint32_t paging_alloc_pages(uint32_t count) {
+ uint32_t ptr = paging_find_pages(count);
+ paging_set_used(ptr, count);
+ return ptr;
+}
+
+uint32_t paging_get_used_pages() {
+ uint32_t n = 0;
+ for (uint32_t i = 0; i < 1024; i++) {
+ for (uint32_t j = 0; j < 1024; j++) {
+ uint8_t flags = page_tables[i][j] & PT_USED;
+ if (flags == 1) n++;
}
}
- return dir;
+ return n;
}
diff --git a/src/kernel/paging/paging.h b/src/kernel/paging/paging.h
index 681b84e..85ef120 100644
--- a/src/kernel/paging/paging.h
+++ b/src/kernel/paging/paging.h
@@ -2,73 +2,57 @@
#define MELVIX_PAGING_H
#include <stdint.h>
-#include "../interrupts/interrupts.h"
-
-typedef struct page {
- uint32_t present : 1; // Page present in memory
- uint32_t rw : 1; // Read-only if clear, readwrite if set
- uint32_t user : 1; // Supervisor level only if clear
- uint32_t accessed : 1; // Has the page been accessed since last refresh?
- uint32_t dirty : 1; // Has the page been written to since last refresh?
- uint32_t unused : 7; // Amalgamation of unused and reserved bits
- uint32_t frame : 20; // Frame address (shifted right 12 bits)
-} 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;
-
-/**
- * Initialize the environment and enable paging
- */
-void initialise_paging();
-
-/**
- * Enable paging bit in CR0 (without initializing)
- */
-void enable_paging();
-
-/**
- * Disable paging bit in CR0
- */
-void disable_paging();
-
-/**
- * Load the page directory into the CR3 register
- * @param new The page directory
- */
-void switch_page_directory(page_directory_t *new);
-
-/**
- * Get a specific page pointer
- * @param address The page address
- * @param make If 1 create the page first
- * @param dir The page directory
- * @return The page pointer
- */
-page_t *get_page(uint32_t address, int make, page_directory_t *dir);
-
-/**
- * Page fault handler
- * @param r The IRQ registers
- */
-void page_fault(struct regs *r);
-
-void alloc_frame(page_t *page, int is_kernel, int is_writeable);
-
-void free_frame(page_t *page);
-
-/**
- * Copy/clone a page directory
- * @param src The page directory
- * @return A new page directory pointer
- */
-page_directory_t *clone_directory(page_directory_t *src);
+
+#define PD_PRESENT 1 << 0
+#define PD_RW 1 << 1
+#define PD_ALL_PRIV 1 << 2
+#define PD_WRITETHR 1 << 3
+#define PD_CACHE_D 1 << 4
+#define PD_ACCESSED 1 << 5
+#define PD_4M_PAGE 1 << 7
+
+#define PT_PRESENT 1 << 0
+#define PT_RW 1 << 1
+#define PT_ALL_PRIV 1 << 2
+#define PT_WRITETHR 1 << 3
+#define PT_CACHE_D 1 << 4
+#define PT_ACCESSED 1 << 5
+#define PT_DIRTY 1 << 6
+#define PT_GLOBAL 1 << 8
+#define PT_USED 1 << 9
+
+void paging_install();
+
+void paging_enable();
+
+void paging_disable();
+
+void paging_map(uint32_t phy, uint32_t virt, uint16_t flags);
+
+uint32_t paging_get_phys(uint32_t virt);
+
+uint16_t paging_get_flags(uint32_t virt);
+
+void paging_set_flags(uint32_t virt, uint32_t count, uint16_t flags);
+
+void paging_set_flag_up(uint32_t virt, uint32_t count, uint32_t flag);
+
+void paging_set_flag_down(uint32_t virt, uint32_t count, uint32_t flag);
+
+void paging_set_present(uint32_t virt, uint32_t count);
+
+void paging_set_absent(uint32_t virt, uint32_t count);
+
+void paging_set_used(uint32_t virt, uint32_t count);
+
+void paging_set_free(uint32_t virt, uint32_t count);
+
+void paging_set_user(uint32_t virt, uint32_t count);
+
+uint32_t paging_find_pages(uint32_t count);
+
+uint32_t paging_alloc_pages(uint32_t count);
+
+uint32_t paging_get_used_pages();
#endif