From 617e23517d703ea2151f9846006c5e126fc4eed3 Mon Sep 17 00:00:00 2001 From: Amelia Coutard <eliottulio.coutard@gmail.com> Date: Mon, 9 May 2022 00:48:36 +0200 Subject: [PATCH] Changed the rounding of usable RAM addresses and the freeing of the multiboot2 info struct to avoid accidentally marking unusable RAM as usable --- src/kernel.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/kernel.cpp b/src/kernel.cpp index 5799f46..32ec362 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -49,8 +49,9 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s asm("mov $_kernel_phys_end,%0" : "=ri"(ptr)); return ptr; })(); - const os::phys_ptr<os::paging::page> info_start{info.get_phys_addr()}; - const os::phys_ptr<os::paging::page> info_end = info_start + (info->total_size - 1 + 0x1000) / 0x1000; // Number of pages taken, rounded up + const os::phys_ptr<os::paging::page> info_start{info.get_phys_addr() / 0x1000 * 0x1000}; // Round start down. + const os::phys_ptr<os::paging::page> info_end{(info.get_phys_addr() + info->total_size + 0x1000 - 1) / 0x1000 * 0x1000}; // Round end up. + bool info_pages_wholly_usable = false; os::framebuffer framebuffer; @@ -59,6 +60,11 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s 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::framebuffer_info: + os::print("Framebuffer:\n"); + os::print(multiboot2::framebuffer_addr(it)); + os::print("->"); + os::print(multiboot2::framebuffer_addr(it) + multiboot2::framebuffer_pitch(it) * multiboot2::framebuffer_height(it)); + os::printc('\n'); framebuffer = os::framebuffer( multiboot2::framebuffer_addr(it), multiboot2::framebuffer_pitch(it), @@ -70,19 +76,14 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s ); break; case multiboot2::info::type_t::memory_map: - os::println("Memory map:"); for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) { - os::print(multiboot2::memory_map_base_addr(it, i)); - os::print("->"); - os::print(multiboot2::memory_map_base_addr(it, i) + multiboot2::memory_map_length(it, i)); - os::printc(':'); - os::printc('0' + multiboot2::memory_map_type(it, i)); - os::printc('\n'); if (multiboot2::memory_map_type(it, i) == 1) { - const os::phys_ptr<os::paging::page> s{multiboot2::memory_map_base_addr(it, i) == 0 ? 0x1000 : multiboot2::memory_map_base_addr(it, i)}; + const os::phys_ptr<os::paging::page> s{ + multiboot2::memory_map_base_addr(it, i) < 0x1000 + ? 0x1000 + : (multiboot2::memory_map_base_addr(it, i) + 0x1000 - 1) / 0x1000 * 0x1000 + }; const os::phys_ptr<os::paging::page> e{multiboot2::memory_map_base_addr(it, i) + multiboot2::memory_map_length(it, i) / 0x1000 * 0x1000}; - if (s == nullptr) { - } if (s < e) { remove_some_mem( s, e, kernel_start, kernel_end, @@ -96,6 +97,14 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s } ); } + bool info_usable = true; + remove_some_mem(info_start, info_end, s, e, [&info_usable](auto, auto) { + info_usable = false; + }); + info_pages_wholly_usable = info_pages_wholly_usable || info_usable; + // info_pages_wholly_usable will only be false if no usable RAM section covers all the multiboot info struct. + // This allows me to make sure that I don't use any unusable RAM, in the very improbable case where the + // multiboot info struct is in a partially usable memory page. } } break; @@ -104,9 +113,14 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s } // Deallocate multiboot info structure: not usable anymore. - page_allocator.deallocate({.ptr = info_start, .size = (info_end.get_phys_addr() - info_start.get_phys_addr()) / 0x1000}); + if (info_pages_wholly_usable) { + page_allocator.deallocate({.ptr = info_start, .size = (info_end.get_phys_addr() - info_start.get_phys_addr()) / 0x1000}); + } else if (info_start + 1 < info_end - 1) { + // Ignore the first and last blocks: ensures all the RAM is truly usable. + page_allocator.deallocate({.ptr = info_start + 1, .size = (info_end.get_phys_addr() - info_start.get_phys_addr()) / 0x1000 - 2}); + } - os::println("RAM:"); + os::print("RAM:\n"); page_allocator.print_all(); for (std::size_t x = 0; x < framebuffer.get_width(); x++) { -- 2.46.0