diff --git a/Kernel/Multiboot.h b/Kernel/Multiboot.h index 1530e9e7bf..c38db14d94 100644 --- a/Kernel/Multiboot.h +++ b/Kernel/Multiboot.h @@ -28,6 +28,14 @@ #include +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; diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index a08c255fb6..6f69959a07 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/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(value.type)] << " range @ " << value.start << " - " << value.end; +} + MemoryManager& MM { return *s_the; @@ -122,25 +127,37 @@ void MemoryManager::parse_memory_map() { RefPtr 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)))) }); + + if (multiboot_info_ptr->flags & 0x4) { + auto* bootmods_start = multiboot_copy_boot_modules_array; + auto* bootmods_end = bootmods_start + multiboot_copy_boot_modules_count; + + 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(low_physical_to_virtual(multiboot_info_ptr->mmap_addr)); + auto* mmap_end = reinterpret_cast(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); - 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; - // FIXME: Maybe make use of stuff below the 1MiB mark? - if (mmap->addr < (1 * MiB)) - 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); diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index db8537dea0..1afd405a37 100644 --- a/Kernel/VM/MemoryManager.h +++ b/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& used_memory_ranges() { return m_used_memory_ranges; } + private: MemoryManager(); ~MemoryManager(); @@ -221,6 +244,7 @@ private: InlineLinkedList m_user_regions; InlineLinkedList m_kernel_regions; + Vector m_used_memory_ranges; InlineLinkedList m_vmobjects; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 669ea74efa..78aa94e2d4 100644 --- a/Kernel/init.cpp +++ b/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(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