From 003989e1b07d801f6b6e18d32c803db746a32c73 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 4 Apr 2023 21:06:14 +0300 Subject: [PATCH] Kernel: Store a pointer to the owner process in PageDirectory This replaces the previous owning address space pointer. This commit should not change any of the existing functionality, but it lays down the groundwork needed to let us properly access the region table under the address space spinlock during page fault handling. --- Kernel/Arch/aarch64/PageDirectory.cpp | 4 +++- Kernel/Arch/aarch64/PageDirectory.h | 9 +++------ Kernel/Arch/x86_64/PageDirectory.cpp | 4 +++- Kernel/Arch/x86_64/PageDirectory.h | 9 +++------ Kernel/Memory/AddressSpace.cpp | 8 +++----- Kernel/Memory/AddressSpace.h | 2 +- Kernel/Memory/MemoryManager.cpp | 7 +++++-- Kernel/Process.cpp | 20 +++++++++++--------- Kernel/Syscalls/execve.cpp | 2 +- 9 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Kernel/Arch/aarch64/PageDirectory.cpp b/Kernel/Arch/aarch64/PageDirectory.cpp index 10670612825..69c25d1eaf3 100644 --- a/Kernel/Arch/aarch64/PageDirectory.cpp +++ b/Kernel/Arch/aarch64/PageDirectory.cpp @@ -62,10 +62,12 @@ UNMAP_AFTER_INIT NonnullLockRefPtr PageDirectory::must_create_ker return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull(); } -ErrorOr> PageDirectory::try_create_for_userspace() +ErrorOr> PageDirectory::try_create_for_userspace(Process& process) { auto directory = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PageDirectory)); + directory->m_process = &process; + directory->m_root_table = TRY(MM.allocate_physical_page()); directory->m_directory_table = TRY(MM.allocate_physical_page()); diff --git a/Kernel/Arch/aarch64/PageDirectory.h b/Kernel/Arch/aarch64/PageDirectory.h index 15f02d760db..079f444ddc0 100644 --- a/Kernel/Arch/aarch64/PageDirectory.h +++ b/Kernel/Arch/aarch64/PageDirectory.h @@ -179,7 +179,7 @@ class PageDirectory final : public AtomicRefCounted { friend class MemoryManager; public: - static ErrorOr> try_create_for_userspace(); + static ErrorOr> try_create_for_userspace(Process&); static NonnullLockRefPtr must_create_kernel_page_directory(); static LockRefPtr find_current(); @@ -197,10 +197,7 @@ public: return m_root_table; } - AddressSpace* address_space() { return m_space; } - AddressSpace const* address_space() const { return m_space; } - - void set_space(Badge, AddressSpace& space) { m_space = &space; } + Process* process() { return m_process; } RecursiveSpinlock& get_lock() { return m_lock; } @@ -212,7 +209,7 @@ private: static void register_page_directory(PageDirectory* directory); static void deregister_page_directory(PageDirectory* directory); - AddressSpace* m_space { nullptr }; + Process* m_process { nullptr }; RefPtr m_root_table; RefPtr m_directory_table; RefPtr m_directory_pages[512]; diff --git a/Kernel/Arch/x86_64/PageDirectory.cpp b/Kernel/Arch/x86_64/PageDirectory.cpp index f7cc16d992c..e1459dee62e 100644 --- a/Kernel/Arch/x86_64/PageDirectory.cpp +++ b/Kernel/Arch/x86_64/PageDirectory.cpp @@ -61,10 +61,12 @@ UNMAP_AFTER_INIT NonnullLockRefPtr PageDirectory::must_create_ker return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull(); } -ErrorOr> PageDirectory::try_create_for_userspace() +ErrorOr> PageDirectory::try_create_for_userspace(Process& process) { auto directory = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PageDirectory)); + directory->m_process = &process; + directory->m_pml4t = TRY(MM.allocate_physical_page()); directory->m_directory_table = TRY(MM.allocate_physical_page()); diff --git a/Kernel/Arch/x86_64/PageDirectory.h b/Kernel/Arch/x86_64/PageDirectory.h index 2035846d959..f45b88e2490 100644 --- a/Kernel/Arch/x86_64/PageDirectory.h +++ b/Kernel/Arch/x86_64/PageDirectory.h @@ -162,7 +162,7 @@ class PageDirectory final : public AtomicRefCounted { friend class MemoryManager; public: - static ErrorOr> try_create_for_userspace(); + static ErrorOr> try_create_for_userspace(Process& process); static NonnullLockRefPtr must_create_kernel_page_directory(); static LockRefPtr find_current(); @@ -180,10 +180,7 @@ public: return m_pml4t; } - AddressSpace* address_space() { return m_space; } - AddressSpace const* address_space() const { return m_space; } - - void set_space(Badge, AddressSpace& space) { m_space = &space; } + Process* process() { return m_process; } RecursiveSpinlock& get_lock() { return m_lock; } @@ -195,7 +192,7 @@ private: static void register_page_directory(PageDirectory* directory); static void deregister_page_directory(PageDirectory* directory); - AddressSpace* m_space { nullptr }; + Process* m_process { nullptr }; RefPtr m_pml4t; RefPtr m_directory_table; RefPtr m_directory_pages[512]; diff --git a/Kernel/Memory/AddressSpace.cpp b/Kernel/Memory/AddressSpace.cpp index fd029234614..2c9e42bd307 100644 --- a/Kernel/Memory/AddressSpace.cpp +++ b/Kernel/Memory/AddressSpace.cpp @@ -19,9 +19,9 @@ namespace Kernel::Memory { -ErrorOr> AddressSpace::try_create(AddressSpace const* parent) +ErrorOr> AddressSpace::try_create(Process& process, AddressSpace const* parent) { - auto page_directory = TRY(PageDirectory::try_create_for_userspace()); + auto page_directory = TRY(PageDirectory::try_create_for_userspace(process)); VirtualRange total_range = [&]() -> VirtualRange { if (parent) @@ -33,9 +33,7 @@ ErrorOr> AddressSpace::try_create(AddressSpace const return VirtualRange(VirtualAddress { base }, userspace_range_ceiling - base); }(); - auto space = TRY(adopt_nonnull_own_or_enomem(new (nothrow) AddressSpace(move(page_directory), total_range))); - space->page_directory().set_space({}, *space); - return space; + return adopt_nonnull_own_or_enomem(new (nothrow) AddressSpace(move(page_directory), total_range)); } AddressSpace::AddressSpace(NonnullLockRefPtr page_directory, VirtualRange total_range) diff --git a/Kernel/Memory/AddressSpace.h b/Kernel/Memory/AddressSpace.h index 6f14aac8b9a..5e0597025a4 100644 --- a/Kernel/Memory/AddressSpace.h +++ b/Kernel/Memory/AddressSpace.h @@ -21,7 +21,7 @@ namespace Kernel::Memory { class AddressSpace { public: - static ErrorOr> try_create(AddressSpace const* parent); + static ErrorOr> try_create(Process&, AddressSpace const* parent); ~AddressSpace(); PageDirectory& page_directory() { return *m_page_directory; } diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index 6d1c59908cc..ff041a23560 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -722,8 +722,11 @@ Region* MemoryManager::find_region_from_vaddr(VirtualAddress vaddr) auto page_directory = PageDirectory::find_current(); if (!page_directory) return nullptr; - VERIFY(page_directory->address_space()); - return find_user_region_from_vaddr(*page_directory->address_space(), vaddr); + auto* process = page_directory->process(); + VERIFY(process); + return process->address_space().with([&](auto& space) { + return find_user_region_from_vaddr(*space, vaddr); + }); } PageFaultResponse MemoryManager::handle_page_fault(PageFault const& fault) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 1c38430aeb3..a6f28c0a3a4 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -286,20 +286,22 @@ void Process::unprotect_data() ErrorOr Process::create(NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, Process* fork_parent) { - OwnPtr new_address_space; - if (fork_parent) { - TRY(fork_parent->address_space().with([&](auto& parent_address_space) -> ErrorOr { - new_address_space = TRY(Memory::AddressSpace::try_create(parent_address_space.ptr())); - return {}; - })); - } else { - new_address_space = TRY(Memory::AddressSpace::try_create(nullptr)); - } auto unveil_tree = UnveilNode { TRY(KString::try_create("/"sv)), UnveilMetadata(TRY(KString::try_create("/"sv))) }; auto exec_unveil_tree = UnveilNode { TRY(KString::try_create("/"sv)), UnveilMetadata(TRY(KString::try_create("/"sv))) }; auto credentials = TRY(Credentials::create(uid, gid, uid, gid, uid, gid, {}, fork_parent ? fork_parent->sid() : 0, fork_parent ? fork_parent->pgid() : 0)); auto process = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Process(move(name), move(credentials), ppid, is_kernel_process, move(current_directory), move(executable), tty, move(unveil_tree), move(exec_unveil_tree)))); + + OwnPtr new_address_space; + if (fork_parent) { + TRY(fork_parent->address_space().with([&](auto& parent_address_space) -> ErrorOr { + new_address_space = TRY(Memory::AddressSpace::try_create(*process, parent_address_space.ptr())); + return {}; + })); + } else { + new_address_space = TRY(Memory::AddressSpace::try_create(*process, nullptr)); + } + auto first_thread = TRY(process->attach_resources(new_address_space.release_nonnull(), fork_parent)); return ProcessAndFirstThread { move(process), move(first_thread) }; diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 15d0b5dfa06..10a91bfb500 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -488,7 +488,7 @@ ErrorOr Process::do_exec(NonnullRefPtr main_program_d auto new_process_name = TRY(KString::try_create(last_part)); auto new_main_thread_name = TRY(new_process_name->try_clone()); - auto allocated_space = TRY(Memory::AddressSpace::try_create(nullptr)); + auto allocated_space = TRY(Memory::AddressSpace::try_create(*this, nullptr)); OwnPtr old_space; auto& new_space = m_space.with([&](auto& space) -> Memory::AddressSpace& { old_space = move(space);