forked from Bananymous/banan-os
Kernel/LibC: Implement mprotect
There may be some race conditions with this but i think this is good enough to start with
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> FileBackedRegion::create(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags)
|
||||
BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> FileBackedRegion::create(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags, int status_flags)
|
||||
{
|
||||
ASSERT(inode->mode().ifreg());
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Kernel
|
||||
if ((size > (size_t)inode->size() || (size_t)offset > (size_t)inode->size() - size))
|
||||
return BAN::Error::from_errno(EOVERFLOW);
|
||||
|
||||
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags);
|
||||
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags, status_flags);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<FileBackedRegion>::adopt(region_ptr);
|
||||
|
||||
TRY(region->initialize(address_range));
|
||||
|
||||
if (type == Type::PRIVATE && (flags & PageTable::Flags::ReadWrite))
|
||||
if (type == Type::PRIVATE)
|
||||
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
||||
|
||||
LockGuard _(inode->m_mutex);
|
||||
@@ -39,8 +39,8 @@ namespace Kernel
|
||||
return region;
|
||||
}
|
||||
|
||||
FileBackedRegion::FileBackedRegion(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, ssize_t size, Type type, PageTable::flags_t flags)
|
||||
: MemoryRegion(page_table, size, type, flags)
|
||||
FileBackedRegion::FileBackedRegion(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||
: MemoryRegion(page_table, size, type, flags, status_flags)
|
||||
, m_inode(inode)
|
||||
, m_offset(offset)
|
||||
{
|
||||
@@ -200,7 +200,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable& page_table)
|
||||
{
|
||||
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||
auto result = TRY(FileBackedRegion::create(m_inode, page_table, m_offset, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
||||
auto result = TRY(FileBackedRegion::create(m_inode, page_table, m_offset, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags, m_status_flags));
|
||||
|
||||
// non-dirty pages can go through demand paging
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> MemoryBackedRegion::create(PageTable& page_table, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags)
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> MemoryBackedRegion::create(PageTable& page_table, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags, int status_flags)
|
||||
{
|
||||
if (type != Type::PRIVATE)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags);
|
||||
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags, status_flags);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<MemoryBackedRegion>::adopt(region_ptr);
|
||||
@@ -19,8 +19,8 @@ namespace Kernel
|
||||
return region;
|
||||
}
|
||||
|
||||
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
||||
: MemoryRegion(page_table, size, type, flags)
|
||||
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||
: MemoryRegion(page_table, size, type, flags, status_flags)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Kernel
|
||||
ASSERT(&PageTable::current() == &m_page_table);
|
||||
|
||||
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
||||
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags, m_status_flags));
|
||||
|
||||
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
||||
{
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
||||
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||
: m_page_table(page_table)
|
||||
, m_size(size)
|
||||
, m_type(type)
|
||||
, m_flags(flags)
|
||||
, m_status_flags(status_flags)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,6 +50,25 @@ namespace Kernel
|
||||
return true;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> MemoryRegion::mprotect(PageTable::flags_t new_page_flags)
|
||||
{
|
||||
if (m_flags == new_page_flags)
|
||||
return {};
|
||||
|
||||
const size_t page_count = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE);
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
const vaddr_t vaddr = m_vaddr + i * PAGE_SIZE;
|
||||
const paddr_t paddr = m_page_table.physical_address_of(vaddr);
|
||||
if (paddr == 0)
|
||||
continue;
|
||||
m_page_table.map_page_at(paddr, vaddr, new_page_flags);
|
||||
}
|
||||
|
||||
m_flags = new_page_flags;
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<bool> MemoryRegion::allocate_page_containing(vaddr_t address, bool wants_write)
|
||||
{
|
||||
ASSERT(contains(address));
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Kernel
|
||||
else
|
||||
{
|
||||
const size_t page_count = size() / PAGE_SIZE;
|
||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
PageTable::with_fast_page(m_paddrs[i], [&] {
|
||||
memset(PageTable::fast_page_as_ptr(), 0, PAGE_SIZE);
|
||||
@@ -120,7 +120,7 @@ namespace Kernel
|
||||
auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), m_flags, m_preallocated, m_has_guard_pages));
|
||||
|
||||
const size_t page_count = size() / PAGE_SIZE;
|
||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
if (m_paddrs[i] == 0)
|
||||
continue;
|
||||
@@ -140,15 +140,17 @@ namespace Kernel
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
||||
BAN::ErrorOr<bool> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
||||
{
|
||||
ASSERT(!m_preallocated);
|
||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||
ASSERT(contains(vaddr));
|
||||
ASSERT(&PageTable::current() == &m_page_table);
|
||||
|
||||
if (m_preallocated)
|
||||
return false;
|
||||
|
||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
||||
ASSERT(m_paddrs[index] == 0);
|
||||
if (m_paddrs[index])
|
||||
return false;
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
@@ -159,7 +161,7 @@ namespace Kernel
|
||||
m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
|
||||
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
|
||||
|
||||
return {};
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user