Kernel: VirtualRange creation can fail

This commit is contained in:
Bananymous 2023-07-19 17:56:26 +03:00
parent 5d2bfc858e
commit 66d9260257
1 changed files with 22 additions and 7 deletions

View File

@ -1,3 +1,4 @@
#include <BAN/ScopeGuard.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/VirtualRange.h> #include <kernel/Memory/VirtualRange.h>
@ -9,35 +10,49 @@ namespace Kernel
ASSERT(size % PAGE_SIZE == 0); ASSERT(size % PAGE_SIZE == 0);
ASSERT(vaddr % PAGE_SIZE == 0); ASSERT(vaddr % PAGE_SIZE == 0);
VirtualRange* result = new VirtualRange(page_table); VirtualRange* result_ptr = new VirtualRange(page_table);
ASSERT(result); if (result_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto result = BAN::UniqPtr<VirtualRange>::adopt(result_ptr);
result->m_kmalloc = false; result->m_kmalloc = false;
result->m_size = size; result->m_size = size;
result->m_flags = flags; result->m_flags = flags;
MUST(result->m_physical_pages.reserve(size / PAGE_SIZE)); TRY(result->m_physical_pages.reserve(size / PAGE_SIZE));
page_table.lock(); page_table.lock();
if (vaddr == 0) if (vaddr == 0)
{ {
vaddr = page_table.get_free_contiguous_pages(size / PAGE_SIZE, 0x300000); vaddr = page_table.get_free_contiguous_pages(size / PAGE_SIZE, 0x300000);
ASSERT(vaddr); if (vaddr == 0)
{
derrorln("out of virtual memory");
return BAN::Error::from_errno(ENOMEM);
}
} }
result->m_vaddr = vaddr; result->m_vaddr = vaddr;
ASSERT(page_table.is_range_free(vaddr, size)); ASSERT(page_table.is_range_free(vaddr, size));
TRY(result->m_physical_pages.reserve(size / PAGE_SIZE));
for (size_t offset = 0; offset < size; offset += PAGE_SIZE) for (size_t offset = 0; offset < size; offset += PAGE_SIZE)
{ {
paddr_t paddr = Heap::get().take_free_page(); paddr_t paddr = Heap::get().take_free_page();
ASSERT(paddr); if (paddr == 0)
{
for (paddr_t release : result->m_physical_pages)
Heap::get().release_page(release);
return BAN::Error::from_errno(ENOMEM);
}
MUST(result->m_physical_pages.push_back(paddr)); MUST(result->m_physical_pages.push_back(paddr));
page_table.map_page_at(paddr, vaddr + offset, flags); page_table.map_page_at(paddr, vaddr + offset, flags);
} }
page_table.unlock(); page_table.unlock();
return BAN::UniqPtr<VirtualRange>::adopt(result); return result;
} }
BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> VirtualRange::create_kmalloc(size_t size) BAN::ErrorOr<BAN::UniqPtr<VirtualRange>> VirtualRange::create_kmalloc(size_t size)
@ -52,7 +67,7 @@ namespace Kernel
if (result->m_vaddr == 0) if (result->m_vaddr == 0)
{ {
delete result; delete result;
return BAN::UniqPtr<VirtualRange>(); return BAN::Error::from_errno(ENOMEM);
} }
return BAN::UniqPtr<VirtualRange>::adopt(result); return BAN::UniqPtr<VirtualRange>::adopt(result);