summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-19 02:17:20 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-19 02:17:20 +0100
commit629c5be10b00dd4d8e5675018e9282b84a9586e3 (patch)
treec90856617dceed5145f5154e99f7c4ca0d625e92 /Kernel
parente88f306d07225486c4f699d69dbfe39d79028586 (diff)
downloadserenity-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.cpp32
-rw-r--r--Kernel/MemoryManager.h3
-rw-r--r--Kernel/ProcFileSystem.cpp5
-rw-r--r--Kernel/Process.cpp7
-rw-r--r--Kernel/Process.h2
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 &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;
+}
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);