From 419055e484f0f0073d5832f7ded5fd3a3e5ad7de Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 11 Dec 2023 20:21:23 -0500 Subject: [PATCH] kernel: instantiate memory separately for each guest process --- src/core/arm/arm_interface.cpp | 2 +- src/core/arm/arm_interface.h | 2 +- src/core/arm/debug.cpp | 14 ++-- src/core/arm/debug.h | 6 +- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 6 +- src/core/arm/dynarmic/arm_dynarmic_32.h | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 6 +- src/core/arm/dynarmic/arm_dynarmic_64.h | 2 +- src/core/core.cpp | 73 ++++++-------------- src/core/core.h | 13 ---- src/core/hle/kernel/k_address_arbiter.cpp | 19 ++--- src/core/hle/kernel/k_condition_variable.cpp | 8 +-- src/core/hle/kernel/k_process.cpp | 18 +++-- src/core/hle/kernel/k_process.h | 15 +++- src/core/hle/kernel/k_thread.h | 6 +- src/core/hle/kernel/kernel.cpp | 13 ---- src/core/hle/kernel/kernel.h | 4 -- 17 files changed, 82 insertions(+), 127 deletions(-) diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 698c9c8ad..5dc7e5d59 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -9,7 +9,7 @@ namespace Core { -void ArmInterface::LogBacktrace(const Kernel::KProcess* process) const { +void ArmInterface::LogBacktrace(Kernel::KProcess* process) const { Kernel::Svc::ThreadContext ctx; this->GetContext(ctx); diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 806c7c9e9..495963eef 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -95,7 +95,7 @@ public: virtual void SignalInterrupt(Kernel::KThread* thread) = 0; // Stack trace generation. - void LogBacktrace(const Kernel::KProcess* process) const; + void LogBacktrace(Kernel::KProcess* process) const; // Debug functionality. virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0; diff --git a/src/core/arm/debug.cpp b/src/core/arm/debug.cpp index af1c34bc3..854509463 100644 --- a/src/core/arm/debug.cpp +++ b/src/core/arm/debug.cpp @@ -79,7 +79,7 @@ constexpr std::array SegmentBases{ 0x7100000000ULL, }; -void SymbolicateBacktrace(const Kernel::KProcess* process, std::vector& out) { +void SymbolicateBacktrace(Kernel::KProcess* process, std::vector& out) { auto modules = FindModules(process); const bool is_64 = process->Is64Bit(); @@ -118,7 +118,7 @@ void SymbolicateBacktrace(const Kernel::KProcess* process, std::vector GetAArch64Backtrace(const Kernel::KProcess* process, +std::vector GetAArch64Backtrace(Kernel::KProcess* process, const Kernel::Svc::ThreadContext& ctx) { std::vector out; auto& memory = process->GetMemory(); @@ -144,7 +144,7 @@ std::vector GetAArch64Backtrace(const Kernel::KProcess* process, return out; } -std::vector GetAArch32Backtrace(const Kernel::KProcess* process, +std::vector GetAArch32Backtrace(Kernel::KProcess* process, const Kernel::Svc::ThreadContext& ctx) { std::vector out; auto& memory = process->GetMemory(); @@ -173,7 +173,7 @@ std::vector GetAArch32Backtrace(const Kernel::KProcess* process, } // namespace std::optional GetThreadName(const Kernel::KThread* thread) { - const auto* process = thread->GetOwnerProcess(); + auto* process = thread->GetOwnerProcess(); if (process->Is64Bit()) { return GetNameFromThreadType64(process->GetMemory(), *thread); } else { @@ -248,7 +248,7 @@ Kernel::KProcessAddress GetModuleEnd(const Kernel::KProcess* process, return cur_addr - 1; } -Loader::AppLoader::Modules FindModules(const Kernel::KProcess* process) { +Loader::AppLoader::Modules FindModules(Kernel::KProcess* process) { Loader::AppLoader::Modules modules; auto& page_table = process->GetPageTable(); @@ -312,7 +312,7 @@ Loader::AppLoader::Modules FindModules(const Kernel::KProcess* process) { return modules; } -Kernel::KProcessAddress FindMainModuleEntrypoint(const Kernel::KProcess* process) { +Kernel::KProcessAddress FindMainModuleEntrypoint(Kernel::KProcess* process) { // Do we have any loaded executable sections? auto modules = FindModules(process); @@ -337,7 +337,7 @@ void InvalidateInstructionCacheRange(const Kernel::KProcess* process, u64 addres } } -std::vector GetBacktraceFromContext(const Kernel::KProcess* process, +std::vector GetBacktraceFromContext(Kernel::KProcess* process, const Kernel::Svc::ThreadContext& ctx) { if (process->Is64Bit()) { return GetAArch64Backtrace(process, ctx); diff --git a/src/core/arm/debug.h b/src/core/arm/debug.h index c542633db..3cd671365 100644 --- a/src/core/arm/debug.h +++ b/src/core/arm/debug.h @@ -14,9 +14,9 @@ std::optional GetThreadName(const Kernel::KThread* thread); std::string_view GetThreadWaitReason(const Kernel::KThread* thread); std::string GetThreadState(const Kernel::KThread* thread); -Loader::AppLoader::Modules FindModules(const Kernel::KProcess* process); +Loader::AppLoader::Modules FindModules(Kernel::KProcess* process); Kernel::KProcessAddress GetModuleEnd(const Kernel::KProcess* process, Kernel::KProcessAddress base); -Kernel::KProcessAddress FindMainModuleEntrypoint(const Kernel::KProcess* process); +Kernel::KProcessAddress FindMainModuleEntrypoint(Kernel::KProcess* process); void InvalidateInstructionCacheRange(const Kernel::KProcess* process, u64 address, u64 size); @@ -28,7 +28,7 @@ struct BacktraceEntry { std::string name; }; -std::vector GetBacktraceFromContext(const Kernel::KProcess* process, +std::vector GetBacktraceFromContext(Kernel::KProcess* process, const Kernel::Svc::ThreadContext& ctx); std::vector GetBacktrace(const Kernel::KThread* thread); diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index f34865e26..c78cfd528 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -15,7 +15,7 @@ using namespace Common::Literals; class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { public: - explicit DynarmicCallbacks32(ArmDynarmic32& parent, const Kernel::KProcess* process) + explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process) : m_parent{parent}, m_memory(process->GetMemory()), m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()}, m_check_memory_access{m_debugger_enabled || @@ -169,7 +169,7 @@ public: ArmDynarmic32& m_parent; Core::Memory::Memory& m_memory; - const Kernel::KProcess* m_process{}; + Kernel::KProcess* m_process{}; const bool m_debugger_enabled{}; const bool m_check_memory_access{}; static constexpr u64 MinimumRunCycles = 10000U; @@ -370,7 +370,7 @@ void ArmDynarmic32::RewindBreakpointInstruction() { this->SetContext(m_breakpoint_context); } -ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, const Kernel::KProcess* process, +ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProcess* process, DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index) : ArmInterface{uses_wall_clock}, m_system{system}, m_exclusive_monitor{exclusive_monitor}, m_cb(std::make_unique(*this, process)), diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 185ac7cbf..b580efe61 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -20,7 +20,7 @@ class System; class ArmDynarmic32 final : public ArmInterface { public: - ArmDynarmic32(System& system, bool uses_wall_clock, const Kernel::KProcess* process, + ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProcess* process, DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index); ~ArmDynarmic32() override; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index dff14756e..f351b13d9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -15,7 +15,7 @@ using namespace Common::Literals; class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { public: - explicit DynarmicCallbacks64(ArmDynarmic64& parent, const Kernel::KProcess* process) + explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process) : m_parent{parent}, m_memory(process->GetMemory()), m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()}, m_check_memory_access{m_debugger_enabled || @@ -216,7 +216,7 @@ public: Core::Memory::Memory& m_memory; u64 m_tpidrro_el0{}; u64 m_tpidr_el0{}; - const Kernel::KProcess* m_process{}; + Kernel::KProcess* m_process{}; const bool m_debugger_enabled{}; const bool m_check_memory_access{}; static constexpr u64 MinimumRunCycles = 10000U; @@ -399,7 +399,7 @@ void ArmDynarmic64::RewindBreakpointInstruction() { this->SetContext(m_breakpoint_context); } -ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, const Kernel::KProcess* process, +ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProcess* process, DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index) : ArmInterface{uses_wall_clock}, m_system{system}, m_exclusive_monitor{exclusive_monitor}, m_cb(std::make_unique(*this, process)), m_core_index{core_index} { diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 4f3dd026f..08cd982b3 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -25,7 +25,7 @@ class System; class ArmDynarmic64 final : public ArmInterface { public: - ArmDynarmic64(System& system, bool uses_wall_clock, const Kernel::KProcess* process, + ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProcess* process, DynarmicExclusiveMonitor& exclusive_monitor, std::size_t core_index); ~ArmDynarmic64() override; diff --git a/src/core/core.cpp b/src/core/core.cpp index b14f74976..66f444d39 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -28,7 +28,6 @@ #include "core/file_sys/savedata_factory.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" -#include "core/gpu_dirty_memory_manager.h" #include "core/hid/hid_core.h" #include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_process.h" @@ -130,11 +129,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, - cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{}, - time_manager{system}, gpu_dirty_memory_write_manager{} { - memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager); - } + : kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system}, + reporter{system}, applet_manager{system}, profile_manager{}, time_manager{system} {} void Initialize(System& system) { device_memory = std::make_unique(); @@ -241,17 +237,17 @@ struct System::Impl { debugger = std::make_unique(system, port); } - SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { + void InitializeKernel(System& system) { LOG_DEBUG(Core, "initialized OK"); // Setting changes may require a full system reinitialization (e.g., disabling multicore). ReinitializeIfNecessary(system); - memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager); - kernel.Initialize(); cpu_manager.Initialize(); + } + SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { /// Reset all glue registrations arp_manager.ResetAll(); @@ -300,17 +296,9 @@ struct System::Impl { return SystemResultStatus::ErrorGetLoader; } - SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; - if (init_result != SystemResultStatus::Success) { - LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", - static_cast(init_result)); - ShutdownMainProcess(); - return init_result; - } + InitializeKernel(system); - telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); - - // Create the process. + // Create the application process. auto main_process = Kernel::KProcess::Create(system.Kernel()); Kernel::KProcess::Register(system.Kernel(), main_process); kernel.AppendNewProcess(main_process); @@ -323,7 +311,18 @@ struct System::Impl { return static_cast( static_cast(SystemResultStatus::ErrorLoader) + static_cast(load_result)); } + + // Set up the rest of the system. + SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; + if (init_result != SystemResultStatus::Success) { + LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", + static_cast(init_result)); + ShutdownMainProcess(); + return init_result; + } + AddGlueRegistrationForProcess(*app_loader, *main_process); + telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); // Initialize cheat engine if (cheat_engine) { @@ -426,7 +425,6 @@ struct System::Impl { cpu_manager.Shutdown(); debugger.reset(); kernel.Shutdown(); - memory.Reset(); Network::RestartSocketOperations(); if (auto room_member = room_network.GetRoomMember().lock()) { @@ -507,7 +505,6 @@ struct System::Impl { std::unique_ptr host1x_core; std::unique_ptr device_memory; std::unique_ptr audio_core; - Core::Memory::Memory memory; Core::HID::HIDCore hid_core; Network::RoomNetwork room_network; @@ -567,9 +564,6 @@ struct System::Impl { std::array dynarmic_ticks{}; std::array microprofile_cpu{}; - std::array - gpu_dirty_memory_write_manager{}; - std::deque> user_channel; }; @@ -652,29 +646,12 @@ void System::PrepareReschedule(const u32 core_index) { impl->kernel.PrepareReschedule(core_index); } -Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() { - const std::size_t core = impl->kernel.GetCurrentHostThreadID(); - return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES - ? core - : Core::Hardware::NUM_CPU_CORES - 1]; -} - -/// Provides a constant reference to the current gou dirty memory manager. -const Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() const { - const std::size_t core = impl->kernel.GetCurrentHostThreadID(); - return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES - ? core - : Core::Hardware::NUM_CPU_CORES - 1]; -} - size_t System::GetCurrentHostThreadID() const { return impl->kernel.GetCurrentHostThreadID(); } void System::GatherGPUDirtyMemory(std::function& callback) { - for (auto& manager : impl->gpu_dirty_memory_write_manager) { - manager.Gather(callback); - } + return this->ApplicationProcess()->GatherGPUDirtyMemory(callback); } PerfStatsResults System::GetAndResetPerfStats() { @@ -723,20 +700,12 @@ const Kernel::KProcess* System::ApplicationProcess() const { return impl->kernel.ApplicationProcess(); } -ExclusiveMonitor& System::Monitor() { - return impl->kernel.GetExclusiveMonitor(); -} - -const ExclusiveMonitor& System::Monitor() const { - return impl->kernel.GetExclusiveMonitor(); -} - Memory::Memory& System::ApplicationMemory() { - return impl->memory; + return impl->kernel.ApplicationProcess()->GetMemory(); } const Core::Memory::Memory& System::ApplicationMemory() const { - return impl->memory; + return impl->kernel.ApplicationProcess()->GetMemory(); } Tegra::GPU& System::GPU() { diff --git a/src/core/core.h b/src/core/core.h index 473204db7..ba5add0dc 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -116,7 +116,6 @@ class CpuManager; class Debugger; class DeviceMemory; class ExclusiveMonitor; -class GPUDirtyMemoryManager; class PerfStats; class Reporter; class SpeedLimiter; @@ -225,12 +224,6 @@ public: /// Prepare the core emulation for a reschedule void PrepareReschedule(u32 core_index); - /// Provides a reference to the gou dirty memory manager. - [[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager(); - - /// Provides a constant reference to the current gou dirty memory manager. - [[nodiscard]] const Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager() const; - void GatherGPUDirtyMemory(std::function& callback); [[nodiscard]] size_t GetCurrentHostThreadID() const; @@ -250,12 +243,6 @@ public: /// Gets a const reference to the underlying CPU manager [[nodiscard]] const CpuManager& GetCpuManager() const; - /// Gets a reference to the exclusive monitor - [[nodiscard]] ExclusiveMonitor& Monitor(); - - /// Gets a constant reference to the exclusive monitor - [[nodiscard]] const ExclusiveMonitor& Monitor() const; - /// Gets a mutable reference to the system memory instance. [[nodiscard]] Core::Memory::Memory& ApplicationMemory(); diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 78d43d729..48889253d 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -4,6 +4,7 @@ #include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/hle/kernel/k_address_arbiter.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_thread.h" @@ -26,9 +27,9 @@ bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) { return true; } -bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) { - auto& monitor = system.Monitor(); - const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); +bool DecrementIfLessThan(KernelCore& kernel, s32* out, KProcessAddress address, s32 value) { + auto& monitor = GetCurrentProcess(kernel).GetExclusiveMonitor(); + const auto current_core = kernel.CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. // KScopedInterruptDisable di; @@ -66,10 +67,10 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address return true; } -bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 value, +bool UpdateIfEqual(KernelCore& kernel, s32* out, KProcessAddress address, s32 value, s32 new_value) { - auto& monitor = system.Monitor(); - const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); + auto& monitor = GetCurrentProcess(kernel).GetExclusiveMonitor(); + const auto current_core = kernel.CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. // KScopedInterruptDisable di; @@ -159,7 +160,7 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(m_system, std::addressof(user_value), addr, value, value + 1), + R_UNLESS(UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, value + 1), ResultInvalidCurrentMemory); R_UNLESS(user_value == value, ResultInvalidState); @@ -219,7 +220,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(m_system, std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, new_value); } else { succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); } @@ -262,7 +263,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(m_system, std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(m_kernel, std::addressof(user_value), addr, value); } else { succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); } diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 7633a51fb..94ea3527a 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -28,10 +28,10 @@ bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) { return true; } -bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u32 if_zero, +bool UpdateLockAtomic(KernelCore& kernel, u32* out, KProcessAddress address, u32 if_zero, u32 new_orr_mask) { - auto& monitor = system.Monitor(); - const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); + auto& monitor = GetCurrentProcess(kernel).GetExclusiveMonitor(); + const auto current_core = kernel.CurrentPhysicalCoreIndex(); u32 expected{}; @@ -208,7 +208,7 @@ void KConditionVariable::SignalImpl(KThread* thread) { // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; if (can_access) [[likely]] { - UpdateLockAtomic(m_system, std::addressof(prev_tag), address, own_tag, + UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); } } diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 3a2635e1f..905d141ea 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1128,7 +1128,8 @@ void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} KProcess::KProcess(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel}, m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()}, - m_handle_table{kernel} {} + m_handle_table{kernel}, m_dirty_memory_managers{}, m_exclusive_monitor{}, + m_memory{kernel.System()} {} KProcess::~KProcess() = default; Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, @@ -1235,7 +1236,11 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { } void KProcess::InitializeInterfaces() { + m_exclusive_monitor = + Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); + this->GetMemory().SetCurrentPageTable(*this); + this->GetMemory().SetGPUDirtyManagers(m_dirty_memory_managers); #ifdef HAS_NCE if (this->Is64Bit() && Settings::IsNceEnabled()) { @@ -1248,13 +1253,13 @@ void KProcess::InitializeInterfaces() { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( m_kernel.System(), m_kernel.IsMulticore(), this, - static_cast(m_kernel.GetExclusiveMonitor()), i); + static_cast(*m_exclusive_monitor), i); } } else { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( m_kernel.System(), m_kernel.IsMulticore(), this, - static_cast(m_kernel.GetExclusiveMonitor()), i); + static_cast(*m_exclusive_monitor), i); } } } @@ -1305,9 +1310,10 @@ bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT return true; } -Core::Memory::Memory& KProcess::GetMemory() const { - // TODO: per-process memory - return m_kernel.System().ApplicationMemory(); +void KProcess::GatherGPUDirtyMemory(std::function& callback) { + for (auto& manager : m_dirty_memory_managers) { + manager.Gather(callback); + } } } // namespace Kernel diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 4b114e39b..53c0e3316 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -7,6 +7,7 @@ #include "core/arm/arm_interface.h" #include "core/file_sys/program_metadata.h" +#include "core/gpu_dirty_memory_manager.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_capabilities.h" @@ -17,6 +18,7 @@ #include "core/hle/kernel/k_system_resource.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread_local_page.h" +#include "core/memory.h" namespace Kernel { @@ -126,6 +128,9 @@ private: #ifdef HAS_NCE std::unordered_map m_post_handlers{}; #endif + std::array m_dirty_memory_managers; + std::unique_ptr m_exclusive_monitor; + Core::Memory::Memory m_memory; private: Result StartTermination(); @@ -502,7 +507,15 @@ public: void InitializeInterfaces(); - Core::Memory::Memory& GetMemory() const; + Core::Memory::Memory& GetMemory() { + return m_memory; + } + + void GatherGPUDirtyMemory(std::function& callback); + + Core::ExclusiveMonitor& GetExclusiveMonitor() const { + return *m_exclusive_monitor; + } public: // Overridden parent functions. diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e9925d231..f13e232b2 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -314,11 +314,7 @@ public: m_current_core_id = core; } - KProcess* GetOwnerProcess() { - return m_parent; - } - - const KProcess* GetOwnerProcess() const { + KProcess* GetOwnerProcess() const { return m_parent; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e479dacde..2efca27c2 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -126,8 +126,6 @@ struct KernelCore::Impl { preemption_event = nullptr; - exclusive_monitor.reset(); - // Cleanup persistent kernel objects auto CleanupObject = [](KAutoObject* obj) { if (obj) { @@ -191,8 +189,6 @@ struct KernelCore::Impl { } void InitializePhysicalCores() { - exclusive_monitor = - Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES); for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { const s32 core{static_cast(i)}; @@ -805,7 +801,6 @@ struct KernelCore::Impl { std::mutex server_lock; std::vector> server_managers; - std::unique_ptr exclusive_monitor; std::array, Core::Hardware::NUM_CPU_CORES> cores; // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others @@ -959,14 +954,6 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() { return *impl->hardware_timer; } -Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { - return *impl->exclusive_monitor; -} - -const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { - return *impl->exclusive_monitor; -} - KAutoObjectWithListContainer& KernelCore::ObjectListContainer() { return *impl->global_object_list_container; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 78c88902c..fefd7aaba 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -170,10 +170,6 @@ public: /// Stops execution of 'id' core, in order to reschedule a new thread. void PrepareReschedule(std::size_t id); - Core::ExclusiveMonitor& GetExclusiveMonitor(); - - const Core::ExclusiveMonitor& GetExclusiveMonitor() const; - KAutoObjectWithListContainer& ObjectListContainer(); const KAutoObjectWithListContainer& ObjectListContainer() const;