mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	kernel: instantiate memory separately for each guest process
This commit is contained in:
		
							parent
							
								
									91290b9be4
								
							
						
					
					
						commit
						419055e484
					
				| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -79,7 +79,7 @@ constexpr std::array<u64, 2> SegmentBases{ | ||||
|     0x7100000000ULL, | ||||
| }; | ||||
| 
 | ||||
| void SymbolicateBacktrace(const Kernel::KProcess* process, std::vector<BacktraceEntry>& out) { | ||||
| void SymbolicateBacktrace(Kernel::KProcess* process, std::vector<BacktraceEntry>& out) { | ||||
|     auto modules = FindModules(process); | ||||
| 
 | ||||
|     const bool is_64 = process->Is64Bit(); | ||||
| @ -118,7 +118,7 @@ void SymbolicateBacktrace(const Kernel::KProcess* process, std::vector<Backtrace | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<BacktraceEntry> GetAArch64Backtrace(const Kernel::KProcess* process, | ||||
| std::vector<BacktraceEntry> GetAArch64Backtrace(Kernel::KProcess* process, | ||||
|                                                 const Kernel::Svc::ThreadContext& ctx) { | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = process->GetMemory(); | ||||
| @ -144,7 +144,7 @@ std::vector<BacktraceEntry> GetAArch64Backtrace(const Kernel::KProcess* process, | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| std::vector<BacktraceEntry> GetAArch32Backtrace(const Kernel::KProcess* process, | ||||
| std::vector<BacktraceEntry> GetAArch32Backtrace(Kernel::KProcess* process, | ||||
|                                                 const Kernel::Svc::ThreadContext& ctx) { | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = process->GetMemory(); | ||||
| @ -173,7 +173,7 @@ std::vector<BacktraceEntry> GetAArch32Backtrace(const Kernel::KProcess* process, | ||||
| } // namespace
 | ||||
| 
 | ||||
| std::optional<std::string> 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<BacktraceEntry> GetBacktraceFromContext(const Kernel::KProcess* process, | ||||
| std::vector<BacktraceEntry> GetBacktraceFromContext(Kernel::KProcess* process, | ||||
|                                                     const Kernel::Svc::ThreadContext& ctx) { | ||||
|     if (process->Is64Bit()) { | ||||
|         return GetAArch64Backtrace(process, ctx); | ||||
|  | ||||
| @ -14,9 +14,9 @@ std::optional<std::string> 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<BacktraceEntry> GetBacktraceFromContext(const Kernel::KProcess* process, | ||||
| std::vector<BacktraceEntry> GetBacktraceFromContext(Kernel::KProcess* process, | ||||
|                                                     const Kernel::Svc::ThreadContext& ctx); | ||||
| std::vector<BacktraceEntry> GetBacktrace(const Kernel::KThread* thread); | ||||
| 
 | ||||
|  | ||||
| @ -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<DynarmicCallbacks32>(*this, process)), | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<DynarmicCallbacks64>(*this, process)), m_core_index{core_index} { | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<Core::DeviceMemory>(); | ||||
| @ -241,17 +237,17 @@ struct System::Impl { | ||||
|         debugger = std::make_unique<Debugger>(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<int>(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<SystemResultStatus>( | ||||
|                 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(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<int>(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<Tegra::Host1x::Host1x> host1x_core; | ||||
|     std::unique_ptr<Core::DeviceMemory> device_memory; | ||||
|     std::unique_ptr<AudioCore::AudioCore> audio_core; | ||||
|     Core::Memory::Memory memory; | ||||
|     Core::HID::HIDCore hid_core; | ||||
|     Network::RoomNetwork room_network; | ||||
| 
 | ||||
| @ -567,9 +564,6 @@ struct System::Impl { | ||||
|     std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | ||||
|     std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; | ||||
| 
 | ||||
|     std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> | ||||
|         gpu_dirty_memory_write_manager{}; | ||||
| 
 | ||||
|     std::deque<std::vector<u8>> 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<void(VAddr, size_t)>& 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() { | ||||
|  | ||||
| @ -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<void(VAddr, size_t)>& 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(); | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|         } | ||||
|  | ||||
| @ -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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -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<Core::ArmDynarmic64>( | ||||
|                 m_kernel.System(), m_kernel.IsMulticore(), this, | ||||
|                 static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i); | ||||
|                 static_cast<Core::DynarmicExclusiveMonitor&>(*m_exclusive_monitor), i); | ||||
|         } | ||||
|     } else { | ||||
|         for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | ||||
|             m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic32>( | ||||
|                 m_kernel.System(), m_kernel.IsMulticore(), this, | ||||
|                 static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i); | ||||
|                 static_cast<Core::DynarmicExclusiveMonitor&>(*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<void(VAddr, size_t)>& callback) { | ||||
|     for (auto& manager : m_dirty_memory_managers) { | ||||
|         manager.Gather(callback); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  | ||||
| @ -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<u64, u64> m_post_handlers{}; | ||||
| #endif | ||||
|     std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> m_dirty_memory_managers; | ||||
|     std::unique_ptr<Core::ExclusiveMonitor> 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<void(VAddr, size_t)>& callback); | ||||
| 
 | ||||
|     Core::ExclusiveMonitor& GetExclusiveMonitor() const { | ||||
|         return *m_exclusive_monitor; | ||||
|     } | ||||
| 
 | ||||
| public: | ||||
|     // Overridden parent functions.
 | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -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<s32>(i)}; | ||||
| 
 | ||||
| @ -805,7 +801,6 @@ struct KernelCore::Impl { | ||||
|     std::mutex server_lock; | ||||
|     std::vector<std::unique_ptr<Service::ServerManager>> server_managers; | ||||
| 
 | ||||
|     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | ||||
|     std::array<std::unique_ptr<Kernel::PhysicalCore>, 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; | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user