From 6eab7b398d2ce658b56f2650c721454a4e41fa2b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 19 Jan 2020 13:44:53 +0100 Subject: [PATCH] Kernel: Make ProcessPagingScope restore CR3 properly Instead of restoring CR3 to the current process's paging scope when a ProcessPagingScope goes out of scope, we now restore exactly whatever the CR3 value was when we created the ProcessPagingScope. This fixes breakage in situations where a process ends up with nested ProcessPagingScopes. This was making profiling very fragile, and with this change it's now possible to profile g++! :^) --- Kernel/Process.cpp | 8 ++++---- Kernel/VM/MemoryManager.cpp | 7 ++++++- Kernel/VM/MemoryManager.h | 8 ++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 38a40b7a75..e663e23b1b 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -734,7 +734,8 @@ int Process::do_exec(NonnullRefPtr main_program_description, Ve #ifdef MM_DEBUG dbgprintf("Process %u exec: PD=%x created\n", pid(), m_page_directory.ptr()); #endif - ProcessPagingScope paging_scope(*this); + + MM.enter_process_paging_scope(*this); Region* region { nullptr }; @@ -775,11 +776,10 @@ int Process::do_exec(NonnullRefPtr main_program_description, Ve m_regions.append(move(executable_region)); ArmedScopeGuard rollback_regions_guard([&]() { - m_page_directory = move(old_page_directory); ASSERT(¤t->process() == this); - MM.enter_process_paging_scope(*this); - executable_region = m_regions.take_first(); + m_page_directory = move(old_page_directory); m_regions = move(old_regions); + MM.enter_process_paging_scope(*this); }); loader = make(region->vaddr().as_ptr(), loader_metadata.size); diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index a134e72dca..d55243d9b3 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -682,10 +682,15 @@ void MemoryManager::dump_kernel_regions() ProcessPagingScope::ProcessPagingScope(Process& process) { ASSERT(current); + asm("movl %%cr3, %%eax" + : "=a"(m_previous_cr3)); MM.enter_process_paging_scope(process); } ProcessPagingScope::~ProcessPagingScope() { - MM.enter_process_paging_scope(current->process()); + InterruptDisabler disabler; + current->tss().cr3 = m_previous_cr3; + asm volatile("movl %%eax, %%cr3" ::"a"(m_previous_cr3) + : "memory"); } diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index 27210ac609..0cd372022d 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -190,9 +190,13 @@ private: bool m_quickmap_in_use { false }; }; -struct ProcessPagingScope { - ProcessPagingScope(Process&); +class ProcessPagingScope { +public: + explicit ProcessPagingScope(Process&); ~ProcessPagingScope(); + +private: + u32 m_previous_cr3 { 0 }; }; template