]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Changed the algorithm that makes the free RAM available, to make it cleaner and more...
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Sat, 8 Oct 2022 18:27:23 +0000 (20:27 +0200)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Sun, 9 Oct 2022 01:03:55 +0000 (03:03 +0200)
src/kernel.cpp

index 1b513076d4cbb2037f190b98678d6d191c9daf68..a52ecab6796cacfd8a443194724e3debf42b9a72 100644 (file)
@@ -4,30 +4,6 @@
 #include "serial.hpp"
 #include "interrupts.hpp"
 
-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,
-               std::invocable<os::phys_ptr<os::paging::page>, os::phys_ptr<os::paging::page>> 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);
-       }
-}
-
 os::idt<32> idt;
 
 extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_start> info) {
@@ -35,64 +11,79 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
        os::assert(os::cpu_has_msr(), "MSRs aren't supported.");
 
        if (!os::init_serial_port()) {
-               os::hlt();
+               while (true) {
+                       os::hlt();
+               }
        }
 
-       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() / 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;
+       {
+               struct {
+                       os::phys_ptr<os::paging::page> start_address = nullptr;
+                       os::phys_ptr<os::paging::page> end_address = nullptr;
+               } available_ram[50];
+               std::size_t available_ram_length = 0;
 
-       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:
-                       for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
-                               if (multiboot2::memory_map_type(it, i) == 1) {
-                                       const os::phys_ptr<os::paging::page> s{(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 < e) {
-                                               remove_some_mem(
-                                               s, e, kernel_start, kernel_end,
-                                               [info_start, info_end] (auto s, auto e) {
-                                                       remove_some_mem(
-                                                       s, e, info_start, info_end,
-                                                       [] (auto s, auto e) {
-                                                               os::paging::page_allocator.deallocate({.ptr = s, .size = std::uint64_t(e - 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::memory_map:
+                               for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
+                                       if (multiboot2::memory_map_type(it, i) == 1) {
+                                               // Rounded up, to avoid including non-ram.
+                                               const os::phys_ptr<os::paging::page>
+                                                       s{(multiboot2::memory_map_base_addr(it, i) + 0x1000 - 1) / 0x1000 * 0x1000};
+                                               // Rounded down, to avoid including non-ram.
+                                               const os::phys_ptr<os::paging::page>
+                                                       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};
                                                }
-                                               );
                                        }
-                                       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;
+                       default: break;
                        }
-                       break;
-               default: break;
                }
-       }
 
-       // Deallocate multiboot info structure: not usable anymore.
-       if (info_pages_wholly_usable) {
-               os::paging::page_allocator.deallocate({.ptr = info_start, .size = std::uint64_t(info_end - info_start)});
-       } else if (info_start + 1 < info_end - 1) {
-               // Ignore the first and last blocks: ensures all the RAM is truly usable.
-               os::paging::page_allocator.deallocate({.ptr = info_start + 1, .size = std::uint64_t(info_end - info_start - 2)});
+               // kernel_start and kernel_end are aligned to 4K by the linker script.
+               const os::phys_ptr<os::paging::page> s = ([]() {
+                       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> e = ([]() {
+                       os::phys_ptr<os::paging::page> ptr = nullptr;
+                       asm("mov $_kernel_phys_end,%0" : "=ri"(ptr));
+                       return ptr - 1; // [s, e], not [s, e[
+               })();
+
+               // Remove kernel from available RAM:
+               for (std::size_t i = 0; i < available_ram_length; i++) {
+                       if (e < available_ram[i].start_address || available_ram[i].end_address < s) {
+                               continue;
+                       }
+                       if (s <= available_ram[i].start_address && available_ram[i].end_address <= e) {
+                               available_ram[i] = available_ram[--available_ram_length];
+                       } else if (s <= available_ram[i].start_address) {
+                               available_ram[i].start_address = e + 1; // Since e < end_address, new start_address <= end_address.
+                       } else if (available_ram[i].end_address <= e) {
+                               available_ram[i].end_address = s - 1; // Since start_address < s, start_address <= new end_address.
+                       } else {
+                               os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
+                               available_ram[available_ram_length] = available_ram[i];
+                               available_ram[i].end_address = s - 1;
+                               available_ram[available_ram_length].start_address = e + 1;
+                               available_ram_length++;
+                       }
+               }
+
+               // Add available RAM to the page allocator (warning: overrides the multiboot info structure):
+               for (std::size_t i = 0; i < available_ram_length; i++) {
+                       os::paging::page_allocator.deallocate({
+                               .ptr = available_ram[i].start_address,
+                               .size = std::size_t(available_ram[i].end_address - available_ram[i].start_address + 1)
+                       });
+               }
        }
 
        os::print("RAM:\n");