From: Amelia Coutard Date: Sat, 7 May 2022 22:37:30 +0000 (+0200) Subject: Added actual detection of RAM, to be able to use all of the computer's memory X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=8cade7acc1c1b1e62c136f5a76f72f2abd5a1841;p=voyage-au-centre-des-fichiers.git Added actual detection of RAM, to be able to use all of the computer's memory --- diff --git a/linker.ld b/linker.ld index 7c4e9f6..7b57d1e 100644 --- a/linker.ld +++ b/linker.ld @@ -5,6 +5,8 @@ SECTIONS { . = 1M; + . = ALIGN(4K); + _kernel_phys_start = .; .bootstrap ALIGN(4K) : { *(.multiboot_header) . = ALIGN(4K); @@ -29,6 +31,8 @@ SECTIONS { *(.bss) *(COMMON) } + . = ALIGN(4K); + _kernel_phys_end = . - KERNEL_VMA; /DISCARD/ : { diff --git a/src/boot.S b/src/boot.S index 6cd3e60..ec6a75f 100644 --- a/src/boot.S +++ b/src/boot.S @@ -96,9 +96,6 @@ PDPT_high: .skip 0x1000 - 16 .align 0x1000 .globl page_list_one_past_end page_list_one_past_end: .skip 0x1000 -#TODO replace with actual RAM detection -.globl test_ram -test_ram: .skip 0x1000 * 256 # 1MiB RAM PML4T: .skip 0x1000 phys_mem_map: .skip 0x1000 * 128 - 8 .align 16 diff --git a/src/kernel.cpp b/src/kernel.cpp index e627ac5..ef4d26f 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -4,6 +4,34 @@ #include "utils.hpp" #include "serial.hpp" +namespace detail { + template concept func_on_mem = std::invocable, os::phys_ptr>; +} + +void remove_some_mem(os::phys_ptr mem_start, + os::phys_ptr mem_end, + os::phys_ptr remove_start, + os::phys_ptr remove_end, + detail::func_on_mem auto callback + ) { + if (remove_start <= mem_start && mem_start < remove_end && remove_end < mem_end) { + // Removes start: + callback(remove_end, mem_end); + } else if (mem_start < remove_start && remove_start < mem_end && mem_end <= remove_end) { + // Removes end: + callback(mem_start, remove_start); + } else if (remove_start <= mem_start && mem_end <= remove_end) { + // Removes all: + } else if (mem_start < remove_start && remove_end < mem_end) { + // Removes middle: + callback(mem_start, remove_start); + callback(remove_end, mem_end); + } else { + // Remove nothing: + callback(mem_start, mem_end); + } +} + extern "C" void kmain(unsigned long magic, os::phys_ptr info) { os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2."); @@ -17,14 +45,23 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr ram_ptr = nullptr; - asm("mov $test_ram - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr)); - page_allocator.deallocate({.ptr = ram_ptr, .size = 256}); - } + const os::phys_ptr kernel_start = ([]() { + os::phys_ptr ptr = nullptr; + asm("mov $_kernel_phys_start,%0" : "=ri"(ptr)); + return ptr; + })(); + const os::phys_ptr kernel_end = ([]() { + os::phys_ptr ptr = nullptr; + asm("mov $_kernel_phys_end,%0" : "=ri"(ptr)); + return ptr; + })(); + const os::phys_ptr info_start{info.get_phys_addr()}; + const os::phys_ptr info_end = info_start + (info->total_size - 1 + 0x1000) / 0x1000; // Number of pages taken, rounded up os::framebuffer framebuffer; + + 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: @@ -39,12 +76,45 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr"); + 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 s{multiboot2::memory_map_base_addr(it, i) == 0 ? 0x1000 : multiboot2::memory_map_base_addr(it, i)}; + const os::phys_ptr 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, + [&page_allocator, info_start, info_end] (auto s, auto e) { + remove_some_mem( + s, e, info_start, info_end, + [&page_allocator] (auto s, auto e) { + page_allocator.deallocate({.ptr = s, .size = (e.get_phys_addr() - s.get_phys_addr()) / 0x1000}); + } + ); + } + ); + } + } + } break; default: break; } } + // 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}); + + os::println("RAM:"); + page_allocator.print_all(); + for (std::size_t x = 0; x < framebuffer.get_width(); x++) { for (std::size_t y = 0; y < framebuffer.get_height(); y++) { framebuffer.putpixel(x, y, { diff --git a/src/multiboot2.hpp b/src/multiboot2.hpp index cbbdf5c..372fb13 100644 --- a/src/multiboot2.hpp +++ b/src/multiboot2.hpp @@ -89,6 +89,25 @@ inline const std::uint8_t* color_info(os::phys_ptr ptr) { return reinterpret_cast(&ptr->rest[24]); } + + inline std::uint32_t memory_map_entry_size(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[0]); + } + inline std::uint32_t memory_map_entry_version(os::phys_ptr ptr) { + return *reinterpret_cast(&ptr->rest[4]); + } + inline std::size_t memory_map_number_of_entries(os::phys_ptr ptr) { + return (ptr->size - 16) / memory_map_entry_size(ptr); + } + inline std::uint64_t memory_map_base_addr(os::phys_ptr ptr, std::size_t index) { + return *reinterpret_cast(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 0]); + } + inline std::uint64_t memory_map_length(os::phys_ptr ptr, std::size_t index) { + return *reinterpret_cast(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 8]); + } + inline std::uint32_t memory_map_type(os::phys_ptr ptr, std::size_t index) { + return *reinterpret_cast(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 16]); + } #endif // __cplusplus #ifdef __cplusplus diff --git a/src/paging.cpp b/src/paging.cpp index d841509..530436c 100644 --- a/src/paging.cpp +++ b/src/paging.cpp @@ -10,10 +10,9 @@ void os::paging::page_allocator::print_all() const { if (is_empty()) { os::println("No RAM left."); } else for (auto it = begin(); it != end(); it = it->next) { - os::print("addr:size = 0x"); os::print(it.get_phys_addr()); - os::print(":0x"); - os::print(it->size); + os::print("->"); + os::print((it + it->size).get_phys_addr()); os::printc('\n'); } }