diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Interrupts/APIC.cpp | 21 | ||||
-rw-r--r-- | Kernel/Memory/MemoryManager.cpp | 58 | ||||
-rw-r--r-- | Kernel/Memory/MemoryManager.h | 3 | ||||
-rw-r--r-- | Kernel/Memory/Region.cpp | 30 | ||||
-rw-r--r-- | Kernel/Memory/Region.h | 6 | ||||
-rw-r--r-- | Kernel/Memory/RegionTree.cpp | 21 | ||||
-rw-r--r-- | Kernel/Memory/RegionTree.h | 3 |
7 files changed, 85 insertions, 57 deletions
diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp index e54437c1fd..75bf6cecfd 100644 --- a/Kernel/Interrupts/APIC.cpp +++ b/Kernel/Interrupts/APIC.cpp @@ -319,19 +319,14 @@ UNMAP_AFTER_INIT bool APIC::init_bsp() return true; } -UNMAP_AFTER_INIT static NonnullOwnPtr<Memory::Region> create_identity_mapped_region(PhysicalAddress paddr, size_t size) +UNMAP_AFTER_INIT static ErrorOr<NonnullOwnPtr<Memory::Region>> create_identity_mapped_region(PhysicalAddress paddr, size_t size) { - auto maybe_vmobject = Memory::AnonymousVMObject::try_create_for_physical_range(paddr, size); - // FIXME: Would be nice to be able to return a ErrorOr from here. - VERIFY(!maybe_vmobject.is_error()); - - auto region_or_error = MM.allocate_kernel_region_with_vmobject( - Memory::VirtualRange { VirtualAddress { static_cast<FlatPtr>(paddr.get()) }, size }, - maybe_vmobject.release_value(), - {}, - Memory::Region::Access::ReadWriteExecute); - VERIFY(!region_or_error.is_error()); - return region_or_error.release_value(); + auto vmobject = TRY(Memory::AnonymousVMObject::try_create_for_physical_range(paddr, size)); + auto region = TRY(Memory::Region::create_unplaced(move(vmobject), 0, {}, Memory::Region::Access::ReadWriteExecute)); + Memory::VirtualRange range { VirtualAddress { paddr.get() }, size }; + TRY(MM.region_tree().place_specifically(*region, range)); + TRY(region->map(MM.kernel_page_directory())); + return region; } UNMAP_AFTER_INIT void APIC::setup_ap_boot_environment() @@ -347,7 +342,7 @@ UNMAP_AFTER_INIT void APIC::setup_ap_boot_environment() constexpr u64 apic_startup_region_base = 0x8000; auto apic_startup_region_size = Memory::page_round_up(apic_ap_start_size + (2 * aps_to_enable * sizeof(FlatPtr))).release_value_but_fixme_should_propagate_errors(); VERIFY(apic_startup_region_size < USER_RANGE_BASE); - auto apic_startup_region = create_identity_mapped_region(PhysicalAddress(apic_startup_region_base), apic_startup_region_size); + auto apic_startup_region = MUST(create_identity_mapped_region(PhysicalAddress(apic_startup_region_base), apic_startup_region_size)); u8* apic_startup_region_ptr = apic_startup_region->vaddr().as_ptr(); memcpy(apic_startup_region_ptr, reinterpret_cast<void const*>(apic_ap_start), apic_ap_start_size); diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index 874bc868a2..70bd903a44 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -451,16 +451,13 @@ UNMAP_AFTER_INIT void MemoryManager::initialize_physical_pages() // Carve out the whole page directory covering the kernel image to make MemoryManager::initialize_physical_pages() happy FlatPtr start_of_range = ((FlatPtr)start_of_kernel_image & ~(FlatPtr)0x1fffff); FlatPtr end_of_range = ((FlatPtr)end_of_kernel_image & ~(FlatPtr)0x1fffff) + 0x200000; - auto reserved_range = MUST(m_region_tree.try_allocate_specific(VirtualAddress(start_of_range), end_of_range - start_of_range)); - (void)MUST(Region::create_unbacked(reserved_range)).leak_ptr(); + MUST(m_region_tree.place_specifically(*MUST(Region::create_unbacked()).leak_ptr(), VirtualRange { VirtualAddress(start_of_range), end_of_range - start_of_range })); } // Allocate a virtual address range for our array + // This looks awkward, but it basically creates a dummy region to occupy the address range permanently. auto range = MUST(m_region_tree.try_allocate_anywhere(physical_page_array_pages * PAGE_SIZE)); - - { - (void)MUST(Region::create_unbacked(range)).leak_ptr(); - } + MUST(m_region_tree.place_specifically(*MUST(Region::create_unbacked()).leak_ptr(), range)); // Now that we have our special m_physical_pages_region region with enough pages to hold the entire array // try to map the entire region into kernel space so we always have it @@ -770,10 +767,14 @@ PageFaultResponse MemoryManager::handle_page_fault(PageFault const& fault) ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_contiguous_kernel_region(size_t size, StringView name, Region::Access access, Region::Cacheable cacheable) { VERIFY(!(size % PAGE_SIZE)); - SpinlockLocker lock(kernel_page_directory().get_lock()); + OwnPtr<KString> name_kstring; + if (!name.is_null()) + name_kstring = TRY(KString::try_create(name)); auto vmobject = TRY(AnonymousVMObject::try_create_physically_contiguous_with_size(size)); - auto range = TRY(m_region_tree.try_allocate_anywhere(size)); - return allocate_kernel_region_with_vmobject(range, move(vmobject), name, access, cacheable); + auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); + TRY(m_region_tree.place_anywhere(*region, size)); + TRY(region->map(kernel_page_directory())); + return region; } ErrorOr<NonnullOwnPtr<Memory::Region>> MemoryManager::allocate_dma_buffer_page(StringView name, Memory::Region::Access access, RefPtr<Memory::PhysicalPage>& dma_buffer_page) @@ -809,27 +810,25 @@ ErrorOr<NonnullOwnPtr<Memory::Region>> MemoryManager::allocate_dma_buffer_pages( ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region(size_t size, StringView name, Region::Access access, AllocationStrategy strategy, Region::Cacheable cacheable) { VERIFY(!(size % PAGE_SIZE)); + OwnPtr<KString> name_kstring; + if (!name.is_null()) + name_kstring = TRY(KString::try_create(name)); auto vmobject = TRY(AnonymousVMObject::try_create_with_size(size, strategy)); - SpinlockLocker lock(kernel_page_directory().get_lock()); - auto range = TRY(m_region_tree.try_allocate_anywhere(size)); - return allocate_kernel_region_with_vmobject(range, move(vmobject), name, access, cacheable); + auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); + TRY(m_region_tree.place_anywhere(*region, size)); + TRY(region->map(kernel_page_directory())); + return region; } ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region(PhysicalAddress paddr, size_t size, StringView name, Region::Access access, Region::Cacheable cacheable) { VERIFY(!(size % PAGE_SIZE)); auto vmobject = TRY(AnonymousVMObject::try_create_for_physical_range(paddr, size)); - SpinlockLocker lock(kernel_page_directory().get_lock()); - auto range = TRY(m_region_tree.try_allocate_anywhere(size)); - return allocate_kernel_region_with_vmobject(range, move(vmobject), name, access, cacheable); -} - -ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region_with_vmobject(VirtualRange const& range, VMObject& vmobject, StringView name, Region::Access access, Region::Cacheable cacheable) -{ OwnPtr<KString> name_kstring; if (!name.is_null()) name_kstring = TRY(KString::try_create(name)); - auto region = TRY(Region::try_create_kernel_only(range, vmobject, 0, move(name_kstring), access, cacheable)); + auto region = TRY(Region::create_unplaced(move(vmobject), 0, move(name_kstring), access, cacheable)); + TRY(m_region_tree.place_anywhere(*region, size, PAGE_SIZE)); TRY(region->map(kernel_page_directory())); return region; } @@ -837,9 +836,15 @@ ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region_with_vmobje ErrorOr<NonnullOwnPtr<Region>> MemoryManager::allocate_kernel_region_with_vmobject(VMObject& vmobject, size_t size, StringView name, Region::Access access, Region::Cacheable cacheable) { VERIFY(!(size % PAGE_SIZE)); - SpinlockLocker lock(kernel_page_directory().get_lock()); - auto range = TRY(m_region_tree.try_allocate_anywhere(size)); - return allocate_kernel_region_with_vmobject(range, vmobject, name, access, cacheable); + + OwnPtr<KString> name_kstring; + if (!name.is_null()) + name_kstring = TRY(KString::try_create(name)); + + auto region = TRY(Region::create_unplaced(vmobject, 0, move(name_kstring), access, cacheable)); + TRY(m_region_tree.place_anywhere(*region, size)); + TRY(region->map(kernel_page_directory())); + return region; } ErrorOr<CommittedPhysicalPageSet> MemoryManager::commit_user_physical_pages(size_t page_count) @@ -1157,13 +1162,6 @@ bool MemoryManager::validate_user_stack(AddressSpace& space, VirtualAddress vadd return validate_user_stack_no_lock(space, vaddr); } -void MemoryManager::register_kernel_region(Region& region) -{ - VERIFY(region.is_kernel()); - SpinlockLocker lock(s_mm_lock); - m_region_tree.regions().insert(region.vaddr().get(), region); -} - void MemoryManager::unregister_kernel_region(Region& region) { VERIFY(region.is_kernel()); diff --git a/Kernel/Memory/MemoryManager.h b/Kernel/Memory/MemoryManager.h index cac1fdce23..f7b63b658e 100644 --- a/Kernel/Memory/MemoryManager.h +++ b/Kernel/Memory/MemoryManager.h @@ -135,6 +135,7 @@ class MemoryManager { friend class PageDirectory; friend class AnonymousVMObject; friend class Region; + friend class RegionTree; friend class VMObject; friend struct ::KmallocGlobalData; @@ -187,7 +188,6 @@ public: ErrorOr<NonnullOwnPtr<Region>> allocate_kernel_region(size_t, StringView name, Region::Access access, AllocationStrategy strategy = AllocationStrategy::Reserve, Region::Cacheable = Region::Cacheable::Yes); ErrorOr<NonnullOwnPtr<Region>> allocate_kernel_region(PhysicalAddress, size_t, StringView name, Region::Access access, Region::Cacheable = Region::Cacheable::Yes); ErrorOr<NonnullOwnPtr<Region>> allocate_kernel_region_with_vmobject(VMObject&, size_t, StringView name, Region::Access access, Region::Cacheable = Region::Cacheable::Yes); - ErrorOr<NonnullOwnPtr<Region>> allocate_kernel_region_with_vmobject(VirtualRange const&, VMObject&, StringView name, Region::Access access, Region::Cacheable = Region::Cacheable::Yes); struct SystemMemoryInfo { PhysicalSize user_physical_pages { 0 }; @@ -255,7 +255,6 @@ private: void initialize_physical_pages(); void register_reserved_ranges(); - void register_kernel_region(Region&); void unregister_kernel_region(Region&); void protect_kernel_image(); diff --git a/Kernel/Memory/Region.cpp b/Kernel/Memory/Region.cpp index 69d48bbea1..57b74b8d23 100644 --- a/Kernel/Memory/Region.cpp +++ b/Kernel/Memory/Region.cpp @@ -22,11 +22,21 @@ namespace Kernel::Memory { -Region::Region(VirtualRange const& range) - : m_range(range) +Region::Region() + : m_range(VirtualRange({}, 0)) { - if (is_kernel()) - MM.register_kernel_region(*this); +} + +Region::Region(NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable cacheable, bool shared) + : m_range(VirtualRange({}, 0)) + , m_offset_in_vmobject(offset_in_vmobject) + , m_vmobject(move(vmobject)) + , m_name(move(name)) + , m_access(access | ((access & 0x7) << 4)) + , m_shared(shared) + , m_cacheable(cacheable == Cacheable::Yes) +{ + m_vmobject->add_region(*this); } Region::Region(VirtualRange const& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable cacheable, bool shared) @@ -43,9 +53,6 @@ Region::Region(VirtualRange const& range, NonnullRefPtr<VMObject> vmobject, size VERIFY((m_range.size() % PAGE_SIZE) == 0); m_vmobject->add_region(*this); - - if (is_kernel()) - MM.register_kernel_region(*this); } Region::~Region() @@ -72,9 +79,14 @@ Region::~Region() } } -ErrorOr<NonnullOwnPtr<Region>> Region::create_unbacked(VirtualRange const& range) +ErrorOr<NonnullOwnPtr<Region>> Region::create_unbacked() +{ + return adopt_nonnull_own_or_enomem(new (nothrow) Region); +} + +ErrorOr<NonnullOwnPtr<Region>> Region::create_unplaced(NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable cacheable) { - return adopt_nonnull_own_or_enomem(new (nothrow) Region(range)); + return adopt_nonnull_own_or_enomem(new (nothrow) Region(move(vmobject), offset_in_vmobject, move(name), access, cacheable, false)); } ErrorOr<NonnullOwnPtr<Region>> Region::try_clone() diff --git a/Kernel/Memory/Region.h b/Kernel/Memory/Region.h index bc73075c85..b3aff78d6e 100644 --- a/Kernel/Memory/Region.h +++ b/Kernel/Memory/Region.h @@ -56,7 +56,8 @@ public: static ErrorOr<NonnullOwnPtr<Region>> try_create_user_accessible(VirtualRange const&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable, bool shared); static ErrorOr<NonnullOwnPtr<Region>> try_create_kernel_only(VirtualRange const&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable = Cacheable::Yes); - static ErrorOr<NonnullOwnPtr<Region>> create_unbacked(VirtualRange const&); + static ErrorOr<NonnullOwnPtr<Region>> create_unbacked(); + static ErrorOr<NonnullOwnPtr<Region>> create_unplaced(NonnullRefPtr<VMObject>, size_t offset_in_vmobject, OwnPtr<KString> name, Region::Access access, Cacheable = Cacheable::Yes); ~Region(); @@ -199,7 +200,8 @@ public: void set_syscall_region(bool b) { m_syscall_region = b; } private: - explicit Region(VirtualRange const&); + Region(); + Region(NonnullRefPtr<VMObject>, size_t offset_in_vmobject, OwnPtr<KString>, Region::Access access, Cacheable, bool shared); Region(VirtualRange const&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, OwnPtr<KString>, Region::Access access, Cacheable, bool shared); [[nodiscard]] bool remap_vmobject_page(size_t page_index, bool with_flush = true); diff --git a/Kernel/Memory/RegionTree.cpp b/Kernel/Memory/RegionTree.cpp index 67d3ef1580..1dfa181b01 100644 --- a/Kernel/Memory/RegionTree.cpp +++ b/Kernel/Memory/RegionTree.cpp @@ -5,6 +5,7 @@ */ #include <AK/Format.h> +#include <Kernel/Memory/MemoryManager.h> #include <Kernel/Memory/RegionTree.h> #include <Kernel/Random.h> @@ -143,9 +144,27 @@ ErrorOr<VirtualRange> RegionTree::try_allocate_randomized(size_t size, size_t al ErrorOr<NonnullOwnPtr<Region>> RegionTree::allocate_unbacked_anywhere(size_t size, size_t alignment) { + auto region = TRY(Region::create_unbacked()); + TRY(place_anywhere(*region, size, alignment)); + return region; +} + +ErrorOr<void> RegionTree::place_anywhere(Region& region, size_t size, size_t alignment) +{ SpinlockLocker locker(m_lock); auto range = TRY(try_allocate_anywhere(size, alignment)); - return Region::create_unbacked(range); + region.m_range = range; + m_regions.insert(region.vaddr().get(), region); + return {}; +} + +ErrorOr<void> RegionTree::place_specifically(Region& region, VirtualRange const& range) +{ + SpinlockLocker locker(m_lock); + auto allocated_range = TRY(try_allocate_specific(range.base(), range.size())); + region.m_range = allocated_range; + m_regions.insert(region.vaddr().get(), region); + return {}; } } diff --git a/Kernel/Memory/RegionTree.h b/Kernel/Memory/RegionTree.h index 9a00db9f43..560a4f2aa0 100644 --- a/Kernel/Memory/RegionTree.h +++ b/Kernel/Memory/RegionTree.h @@ -34,6 +34,9 @@ public: ErrorOr<NonnullOwnPtr<Region>> allocate_unbacked_anywhere(size_t size, size_t alignment = PAGE_SIZE); + ErrorOr<void> place_anywhere(Region&, size_t size, size_t alignment = PAGE_SIZE); + ErrorOr<void> place_specifically(Region&, VirtualRange const&); + ErrorOr<VirtualRange> try_allocate_anywhere(size_t size, size_t alignment = PAGE_SIZE); ErrorOr<VirtualRange> try_allocate_specific(VirtualAddress base, size_t size); ErrorOr<VirtualRange> try_allocate_randomized(size_t size, size_t alignment = PAGE_SIZE); |