1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 10:27:35 +00:00

Kernel: More gracefully handle out-of-memory when creating PageDirectory

This commit is contained in:
Tom 2020-09-27 08:10:10 -06:00 committed by Andreas Kling
parent ae956edf6e
commit bf9be3ec01
3 changed files with 23 additions and 5 deletions

View file

@ -284,11 +284,15 @@ KResultOr<Process::LoadResult> Process::load(NonnullRefPtr<FileDescription> main
NonnullOwnPtrVector<Region> old_regions;
{
auto page_directory = PageDirectory::create_for_userspace(*this);
if (!page_directory)
return KResult(-ENOMEM);
// Need to make sure we don't swap contexts in the middle
ScopedCritical critical;
old_page_directory = move(m_page_directory);
old_regions = move(m_regions);
m_page_directory = PageDirectory::create_for_userspace(*this);
m_page_directory = page_directory.release_nonnull();
}
ArmedScopeGuard rollback_regions_guard([&]() {

View file

@ -74,7 +74,6 @@ PageDirectory::PageDirectory()
}
PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator)
: m_process(&process)
{
ScopedSpinLock lock(s_mm_lock);
if (parent_range_allocator) {
@ -87,9 +86,17 @@ PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_rang
// Set up a userspace page directory
m_directory_table = MM.allocate_user_physical_page();
if (!m_directory_table)
return;
m_directory_pages[0] = MM.allocate_user_physical_page();
if (!m_directory_pages[0])
return;
m_directory_pages[1] = MM.allocate_user_physical_page();
if (!m_directory_pages[1])
return;
m_directory_pages[2] = MM.allocate_user_physical_page();
if (!m_directory_pages[2])
return;
// Share the top 1 GiB of kernel-only mappings (>=3GiB or >=0xc0000000)
m_directory_pages[3] = MM.kernel_page_directory().m_directory_pages[3];
@ -135,6 +142,9 @@ PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_rang
auto* new_pd = MM.quickmap_pd(*this, 0);
memcpy(new_pd, &buffer, sizeof(PageDirectoryEntry));
// If we got here, we successfully created it. Set m_process now
m_process = &process;
cr3_map().set(cr3(), this);
}
@ -144,6 +154,7 @@ PageDirectory::~PageDirectory()
dbg() << "MM: ~PageDirectory K" << this;
#endif
ScopedSpinLock lock(s_mm_lock);
if (m_process)
cr3_map().remove(cr3());
}

View file

@ -40,9 +40,12 @@ class PageDirectory : public RefCounted<PageDirectory> {
friend class MemoryManager;
public:
static NonnullRefPtr<PageDirectory> create_for_userspace(Process& process, const RangeAllocator* parent_range_allocator = nullptr)
static RefPtr<PageDirectory> create_for_userspace(Process& process, const RangeAllocator* parent_range_allocator = nullptr)
{
return adopt(*new PageDirectory(process, parent_range_allocator));
auto page_directory = adopt(*new PageDirectory(process, parent_range_allocator));
if (!page_directory->process())
return {};
return page_directory;
}
static NonnullRefPtr<PageDirectory> create_kernel_page_directory() { return adopt(*new PageDirectory); }
static RefPtr<PageDirectory> find_by_cr3(u32);