1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:28:11 +00:00

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.
This commit is contained in:
Idan Horowitz 2023-04-04 21:06:14 +03:00
parent 65641187ff
commit 003989e1b0
9 changed files with 33 additions and 32 deletions

View file

@ -62,10 +62,12 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<PageDirectory> PageDirectory::must_create_ker
return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull(); return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull();
} }
ErrorOr<NonnullLockRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace() ErrorOr<NonnullLockRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace(Process& process)
{ {
auto directory = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PageDirectory)); 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_root_table = TRY(MM.allocate_physical_page());
directory->m_directory_table = TRY(MM.allocate_physical_page()); directory->m_directory_table = TRY(MM.allocate_physical_page());

View file

@ -179,7 +179,7 @@ class PageDirectory final : public AtomicRefCounted<PageDirectory> {
friend class MemoryManager; friend class MemoryManager;
public: public:
static ErrorOr<NonnullLockRefPtr<PageDirectory>> try_create_for_userspace(); static ErrorOr<NonnullLockRefPtr<PageDirectory>> try_create_for_userspace(Process&);
static NonnullLockRefPtr<PageDirectory> must_create_kernel_page_directory(); static NonnullLockRefPtr<PageDirectory> must_create_kernel_page_directory();
static LockRefPtr<PageDirectory> find_current(); static LockRefPtr<PageDirectory> find_current();
@ -197,10 +197,7 @@ public:
return m_root_table; return m_root_table;
} }
AddressSpace* address_space() { return m_space; } Process* process() { return m_process; }
AddressSpace const* address_space() const { return m_space; }
void set_space(Badge<AddressSpace>, AddressSpace& space) { m_space = &space; }
RecursiveSpinlock<LockRank::None>& get_lock() { return m_lock; } RecursiveSpinlock<LockRank::None>& get_lock() { return m_lock; }
@ -212,7 +209,7 @@ private:
static void register_page_directory(PageDirectory* directory); static void register_page_directory(PageDirectory* directory);
static void deregister_page_directory(PageDirectory* directory); static void deregister_page_directory(PageDirectory* directory);
AddressSpace* m_space { nullptr }; Process* m_process { nullptr };
RefPtr<PhysicalPage> m_root_table; RefPtr<PhysicalPage> m_root_table;
RefPtr<PhysicalPage> m_directory_table; RefPtr<PhysicalPage> m_directory_table;
RefPtr<PhysicalPage> m_directory_pages[512]; RefPtr<PhysicalPage> m_directory_pages[512];

View file

@ -61,10 +61,12 @@ UNMAP_AFTER_INIT NonnullLockRefPtr<PageDirectory> PageDirectory::must_create_ker
return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull(); return adopt_lock_ref_if_nonnull(new (nothrow) PageDirectory).release_nonnull();
} }
ErrorOr<NonnullLockRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace() ErrorOr<NonnullLockRefPtr<PageDirectory>> PageDirectory::try_create_for_userspace(Process& process)
{ {
auto directory = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PageDirectory)); 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_pml4t = TRY(MM.allocate_physical_page());
directory->m_directory_table = TRY(MM.allocate_physical_page()); directory->m_directory_table = TRY(MM.allocate_physical_page());

View file

@ -162,7 +162,7 @@ class PageDirectory final : public AtomicRefCounted<PageDirectory> {
friend class MemoryManager; friend class MemoryManager;
public: public:
static ErrorOr<NonnullLockRefPtr<PageDirectory>> try_create_for_userspace(); static ErrorOr<NonnullLockRefPtr<PageDirectory>> try_create_for_userspace(Process& process);
static NonnullLockRefPtr<PageDirectory> must_create_kernel_page_directory(); static NonnullLockRefPtr<PageDirectory> must_create_kernel_page_directory();
static LockRefPtr<PageDirectory> find_current(); static LockRefPtr<PageDirectory> find_current();
@ -180,10 +180,7 @@ public:
return m_pml4t; return m_pml4t;
} }
AddressSpace* address_space() { return m_space; } Process* process() { return m_process; }
AddressSpace const* address_space() const { return m_space; }
void set_space(Badge<AddressSpace>, AddressSpace& space) { m_space = &space; }
RecursiveSpinlock<LockRank::None>& get_lock() { return m_lock; } RecursiveSpinlock<LockRank::None>& get_lock() { return m_lock; }
@ -195,7 +192,7 @@ private:
static void register_page_directory(PageDirectory* directory); static void register_page_directory(PageDirectory* directory);
static void deregister_page_directory(PageDirectory* directory); static void deregister_page_directory(PageDirectory* directory);
AddressSpace* m_space { nullptr }; Process* m_process { nullptr };
RefPtr<PhysicalPage> m_pml4t; RefPtr<PhysicalPage> m_pml4t;
RefPtr<PhysicalPage> m_directory_table; RefPtr<PhysicalPage> m_directory_table;
RefPtr<PhysicalPage> m_directory_pages[512]; RefPtr<PhysicalPage> m_directory_pages[512];

View file

@ -19,9 +19,9 @@
namespace Kernel::Memory { namespace Kernel::Memory {
ErrorOr<NonnullOwnPtr<AddressSpace>> AddressSpace::try_create(AddressSpace const* parent) ErrorOr<NonnullOwnPtr<AddressSpace>> 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 { VirtualRange total_range = [&]() -> VirtualRange {
if (parent) if (parent)
@ -33,9 +33,7 @@ ErrorOr<NonnullOwnPtr<AddressSpace>> AddressSpace::try_create(AddressSpace const
return VirtualRange(VirtualAddress { base }, userspace_range_ceiling - base); return VirtualRange(VirtualAddress { base }, userspace_range_ceiling - base);
}(); }();
auto space = TRY(adopt_nonnull_own_or_enomem(new (nothrow) AddressSpace(move(page_directory), total_range))); return adopt_nonnull_own_or_enomem(new (nothrow) AddressSpace(move(page_directory), total_range));
space->page_directory().set_space({}, *space);
return space;
} }
AddressSpace::AddressSpace(NonnullLockRefPtr<PageDirectory> page_directory, VirtualRange total_range) AddressSpace::AddressSpace(NonnullLockRefPtr<PageDirectory> page_directory, VirtualRange total_range)

View file

@ -21,7 +21,7 @@ namespace Kernel::Memory {
class AddressSpace { class AddressSpace {
public: public:
static ErrorOr<NonnullOwnPtr<AddressSpace>> try_create(AddressSpace const* parent); static ErrorOr<NonnullOwnPtr<AddressSpace>> try_create(Process&, AddressSpace const* parent);
~AddressSpace(); ~AddressSpace();
PageDirectory& page_directory() { return *m_page_directory; } PageDirectory& page_directory() { return *m_page_directory; }

View file

@ -722,8 +722,11 @@ Region* MemoryManager::find_region_from_vaddr(VirtualAddress vaddr)
auto page_directory = PageDirectory::find_current(); auto page_directory = PageDirectory::find_current();
if (!page_directory) if (!page_directory)
return nullptr; return nullptr;
VERIFY(page_directory->address_space()); auto* process = page_directory->process();
return find_user_region_from_vaddr(*page_directory->address_space(), vaddr); 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) PageFaultResponse MemoryManager::handle_page_fault(PageFault const& fault)

View file

@ -286,20 +286,22 @@ void Process::unprotect_data()
ErrorOr<Process::ProcessAndFirstThread> Process::create(NonnullOwnPtr<KString> name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> current_directory, RefPtr<Custody> executable, RefPtr<TTY> tty, Process* fork_parent) ErrorOr<Process::ProcessAndFirstThread> Process::create(NonnullOwnPtr<KString> name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr<Custody> current_directory, RefPtr<Custody> executable, RefPtr<TTY> tty, Process* fork_parent)
{ {
OwnPtr<Memory::AddressSpace> new_address_space;
if (fork_parent) {
TRY(fork_parent->address_space().with([&](auto& parent_address_space) -> ErrorOr<void> {
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 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 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 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)))); 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<Memory::AddressSpace> new_address_space;
if (fork_parent) {
TRY(fork_parent->address_space().with([&](auto& parent_address_space) -> ErrorOr<void> {
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)); auto first_thread = TRY(process->attach_resources(new_address_space.release_nonnull(), fork_parent));
return ProcessAndFirstThread { move(process), move(first_thread) }; return ProcessAndFirstThread { move(process), move(first_thread) };

View file

@ -488,7 +488,7 @@ ErrorOr<void> Process::do_exec(NonnullRefPtr<OpenFileDescription> main_program_d
auto new_process_name = TRY(KString::try_create(last_part)); auto new_process_name = TRY(KString::try_create(last_part));
auto new_main_thread_name = TRY(new_process_name->try_clone()); 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<Memory::AddressSpace> old_space; OwnPtr<Memory::AddressSpace> old_space;
auto& new_space = m_space.with([&](auto& space) -> Memory::AddressSpace& { auto& new_space = m_space.with([&](auto& space) -> Memory::AddressSpace& {
old_space = move(space); old_space = move(space);