diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-11-19 02:17:20 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-11-19 02:17:20 +0100 |
commit | 629c5be10b00dd4d8e5675018e9282b84a9586e3 (patch) | |
tree | c90856617dceed5145f5154e99f7c4ca0d625e92 /Kernel | |
parent | e88f306d07225486c4f699d69dbfe39d79028586 (diff) | |
download | serenity-629c5be10b00dd4d8e5675018e9282b84a9586e3.zip |
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! :^)
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/MemoryManager.cpp | 32 | ||||
-rw-r--r-- | Kernel/MemoryManager.h | 3 | ||||
-rw-r--r-- | Kernel/ProcFileSystem.cpp | 5 | ||||
-rw-r--r-- | Kernel/Process.cpp | 7 | ||||
-rw-r--r-- | Kernel/Process.h | 2 |
5 files changed, 42 insertions, 7 deletions
diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index e3416bcb22..a81b6767c3 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -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(); @@ -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)) { @@ -761,3 +781,13 @@ inline bool PageDirectory::is_active() const { 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; +} diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index a1230253ba..d68a458d01 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -132,6 +132,8 @@ public: int commit(Process&); int decommit(Process&); + size_t committed() const; + LinearAddress linearAddress; size_t size { 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 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(); diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 5ee814150b..460fbe6368 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -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'; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 8dd94efec1..34758bf2e8 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -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()) { @@ -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(); } @@ -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(); diff --git a/Kernel/Process.h b/Kernel/Process.h index e5d8929228..2a03dcd400 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -283,7 +283,7 @@ private: 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); |