feature (kernel): implemented Page Maps
This commit is contained in:
parent
45f18251a9
commit
9e61513014
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||
*
|
||||
* NoxOS is free software:
|
||||
* you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOX_PAGE_MAP_H
|
||||
#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)
|
||||
|
||||
typedef enum {
|
||||
PM_FLAG_PRESENT = 0b0000000000000001, // 1 << 0
|
||||
PM_FLAG_READ_WRITE = 0b0000000000000010, // 1 << 1
|
||||
PM_FLAG_USER_SUPER = 0b0000000000000100, // 1 << 2
|
||||
PM_FLAG_WRITE_THROUGH = 0b0000000000001000, // 1 << 3
|
||||
PM_FLAG_CACHE_DISABLED = 0b0000000000010000, // 1 << 4
|
||||
PM_FLAG_ACCESSED = 0b0000000000100000, // 1 << 5
|
||||
PM_FLAG_LARGER_PAGES = 0b0000000010000000, // 1 << 7
|
||||
PM_FLAG_CUSTOM_0 = 0b0000001000000000, // 1 << 9
|
||||
PM_FLAG_CUSTOM_1 = 0b0000010000000000, // 1 << 10
|
||||
PM_FLAG_CUSTOM_2 = 0b0000100000000000, // 1 << 11
|
||||
PM_FLAG_NO_EXECUTE = 0x8000000000000000 // 1 << 63
|
||||
} page_map_flag_E;
|
||||
|
||||
typedef struct {
|
||||
uint64_t entries[512];
|
||||
}__attribute__((aligned(0x1000))) page_map_T;
|
||||
|
||||
page_map_T* page_map_create ();
|
||||
extern page_map_T* page_map_fetch_current ();
|
||||
extern void page_map_load (page_map_T* page_map);
|
||||
void page_map_map_memory (page_map_T* page_map, void* virtual_address, void* physical_address, uint64_t flags);
|
||||
void page_map_unmap_memory (page_map_T* page_map, void* virtual_address);
|
||||
void page_map_destruct (page_map_T* page_map);
|
||||
|
||||
void page_map_entry_set_flags (uint64_t* entry, uint64_t flags);
|
||||
bool page_map_entry_get_flag (uint64_t* entry, page_map_flag_E flag);
|
||||
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);
|
||||
|
||||
extern page_map_T* g_kernel_page_map;
|
||||
|
||||
#endif //NOX_PAGE_MAP_H
|
|
@ -19,6 +19,9 @@
|
|||
#include "platform/gdt.h"
|
||||
#include "platform/interrupts.h"
|
||||
#include "mm/page_frame.h"
|
||||
#include "mm/page_map.h"
|
||||
|
||||
#include "utils/memory.h"
|
||||
|
||||
void limine_terminal_print(boot_info_T* boot_info, string_t string) {
|
||||
boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string));
|
||||
|
@ -28,6 +31,7 @@ void kernel_init(boot_info_T* boot_info) {
|
|||
gdt_init();
|
||||
pframe_manager_init(boot_info);
|
||||
idt_init();
|
||||
paging_init(boot_info);
|
||||
}
|
||||
|
||||
void kmain(boot_info_T boot_info) {
|
||||
|
@ -38,7 +42,12 @@ void kmain(boot_info_T boot_info) {
|
|||
kernel_init(&boot_info);
|
||||
|
||||
// this should cause a kernel panic
|
||||
int x = 1312 / 0;
|
||||
// int x = 1312 / 0;
|
||||
|
||||
page_map_map_memory(g_kernel_page_map, (void*)0x100000000000, pframe_request(), PM_FLAG_READ_WRITE);
|
||||
memory_copy("test string", (void*)0x100000000000, 13);
|
||||
log(LOG_DEBUG, (string_t)0x100000000000);
|
||||
|
||||
|
||||
CORE_HALT_FOREVER
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||
*
|
||||
* NoxOS is free software:
|
||||
* you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mm/page_map.h"
|
||||
#include "mm/page_frame.h"
|
||||
#include "mm/memory_map.h"
|
||||
#include "utils/memory.h"
|
||||
#include "utils/math.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
page_map_T* g_kernel_page_map;
|
||||
|
||||
page_map_T* page_map_create() {
|
||||
page_map_T* page_map = pframe_request();
|
||||
memory_set(page_map, 0, PFRAME_SIZE);
|
||||
|
||||
return page_map;
|
||||
}
|
||||
|
||||
page_map_T* page_map_request_entry(page_map_T* page_map, uint16_t index) {
|
||||
uint64_t* entry = &page_map->entries[index];
|
||||
|
||||
if (page_map_entry_get_flag(entry, PM_FLAG_PRESENT)) {
|
||||
return page_map_entry_get_address(entry);
|
||||
}
|
||||
|
||||
page_map_T* table = pframe_request();
|
||||
memory_set(table, 0, PFRAME_SIZE);
|
||||
page_map_entry_set_address(entry, (void*)((uint64_t)table >> 12));
|
||||
|
||||
page_map_entry_set_flags(entry, PM_FLAG_PRESENT | PM_FLAG_READ_WRITE);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void page_map_map_memory(page_map_T* page_map, void* virtual_address, void* physical_address, uint64_t flags) {
|
||||
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;
|
||||
page_map_T* page_directory_page = page_map_request_entry(page_map, page_directory_page_index);
|
||||
page_map_T* page_directory = page_map_request_entry(page_directory_page, page_directory_index);
|
||||
page_map_T* page_table = page_map_request_entry(page_directory, page_table_index);
|
||||
uint64_t* page = &page_table->entries[page_index];
|
||||
|
||||
page_map_entry_set_address(page, (void*)((uint64_t)physical_address >> 12));
|
||||
page_map_entry_set_flags(page, PM_FLAG_PRESENT | flags);
|
||||
}
|
||||
|
||||
void page_map_unmap_memory(page_map_T* page_map, void* virtual_address) {
|
||||
|
||||
}
|
||||
|
||||
void page_map_destruct(page_map_T* page_map) {
|
||||
|
||||
}
|
||||
|
||||
void page_map_entry_set_flags(uint64_t* entry, uint64_t flags) {
|
||||
*entry |= flags;
|
||||
}
|
||||
|
||||
bool page_map_entry_get_flag(uint64_t* entry, page_map_flag_E flag) {
|
||||
return ((*entry & flag) > 0);
|
||||
}
|
||||
|
||||
void page_map_entry_set_address(uint64_t* entry, void* address) {
|
||||
uint64_t masked_address = (uint64_t)address & 0x000000ffffffffff;
|
||||
|
||||
*entry &= 0xfff0000000000fff;
|
||||
*entry |= (masked_address << 12);
|
||||
}
|
||||
|
||||
void* page_map_entry_get_address(uint64_t* entry) {
|
||||
return (void*)(*entry & 0x000ffffffffff000);
|
||||
}
|
||||
|
||||
void paging_init(boot_info_T* boot_info) {
|
||||
// fetching the page map that was created by the bootloader
|
||||
g_kernel_page_map = page_map_fetch_current();
|
||||
|
||||
log(LOG_INFO, "Paging Initialized");
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
page_map_load:
|
||||
mov cr3, rax
|
||||
ret
|
||||
GLOBAL page_map_load
|
||||
|
||||
page_map_fetch_current:
|
||||
mov rax, cr3
|
||||
ret
|
||||
GLOBAL page_map_fetch_current
|
Loading…
Reference in New Issue