mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:07:35 +00:00
Add basic zero faults.
mmap() will now map uncommitted pages that get allocated and zeroed upon the first access. I also made /proc/PID/vm show number of "committed" bytes in each region. This is so cool! :^)
This commit is contained in:
parent
e88f306d07
commit
629c5be10b
5 changed files with 42 additions and 7 deletions
|
@ -224,6 +224,24 @@ Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MemoryManager::zero_page(PageDirectory& page_directory, Region& region, unsigned page_index_in_region)
|
||||||
|
{
|
||||||
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
auto& vmo = region.vmo();
|
||||||
|
auto physical_page = allocate_physical_page();
|
||||||
|
byte* dest_ptr = quickmap_page(*physical_page);
|
||||||
|
memset(dest_ptr, 0, PAGE_SIZE);
|
||||||
|
#ifdef PAGE_FAULT_DEBUG
|
||||||
|
dbgprintf(" >> ZERO P%x\n", physical_page->paddr().get());
|
||||||
|
#endif
|
||||||
|
unquickmap_page();
|
||||||
|
region.cow_map.set(page_index_in_region, false);
|
||||||
|
vmo.physical_pages()[page_index_in_region] = move(physical_page);
|
||||||
|
unquickmap_page();
|
||||||
|
remap_region_page(&page_directory, region, page_index_in_region, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MemoryManager::copy_on_write(Process& process, Region& region, unsigned page_index_in_region)
|
bool MemoryManager::copy_on_write(Process& process, Region& region, unsigned page_index_in_region)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
@ -325,7 +343,9 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault)
|
||||||
page_in_from_vnode(*current->m_page_directory, *region, page_index_in_region);
|
page_in_from_vnode(*current->m_page_directory, *region, page_index_in_region);
|
||||||
return PageFaultResponse::Continue;
|
return PageFaultResponse::Continue;
|
||||||
} else {
|
} else {
|
||||||
kprintf("NP(error) fault in Region{%p}[%u]\n", region, page_index_in_region);
|
dbgprintf("NP(zero) fault in Region{%p}[%u]\n", region, page_index_in_region);
|
||||||
|
zero_page(*current->m_page_directory, *region, page_index_in_region);
|
||||||
|
return PageFaultResponse::Continue;
|
||||||
}
|
}
|
||||||
} else if (fault.is_protection_violation()) {
|
} else if (fault.is_protection_violation()) {
|
||||||
if (region->cow_map.get(page_index_in_region)) {
|
if (region->cow_map.get(page_index_in_region)) {
|
||||||
|
@ -761,3 +781,13 @@ inline bool PageDirectory::is_active() const
|
||||||
{
|
{
|
||||||
return ¤t->page_directory() == this;
|
return ¤t->page_directory() == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Region::committed() const
|
||||||
|
{
|
||||||
|
size_t bytes = 0;
|
||||||
|
for (size_t i = 0; i < page_count(); ++i) {
|
||||||
|
if (m_vmo->physical_pages()[first_page_index() + i])
|
||||||
|
bytes += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
|
@ -132,6 +132,8 @@ public:
|
||||||
int commit(Process&);
|
int commit(Process&);
|
||||||
int decommit(Process&);
|
int decommit(Process&);
|
||||||
|
|
||||||
|
size_t committed() const;
|
||||||
|
|
||||||
LinearAddress linearAddress;
|
LinearAddress linearAddress;
|
||||||
size_t size { 0 };
|
size_t size { 0 };
|
||||||
size_t m_offset_in_vmo { 0 };
|
size_t m_offset_in_vmo { 0 };
|
||||||
|
@ -209,6 +211,7 @@ private:
|
||||||
|
|
||||||
bool copy_on_write(Process&, Region&, unsigned page_index_in_region);
|
bool copy_on_write(Process&, Region&, unsigned page_index_in_region);
|
||||||
bool page_in_from_vnode(PageDirectory&, Region&, unsigned page_index_in_region);
|
bool page_in_from_vnode(PageDirectory&, Region&, unsigned page_index_in_region);
|
||||||
|
bool zero_page(PageDirectory&, Region& region, unsigned page_index_in_region);
|
||||||
|
|
||||||
byte* quickmap_page(PhysicalPage&);
|
byte* quickmap_page(PhysicalPage&);
|
||||||
void unquickmap_page();
|
void unquickmap_page();
|
||||||
|
|
|
@ -52,12 +52,13 @@ ByteBuffer procfs$pid_vm(Process& process)
|
||||||
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 160 + 4096, buffer);
|
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 160 + 4096, buffer);
|
||||||
memset(buffer, 0, stringImpl->length());
|
memset(buffer, 0, stringImpl->length());
|
||||||
char* ptr = buffer;
|
char* ptr = buffer;
|
||||||
ptr += ksprintf(ptr, "BEGIN END SIZE NAME\n");
|
ptr += ksprintf(ptr, "BEGIN END SIZE COMMIT NAME\n");
|
||||||
for (auto& region : process.regions()) {
|
for (auto& region : process.regions()) {
|
||||||
ptr += ksprintf(ptr, "%x -- %x %x %s\n",
|
ptr += ksprintf(ptr, "%x -- %x %x %x %s\n",
|
||||||
region->linearAddress.get(),
|
region->linearAddress.get(),
|
||||||
region->linearAddress.offset(region->size - 1).get(),
|
region->linearAddress.offset(region->size - 1).get(),
|
||||||
region->size,
|
region->size,
|
||||||
|
region->committed(),
|
||||||
region->name.characters());
|
region->name.characters());
|
||||||
}
|
}
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
|
@ -65,7 +65,7 @@ Vector<Process*> Process::allProcesses()
|
||||||
return processes;
|
return processes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name, bool is_readable, bool is_writable)
|
Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name, bool is_readable, bool is_writable, bool commit)
|
||||||
{
|
{
|
||||||
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
||||||
if (laddr.is_null()) {
|
if (laddr.is_null()) {
|
||||||
|
@ -74,7 +74,8 @@ Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name
|
||||||
}
|
}
|
||||||
laddr.mask(0xfffff000);
|
laddr.mask(0xfffff000);
|
||||||
m_regions.append(adopt(*new Region(laddr, size, move(name), is_readable, is_writable)));
|
m_regions.append(adopt(*new Region(laddr, size, move(name), is_readable, is_writable)));
|
||||||
m_regions.last()->commit(*this);
|
if (commit)
|
||||||
|
m_regions.last()->commit(*this);
|
||||||
MM.mapRegion(*this, *m_regions.last());
|
MM.mapRegion(*this, *m_regions.last());
|
||||||
return m_regions.last().ptr();
|
return m_regions.last().ptr();
|
||||||
}
|
}
|
||||||
|
@ -161,7 +162,7 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
// FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
|
// FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
|
||||||
ASSERT(addr == nullptr);
|
ASSERT(addr == nullptr);
|
||||||
auto* region = allocate_region(LinearAddress(), size, "mmap", prot & PROT_READ, prot & PROT_WRITE);
|
auto* region = allocate_region(LinearAddress(), size, "mmap", prot & PROT_READ, prot & PROT_WRITE, false);
|
||||||
if (!region)
|
if (!region)
|
||||||
return (void*)-ENOMEM;
|
return (void*)-ENOMEM;
|
||||||
return region->linearAddress.asPtr();
|
return region->linearAddress.asPtr();
|
||||||
|
|
|
@ -283,7 +283,7 @@ private:
|
||||||
|
|
||||||
TTY* m_tty { nullptr };
|
TTY* m_tty { nullptr };
|
||||||
|
|
||||||
Region* allocate_region(LinearAddress, size_t, String&& name, bool is_readable = true, bool is_writable = true);
|
Region* allocate_region(LinearAddress, size_t, String&& name, bool is_readable = true, bool is_writable = true, bool commit = true);
|
||||||
Region* allocate_file_backed_region(LinearAddress, size_t, RetainPtr<Vnode>&& vnode, String&& name, bool is_readable, bool is_writable);
|
Region* allocate_file_backed_region(LinearAddress, size_t, RetainPtr<Vnode>&& vnode, String&& name, bool is_readable, bool is_writable);
|
||||||
Region* allocate_region_with_vmo(LinearAddress, size_t, RetainPtr<VMObject>&&, size_t offset_in_vmo, String&& name, bool is_readable, bool is_writable);
|
Region* allocate_region_with_vmo(LinearAddress, size_t, RetainPtr<VMObject>&&, size_t offset_in_vmo, String&& name, bool is_readable, bool is_writable);
|
||||||
bool deallocate_region(Region& region);
|
bool deallocate_region(Region& region);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue