From cae310826e3c8a0b645f0bd11d272e2a97f13761 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Fri, 10 Feb 2023 19:29:05 +0100 Subject: [PATCH] fix (kernel): polished up page map management --- kernel/inc/mm/page_map.h | 4 +-- kernel/src/kmain.c | 2 +- kernel/src/mm/page_map.c | 54 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/kernel/inc/mm/page_map.h b/kernel/inc/mm/page_map.h index faec013..0c6fd08 100644 --- a/kernel/inc/mm/page_map.h +++ b/kernel/inc/mm/page_map.h @@ -17,7 +17,6 @@ #define NOX_PAGE_MAP_H #include "utils/stdtypes.h" -#include "boot/boot_info.h" #define VIRTUAL_ADDRESS_MAX 0x1000000000000 // 256 TB (the limit of PML4s) @@ -28,6 +27,7 @@ typedef enum { PM_FLAG_WRITE_THROUGH = 0b0000000000001000, // 1 << 3 PM_FLAG_CACHE_DISABLED = 0b0000000000010000, // 1 << 4 PM_FLAG_ACCESSED = 0b0000000000100000, // 1 << 5 + PM_FLAG_DIRTY = 0b0000000001000000, // 1 << 6 PM_FLAG_LARGER_PAGES = 0b0000000010000000, // 1 << 7 PM_FLAG_CUSTOM_0 = 0b0000001000000000, // 1 << 9 PM_FLAG_CUSTOM_1 = 0b0000010000000000, // 1 << 10 @@ -51,7 +51,7 @@ bool page_map_entry_get_flag (uint64_t* entry, page_map_f void page_map_entry_set_address (uint64_t* entry, void* address); void* page_map_entry_get_address (uint64_t* entry); -void paging_init (boot_info_T* boot_info); +void paging_init (); extern page_map_T* g_kernel_page_map; diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 111eb9b..59f95b8 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -31,7 +31,7 @@ void kernel_init(boot_info_T* boot_info) { gdt_init(); pframe_manager_init(boot_info); idt_init(); - paging_init(boot_info); + paging_init(); } void kmain(boot_info_T boot_info) { diff --git a/kernel/src/mm/page_map.c b/kernel/src/mm/page_map.c index 486f6de..1a65db6 100644 --- a/kernel/src/mm/page_map.c +++ b/kernel/src/mm/page_map.c @@ -63,11 +63,63 @@ void page_map_map_memory(page_map_T* page_map, void* virtual_address, void* phys } void page_map_unmap_memory(page_map_T* page_map, void* virtual_address) { + virtual_address = (void*)FLOOR_TO((uint64_t)virtual_address, PFRAME_SIZE); + // Intel's Developer Manual has a nice graph, that explains how these indexes are calculated + uint16_t page_index = ((uint64_t)virtual_address >> 12) & 0x1FF; + uint16_t page_table_index = ((uint64_t)virtual_address >> 21) & 0x1FF; + uint16_t page_directory_index = ((uint64_t)virtual_address >> 30) & 0x1FF; + uint16_t page_directory_page_index = ((uint64_t)virtual_address >> 39) & 0x1FF; + + if (!page_map_entry_get_flag(&page_map->entries[page_directory_page_index], PM_FLAG_PRESENT)) { + return; + } + page_map_T* page_directory_page = page_map_entry_get_address(&page_map->entries[page_directory_page_index]); + + if (!page_map_entry_get_flag(&page_directory_page->entries[page_directory_index], PM_FLAG_PRESENT)) { + return; + } + page_map_T* page_directory = page_map_entry_get_address(&page_directory_page->entries[page_directory_index]); + + if (!page_map_entry_get_flag(&page_directory->entries[page_table_index], PM_FLAG_PRESENT)) { + return; + } + page_map_T* page_table = page_map_entry_get_address(&page_directory->entries[page_table_index]); + + // zeroing out the complete entry + page_table->entries[page_index] = 0; } void page_map_destruct(page_map_T* page_map) { + for (uint16_t page_directory_page_index = 0; page_directory_page_index < 512; page_directory_page_index++) { + if (!page_map_entry_get_flag(&page_map->entries[page_directory_page_index], PM_FLAG_PRESENT)) { + continue; + } + page_map_T* page_directory_page = page_map_entry_get_address(&page_map->entries[page_directory_page_index]); + for (uint16_t page_directory_index = 0; page_directory_index < 512; page_directory_index++) { + if (!page_map_entry_get_flag(&page_directory_page->entries[page_directory_index], PM_FLAG_PRESENT)) { + continue; + } + page_map_T *page_directory = page_map_entry_get_address(&page_directory_page->entries[page_directory_index]); + + for (uint16_t page_table_index = 0; page_table_index < 512; page_table_index++) { + if (!page_map_entry_get_flag(&page_directory->entries[page_table_index], PM_FLAG_PRESENT)) { + continue; + } + page_map_T *page_table = page_map_entry_get_address(&page_directory->entries[page_table_index]); + + + pframe_free(page_table); + } + + pframe_free(page_directory); + } + + pframe_free(page_directory_page); + } + + pframe_free(page_map); } void page_map_entry_set_flags(uint64_t* entry, uint64_t flags) { @@ -89,7 +141,7 @@ void* page_map_entry_get_address(uint64_t* entry) { return (void*)(*entry & 0x000ffffffffff000); } -void paging_init(boot_info_T* boot_info) { +void paging_init() { // fetching the page map that was created by the bootloader g_kernel_page_map = page_map_fetch_current();