fix (kernel): polished up page map management

This commit is contained in:
antifallobst 2023-02-10 19:29:05 +01:00
parent 766e7dbaf5
commit cae310826e
3 changed files with 56 additions and 4 deletions

View File

@ -17,7 +17,6 @@
#define NOX_PAGE_MAP_H #define NOX_PAGE_MAP_H
#include "utils/stdtypes.h" #include "utils/stdtypes.h"
#include "boot/boot_info.h"
#define VIRTUAL_ADDRESS_MAX 0x1000000000000 // 256 TB (the limit of PML4s) #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_WRITE_THROUGH = 0b0000000000001000, // 1 << 3
PM_FLAG_CACHE_DISABLED = 0b0000000000010000, // 1 << 4 PM_FLAG_CACHE_DISABLED = 0b0000000000010000, // 1 << 4
PM_FLAG_ACCESSED = 0b0000000000100000, // 1 << 5 PM_FLAG_ACCESSED = 0b0000000000100000, // 1 << 5
PM_FLAG_DIRTY = 0b0000000001000000, // 1 << 6
PM_FLAG_LARGER_PAGES = 0b0000000010000000, // 1 << 7 PM_FLAG_LARGER_PAGES = 0b0000000010000000, // 1 << 7
PM_FLAG_CUSTOM_0 = 0b0000001000000000, // 1 << 9 PM_FLAG_CUSTOM_0 = 0b0000001000000000, // 1 << 9
PM_FLAG_CUSTOM_1 = 0b0000010000000000, // 1 << 10 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_set_address (uint64_t* entry, void* address);
void* page_map_entry_get_address (uint64_t* entry); 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; extern page_map_T* g_kernel_page_map;

View File

@ -31,7 +31,7 @@ void kernel_init(boot_info_T* boot_info) {
gdt_init(); gdt_init();
pframe_manager_init(boot_info); pframe_manager_init(boot_info);
idt_init(); idt_init();
paging_init(boot_info); paging_init();
} }
void kmain(boot_info_T boot_info) { void kmain(boot_info_T boot_info) {

View File

@ -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) { 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) { 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) { 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); 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 // fetching the page map that was created by the bootloader
g_kernel_page_map = page_map_fetch_current(); g_kernel_page_map = page_map_fetch_current();