From cf71eed83e0ba435c9bc4f8d29b4293a0f152adf Mon Sep 17 00:00:00 2001 From: Amelia Coutard Date: Mon, 11 Dec 2023 23:21:53 +0100 Subject: [PATCH] Added setup of the new and improved memory map --- kernel/linker.ld | 2 +- kernel/src/kernel.cpp | 142 +++++++++++++++++++++++++++++++----------- 2 files changed, 105 insertions(+), 39 deletions(-) diff --git a/kernel/linker.ld b/kernel/linker.ld index b3fa2b6..a240be3 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -45,7 +45,7 @@ SECTIONS { *(.eh_frame) } . = ALIGN(4K); - _kernel_rw_start = . - KERNEL_VMA; + _kernel_phys_rw_start = . - KERNEL_VMA; .data ALIGN(4K) : AT(ADDR(.data) - KERNEL_VMA) { *(.data) *(.data*) diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index f2624b6..e37a9a4 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -23,10 +23,18 @@ os::idt<32> idt; extern "C" os::tss TSS; extern "C" char interrupt_stack_top; extern "C" os::paging::PML4T old_PML4T; +char _kernel_phys_start; +char _kernel_phys_rw_start; +char _kernel_phys_end; -os::paging::page<0> bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB +os::paging::page<0> bootstrap_pages_for_memory[256]; // 256 pages = 1MiB extern "C" void kmain(unsigned long magic, os::phys_ptr info) { + if (!os::init_serial_port()) { + while (true) { + os::hlt(); + } + } os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2."); os::paging::page_allocator.deallocate({ @@ -35,21 +43,87 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr{std::uintptr_t(&os::paging::global_PML4T) - 0xFFFF'FFFF'8000'0000}); - os::print("Begin MMAP print.\n"); - os::paging::on_all_pages(os::paging::global_PML4T, [](os::paging::page* vaddr, os::phys_ptr> paddr) { - os::print("{} -> {} ({})\n", vaddr, (void*)paddr.get_phys_addr(), depth); - }); - os::print("End MMAP print.\n"); - - if (!os::init_serial_port()) { - while (true) { - os::hlt(); + // Initialise kernel map. + os::assert(std::size_t(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !"); + os::assert(std::size_t(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !"); + os::assert(std::size_t(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !"); + for (std::size_t i = std::size_t(&_kernel_phys_start); i < std::size_t(&_kernel_phys_rw_start); ) { + if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) { + os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .AVL_or_MPK = 0, .NX = 0 }); + i += 1024 * 1024 * 1024; + } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) { + os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 0 }); + i += 1024 * 1024 * 2; + } else { + os::paging::map_page<0, 3>(os::paging::global_PML4T, (os::paging::page<0>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 0 }); + i += 1024 * 4; } } + for (std::size_t i = std::size_t(&_kernel_phys_rw_start); i < std::size_t(&_kernel_phys_end); ) { + if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) { + os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .AVL_or_MPK = 0, .NX = 1 }); + i += 1024 * 1024 * 1024; + } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) { + os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 }); + i += 1024 * 1024 * 2; + } else { + os::paging::map_page<0, 3>(os::paging::global_PML4T, (os::paging::page<0>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr>(i), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 }); + i += 1024 * 4; + } + } + // Initialise physical memory map. + for (auto it = multiboot2::next(info); it->type != multiboot2::info::type_t::end; it = multiboot2::next(it)) { + switch (it->type) { + case multiboot2::info::type_t::memory_map: + os::print("RAM:\n"); + for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) { + std::size_t const s = multiboot2::memory_map_base_addr(it, i); + std::size_t const e = s + multiboot2::memory_map_length(it, i); + os::print("{} -> {} : {}\n", (void*)s, (void*)e, multiboot2::memory_map_type(it, i)); + if (multiboot2::memory_map_type(it, i) != 1) { + continue; + } + if (e <= 1024 * 1024) { // I'll ignore lower memory for now. + continue; + } + os::assert(s % 0x1000 == 0, "Memory map unaligned on page boundaries."); + os::assert(e % 0x1000 == 0, "Memory map unaligned on page boundaries."); + for (std::size_t j = s; j < e; ) { + if (j % (1024 * 1024 * 1024) == 0 && j + 1024 * 1024 * 1024 < e) { + os::paging::map_page<2, 3>( + os::paging::global_PML4T, + (os::paging::page<2>*)(0xFFFF'8000'0000'0000 + j), + os::phys_ptr>(j), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .AVL_or_MPK = 0, .NX = 1 }); + j += 1024 * 1024 * 1024; + } else if (j % (1024 * 1024 * 2) == 0 && j + 1024 * 1024 * 2 < e) { + os::paging::map_page<1, 3>(os::paging::global_PML4T, + (os::paging::page<1>*)(0xFFFF'8000'0000'0000 + j), + os::phys_ptr>(j), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 }); + j += 1024 * 1024 * 2; + } else { + os::paging::map_page<0, 3>(os::paging::global_PML4T, + (os::paging::page<0>*)(0xFFFF'8000'0000'0000 + j), + os::phys_ptr>(j), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 }); + j += 1024 * 4; + } + } + } + os::print("RAM END\n"); + break; + default: break; + } + } + // /TODO + os::paging::load_pml4t(os::phys_ptr{std::uintptr_t(&os::paging::global_PML4T) - 0xFFFF'FFFF'8000'0000}); { // Enable interrupts really early so I don't have to manually manage memory... Will make better later, when I make utils.hpp/incrementing_int64_map better. os::isr_info isr_info[32]; @@ -88,6 +162,11 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr(os::paging::global_PML4T, + (os::paging::page<0>*)(0xFFFF'8000'fee0'0000), + os::phys_ptr>(0x0000'0000'fee0'0000), + { .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 1, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 }); os::enable_interrupts(isr_info, idt); } @@ -119,23 +198,18 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr> - s{(multiboot2::memory_map_base_addr(it, i) + 0x1000 - 1) / 0x1000 * 0x1000}; - // Rounded down, to avoid including non-ram. - const os::phys_ptr> - e{(multiboot2::memory_map_base_addr(it, i) + multiboot2::memory_map_length(it, i)) / 0x1000 * 0x1000 - 0x1000}; - if (s <= e) { // In the case where no full page is included in the ram section, don't add it. - os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably."); - available_ram[available_ram_length++] = {.start_address = s, .end_address = e}; - os::print("{} -> {} ({})\n", s, e + 1, (unsigned long)(e + 1 - s)); - } + if (multiboot2::memory_map_type(it, i) != 1) { + continue; + } + const os::phys_ptr> s{multiboot2::memory_map_base_addr(it, i)}; + const os::phys_ptr> e{s + multiboot2::memory_map_length(it, i) / 0x1000}; + if (e.get_phys_addr() <= 1024 * 1024) { // I'll ignore lower memory for now. + continue; } + os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably."); + available_ram[available_ram_length++] = {.start_address = s, .end_address = e}; } - os::print("RAM END\n"); break; case multiboot2::info::type_t::modules: os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it)); @@ -152,16 +226,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr> kernel_s = ([]() { - os::phys_ptr> ptr = nullptr; - asm("mov $_kernel_phys_start,%0" : "=ri"(ptr)); - return ptr; - })(); - const os::phys_ptr> kernel_e = ([]() { - os::phys_ptr> ptr = nullptr; - asm("mov $_kernel_phys_end,%0" : "=ri"(ptr)); - return ptr - 1; // [s, e], not [s, e[ - })(); + const os::phys_ptr> kernel_s{std::size_t(&_kernel_phys_start)}; + const os::phys_ptr> kernel_e{std::size_t(&_kernel_phys_end)}; // Remove kernel from available RAM: for (std::size_t i = 0; i < available_ram_length; i++) { -- 2.47.0