mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 10:37:41 +00:00
Kernel: More gracefully handle out-of-memory when creating PageDirectory
This commit is contained in:
parent
ae956edf6e
commit
bf9be3ec01
3 changed files with 23 additions and 5 deletions
|
@ -284,11 +284,15 @@ KResultOr<Process::LoadResult> Process::load(NonnullRefPtr<FileDescription> main
|
||||||
NonnullOwnPtrVector<Region> old_regions;
|
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
|
// Need to make sure we don't swap contexts in the middle
|
||||||
ScopedCritical critical;
|
ScopedCritical critical;
|
||||||
old_page_directory = move(m_page_directory);
|
old_page_directory = move(m_page_directory);
|
||||||
old_regions = move(m_regions);
|
old_regions = move(m_regions);
|
||||||
m_page_directory = PageDirectory::create_for_userspace(*this);
|
m_page_directory = page_directory.release_nonnull();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArmedScopeGuard rollback_regions_guard([&]() {
|
ArmedScopeGuard rollback_regions_guard([&]() {
|
||||||
|
|
|
@ -74,7 +74,6 @@ PageDirectory::PageDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator)
|
PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator)
|
||||||
: m_process(&process)
|
|
||||||
{
|
{
|
||||||
ScopedSpinLock lock(s_mm_lock);
|
ScopedSpinLock lock(s_mm_lock);
|
||||||
if (parent_range_allocator) {
|
if (parent_range_allocator) {
|
||||||
|
@ -87,9 +86,17 @@ PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_rang
|
||||||
|
|
||||||
// Set up a userspace page directory
|
// Set up a userspace page directory
|
||||||
m_directory_table = MM.allocate_user_physical_page();
|
m_directory_table = MM.allocate_user_physical_page();
|
||||||
|
if (!m_directory_table)
|
||||||
|
return;
|
||||||
m_directory_pages[0] = MM.allocate_user_physical_page();
|
m_directory_pages[0] = MM.allocate_user_physical_page();
|
||||||
|
if (!m_directory_pages[0])
|
||||||
|
return;
|
||||||
m_directory_pages[1] = MM.allocate_user_physical_page();
|
m_directory_pages[1] = MM.allocate_user_physical_page();
|
||||||
|
if (!m_directory_pages[1])
|
||||||
|
return;
|
||||||
m_directory_pages[2] = MM.allocate_user_physical_page();
|
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)
|
// Share the top 1 GiB of kernel-only mappings (>=3GiB or >=0xc0000000)
|
||||||
m_directory_pages[3] = MM.kernel_page_directory().m_directory_pages[3];
|
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);
|
auto* new_pd = MM.quickmap_pd(*this, 0);
|
||||||
memcpy(new_pd, &buffer, sizeof(PageDirectoryEntry));
|
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);
|
cr3_map().set(cr3(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +154,8 @@ PageDirectory::~PageDirectory()
|
||||||
dbg() << "MM: ~PageDirectory K" << this;
|
dbg() << "MM: ~PageDirectory K" << this;
|
||||||
#endif
|
#endif
|
||||||
ScopedSpinLock lock(s_mm_lock);
|
ScopedSpinLock lock(s_mm_lock);
|
||||||
cr3_map().remove(cr3());
|
if (m_process)
|
||||||
|
cr3_map().remove(cr3());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,12 @@ class PageDirectory : public RefCounted<PageDirectory> {
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
|
|
||||||
public:
|
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 NonnullRefPtr<PageDirectory> create_kernel_page_directory() { return adopt(*new PageDirectory); }
|
||||||
static RefPtr<PageDirectory> find_by_cr3(u32);
|
static RefPtr<PageDirectory> find_by_cr3(u32);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue