]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Added actual detection of RAM, to be able to use all of the computer's memory
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Sat, 7 May 2022 22:37:30 +0000 (00:37 +0200)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Sat, 7 May 2022 22:37:30 +0000 (00:37 +0200)
linker.ld
src/boot.S
src/kernel.cpp
src/multiboot2.hpp
src/paging.cpp

index 7c4e9f6a66f0db9cf44741ac0edb23858645a7f2..7b57d1eab9d2e3743c3ed73e3526c838a6fc3528 100644 (file)
--- 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/ : {
index 6cd3e606aa5243d8e5c2aa7eed066596715bd091..ec6a75f563c815730b16f0722030bff76c6015e6 100644 (file)
@@ -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
index e627ac54e5d5f1cbdb570a915438c6fc02d10699..ef4d26f32b598ccab643ac6a57d069b1dab20fb6 100644 (file)
@@ -4,6 +4,34 @@
 #include "utils.hpp"
 #include "serial.hpp"
 
+namespace detail {
+       template <typename F> concept func_on_mem = std::invocable<F, os::phys_ptr<os::paging::page>, os::phys_ptr<os::paging::page>>;
+}
+
+void remove_some_mem(os::phys_ptr<os::paging::page> mem_start,
+               os::phys_ptr<os::paging::page> mem_end,
+               os::phys_ptr<os::paging::page> remove_start,
+               os::phys_ptr<os::paging::page> 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<const multiboot2::info_start> 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<const multiboot2::info_s
                asm("mov $page_list_one_past_end - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr));
                return ram_ptr;
        })()};
-       {
-               os::phys_ptr<os::paging::page> ram_ptr = nullptr;
-               asm("mov $test_ram - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr));
-               page_allocator.deallocate({.ptr = ram_ptr, .size = 256});
-       }
+       const os::phys_ptr<os::paging::page> kernel_start = ([]() {
+               os::phys_ptr<os::paging::page> ptr = nullptr;
+               asm("mov $_kernel_phys_start,%0" : "=ri"(ptr));
+               return ptr;
+       })();
+       const os::phys_ptr<os::paging::page> kernel_end = ([]() {
+               os::phys_ptr<os::paging::page> ptr = nullptr;
+               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
 
        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<const multiboot2::info_s
                        );
                        break;
                case multiboot2::info::type_t::memory_map:
-                       os::println("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> 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, {
index cbbdf5c9425c3debe12bb3633a50166dcd83b26d..372fb1378cd89737e8ffd54e716060e028eb402b 100644 (file)
        inline const std::uint8_t* color_info(os::phys_ptr<const info> ptr) {
                return reinterpret_cast<const std::uint8_t*>(&ptr->rest[24]);
        }
+
+       inline std::uint32_t memory_map_entry_size(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[0]);
+       }
+       inline std::uint32_t memory_map_entry_version(os::phys_ptr<const info> ptr) {
+               return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[4]);
+       }
+       inline std::size_t memory_map_number_of_entries(os::phys_ptr<const info> ptr) {
+               return (ptr->size - 16) / memory_map_entry_size(ptr);
+       }
+       inline std::uint64_t memory_map_base_addr(os::phys_ptr<const info> ptr, std::size_t index) {
+               return *reinterpret_cast<const std::uint64_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index +  0]);
+       }
+       inline std::uint64_t memory_map_length(os::phys_ptr<const info> ptr, std::size_t index) {
+               return *reinterpret_cast<const std::uint64_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index +  8]);
+       }
+       inline std::uint32_t memory_map_type(os::phys_ptr<const info> ptr, std::size_t index) {
+               return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 16]);
+       }
 #endif // __cplusplus
 
 #ifdef __cplusplus
index d84150933a45826f2867cc92ae766de5f22dc278..530436c983e8c36df8172daaf67f1e9522b69680 100644 (file)
@@ -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');
        }
 }