Kernel: Implement MemoryRegion pinning

This allows process to pin a MemoryRegion into users memory space for
syscall duration without allowing user to munmap the region.
This commit is contained in:
Bananymous 2025-04-22 04:30:07 +03:00
parent 808c97020a
commit d54489bbcb
3 changed files with 12 additions and 2 deletions

View File

@ -3,8 +3,7 @@
#include <BAN/UniqPtr.h> #include <BAN/UniqPtr.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/Memory/Types.h> #include <kernel/Memory/Types.h>
#include <kernel/ThreadBlocker.h>
#include <stddef.h>
namespace Kernel namespace Kernel
{ {
@ -42,6 +41,10 @@ namespace Kernel
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); } size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
size_t physical_page_count() const { return m_physical_page_count; } size_t physical_page_count() const { return m_physical_page_count; }
void pin() { m_pinned_count++; }
void unpin() { if (--m_pinned_count == 0) m_pinned_blocker.unblock(); }
void wait_not_pinned() { while (m_pinned_count) m_pinned_blocker.block_with_timeout_ms(100); }
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0; virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
// Returns error if no memory was available // Returns error if no memory was available
@ -64,6 +67,9 @@ namespace Kernel
const PageTable::flags_t m_flags; const PageTable::flags_t m_flags;
vaddr_t m_vaddr { 0 }; vaddr_t m_vaddr { 0 };
size_t m_physical_page_count { 0 }; size_t m_physical_page_count { 0 };
BAN::Atomic<size_t> m_pinned_count { 0 };
ThreadBlocker m_pinned_blocker;
}; };
} }

View File

@ -13,6 +13,7 @@ namespace Kernel
MemoryRegion::~MemoryRegion() MemoryRegion::~MemoryRegion()
{ {
ASSERT(m_pinned_count == 0);
if (m_vaddr) if (m_vaddr)
m_page_table.unmap_range(m_vaddr, m_size); m_page_table.unmap_range(m_vaddr, m_size);
} }

View File

@ -1806,7 +1806,10 @@ namespace Kernel
const vaddr_t region_s = region->vaddr(); const vaddr_t region_s = region->vaddr();
const vaddr_t region_e = region->vaddr() + region->size(); const vaddr_t region_e = region->vaddr() + region->size();
if (vaddr <= region_s && region_e <= vaddr + len) if (vaddr <= region_s && region_e <= vaddr + len)
{
region->wait_not_pinned();
m_mapped_regions.remove(i--); m_mapped_regions.remove(i--);
}
else if (region->overlaps(vaddr, len)) else if (region->overlaps(vaddr, len))
dwarnln("TODO: partial region munmap"); dwarnln("TODO: partial region munmap");
} }