mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 11:42:38 +03:00
326c6130a5
PageDirectory gets initialized step-by-step in PageDirectory::try_create_for_userspace(). This initialization may fail anywhere in this function - for example, we may not be able to allocate a directory table, in which case PageDirectory::try_create_for_userspace() will return a null pointer. We recognize this condition and early-return ENOMEM. However, at this point, we need to correctly destruct the only partially initialized PageDirectory. Previously, PageDirectory::~PageDirectory() would assume that the object it was destructing was always fully initialized. It now uses the new helper PageDirectory::is_cr3_initialized() to correctly recognize when the directory table was not yet initialized. This helper checks if the pointer to the directory table is null. Only if it is not null does the destructor try to fetch the directory table using PageDirectory::cr3().
80 lines
2.0 KiB
C++
80 lines
2.0 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/HashMap.h>
|
|
#include <AK/IntrusiveRedBlackTree.h>
|
|
#include <AK/RefCounted.h>
|
|
#include <AK/RefPtr.h>
|
|
#include <Kernel/Forward.h>
|
|
#include <Kernel/Memory/PhysicalPage.h>
|
|
#include <Kernel/Memory/VirtualRangeAllocator.h>
|
|
|
|
namespace Kernel::Memory {
|
|
|
|
class PageDirectory : public RefCounted<PageDirectory> {
|
|
friend class MemoryManager;
|
|
|
|
public:
|
|
static ErrorOr<NonnullRefPtr<PageDirectory>> try_create_for_userspace(VirtualRangeAllocator const* parent_range_allocator = nullptr);
|
|
static NonnullRefPtr<PageDirectory> must_create_kernel_page_directory();
|
|
static RefPtr<PageDirectory> find_by_cr3(FlatPtr);
|
|
|
|
~PageDirectory();
|
|
|
|
void allocate_kernel_directory();
|
|
|
|
FlatPtr cr3() const
|
|
{
|
|
#if ARCH(X86_64)
|
|
return m_pml4t->paddr().get();
|
|
#else
|
|
return m_directory_table->paddr().get();
|
|
#endif
|
|
}
|
|
|
|
bool is_cr3_initialized() const
|
|
{
|
|
#if ARCH(X86_64)
|
|
return m_pml4t;
|
|
#else
|
|
return m_directory_table;
|
|
#endif
|
|
}
|
|
|
|
VirtualRangeAllocator& range_allocator() { return m_range_allocator; }
|
|
VirtualRangeAllocator const& range_allocator() const { return m_range_allocator; }
|
|
|
|
AddressSpace* address_space() { return m_space; }
|
|
const AddressSpace* address_space() const { return m_space; }
|
|
|
|
void set_space(Badge<AddressSpace>, AddressSpace& space) { m_space = &space; }
|
|
|
|
RecursiveSpinlock& get_lock() { return m_lock; }
|
|
|
|
// This has to be public to let the global singleton access the member pointer
|
|
IntrusiveRedBlackTreeNode<FlatPtr, PageDirectory, RawPtr<PageDirectory>> m_tree_node;
|
|
|
|
private:
|
|
PageDirectory();
|
|
|
|
AddressSpace* m_space { nullptr };
|
|
VirtualRangeAllocator m_range_allocator;
|
|
#if ARCH(X86_64)
|
|
RefPtr<PhysicalPage> m_pml4t;
|
|
#endif
|
|
RefPtr<PhysicalPage> m_directory_table;
|
|
#if ARCH(X86_64)
|
|
RefPtr<PhysicalPage> m_directory_pages[512];
|
|
#else
|
|
RefPtr<PhysicalPage> m_directory_pages[4];
|
|
#endif
|
|
RecursiveSpinlock m_lock;
|
|
};
|
|
|
|
}
|