]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Added setup of the new and improved memory map
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Mon, 11 Dec 2023 22:21:53 +0000 (23:21 +0100)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Mon, 11 Dec 2023 22:21:53 +0000 (23:21 +0100)
kernel/linker.ld
kernel/src/kernel.cpp

index b3fa2b6ff9db70ca67d7661fca2c08efd5275ffb..a240be3e29d9c692d0568d6c791c7f8ee77f8abe 100644 (file)
@@ -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*)
index f2624b6dfe802414101928336568a57d01fd41db..e37a9a494a11820612561feacdc9b320df308db6 100644 (file)
@@ -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<const multiboot2::info_start> 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<const multiboot2::info_s
        });
 
        os::assert(os::cpu_has_msr(), "MSRs aren't supported.");
-       // TODO: Initialise new PML4T
-       os::paging::global_PML4T = old_PML4T;
-       // /TODO
-       os::paging::load_pml4t(os::phys_ptr<os::paging::PML4T>{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, []<std::size_t depth>(os::paging::page<depth>* vaddr, os::phys_ptr<os::paging::page<depth>> 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<os::paging::page<2>>(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<os::paging::page<1>>(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<os::paging::page<0>>(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<os::paging::page<2>>(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<os::paging::page<1>>(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<os::paging::page<0>>(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<os::paging::page<2>>(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<os::paging::page<1>>(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<os::paging::page<0>>(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<os::paging::PML4T>{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<const multiboot2::info_s
                asm ("movq $handler_0x1d,%0" : "=ri"(isr_info[0x1d].addr) : );
                asm ("movq $handler_0x1e,%0" : "=ri"(isr_info[0x1e].addr) : );
                asm ("movq $handler_0x1f,%0" : "=ri"(isr_info[0x1f].addr) : );
+               // Map local APIC in.
+               os::paging::map_page<0, 3>(os::paging::global_PML4T,
+                       (os::paging::page<0>*)(0xFFFF'8000'fee0'0000),
+                       os::phys_ptr<os::paging::page<0>>(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<const multiboot2::info_s
                                );
                                break;
                        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++) {
-                                       if (multiboot2::memory_map_type(it, i) == 1) {
-                                               // Rounded up, to avoid including non-ram.
-                                               const os::phys_ptr<os::paging::page<0>>
-                                                       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<0>>
-                                                       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<os::paging::page<0>> s{multiboot2::memory_map_base_addr(it, i)};
+                                       const os::phys_ptr<os::paging::page<0>> 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<const multiboot2::info_s
                os::assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
 
                // kernel_start and kernel_end are aligned to 4K by the linker script.
-               const os::phys_ptr<os::paging::page<0>> kernel_s = ([]() {
-                       os::phys_ptr<os::paging::page<0>> ptr = nullptr;
-                       asm("mov $_kernel_phys_start,%0" : "=ri"(ptr));
-                       return ptr;
-               })();
-               const os::phys_ptr<os::paging::page<0>> kernel_e = ([]() {
-                       os::phys_ptr<os::paging::page<0>> ptr = nullptr;
-                       asm("mov $_kernel_phys_end,%0" : "=ri"(ptr));
-                       return ptr - 1; // [s, e], not [s, e[
-               })();
+               const os::phys_ptr<os::paging::page<0>> kernel_s{std::size_t(&_kernel_phys_start)};
+               const os::phys_ptr<os::paging::page<0>> kernel_e{std::size_t(&_kernel_phys_end)};
 
                // Remove kernel from available RAM:
                for (std::size_t i = 0; i < available_ram_length; i++) {