From ec056f3bd1a20a52b4d47815a24704c09abb92c5 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Tue, 19 Jan 2021 19:13:03 +0100 Subject: Kernel: Parse boot modules from Multiboot specification --- Kernel/VM/MemoryManager.cpp | 45 +++++++++++++++++++++++++++++++-------------- Kernel/VM/MemoryManager.h | 24 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 14 deletions(-) (limited to 'Kernel/VM') 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)))) }); - 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(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); + + 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); 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; -- cgit v1.2.3