Skip to content

Commit

Permalink
Add basic zero faults.
Browse files Browse the repository at this point in the history
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! :^)
  • Loading branch information
awesomekling committed Nov 19, 2018
1 parent e88f306 commit 629c5be
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
32 changes: 31 additions & 1 deletion Kernel/MemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,24 @@ Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr)
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)
{
ASSERT_INTERRUPTS_DISABLED();
Expand Down Expand Up @@ -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);
return PageFaultResponse::Continue;
} 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()) {
if (region->cow_map.get(page_index_in_region)) {
Expand Down Expand Up @@ -761,3 +781,13 @@ inline bool PageDirectory::is_active() const
{
return &current->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;
}
3 changes: 3 additions & 0 deletions Kernel/MemoryManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class Region : public Retainable<Region> {
int commit(Process&);
int decommit(Process&);

size_t committed() const;

LinearAddress linearAddress;
size_t size { 0 };
size_t m_offset_in_vmo { 0 };
Expand Down Expand Up @@ -209,6 +211,7 @@ class MemoryManager {

bool copy_on_write(Process&, 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&);
void unquickmap_page();
Expand Down
5 changes: 3 additions & 2 deletions Kernel/ProcFileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,13 @@ ByteBuffer procfs$pid_vm(Process& process)
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 160 + 4096, buffer);
memset(buffer, 0, stringImpl->length());
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()) {
ptr += ksprintf(ptr, "%x -- %x %x %s\n",
ptr += ksprintf(ptr, "%x -- %x %x %x %s\n",
region->linearAddress.get(),
region->linearAddress.offset(region->size - 1).get(),
region->size,
region->committed(),
region->name.characters());
}
*ptr = '\0';
Expand Down
7 changes: 4 additions & 3 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Vector<Process*> Process::allProcesses()
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?
if (laddr.is_null()) {
Expand All @@ -74,7 +74,8 @@ Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name
}
laddr.mask(0xfffff000);
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());
return m_regions.last().ptr();
}
Expand Down Expand Up @@ -161,7 +162,7 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
InterruptDisabler disabler;
// FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
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)
return (void*)-ENOMEM;
return region->linearAddress.asPtr();
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class Process : public InlineLinkedListNode<Process> {

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_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);
Expand Down

0 comments on commit 629c5be

Please sign in to comment.