Ver código fonte

Merge pull request #12394 from liamwhite/per-process-memory

 general: properly support multiple memory instances
Fernando S 2 anos atrás
pai
commit
05e3db3ac9
39 arquivos alterados com 1242 adições e 368 exclusões
  1. 1 1
      src/core/arm/arm_interface.cpp
  2. 1 1
      src/core/arm/arm_interface.h
  3. 7 7
      src/core/arm/debug.cpp
  4. 3 3
      src/core/arm/debug.h
  5. 3 3
      src/core/arm/dynarmic/arm_dynarmic_32.cpp
  6. 1 1
      src/core/arm/dynarmic/arm_dynarmic_32.h
  7. 3 3
      src/core/arm/dynarmic/arm_dynarmic_64.cpp
  8. 1 1
      src/core/arm/dynarmic/arm_dynarmic_64.h
  9. 21 52
      src/core/core.cpp
  10. 0 13
      src/core/core.h
  11. 5 1
      src/core/file_sys/program_metadata.cpp
  12. 11 2
      src/core/file_sys/program_metadata.h
  13. 10 9
      src/core/hle/kernel/k_address_arbiter.cpp
  14. 2 3
      src/core/hle/kernel/k_client_port.cpp
  15. 4 4
      src/core/hle/kernel/k_condition_variable.cpp
  16. 5 3
      src/core/hle/kernel/k_handle_table.h
  17. 31 19
      src/core/hle/kernel/k_process.cpp
  18. 15 2
      src/core/hle/kernel/k_process.h
  19. 1024 111
      src/core/hle/kernel/k_server_session.cpp
  20. 11 4
      src/core/hle/kernel/k_server_session.h
  21. 1 2
      src/core/hle/kernel/k_session.cpp
  22. 1 2
      src/core/hle/kernel/k_thread.cpp
  23. 1 5
      src/core/hle/kernel/k_thread.h
  24. 0 34
      src/core/hle/kernel/kernel.cpp
  25. 0 7
      src/core/hle/kernel/kernel.h
  26. 10 10
      src/core/hle/kernel/message_buffer.h
  27. 0 1
      src/core/hle/kernel/svc/svc_info.cpp
  28. 2 4
      src/core/hle/kernel/svc/svc_ipc.cpp
  29. 2 0
      src/core/hle/kernel/svc_results.h
  30. 1 1
      src/core/hle/service/fatal/fatal.cpp
  31. 2 2
      src/core/hle/service/ipc_helpers.h
  32. 7 14
      src/core/hle/service/server_manager.cpp
  33. 11 1
      src/core/hle/service/set/set_sys.cpp
  34. 1 0
      src/core/hle/service/set/set_sys.h
  35. 19 17
      src/core/hle/service/sm/sm.cpp
  36. 4 4
      src/core/hle/service/sm/sm.h
  37. 3 4
      src/core/hle/service/sm/sm_controller.cpp
  38. 4 3
      src/core/loader/deconstructed_rom_directory.cpp
  39. 14 14
      src/core/memory.cpp

+ 1 - 1
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);
 

+ 1 - 1
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;

+ 7 - 7
src/core/arm/debug.cpp

@@ -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);

+ 3 - 3
src/core/arm/debug.h

@@ -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);
 

+ 3 - 3
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<DynarmicCallbacks32>(*this, process)),

+ 1 - 1
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;
 

+ 3 - 3
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<DynarmicCallbacks64>(*this, process)), m_core_index{core_index} {

+ 1 - 1
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;
 

+ 21 - 52
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<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;
-        }
-
-        telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
+        InitializeKernel(system);
 
-        // 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() {

+ 0 - 13
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<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();
 

+ 5 - 1
src/core/file_sys/program_metadata.cpp

@@ -166,6 +166,10 @@ u32 ProgramMetadata::GetSystemResourceSize() const {
     return npdm_header.system_resource_size;
 }
 
+PoolPartition ProgramMetadata::GetPoolPartition() const {
+    return acid_header.pool_partition;
+}
+
 const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCapabilities() const {
     return aci_kernel_capabilities;
 }
@@ -201,7 +205,7 @@ void ProgramMetadata::Print() const {
     // Begin ACID printing (potential perms, signed)
     LOG_DEBUG(Service_FS, "Magic:                  {:.4}", acid_header.magic.data());
     LOG_DEBUG(Service_FS, "Flags:                  0x{:02X}", acid_header.flags);
-    LOG_DEBUG(Service_FS, " > Is Retail:           {}", acid_header.is_retail ? "YES" : "NO");
+    LOG_DEBUG(Service_FS, " > Is Retail:           {}", acid_header.production_flag ? "YES" : "NO");
     LOG_DEBUG(Service_FS, "Title ID Min:           0x{:016X}", acid_header.title_id_min);
     LOG_DEBUG(Service_FS, "Title ID Max:           0x{:016X}", acid_header.title_id_max);
     LOG_DEBUG(Service_FS, "Filesystem Access:      0x{:016X}\n", acid_file_access.permissions);

+ 11 - 2
src/core/file_sys/program_metadata.h

@@ -34,6 +34,13 @@ enum class ProgramFilePermission : u64 {
     Everything = 1ULL << 63,
 };
 
+enum class PoolPartition : u32 {
+    Application = 0,
+    Applet = 1,
+    System = 2,
+    SystemNonSecure = 3,
+};
+
 /**
  * Helper which implements an interface to parse Program Description Metadata (NPDM)
  * Data can either be loaded from a file path or with data and an offset into it.
@@ -72,6 +79,7 @@ public:
     u64 GetTitleID() const;
     u64 GetFilesystemPermissions() const;
     u32 GetSystemResourceSize() const;
+    PoolPartition GetPoolPartition() const;
     const KernelCapabilityDescriptors& GetKernelCapabilities() const;
     const std::array<u8, 0x10>& GetName() const {
         return npdm_header.application_name;
@@ -116,8 +124,9 @@ private:
         union {
             u32 flags;
 
-            BitField<0, 1, u32> is_retail;
-            BitField<1, 31, u32> flags_unk;
+            BitField<0, 1, u32> production_flag;
+            BitField<1, 1, u32> unqualified_approval;
+            BitField<2, 4, PoolPartition> pool_partition;
         };
         u64_le title_id_min;
         u64_le title_id_max;

+ 10 - 9
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);
         }

+ 2 - 3
src/core/hle/kernel/k_client_port.cpp

@@ -58,9 +58,8 @@ Result KClientPort::CreateSession(KClientSession** out) {
     KSession* session{};
 
     // Reserve a new session from the resource limit.
-    //! FIXME: we are reserving this from the wrong resource limit!
-    KScopedResourceReservation session_reservation(
-        m_kernel.ApplicationProcess()->GetResourceLimit(), LimitableResource::SessionCountMax);
+    KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel),
+                                                   LimitableResource::SessionCountMax);
     R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
 
     // Allocate a session normally.

+ 4 - 4
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);
         }
     }

+ 5 - 3
src/core/hle/kernel/k_handle_table.h

@@ -30,7 +30,7 @@ public:
 public:
     explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {}
 
-    Result Initialize(s32 size) {
+    Result Initialize(KProcess* owner, s32 size) {
         // Check that the table size is valid.
         R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
 
@@ -44,6 +44,7 @@ public:
         m_next_linear_id = MinLinearId;
         m_count = 0;
         m_free_head_index = -1;
+        m_owner = owner;
 
         // Free all entries.
         for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
@@ -90,8 +91,8 @@ public:
         // Handle pseudo-handles.
         if constexpr (std::derived_from<KProcess, T>) {
             if (handle == Svc::PseudoHandle::CurrentProcess) {
-                //! FIXME: this is the wrong process!
-                auto* const cur_process = m_kernel.ApplicationProcess();
+                // TODO: this should be the current process
+                auto* const cur_process = m_owner;
                 ASSERT(cur_process != nullptr);
                 return cur_process;
             }
@@ -301,6 +302,7 @@ private:
 
 private:
     KernelCore& m_kernel;
+    KProcess* m_owner{};
     std::array<EntryInfo, MaxTableSize> m_entry_infos{};
     std::array<KAutoObject*, MaxTableSize> m_objects{};
     mutable KSpinLock m_lock;

+ 31 - 19
src/core/hle/kernel/k_process.cpp

@@ -306,12 +306,16 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa
             False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
         R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
                                       params.code_address, params.code_num_pages * PageSize,
-                                      m_system_resource, res_limit, this->GetMemory(), 0));
+                                      m_system_resource, res_limit, m_memory, 0));
     }
     ON_RESULT_FAILURE_2 {
         m_page_table.Finalize();
     };
 
+    // Ensure our memory is initialized.
+    m_memory.SetCurrentPageTable(*this);
+    m_memory.SetGPUDirtyManagers(m_dirty_memory_managers);
+
     // Ensure we can insert the code region.
     R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
                                      KMemoryState::Code),
@@ -399,12 +403,16 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
             False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
         R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
                                       params.code_address, code_size, m_system_resource, res_limit,
-                                      this->GetMemory(), aslr_space_start));
+                                      m_memory, aslr_space_start));
     }
     ON_RESULT_FAILURE_2 {
         m_page_table.Finalize();
     };
 
+    // Ensure our memory is initialized.
+    m_memory.SetCurrentPageTable(*this);
+    m_memory.SetGPUDirtyManagers(m_dirty_memory_managers);
+
     // Ensure we can insert the code region.
     R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),
              ResultInvalidMemoryRegion);
@@ -1094,8 +1102,7 @@ void KProcess::UnpinThread(KThread* thread) {
 
 Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids,
                                s32 max_out_count) {
-    // TODO: use current memory reference
-    auto& memory = m_kernel.System().ApplicationMemory();
+    auto& memory = this->GetMemory();
 
     // Lock the list.
     KScopedLightLock lk(m_list_lock);
@@ -1128,14 +1135,15 @@ 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,
                                   KProcessAddress aslr_space_start, bool is_hbl) {
     // Create a resource limit for the process.
-    const auto physical_memory_size =
-        m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application);
+    const auto pool = static_cast<KMemoryManager::Pool>(metadata.GetPoolPartition());
+    const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool);
     auto* res_limit =
         Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
 
@@ -1146,8 +1154,10 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
     Svc::CreateProcessFlag flag{};
     u64 code_address{};
 
-    // We are an application.
-    flag |= Svc::CreateProcessFlag::IsApplication;
+    // Determine if we are an application.
+    if (pool == KMemoryManager::Pool::Application) {
+        flag |= Svc::CreateProcessFlag::IsApplication;
+    }
 
     // If we are 64-bit, create as such.
     if (metadata.Is64BitProgram()) {
@@ -1196,8 +1206,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
     std::memcpy(params.name.data(), name.data(), sizeof(params.name));
 
     // Initialize for application process.
-    R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit,
-                           KMemoryManager::Pool::Application, aslr_space_start));
+    R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool,
+                           aslr_space_start));
 
     // Assign remaining properties.
     m_is_hbl = is_hbl;
@@ -1223,7 +1233,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
     ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
 
 #ifdef HAS_NCE
-    if (Settings::IsNceEnabled()) {
+    if (this->IsApplication() && Settings::IsNceEnabled()) {
         auto& buffer = m_kernel.System().DeviceMemory().buffer;
         const auto& code = code_set.CodeSegment();
         const auto& patch = code_set.PatchSegment();
@@ -1235,10 +1245,11 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
 }
 
 void KProcess::InitializeInterfaces() {
-    this->GetMemory().SetCurrentPageTable(*this);
+    m_exclusive_monitor =
+        Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES);
 
 #ifdef HAS_NCE
-    if (this->Is64Bit() && Settings::IsNceEnabled()) {
+    if (this->IsApplication() && Settings::IsNceEnabled()) {
         for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
             m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i);
         }
@@ -1248,13 +1259,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 +1316,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

+ 15 - 2
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<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.
@@ -539,7 +552,7 @@ private:
 
     Result InitializeHandleTable(s32 size) {
         // Try to initialize the handle table.
-        R_TRY(m_handle_table.Initialize(size));
+        R_TRY(m_handle_table.Initialize(this, size));
 
         // We succeeded, so note that we did.
         m_is_handle_table_initialized = true;

Diferenças do arquivo suprimidas por serem muito extensas
+ 1024 - 111
src/core/hle/kernel/k_server_session.cpp


+ 11 - 4
src/core/hle/kernel/k_server_session.h

@@ -49,14 +49,21 @@ public:
     bool IsSignaled() const override;
     void OnClientClosed();
 
-    /// TODO: flesh these out to match the real kernel
     Result OnRequest(KSessionRequest* request);
-    Result SendReply(bool is_hle = false);
-    Result ReceiveRequest(std::shared_ptr<Service::HLERequestContext>* out_context = nullptr,
+    Result SendReply(uintptr_t server_message, uintptr_t server_buffer_size,
+                     KPhysicalAddress server_message_paddr, bool is_hle = false);
+    Result ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size,
+                          KPhysicalAddress server_message_paddr,
+                          std::shared_ptr<Service::HLERequestContext>* out_context = nullptr,
                           std::weak_ptr<Service::SessionRequestManager> manager = {});
 
     Result SendReplyHLE() {
-        return SendReply(true);
+        R_RETURN(this->SendReply(0, 0, 0, true));
+    }
+
+    Result ReceiveRequestHLE(std::shared_ptr<Service::HLERequestContext>* out_context,
+                             std::weak_ptr<Service::SessionRequestManager> manager) {
+        R_RETURN(this->ReceiveRequest(0, 0, 0, out_context, manager));
     }
 
 private:

+ 1 - 2
src/core/hle/kernel/k_session.cpp

@@ -33,8 +33,7 @@ void KSession::Initialize(KClientPort* client_port, uintptr_t name) {
     m_name = name;
 
     // Set our owner process.
-    //! FIXME: this is the wrong process!
-    m_process = m_kernel.ApplicationProcess();
+    m_process = GetCurrentProcessPointer(m_kernel);
     m_process->Open();
 
     // Set our port.

+ 1 - 2
src/core/hle/kernel/k_thread.cpp

@@ -1422,8 +1422,7 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
 }
 
 Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel) {
-    // TODO: per-process memory
-    return kernel.System().ApplicationMemory();
+    return GetCurrentProcess(kernel).GetMemory();
 }
 
 KScopedDisableDispatch::~KScopedDisableDispatch() {

+ 1 - 5
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;
     }
 

+ 0 - 34
src/core/hle/kernel/kernel.cpp

@@ -68,8 +68,6 @@ struct KernelCore::Impl {
 
         global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel);
         global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
-        global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
-        global_handle_table->Initialize(KHandleTable::MaxTableSize);
 
         is_phantom_mode_for_singlecore = false;
 
@@ -121,13 +119,8 @@ struct KernelCore::Impl {
         next_user_process_id = KProcess::ProcessIdMin;
         next_thread_id = 1;
 
-        global_handle_table->Finalize();
-        global_handle_table.reset();
-
         preemption_event = nullptr;
 
-        exclusive_monitor.reset();
-
         // Cleanup persistent kernel objects
         auto CleanupObject = [](KAutoObject* obj) {
             if (obj) {
@@ -191,8 +184,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)};
 
@@ -791,10 +782,6 @@ struct KernelCore::Impl {
 
     std::shared_ptr<Core::Timing::EventType> preemption_event;
 
-    // This is the kernel's handle table or supervisor handle table which
-    // stores all the objects in place.
-    std::unique_ptr<KHandleTable> global_handle_table;
-
     std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
 
     std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
@@ -805,7 +792,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
@@ -882,10 +868,6 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
     return impl->system_resource_limit;
 }
 
-KScopedAutoObject<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
-    return impl->global_handle_table->GetObject<KThread>(handle);
-}
-
 void KernelCore::AppendNewProcess(KProcess* process) {
     impl->process_list.push_back(process);
 }
@@ -959,14 +941,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;
 }
@@ -1030,14 +1004,6 @@ u64 KernelCore::CreateNewUserProcessID() {
     return impl->next_user_process_id++;
 }
 
-KHandleTable& KernelCore::GlobalHandleTable() {
-    return *impl->global_handle_table;
-}
-
-const KHandleTable& KernelCore::GlobalHandleTable() const {
-    return *impl->global_handle_table;
-}
-
 void KernelCore::RegisterCoreThread(std::size_t core_id) {
     impl->RegisterCoreThread(core_id);
 }

+ 0 - 7
src/core/hle/kernel/kernel.h

@@ -116,9 +116,6 @@ public:
     /// Retrieves a shared pointer to the system resource limit instance.
     KResourceLimit* GetSystemResourceLimit();
 
-    /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
-    KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
-
     /// Adds the given shared pointer to an internal list of active processes.
     void AppendNewProcess(KProcess* process);
 
@@ -170,10 +167,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;

+ 10 - 10
src/core/hle/kernel/message_buffer.h

@@ -18,13 +18,13 @@ public:
         static constexpr inline u64 NullTag = 0;
 
     public:
-        enum class ReceiveListCountType : u32 {
-            None = 0,
-            ToMessageBuffer = 1,
-            ToSingleBuffer = 2,
+        enum ReceiveListCountType : u32 {
+            ReceiveListCountType_None = 0,
+            ReceiveListCountType_ToMessageBuffer = 1,
+            ReceiveListCountType_ToSingleBuffer = 2,
 
-            CountOffset = 2,
-            CountMax = 13,
+            ReceiveListCountType_CountOffset = 2,
+            ReceiveListCountType_CountMax = 13,
         };
 
     private:
@@ -591,16 +591,16 @@ public:
         // Add the size of the receive list.
         const auto count = hdr.GetReceiveListCount();
         switch (count) {
-        case MessageHeader::ReceiveListCountType::None:
+        case MessageHeader::ReceiveListCountType_None:
             break;
-        case MessageHeader::ReceiveListCountType::ToMessageBuffer:
+        case MessageHeader::ReceiveListCountType_ToMessageBuffer:
             break;
-        case MessageHeader::ReceiveListCountType::ToSingleBuffer:
+        case MessageHeader::ReceiveListCountType_ToSingleBuffer:
             msg_size += ReceiveListEntry::GetDataSize();
             break;
         default:
             msg_size += (static_cast<s32>(count) -
-                         static_cast<s32>(MessageHeader::ReceiveListCountType::CountOffset)) *
+                         static_cast<s32>(MessageHeader::ReceiveListCountType_CountOffset)) *
                         ReceiveListEntry::GetDataSize();
             break;
         }

+ 0 - 1
src/core/hle/kernel/svc/svc_info.cpp

@@ -118,7 +118,6 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
             R_SUCCEED();
 
         case InfoType::IsApplication:
-            LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
             *result = process->IsApplication();
             R_SUCCEED();
 

+ 2 - 4
src/core/hle/kernel/svc/svc_ipc.cpp

@@ -48,8 +48,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes
         };
 
         // Send the reply.
-        R_TRY(session->SendReply());
-        // R_TRY(session->SendReply(message, buffer_size, message_paddr));
+        R_TRY(session->SendReply(message, buffer_size, message_paddr));
     }
 
     // Receive a message.
@@ -85,8 +84,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes
             if (R_SUCCEEDED(result)) {
                 KServerSession* session = objs[index]->DynamicCast<KServerSession*>();
                 if (session != nullptr) {
-                    // result = session->ReceiveRequest(message, buffer_size, message_paddr);
-                    result = session->ReceiveRequest();
+                    result = session->ReceiveRequest(message, buffer_size, message_paddr);
                     if (ResultNotFound == result) {
                         continue;
                     }

+ 2 - 0
src/core/hle/kernel/svc_results.h

@@ -38,7 +38,9 @@ constexpr Result ResultInvalidState{ErrorModule::Kernel, 125};
 constexpr Result ResultReservedUsed{ErrorModule::Kernel, 126};
 constexpr Result ResultPortClosed{ErrorModule::Kernel, 131};
 constexpr Result ResultLimitReached{ErrorModule::Kernel, 132};
+constexpr Result ResultReceiveListBroken{ErrorModule::Kernel, 258};
 constexpr Result ResultOutOfAddressSpace{ErrorModule::Kernel, 259};
+constexpr Result ResultMessageTooLarge{ErrorModule::Kernel, 260};
 constexpr Result ResultInvalidId{ErrorModule::Kernel, 519};
 
 } // namespace Kernel

+ 1 - 1
src/core/hle/service/fatal/fatal.cpp

@@ -89,7 +89,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F
         crash_report += fmt::format("    ESR:                         {:016x}\n", info.esr);
         crash_report += fmt::format("    FAR:                         {:016x}\n", info.far);
         crash_report += "\nBacktrace:\n";
-        for (size_t i = 0; i < info.backtrace_size; i++) {
+        for (u32 i = 0; i < std::min<u32>(info.backtrace_size, 32); i++) {
             crash_report +=
                 fmt::format("    Backtrace[{:02d}]:               {:016x}\n", i, info.backtrace[i]);
         }

+ 2 - 2
src/core/hle/service/ipc_helpers.h

@@ -151,8 +151,8 @@ public:
         if (manager->IsDomain()) {
             context->AddDomainObject(std::move(iface));
         } else {
-            kernel.ApplicationProcess()->GetResourceLimit()->Reserve(
-                Kernel::LimitableResource::SessionCountMax, 1);
+            ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(
+                Kernel::LimitableResource::SessionCountMax, 1));
 
             auto* session = Kernel::KSession::Create(kernel);
             session->Initialize(nullptr, 0);

+ 7 - 14
src/core/hle/service/server_manager.cpp

@@ -47,7 +47,7 @@ ServerManager::~ServerManager() {
     m_stopped.Wait();
     m_threads.clear();
 
-    // Clean up ports.
+    // Clean up server ports.
     for (const auto& [port, handler] : m_ports) {
         port->Close();
     }
@@ -97,22 +97,15 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
                                            u32 max_sessions) {
     ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
 
-    // Add the new server to sm:.
-    ASSERT(R_SUCCEEDED(
-        m_system.ServiceManager().RegisterService(service_name, max_sessions, handler_factory)));
-
-    // Get the registered port.
-    Kernel::KPort* port{};
-    ASSERT(
-        R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name)));
-
-    // Open a new reference to the server port.
-    port->GetServerPort().Open();
+    // Add the new server to sm: and get the moved server port.
+    Kernel::KServerPort* server_port{};
+    R_ASSERT(m_system.ServiceManager().RegisterService(std::addressof(server_port), service_name,
+                                                       max_sessions, handler_factory));
 
     // Begin tracking the server port.
     {
         std::scoped_lock ll{m_list_mutex};
-        m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory));
+        m_ports.emplace(server_port, std::move(handler_factory));
     }
 
     // Signal the wakeup event.
@@ -372,7 +365,7 @@ Result ServerManager::OnSessionEvent(Kernel::KServerSession* session,
 
     // Try to receive a message.
     std::shared_ptr<HLERequestContext> context;
-    rc = session->ReceiveRequest(&context, manager);
+    rc = session->ReceiveRequestHLE(&context, manager);
 
     // If the session has been closed, we're done.
     if (rc == Kernel::ResultSessionClosed) {

+ 11 - 1
src/core/hle/service/set/set_sys.cpp

@@ -507,6 +507,14 @@ void SET_SYS::SetTvSettings(HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
+void SET_SYS::GetDebugModeFlag(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_SET, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(0);
+}
+
 void SET_SYS::GetQuestFlag(HLERequestContext& ctx) {
     LOG_WARNING(Service_SET, "(STUBBED) called");
 
@@ -926,7 +934,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"},
         {59, &SET_SYS::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"},
         {60, &SET_SYS::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"},
         {61, &SET_SYS::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"},
-        {62, nullptr, "GetDebugModeFlag"},
+        {62, &SET_SYS::GetDebugModeFlag, "GetDebugModeFlag"},
         {63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
         {64, nullptr, "SetPrimaryAlbumStorage"},
         {65, nullptr, "GetUsb30EnableFlag"},
@@ -1143,6 +1151,8 @@ void SET_SYS::StoreSettings() {
 }
 
 void SET_SYS::StoreSettingsThreadFunc(std::stop_token stop_token) {
+    Common::SetCurrentThreadName("SettingsStore");
+
     while (Common::StoppableTimedWait(stop_token, std::chrono::minutes(1))) {
         std::scoped_lock l{m_save_needed_mutex};
         if (!std::exchange(m_save_needed, false)) {

+ 1 - 0
src/core/hle/service/set/set_sys.h

@@ -98,6 +98,7 @@ private:
     void GetSettingsItemValue(HLERequestContext& ctx);
     void GetTvSettings(HLERequestContext& ctx);
     void SetTvSettings(HLERequestContext& ctx);
+    void GetDebugModeFlag(HLERequestContext& ctx);
     void GetQuestFlag(HLERequestContext& ctx);
     void GetDeviceTimeZoneLocationName(HLERequestContext& ctx);
     void SetDeviceTimeZoneLocationName(HLERequestContext& ctx);

+ 19 - 17
src/core/hle/service/sm/sm.cpp

@@ -29,8 +29,7 @@ ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {
 
 ServiceManager::~ServiceManager() {
     for (auto& [name, port] : service_ports) {
-        port->GetClientPort().Close();
-        port->GetServerPort().Close();
+        port->Close();
     }
 
     if (deferral_event) {
@@ -50,8 +49,8 @@ static Result ValidateServiceName(const std::string& name) {
     return ResultSuccess;
 }
 
-Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
-                                       SessionRequestHandlerFactory handler) {
+Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, std::string name,
+                                       u32 max_sessions, SessionRequestHandlerFactory handler) {
     R_TRY(ValidateServiceName(name));
 
     std::scoped_lock lk{lock};
@@ -66,13 +65,17 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
     // Register the port.
     Kernel::KPort::Register(kernel, port);
 
-    service_ports.emplace(name, port);
+    service_ports.emplace(name, std::addressof(port->GetClientPort()));
     registered_services.emplace(name, handler);
     if (deferral_event) {
         deferral_event->Signal();
     }
 
-    return ResultSuccess;
+    // Set our output.
+    *out_server_port = std::addressof(port->GetServerPort());
+
+    // We succeeded.
+    R_SUCCEED();
 }
 
 Result ServiceManager::UnregisterService(const std::string& name) {
@@ -91,7 +94,8 @@ Result ServiceManager::UnregisterService(const std::string& name) {
     return ResultSuccess;
 }
 
-Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) {
+Result ServiceManager::GetServicePort(Kernel::KClientPort** out_client_port,
+                                      const std::string& name) {
     R_TRY(ValidateServiceName(name));
 
     std::scoped_lock lk{lock};
@@ -101,7 +105,7 @@ Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::strin
         return Service::SM::ResultNotRegistered;
     }
 
-    *out_port = it->second;
+    *out_client_port = it->second;
     return ResultSuccess;
 }
 
@@ -172,8 +176,8 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
     std::string name(PopServiceName(rp));
 
     // Find the named port.
-    Kernel::KPort* port{};
-    auto port_result = service_manager.GetServicePort(&port, name);
+    Kernel::KClientPort* client_port{};
+    auto port_result = service_manager.GetServicePort(&client_port, name);
     if (port_result == Service::SM::ResultInvalidServiceName) {
         LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
         return Service::SM::ResultInvalidServiceName;
@@ -187,7 +191,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
 
     // Create a new session.
     Kernel::KClientSession* session{};
-    if (const auto result = port->GetClientPort().CreateSession(&session); result.IsError()) {
+    if (const auto result = client_port->CreateSession(&session); result.IsError()) {
         LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
         return result;
     }
@@ -221,7 +225,9 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
     LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name,
               max_session_count, is_light);
 
-    if (const auto result = service_manager.RegisterService(name, max_session_count, nullptr);
+    Kernel::KServerPort* server_port{};
+    if (const auto result = service_manager.RegisterService(std::addressof(server_port), name,
+                                                            max_session_count, nullptr);
         result.IsError()) {
         LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", result.raw);
         IPC::ResponseBuilder rb{ctx, 2};
@@ -229,13 +235,9 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
         return;
     }
 
-    auto* port = Kernel::KPort::Create(kernel);
-    port->Initialize(ServerSessionCountMax, is_light, 0);
-    SCOPE_EXIT({ port->GetClientPort().Close(); });
-
     IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
     rb.Push(ResultSuccess);
-    rb.PushMoveObjects(port->GetServerPort());
+    rb.PushMoveObjects(server_port);
 }
 
 void SM::UnregisterService(HLERequestContext& ctx) {

+ 4 - 4
src/core/hle/service/sm/sm.h

@@ -56,10 +56,10 @@ public:
     explicit ServiceManager(Kernel::KernelCore& kernel_);
     ~ServiceManager();
 
-    Result RegisterService(std::string name, u32 max_sessions,
-                           SessionRequestHandlerFactory handler_factory);
+    Result RegisterService(Kernel::KServerPort** out_server_port, std::string name,
+                           u32 max_sessions, SessionRequestHandlerFactory handler_factory);
     Result UnregisterService(const std::string& name);
-    Result GetServicePort(Kernel::KPort** out_port, const std::string& name);
+    Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name);
 
     template <Common::DerivedFrom<SessionRequestHandler> T>
     std::shared_ptr<T> GetService(const std::string& service_name) const {
@@ -84,7 +84,7 @@ private:
     /// Map of registered services, retrieved using GetServicePort.
     std::mutex lock;
     std::unordered_map<std::string, SessionRequestHandlerFactory> registered_services;
-    std::unordered_map<std::string, Kernel::KPort*> service_ports;
+    std::unordered_map<std::string, Kernel::KClientPort*> service_ports;
 
     /// Kernel context
     Kernel::KernelCore& kernel;

+ 3 - 4
src/core/hle/service/sm/sm_controller.cpp

@@ -28,7 +28,6 @@ void Controller::ConvertCurrentObjectToDomain(HLERequestContext& ctx) {
 void Controller::CloneCurrentObject(HLERequestContext& ctx) {
     LOG_DEBUG(Service, "called");
 
-    auto& process = *ctx.GetThread().GetOwnerProcess();
     auto session_manager = ctx.GetManager();
 
     // FIXME: this is duplicated from the SVC, it should just call it instead
@@ -36,11 +35,11 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) {
 
     // Reserve a new session from the process resource limit.
     Kernel::KScopedResourceReservation session_reservation(
-        &process, Kernel::LimitableResource::SessionCountMax);
+        Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax);
     ASSERT(session_reservation.Succeeded());
 
     // Create the session.
-    Kernel::KSession* session = Kernel::KSession::Create(system.Kernel());
+    Kernel::KSession* session = Kernel::KSession::Create(kernel);
     ASSERT(session != nullptr);
 
     // Initialize the session.
@@ -50,7 +49,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) {
     session_reservation.Commit();
 
     // Register the session.
-    Kernel::KSession::Register(system.Kernel(), session);
+    Kernel::KSession::Register(kernel, session);
 
     // Register with server manager.
     session_manager->GetServerManager().RegisterSession(&session->GetServerSession(),

+ 4 - 3
src/core/loader/deconstructed_rom_directory.cpp

@@ -129,9 +129,10 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
     }
     metadata.Print();
 
-    // Enable NCE only for programs with 39-bit address space.
+    // Enable NCE only for applications with 39-bit address space.
     const bool is_39bit =
         metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit;
+    const bool is_application = metadata.GetPoolPartition() == FileSys::PoolPartition::Application;
     Settings::SetNceEnabled(is_39bit);
 
     const std::array static_modules = {"rtld",    "main",    "subsdk0", "subsdk1", "subsdk2",
@@ -147,7 +148,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
 
     const auto GetPatcher = [&](size_t i) -> Core::NCE::Patcher* {
 #ifdef HAS_NCE
-        if (Settings::IsNceEnabled()) {
+        if (is_application && Settings::IsNceEnabled()) {
             return &module_patchers[i];
         }
 #endif
@@ -175,7 +176,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
 
     // Enable direct memory mapping in case of NCE.
     const u64 fastmem_base = [&]() -> size_t {
-        if (Settings::IsNceEnabled()) {
+        if (is_application && Settings::IsNceEnabled()) {
             auto& buffer = system.DeviceMemory().buffer;
             buffer.EnableDirectMappedAddress();
             return reinterpret_cast<u64>(buffer.VirtualBasePointer());

+ 14 - 14
src/core/memory.cpp

@@ -45,7 +45,13 @@ struct Memory::Impl {
 
     void SetCurrentPageTable(Kernel::KProcess& process) {
         current_page_table = &process.GetPageTable().GetImpl();
-        current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
+
+        if (std::addressof(process) == system.ApplicationProcess() &&
+            Settings::IsFastmemEnabled()) {
+            current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
+        } else {
+            current_page_table->fastmem_arena = nullptr;
+        }
     }
 
     void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
@@ -57,7 +63,7 @@ struct Memory::Impl {
         MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target,
                  Common::PageType::Memory);
 
-        if (Settings::IsFastmemEnabled()) {
+        if (current_page_table->fastmem_arena) {
             system.DeviceMemory().buffer.Map(GetInteger(base),
                                              GetInteger(target) - DramMemoryMap::Base, size, perms);
         }
@@ -69,7 +75,7 @@ struct Memory::Impl {
         MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0,
                  Common::PageType::Unmapped);
 
-        if (Settings::IsFastmemEnabled()) {
+        if (current_page_table->fastmem_arena) {
             system.DeviceMemory().buffer.Unmap(GetInteger(base), size);
         }
     }
@@ -79,7 +85,7 @@ struct Memory::Impl {
         ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
         ASSERT_MSG((vaddr & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", vaddr);
 
-        if (!Settings::IsFastmemEnabled()) {
+        if (!current_page_table->fastmem_arena) {
             return;
         }
 
@@ -88,11 +94,6 @@ struct Memory::Impl {
         const bool is_x =
             True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled();
 
-        if (!current_page_table) {
-            system.DeviceMemory().buffer.Protect(vaddr, size, is_r, is_w, is_x);
-            return;
-        }
-
         u64 protect_bytes{};
         u64 protect_begin{};
         for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) {
@@ -239,7 +240,7 @@ struct Memory::Impl {
 
     bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped,
                    auto on_memory, auto on_rasterizer, auto increment) {
-        const auto& page_table = system.ApplicationProcess()->GetPageTable().GetImpl();
+        const auto& page_table = *current_page_table;
         std::size_t remaining_size = size;
         std::size_t page_index = addr >> YUZU_PAGEBITS;
         std::size_t page_offset = addr & YUZU_PAGEMASK;
@@ -484,7 +485,7 @@ struct Memory::Impl {
             return;
         }
 
-        if (Settings::IsFastmemEnabled()) {
+        if (current_page_table->fastmem_arena) {
             system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug);
         }
 
@@ -541,7 +542,7 @@ struct Memory::Impl {
             return;
         }
 
-        if (Settings::IsFastmemEnabled()) {
+        if (current_page_table->fastmem_arena) {
             const bool is_read_enable =
                 !Settings::values.use_reactive_flushing.GetValue() || !cached;
             system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached);
@@ -886,8 +887,7 @@ void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress
 }
 
 bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
-    const Kernel::KProcess& process = *system.ApplicationProcess();
-    const auto& page_table = process.GetPageTable().GetImpl();
+    const auto& page_table = *impl->current_page_table;
     const size_t page = vaddr >> YUZU_PAGEBITS;
     if (page >= page_table.pointers.size()) {
         return false;

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff