Explorar o código

Kernel: Parse boot modules from Multiboot specification

Jean-Baptiste Boric %!s(int64=4) %!d(string=hai) anos
pai
achega
ec056f3bd1
Modificáronse 4 ficheiros con 68 adicións e 15 borrados
  1. 8 0
      Kernel/Multiboot.h
  2. 31 14
      Kernel/VM/MemoryManager.cpp
  3. 24 0
      Kernel/VM/MemoryManager.h
  4. 5 1
      Kernel/init.cpp

+ 8 - 0
Kernel/Multiboot.h

@@ -28,6 +28,14 @@
 
 #include <AK/Types.h>
 
+struct multiboot_module_entry {
+    u32 start;
+    u32 end;
+    u32 string_addr;
+    u32 reserved;
+};
+typedef struct multiboot_module_entry multiboot_module_entry_t;
+
 struct multiboot_aout_symbol_table {
     u32 tabsize;
     u32 strsize;

+ 31 - 14
Kernel/VM/MemoryManager.cpp

@@ -64,6 +64,11 @@ namespace Kernel {
 static MemoryManager* s_the;
 RecursiveSpinLock s_mm_lock;
 
+const LogStream& operator<<(const LogStream& stream, const UsedMemoryRange& value)
+{
+    return stream << UserMemoryRangeTypeNames[static_cast<int>(value.type)] << " range @ " << value.start << " - " << value.end;
+}
+
 MemoryManager& MM
 {
     return *s_the;
@@ -122,25 +127,37 @@ void MemoryManager::parse_memory_map()
 {
     RefPtr<PhysicalRegion> region;
 
-    // We need to make sure we exclude the kmalloc range as well as the kernel image.
-    // The kmalloc range directly follows the kernel image
-    const PhysicalAddress used_range_start(virtual_to_low_physical(FlatPtr(&start_of_kernel_image)));
-    const PhysicalAddress used_range_end(virtual_to_low_physical(FlatPtr(&end_of_kernel_image)));
-    klog() << "MM: kernel range: " << used_range_start << " - " << used_range_end;
+    // Register used memory regions that we know of.
+    m_used_memory_ranges.ensure_capacity(4);
+    m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::LowMemory, PhysicalAddress(0x00000000), PhysicalAddress(1 * MiB) });
+    m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::Kernel, PhysicalAddress(virtual_to_low_physical(FlatPtr(&start_of_kernel_image))), PhysicalAddress(PAGE_ROUND_UP(virtual_to_low_physical(FlatPtr(&end_of_kernel_image)))) });
 
-    auto* mmap = (multiboot_memory_map_t*)(low_physical_to_virtual(multiboot_info_ptr->mmap_addr));
-    for (; (unsigned long)mmap < (low_physical_to_virtual(multiboot_info_ptr->mmap_addr)) + (multiboot_info_ptr->mmap_length); mmap = (multiboot_memory_map_t*)((unsigned long)mmap + mmap->size + sizeof(mmap->size))) {
-        klog() << "MM: Multiboot mmap: base_addr = " << String::format("0x%08llx", mmap->addr) << ", length = " << String::format("0x%08llx", mmap->len) << ", type = 0x" << String::format("%x", mmap->type);
-        if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
-            continue;
+    if (multiboot_info_ptr->flags & 0x4) {
+        auto* bootmods_start = multiboot_copy_boot_modules_array;
+        auto* bootmods_end = bootmods_start + multiboot_copy_boot_modules_count;
 
-        // FIXME: Maybe make use of stuff below the 1MiB mark?
-        if (mmap->addr < (1 * MiB))
+        for (auto* bootmod = bootmods_start; bootmod < bootmods_end; bootmod++) {
+            m_used_memory_ranges.append(UsedMemoryRange { UsedMemoryRangeType::BootModule, PhysicalAddress(bootmod->start), PhysicalAddress(bootmod->end) });
+        }
+    }
+
+    auto* mmap_begin = reinterpret_cast<multiboot_memory_map_t*>(low_physical_to_virtual(multiboot_info_ptr->mmap_addr));
+    auto* mmap_end = reinterpret_cast<multiboot_memory_map_t*>(low_physical_to_virtual(multiboot_info_ptr->mmap_addr) + multiboot_info_ptr->mmap_length);
+
+    for (auto used_range : m_used_memory_ranges) {
+        klog() << "MM: " << used_range;
+    }
+
+    for (auto* mmap = mmap_begin; mmap < mmap_end; mmap++) {
+        klog() << "MM: Multiboot mmap: address = " << String::format("0x%016llx", mmap->addr) << ", length = " << String::format("0x%016llx", mmap->len) << ", type = 0x" << String::format("%x", mmap->type);
+
+        if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE)
             continue;
 
         if ((mmap->addr + mmap->len) > 0xffffffff)
             continue;
 
+        // Fix up unaligned memory regions.
         auto diff = (FlatPtr)mmap->addr % PAGE_SIZE;
         if (diff != 0) {
             klog() << "MM: got an unaligned region base from the bootloader; correcting " << String::format("%p", (void*)mmap->addr) << " by " << diff << " bytes";
@@ -188,12 +205,12 @@ void MemoryManager::parse_memory_map()
 
     for (auto& region : m_super_physical_regions) {
         m_super_physical_pages += region.finalize_capacity();
-        klog() << "Super physical region: " << region.lower() << " - " << region.upper();
+        klog() << "MM: Super physical region: " << region.lower() << " - " << region.upper();
     }
 
     for (auto& region : m_user_physical_regions) {
         m_user_physical_pages += region.finalize_capacity();
-        klog() << "User physical region: " << region.lower() << " - " << region.upper();
+        klog() << "MM: User physical region: " << region.lower() << " - " << region.upper();
     }
 
     ASSERT(m_super_physical_pages > 0);

+ 24 - 0
Kernel/VM/MemoryManager.h

@@ -67,6 +67,26 @@ inline u32 virtual_to_low_physical(u32 physical)
 class KBuffer;
 class SynthFSInode;
 
+enum class UsedMemoryRangeType {
+    LowMemory = 0,
+    Kernel,
+    BootModule,
+};
+
+constexpr static const char* UserMemoryRangeTypeNames[] {
+    "Low memory",
+    "Kernel",
+    "Boot module",
+};
+
+struct UsedMemoryRange {
+    UsedMemoryRangeType type;
+    PhysicalAddress start;
+    PhysicalAddress end;
+};
+
+const LogStream& operator<<(const LogStream& stream, const UsedMemoryRange& value);
+
 #define MM Kernel::MemoryManager::the()
 
 struct MemoryManagerData {
@@ -93,6 +113,7 @@ public:
     static MemoryManager& the();
     static bool is_initialized();
 
+    static void early_initialize();
     static void initialize(u32 cpu);
 
     static inline MemoryManagerData& get_data()
@@ -165,6 +186,8 @@ public:
 
     PageDirectory& kernel_page_directory() { return *m_kernel_page_directory; }
 
+    const Vector<UsedMemoryRange>& used_memory_ranges() { return m_used_memory_ranges; }
+
 private:
     MemoryManager();
     ~MemoryManager();
@@ -221,6 +244,7 @@ private:
 
     InlineLinkedList<Region> m_user_regions;
     InlineLinkedList<Region> m_kernel_regions;
+    Vector<UsedMemoryRange> m_used_memory_ranges;
 
     InlineLinkedList<VMObject> m_vmobjects;
 

+ 5 - 1
Kernel/init.cpp

@@ -79,6 +79,9 @@ extern ctor_func_t end_ctors;
 extern u32 __stack_chk_guard;
 u32 __stack_chk_guard;
 
+multiboot_module_entry_t multiboot_copy_boot_modules_array[16];
+size_t multiboot_copy_boot_modules_count;
+
 namespace Kernel {
 
 [[noreturn]] static void init_stage2(void*);
@@ -111,7 +114,8 @@ extern "C" [[noreturn]] void init()
     // We need to copy the command line before kmalloc is initialized,
     // as it may overwrite parts of multiboot!
     CommandLine::early_initialize(reinterpret_cast<const char*>(low_physical_to_virtual(multiboot_info_ptr->cmdline)));
-
+    memcpy(multiboot_copy_boot_modules_array, (u8*)low_physical_to_virtual(multiboot_info_ptr->mods_addr), multiboot_info_ptr->mods_count * sizeof(multiboot_module_entry_t));
+    multiboot_copy_boot_modules_count = multiboot_info_ptr->mods_count;
     s_bsp_processor.early_initialize(0);
 
     // Invoke the constructors needed for the kernel heap