From 57abb03deb9f13d3b8195d29d22791551c5ca7ba Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 21 Apr 2018 17:34:33 -0700 Subject: [PATCH] Rearrange memory manager into two classes. page_manager and memory_manager are now separate, and are also pre allocated in the kernel so they don't have to allocate themselves. --- src/kernel/main.cpp | 2 +- src/kernel/memory.cpp | 5 ++-- src/kernel/memory.h | 22 ++++++++------- src/kernel/memory_bootstrap.cpp | 2 +- src/kernel/memory_pages.cpp | 18 ++++++++---- src/kernel/memory_pages.h | 49 +++++++++++++++++++++++++-------- 6 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 9e5ca8f..3e6ff73 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -42,7 +42,7 @@ kernel_main(popcorn_data *header) { console cons = load_console(header); - memory_manager::create( + memory_initialize_managers( header->memory_map, header->memory_map_length, header->memory_map_desc_size); diff --git a/src/kernel/memory.cpp b/src/kernel/memory.cpp index 2cbbc85..2a99900 100644 --- a/src/kernel/memory.cpp +++ b/src/kernel/memory.cpp @@ -3,8 +3,9 @@ #include "memory.h" #include "memory_pages.h" -memory_manager *memory_manager::s_instance = nullptr; +memory_manager g_memory_manager; -memory_manager::memory_manager(page_block *free, page_block *used, void *scratch, size_t scratch_len) +memory_manager::memory_manager() { + kassert(this == &g_memory_manager, "Attempt to create another memory_manager."); } diff --git a/src/kernel/memory.h b/src/kernel/memory.h index f7af2c5..0df400d 100644 --- a/src/kernel/memory.h +++ b/src/kernel/memory.h @@ -1,21 +1,23 @@ #pragma once +/// \file memory.h +/// The block memory manager and related definitions. #include -struct page_block; - +/// Manager for allocation of virtual memory. class memory_manager { public: + memory_manager(); - static void create(const void *memory_map, size_t map_length, size_t desc_length); - static memory_manager * get() { return s_instance; } - -private: - memory_manager(page_block *free, page_block *used, void *scratch, size_t scratch_len); - - memory_manager() = delete; memory_manager(const memory_manager &) = delete; - static memory_manager * s_instance; +private: + friend class page_manager; }; + +extern memory_manager g_memory_manager; + +/// Bootstrap the memory managers. +void memory_initialize_managers(const void *memory_map, size_t map_length, size_t desc_length); + diff --git a/src/kernel/memory_bootstrap.cpp b/src/kernel/memory_bootstrap.cpp index 77af51d..d26e5ea 100644 --- a/src/kernel/memory_bootstrap.cpp +++ b/src/kernel/memory_bootstrap.cpp @@ -227,7 +227,7 @@ gather_block_lists( } void -memory_manager::create(const void *memory_map, size_t map_length, size_t desc_length) +memory_initialize_managers(const void *memory_map, size_t map_length, size_t desc_length) { console *cons = console::get(); diff --git a/src/kernel/memory_pages.cpp b/src/kernel/memory_pages.cpp index a4618a1..46db592 100644 --- a/src/kernel/memory_pages.cpp +++ b/src/kernel/memory_pages.cpp @@ -1,13 +1,23 @@ +#include "assert.h" #include "console.h" #include "memory_pages.h" +page_manager g_page_manager; + +page_manager::page_manager() : + m_free(nullptr), + m_used(nullptr), + m_pool(nullptr) +{ + kassert(this == &g_page_manager, "Attempt to create another page_manager."); +} + + page_block * page_block::list_consolidate() { - page_block *cur = this; page_block *freed_head = nullptr, **freed = &freed_head; - - while (cur) { + for (page_block *cur = this; cur; cur = cur->next) { page_block *next = cur->next; if (next && cur->flags == next->flags && @@ -21,8 +31,6 @@ page_block::list_consolidate() freed = &next->next; continue; } - - cur = next; } return freed_head; diff --git a/src/kernel/memory_pages.h b/src/kernel/memory_pages.h index e3558e5..1523abf 100644 --- a/src/kernel/memory_pages.h +++ b/src/kernel/memory_pages.h @@ -1,25 +1,51 @@ #pragma once /// \file memory_pages.h -/// Structures related to handling memory paging. +/// The page memory manager and related definitions. #include #include "kutil/enum_bitfields.h" +class page_block; + + +/// Manager for allocation of physical pages. +class page_manager +{ +public: + page_manager(); + + page_manager(const page_manager &) = delete; + +private: + friend void memory_initialize_managers(const void *, size_t, size_t); + + /// Set up the memory manager from bootstraped memory + static void init(page_block *free, page_block *used, uint64_t scratch); + + /// Initialize the virtual memory manager based on this object's state + void init_memory_manager(); + + page_block *m_free; ///< Free pages list + page_block *m_used; ///< In-use pages list + page_block *m_pool; ///< Cache of unused page_block structs +}; + +/// Global page manager. +extern page_manager g_page_manager; + + /// Flags used by `page_block`. enum class page_block_flags : uint32_t { - // Not a flag value, but for comparison - free = 0x00000000, + free = 0x00000000, ///< Not a flag, value for free memory + used = 0x00000001, ///< Memory is in use + mapped = 0x00000002, ///< Memory is mapped to virtual address + pending_free = 0x00000004, ///< Memory should be freed - used = 0x00000001, - mapped = 0x00000002, - pending_free = 0x00000004, - - nonvolatile = 0x00000010, - acpi_wait = 0x00000020, - - permanent = 0x80000000, + nonvolatile = 0x00000010, ///< Memory is non-volatile storage + acpi_wait = 0x00000020, ///< Memory should be freed after ACPI init + permanent = 0x80000000, ///< Memory is permanently unusable max_flags }; @@ -67,6 +93,7 @@ struct page_table_indices uint64_t index[4]; ///< Indices for each level of tables. }; + /// Calculate a page-aligned address. /// \arg p The address to align. /// \returns The next page-aligned address _after_ `p`.