diff options
Diffstat (limited to 'src/kernel/paging')
-rw-r--r-- | src/kernel/paging/kheap.c | 295 | ||||
-rw-r--r-- | src/kernel/paging/kheap.h | 108 | ||||
-rw-r--r-- | src/kernel/paging/ordered_array.c | 66 | ||||
-rw-r--r-- | src/kernel/paging/ordered_array.h | 66 | ||||
-rw-r--r-- | src/kernel/paging/paging.c | 274 | ||||
-rw-r--r-- | src/kernel/paging/paging.h | 120 |
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 |