ソースを参照

general: properly support multiple memory instances

Liam 2 年 前
コミット
31bf57a310

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

+ 1 - 2
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);
+        GetCurrentProcessPointer(m_kernel)->GetResourceLimit(), LimitableResource::SessionCountMax);
     R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
 
     // Allocate a session normally.

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

+ 21 - 15
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,15 +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_dirty_memory_managers{}, m_exclusive_monitor{},
-      m_memory{kernel.System()} {}
+      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);
 
@@ -1147,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()) {
@@ -1197,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;
@@ -1239,9 +1248,6 @@ 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()) {
         for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {

+ 1 - 1
src/core/hle/kernel/k_process.h

@@ -552,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;

+ 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() {

+ 0 - 21
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,9 +119,6 @@ struct KernelCore::Impl {
         next_user_process_id = KProcess::ProcessIdMin;
         next_thread_id = 1;
 
-        global_handle_table->Finalize();
-        global_handle_table.reset();
-
         preemption_event = nullptr;
 
         // Cleanup persistent kernel objects
@@ -787,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;
@@ -877,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);
 }
@@ -1017,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 - 3
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);
 

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

+ 6 - 13
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.

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

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