diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 696a1f9eaa..cdebb0bd89 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -293,8 +293,6 @@ add_library(core STATIC
     hle/kernel/physical_memory.h
     hle/kernel/process_capability.cpp
     hle/kernel/process_capability.h
-    hle/kernel/service_thread.cpp
-    hle/kernel/service_thread.h
     hle/kernel/slab_helpers.h
     hle/kernel/svc.cpp
     hle/kernel/svc.h
@@ -684,6 +682,10 @@ add_library(core STATIC
     hle/service/ptm/ts.h
     hle/service/kernel_helpers.cpp
     hle/service/kernel_helpers.h
+    hle/service/mutex.cpp
+    hle/service/mutex.h
+    hle/service/server_manager.cpp
+    hle/service/server_manager.h
     hle/service/service.cpp
     hle/service/service.h
     hle/service/set/set.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index fb9b25d12c..4a1372d156 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -380,9 +380,7 @@ struct System::Impl {
             gpu_core->NotifyShutdown();
         }
 
-        kernel.ShutdownCores();
-        cpu_manager.Shutdown();
-        debugger.reset();
+        kernel.SuspendApplication(true);
         if (services) {
             services->KillNVNFlinger();
         }
@@ -398,6 +396,9 @@ struct System::Impl {
         gpu_core.reset();
         host1x_core.reset();
         perf_stats.reset();
+        kernel.ShutdownCores();
+        cpu_manager.Shutdown();
+        debugger.reset();
         kernel.Shutdown();
         memory.Reset();
 
@@ -938,6 +939,10 @@ const Network::RoomNetwork& System::GetRoomNetwork() const {
     return impl->room_network;
 }
 
+void System::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
+    return impl->kernel.RunServer(std::move(server_manager));
+}
+
 void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) {
     impl->execute_program_callback = std::move(callback);
 }
diff --git a/src/core/core.h b/src/core/core.h
index 0042ac170d..91e78672ef 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -61,6 +61,8 @@ namespace Glue {
 class ARPManager;
 }
 
+class ServerManager;
+
 namespace SM {
 class ServiceManager;
 } // namespace SM
@@ -417,6 +419,9 @@ public:
     /// Tells if the system debugger is enabled.
     [[nodiscard]] bool DebuggerEnabled() const;
 
+    /// Runs a server instance until shutdown.
+    void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);
+
     /// Type used for the frontend to designate a callback for System to re-launch the application
     /// using a specified program index.
     using ExecuteProgramCallback = std::function<void(std::size_t)>;
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index a9675df76d..a1589fecb5 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -16,6 +16,7 @@
 #include "core/debugger/debugger_interface.h"
 #include "core/debugger/gdbstub.h"
 #include "core/hle/kernel/global_scheduler_context.h"
+#include "core/hle/kernel/k_process.h"
 #include "core/hle/kernel/k_scheduler.h"
 
 template <typename Readable, typename Buffer, typename Callback>
@@ -284,12 +285,12 @@ private:
     void UpdateActiveThread() {
         const auto& threads{ThreadList()};
         if (std::find(threads.begin(), threads.end(), state->active_thread) == threads.end()) {
-            state->active_thread = threads[0];
+            state->active_thread = threads.front();
         }
     }
 
-    const std::vector<Kernel::KThread*>& ThreadList() {
-        return system.GlobalSchedulerContext().GetThreadList();
+    const std::list<Kernel::KThread*>& ThreadList() {
+        return system.ApplicationProcess()->GetThreadList();
     }
 
 private:
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 945ec528e1..18afe97e12 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -573,7 +573,7 @@ void GDBStub::HandleQuery(std::string_view command) {
         SendReply(PaginateBuffer(buffer, command.substr(21)));
     } else if (command.starts_with("fThreadInfo")) {
         // beginning of list
-        const auto& threads = system.GlobalSchedulerContext().GetThreadList();
+        const auto& threads = system.ApplicationProcess()->GetThreadList();
         std::vector<std::string> thread_ids;
         for (const auto& thread : threads) {
             thread_ids.push_back(fmt::format("{:x}", thread->GetThreadID()));
@@ -587,7 +587,7 @@ void GDBStub::HandleQuery(std::string_view command) {
         buffer += R"(<?xml version="1.0"?>)";
         buffer += "<threads>";
 
-        const auto& threads = system.GlobalSchedulerContext().GetThreadList();
+        const auto& threads = system.ApplicationProcess()->GetThreadList();
         for (const auto* thread : threads) {
             auto thread_name{GetThreadName(system, thread)};
             if (!thread_name) {
@@ -817,7 +817,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
 }
 
 Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
-    const auto& threads{system.GlobalSchedulerContext().GetThreadList()};
+    const auto& threads{system.ApplicationProcess()->GetThreadList()};
     for (auto* thread : threads) {
         if (thread->GetThreadID() == thread_id) {
             return thread;
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 38d6cfaff2..f8ab55d83e 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -15,6 +15,7 @@
 #include "core/hle/kernel/k_resource_limit.h"
 #include "core/hle/kernel/k_session.h"
 #include "core/hle/result.h"
+#include "core/hle/service/server_manager.h"
 
 namespace IPC {
 
@@ -145,7 +146,9 @@ public:
 
     template <class T>
     void PushIpcInterface(std::shared_ptr<T> iface) {
-        if (context->GetManager()->IsDomain()) {
+        auto manager{context->GetManager()};
+
+        if (manager->IsDomain()) {
             context->AddDomainObject(std::move(iface));
         } else {
             kernel.ApplicationProcess()->GetResourceLimit()->Reserve(
@@ -153,8 +156,11 @@ public:
 
             auto* session = Kernel::KSession::Create(kernel);
             session->Initialize(nullptr, iface->GetServiceName());
-            iface->RegisterSession(&session->GetServerSession(),
-                                   std::make_shared<Kernel::SessionRequestManager>(kernel));
+
+            auto next_manager = std::make_shared<Kernel::SessionRequestManager>(
+                kernel, manager->GetServerManager());
+            next_manager->SetSessionHandler(iface);
+            manager->GetServerManager().RegisterSession(&session->GetServerSession(), next_manager);
 
             context->AddMoveObject(&session->GetClientSession());
         }
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 494151eef9..876fbbe534 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -21,36 +21,18 @@
 #include "core/hle/kernel/k_server_session.h"
 #include "core/hle/kernel/k_thread.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/service_thread.h"
 #include "core/memory.h"
 
 namespace Kernel {
 
-SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
-                                             ServiceThreadType thread_type)
-    : kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
-                                          ? kernel.CreateServiceThread(service_name_)
-                                          : kernel.GetDefaultServiceThread()} {}
+SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_)
+    : kernel{kernel_} {}
 
-SessionRequestHandler::~SessionRequestHandler() {
-    kernel.ReleaseServiceThread(service_thread);
-}
+SessionRequestHandler::~SessionRequestHandler() = default;
 
-void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
-    auto* server_session = server_port->AcceptSession();
-    ASSERT(server_session != nullptr);
-
-    RegisterSession(server_session, std::make_shared<SessionRequestManager>(kernel));
-}
-
-void SessionRequestHandler::RegisterSession(KServerSession* server_session,
-                                            std::shared_ptr<SessionRequestManager> manager) {
-    manager->SetSessionHandler(shared_from_this());
-    service_thread.RegisterServerSession(server_session, manager);
-    server_session->Close();
-}
-
-SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {}
+SessionRequestManager::SessionRequestManager(KernelCore& kernel_,
+                                             Service::ServerManager& server_manager_)
+    : kernel{kernel_}, server_manager{server_manager_} {}
 
 SessionRequestManager::~SessionRequestManager() = default;
 
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 5bf4f171bc..b4364f9845 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -31,12 +31,8 @@ class ResponseBuilder;
 
 namespace Service {
 class ServiceFrameworkBase;
-}
-
-enum class ServiceThreadType {
-    Default,
-    CreateNew,
-};
+class ServerManager;
+} // namespace Service
 
 namespace Kernel {
 
@@ -53,9 +49,6 @@ class KThread;
 class KReadableEvent;
 class KSession;
 class SessionRequestManager;
-class ServiceThread;
-
-enum class ThreadWakeupReason;
 
 /**
  * Interface implemented by HLE Session handlers.
@@ -64,8 +57,7 @@ enum class ThreadWakeupReason;
  */
 class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
 public:
-    SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
-                          ServiceThreadType thread_type);
+    SessionRequestHandler(KernelCore& kernel_, const char* service_name_);
     virtual ~SessionRequestHandler();
 
     /**
@@ -79,17 +71,8 @@ public:
     virtual Result HandleSyncRequest(Kernel::KServerSession& session,
                                      Kernel::HLERequestContext& context) = 0;
 
-    void AcceptSession(KServerPort* server_port);
-    void RegisterSession(KServerSession* server_session,
-                         std::shared_ptr<SessionRequestManager> manager);
-
-    ServiceThread& GetServiceThread() const {
-        return service_thread;
-    }
-
 protected:
     KernelCore& kernel;
-    ServiceThread& service_thread;
 };
 
 using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@@ -102,7 +85,7 @@ using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
  */
 class SessionRequestManager final {
 public:
-    explicit SessionRequestManager(KernelCore& kernel);
+    explicit SessionRequestManager(KernelCore& kernel, Service::ServerManager& server_manager);
     ~SessionRequestManager();
 
     bool IsDomain() const {
@@ -155,23 +138,36 @@ public:
         session_handler = std::move(handler);
     }
 
-    ServiceThread& GetServiceThread() const {
-        return session_handler->GetServiceThread();
-    }
-
     bool HasSessionRequestHandler(const HLERequestContext& context) const;
 
     Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context);
     Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context);
 
+    Service::ServerManager& GetServerManager() {
+        return server_manager;
+    }
+
+    // TODO: remove this when sm: is implemented with the proper IUserInterface
+    // abstraction, creating a new C++ handler object for each session:
+
+    bool GetIsInitializedForSm() const {
+        return is_initialized_for_sm;
+    }
+
+    void SetIsInitializedForSm() {
+        is_initialized_for_sm = true;
+    }
+
 private:
     bool convert_to_domain{};
     bool is_domain{};
+    bool is_initialized_for_sm{};
     SessionRequestHandlerPtr session_handler;
     std::vector<SessionRequestHandlerPtr> domain_handlers;
 
 private:
     KernelCore& kernel;
+    Service::ServerManager& server_manager;
 };
 
 /**
@@ -374,6 +370,14 @@ public:
         return manager.lock();
     }
 
+    bool GetIsDeferred() const {
+        return is_deferred;
+    }
+
+    void SetIsDeferred(bool is_deferred_ = true) {
+        is_deferred = is_deferred_;
+    }
+
 private:
     friend class IPC::ResponseBuilder;
 
@@ -408,6 +412,7 @@ private:
     u32 domain_offset{};
 
     std::weak_ptr<SessionRequestManager> manager{};
+    bool is_deferred{false};
 
     KernelCore& kernel;
     Core::Memory::Memory& memory;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 0e4283a0cd..d9c1a0eb32 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -119,7 +119,6 @@ void KProcess::DecrementRunningThreadCount() {
 
     if (const auto prev = num_running_threads--; prev == 1) {
         // TODO(bunnei): Process termination to be implemented when multiprocess is supported.
-        UNIMPLEMENTED_MSG("KProcess termination is not implemennted!");
     }
 }
 
@@ -357,9 +356,6 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
     system_resource_size = metadata.GetSystemResourceSize();
     image_size = code_size;
 
-    // We currently do not support process-specific system resource
-    UNIMPLEMENTED_IF(system_resource_size != 0);
-
     KScopedResourceReservation memory_reservation(
         resource_limit, LimitableResource::PhysicalMemoryMax, code_size + system_resource_size);
     if (!memory_reservation.Succeeded()) {
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 2d3da9d669..599d05947a 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -29,6 +29,7 @@
 #include "core/hle/kernel/k_thread_queue.h"
 #include "core/hle/kernel/k_worker_task_manager.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/svc.h"
 #include "core/hle/kernel/svc_results.h"
 #include "core/hle/kernel/svc_types.h"
 #include "core/hle/result.h"
@@ -298,6 +299,25 @@ Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThr
                               ThreadType::User, system.GetCpuManager().GetGuestThreadFunc()));
 }
 
+Result KThread::InitializeServiceThread(Core::System& system, KThread* thread,
+                                        std::function<void()>&& func, s32 prio, s32 virt_core,
+                                        KProcess* owner) {
+    system.Kernel().GlobalSchedulerContext().AddThread(thread);
+    std::function<void()> func2{[&system, func{std::move(func)}] {
+        // Similar to UserModeThreadStarter.
+        system.Kernel().CurrentScheduler()->OnThreadStart();
+
+        // Run the guest function.
+        func();
+
+        // Exit.
+        Svc::ExitThread(system);
+    }};
+
+    R_RETURN(InitializeThread(thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority,
+                              std::move(func2)));
+}
+
 void KThread::PostDestroy(uintptr_t arg) {
     KProcess* owner = reinterpret_cast<KProcess*>(arg & ~1ULL);
     const bool resource_limit_release_hint = (arg & 1);
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index ca82ce3b62..a04de21bce 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -434,6 +434,10 @@ public:
                                                      VAddr user_stack_top, s32 prio, s32 virt_core,
                                                      KProcess* owner);
 
+    [[nodiscard]] static Result InitializeServiceThread(Core::System& system, KThread* thread,
+                                                        std::function<void()>&& thread_func,
+                                                        s32 prio, s32 virt_core, KProcess* owner);
+
 public:
     struct StackParameters {
         u8 svc_permission[0x10];
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 2ff253183b..ce94d3605f 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -34,14 +34,15 @@
 #include "core/hle/kernel/k_process.h"
 #include "core/hle/kernel/k_resource_limit.h"
 #include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_resource_reservation.h"
 #include "core/hle/kernel/k_shared_memory.h"
 #include "core/hle/kernel/k_system_resource.h"
 #include "core/hle/kernel/k_thread.h"
 #include "core/hle/kernel/k_worker_task_manager.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/physical_core.h"
-#include "core/hle/kernel/service_thread.h"
 #include "core/hle/result.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/memory.h"
 
@@ -55,9 +56,7 @@ struct KernelCore::Impl {
     static constexpr size_t BlockInfoSlabHeapSize = 4000;
     static constexpr size_t ReservedDynamicPageCount = 64;
 
-    explicit Impl(Core::System& system_, KernelCore& kernel_)
-        : service_threads_manager{1, "ServiceThreadsManager"},
-          service_thread_barrier{2}, system{system_} {}
+    explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {}
 
     void SetMulticore(bool is_multi) {
         is_multicore = is_multi;
@@ -98,8 +97,6 @@ struct KernelCore::Impl {
 
         InitializeHackSharedMemory();
         RegisterHostThread(nullptr);
-
-        default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
     }
 
     void InitializeCores() {
@@ -140,11 +137,6 @@ struct KernelCore::Impl {
 
         preemption_event = nullptr;
 
-        for (auto& iter : named_ports) {
-            iter.second->Close();
-        }
-        named_ports.clear();
-
         exclusive_monitor.reset();
 
         // Cleanup persistent kernel objects
@@ -207,8 +199,9 @@ struct KernelCore::Impl {
     }
 
     void CloseServices() {
-        // Ensures all service threads gracefully shutdown.
-        ClearServiceThreads();
+        // Ensures all servers gracefully shutdown.
+        std::scoped_lock lk{server_lock};
+        server_managers.clear();
     }
 
     void InitializePhysicalCores() {
@@ -761,55 +754,6 @@ struct KernelCore::Impl {
                                       "HidBus:SharedMemory");
     }
 
-    KClientPort* CreateNamedServicePort(std::string name) {
-        auto search = service_interface_factory.find(name);
-        if (search == service_interface_factory.end()) {
-            UNIMPLEMENTED();
-            return {};
-        }
-
-        return &search->second(system.ServiceManager(), system);
-    }
-
-    void RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
-        auto search = service_interface_handlers.find(name);
-        if (search == service_interface_handlers.end()) {
-            return;
-        }
-
-        search->second(system.ServiceManager(), server_port);
-    }
-
-    Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
-        auto* ptr = new ServiceThread(kernel, name);
-
-        service_threads_manager.QueueWork(
-            [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
-
-        return *ptr;
-    }
-
-    void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
-        auto* ptr = &service_thread;
-
-        if (ptr == default_service_thread) {
-            // Nothing to do here, the service is using default_service_thread, which will be
-            // released on shutdown.
-            return;
-        }
-
-        service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
-    }
-
-    void ClearServiceThreads() {
-        service_threads_manager.QueueWork([this] {
-            service_threads.clear();
-            default_service_thread = nullptr;
-            service_thread_barrier.Sync();
-        });
-        service_thread_barrier.Sync();
-    }
-
     std::mutex registered_objects_lock;
     std::mutex registered_in_use_objects_lock;
 
@@ -839,14 +783,12 @@ struct KernelCore::Impl {
 
     std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
 
-    /// Map of named ports managed by the kernel, which can be retrieved using
-    /// the ConnectToPort SVC.
-    std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
-    std::unordered_map<std::string, ServiceInterfaceHandlerFn> service_interface_handlers;
-    NamedPortTable named_ports;
     std::unordered_set<KAutoObject*> registered_objects;
     std::unordered_set<KAutoObject*> registered_in_use_objects;
 
+    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;
 
@@ -881,12 +823,6 @@ struct KernelCore::Impl {
     // Memory layout
     std::unique_ptr<KMemoryLayout> memory_layout;
 
-    // Threads used for services
-    std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
-    ServiceThread* default_service_thread{};
-    Common::ThreadWorker service_threads_manager;
-    Common::Barrier service_thread_barrier;
-
     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{};
     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
 
@@ -1050,23 +986,6 @@ void KernelCore::PrepareReschedule(std::size_t id) {
     // TODO: Reimplement, this
 }
 
-void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) {
-    impl->service_interface_factory.emplace(std::move(name), factory);
-}
-
-void KernelCore::RegisterInterfaceForNamedService(std::string name,
-                                                  ServiceInterfaceHandlerFn&& handler) {
-    impl->service_interface_handlers.emplace(std::move(name), handler);
-}
-
-KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
-    return impl->CreateNamedServicePort(std::move(name));
-}
-
-void KernelCore::RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
-    impl->RegisterNamedServiceHandler(std::move(name), server_port);
-}
-
 void KernelCore::RegisterKernelObject(KAutoObject* object) {
     std::scoped_lock lk{impl->registered_objects_lock};
     impl->registered_objects.insert(object);
@@ -1087,8 +1006,19 @@ void KernelCore::UnregisterInUseObject(KAutoObject* object) {
     impl->registered_in_use_objects.erase(object);
 }
 
-bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
-    return port != impl->named_ports.cend();
+void KernelCore::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
+    auto* manager = server_manager.get();
+
+    {
+        std::scoped_lock lk{impl->server_lock};
+        if (impl->is_shutting_down) {
+            return;
+        }
+
+        impl->server_managers.emplace_back(std::move(server_manager));
+    }
+
+    manager->LoopProcess();
 }
 
 u32 KernelCore::CreateNewObjectID() {
@@ -1127,6 +1057,87 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) {
     }
 }
 
+static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
+                                      std::string&& thread_name, std::function<void()>&& func) {
+    // Reserve a new thread from the process resource limit.
+    KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
+    ASSERT(thread_reservation.Succeeded());
+
+    // Initialize the thread.
+    KThread* thread = KThread::Create(kernel);
+    ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process)));
+
+    // Commit the thread reservation.
+    thread_reservation.Commit();
+
+    return std::jthread(
+        [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] {
+            // Set the thread name.
+            Common::SetCurrentThreadName(thread_name.c_str());
+
+            // Register the thread.
+            kernel.RegisterHostThread(thread);
+
+            // Run the callback.
+            func();
+
+            // Close the thread.
+            // This will free the process if it is the last reference.
+            thread->Close();
+        });
+}
+
+std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
+                                              std::function<void()> func) {
+    // Make a new process.
+    KProcess* process = KProcess::Create(*this);
+    ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
+                                            GetSystemResourceLimit())));
+
+    // Ensure that we don't hold onto any extra references.
+    SCOPE_EXIT({ process->Close(); });
+
+    // Run the host thread.
+    return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func));
+}
+
+std::jthread KernelCore::RunOnHostCoreThread(std::string&& thread_name,
+                                             std::function<void()> func) {
+    // Get the current process.
+    KProcess* process = GetCurrentProcessPointer(*this);
+
+    // Run the host thread.
+    return RunHostThreadFunc(*this, process, std::move(thread_name), std::move(func));
+}
+
+void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func) {
+    constexpr s32 ServiceThreadPriority = 16;
+    constexpr s32 ServiceThreadCore = 3;
+
+    // Make a new process.
+    KProcess* process = KProcess::Create(*this);
+    ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
+                                            GetSystemResourceLimit())));
+
+    // Ensure that we don't hold onto any extra references.
+    SCOPE_EXIT({ process->Close(); });
+
+    // Reserve a new thread from the process resource limit.
+    KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
+    ASSERT(thread_reservation.Succeeded());
+
+    // Initialize the thread.
+    KThread* thread = KThread::Create(*this);
+    ASSERT(R_SUCCEEDED(KThread::InitializeServiceThread(
+        System(), thread, std::move(func), ServiceThreadPriority, ServiceThreadCore, process)));
+
+    // Commit the thread reservation.
+    thread_reservation.Commit();
+
+    // Begin running the thread.
+    ASSERT(R_SUCCEEDED(thread->Run()));
+}
+
 u32 KernelCore::GetCurrentHostThreadID() const {
     return impl->GetCurrentHostThreadID();
 }
@@ -1271,18 +1282,6 @@ void KernelCore::ExitSVCProfile() {
     MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
 }
 
-Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
-    return impl->CreateServiceThread(*this, name);
-}
-
-Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
-    return *impl->default_service_thread;
-}
-
-void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
-    impl->ReleaseServiceThread(service_thread);
-}
-
 Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
     return impl->slab_resource_counts;
 }
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 6e0668f7f9..4449f69493 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -9,6 +9,8 @@
 #include <string>
 #include <unordered_map>
 #include <vector>
+
+#include "common/polyfill_thread.h"
 #include "core/hardware_properties.h"
 #include "core/hle/kernel/k_auto_object.h"
 #include "core/hle/kernel/k_slab_heap.h"
@@ -24,6 +26,10 @@ class CoreTiming;
 struct EventType;
 } // namespace Core::Timing
 
+namespace Service {
+class ServerManager;
+}
+
 namespace Service::SM {
 class ServiceManager;
 }
@@ -65,13 +71,6 @@ class KTransferMemory;
 class KWorkerTaskManager;
 class KCodeMemory;
 class PhysicalCore;
-class ServiceThread;
-class Synchronization;
-
-using ServiceInterfaceFactory =
-    std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
-
-using ServiceInterfaceHandlerFn = std::function<void(Service::SM::ServiceManager&, KServerPort*)>;
 
 namespace Init {
 struct KSlabResourceCounts;
@@ -80,15 +79,8 @@ struct KSlabResourceCounts;
 template <typename T>
 class KSlabHeap;
 
-using EmuThreadHandle = uintptr_t;
-constexpr EmuThreadHandle EmuThreadHandleInvalid{};
-constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63};
-
 /// Represents a single instance of the kernel.
 class KernelCore {
-private:
-    using NamedPortTable = std::unordered_map<std::string, KClientPort*>;
-
 public:
     /// Constructs an instance of the kernel using the given System
     /// instance as a context for any necessary system-related state,
@@ -196,18 +188,6 @@ public:
 
     void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
 
-    /// Registers a named HLE service, passing a factory used to open a port to that service.
-    void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory);
-
-    /// Registers a setup function for the named HLE service.
-    void RegisterInterfaceForNamedService(std::string name, ServiceInterfaceHandlerFn&& handler);
-
-    /// Opens a port to a service previously registered with RegisterNamedService.
-    KClientPort* CreateNamedServicePort(std::string name);
-
-    /// Accepts a session on a port created by CreateNamedServicePort.
-    void RegisterNamedServiceHandler(std::string name, KServerPort* server_port);
-
     /// Registers all kernel objects with the global emulation state, this is purely for tracking
     /// leaks after emulation has been shutdown.
     void RegisterKernelObject(KAutoObject* object);
@@ -224,8 +204,8 @@ public:
     /// destroyed during the current emulation session.
     void UnregisterInUseObject(KAutoObject* object);
 
-    /// Determines whether or not the given port is a valid named port.
-    bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
+    // Runs the given server manager until shutdown.
+    void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);
 
     /// Gets the current host_thread/guest_thread pointer.
     KThread* GetCurrentEmuThread() const;
@@ -242,6 +222,12 @@ public:
     /// Register the current thread as a non CPU core thread.
     void RegisterHostThread(KThread* existing_thread = nullptr);
 
+    void RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func);
+
+    std::jthread RunOnHostCoreProcess(std::string&& process_name, std::function<void()> func);
+
+    std::jthread RunOnHostCoreThread(std::string&& thread_name, std::function<void()> func);
+
     /// Gets global data for KObjectName.
     KObjectNameGlobalData& ObjectNameGlobalData();
 
@@ -310,33 +296,6 @@ public:
 
     void ExitSVCProfile();
 
-    /**
-     * Creates a host thread to execute HLE service requests, which are used to execute service
-     * routines asynchronously. While these are allocated per ServerSession, these need to be owned
-     * and managed outside of ServerSession to avoid a circular dependency. In general, most
-     * services can just use the default service thread, and not need their own host service thread.
-     * See GetDefaultServiceThread.
-     * @param name String name for the ServerSession creating this thread, used for debug
-     * purposes.
-     * @returns A reference to the newly created service thread.
-     */
-    Kernel::ServiceThread& CreateServiceThread(const std::string& name);
-
-    /**
-     * Gets the default host service thread, which executes HLE service requests. Unless service
-     * requests need to block on the host, the default service thread should be used in favor of
-     * creating a new service thread.
-     * @returns A reference to the default service thread.
-     */
-    Kernel::ServiceThread& GetDefaultServiceThread() const;
-
-    /**
-     * Releases a HLE service thread, instructing KernelCore to free it. This should be called when
-     * the ServerSession associated with the thread is destroyed.
-     * @param service_thread Service thread to release.
-     */
-    void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
-
     /// Workaround for single-core mode when preempting threads while idle.
     bool IsPhantomModeForSingleCore() const;
     void SetIsPhantomModeForSingleCore(bool value);
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
deleted file mode 100644
index 38afa720b9..0000000000
--- a/src/core/hle/kernel/service_thread.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <functional>
-#include <map>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include "common/polyfill_thread.h"
-#include "common/scope_exit.h"
-#include "common/thread.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_scoped_resource_reservation.h"
-#include "core/hle/kernel/k_session.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/service_thread.h"
-
-namespace Kernel {
-
-class ServiceThread::Impl final {
-public:
-    explicit Impl(KernelCore& kernel, const std::string& service_name);
-    ~Impl();
-
-    void WaitAndProcessImpl();
-    void SessionClosed(KServerSession* server_session,
-                       std::shared_ptr<SessionRequestManager> manager);
-    void LoopProcess();
-
-    void RegisterServerSession(KServerSession* session,
-                               std::shared_ptr<SessionRequestManager> manager);
-
-private:
-    KernelCore& kernel;
-    const std::string m_service_name;
-
-    std::jthread m_host_thread{};
-    std::mutex m_session_mutex{};
-    std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions{};
-    KEvent* m_wakeup_event{};
-    KThread* m_thread{};
-    std::atomic<bool> m_shutdown_requested{};
-};
-
-void ServiceThread::Impl::WaitAndProcessImpl() {
-    // Create local list of waitable sessions.
-    std::vector<KSynchronizationObject*> objs;
-    std::vector<std::shared_ptr<SessionRequestManager>> managers;
-
-    {
-        // Lock to get the set.
-        std::scoped_lock lk{m_session_mutex};
-
-        // Reserve the needed quantity.
-        objs.reserve(m_sessions.size() + 1);
-        managers.reserve(m_sessions.size());
-
-        // Copy to our local list.
-        for (const auto& [session, manager] : m_sessions) {
-            objs.push_back(session);
-            managers.push_back(manager);
-        }
-
-        // Insert the wakeup event at the end.
-        objs.push_back(&m_wakeup_event->GetReadableEvent());
-    }
-
-    // Wait on the list of sessions.
-    s32 index{-1};
-    Result rc = KSynchronizationObject::Wait(kernel, &index, objs.data(),
-                                             static_cast<s32>(objs.size()), -1);
-    ASSERT(!rc.IsFailure());
-
-    // If this was the wakeup event, clear it and finish.
-    if (index >= static_cast<s64>(objs.size() - 1)) {
-        m_wakeup_event->Clear();
-        return;
-    }
-
-    // This event is from a server session.
-    auto* server_session = static_cast<KServerSession*>(objs[index]);
-    auto& manager = managers[index];
-
-    // Fetch the HLE request context.
-    std::shared_ptr<HLERequestContext> context;
-    rc = server_session->ReceiveRequest(&context, manager);
-
-    // If the session was closed, handle that.
-    if (rc == ResultSessionClosed) {
-        SessionClosed(server_session, manager);
-
-        // Finish.
-        return;
-    }
-
-    // TODO: handle other cases
-    ASSERT(rc == ResultSuccess);
-
-    // Perform the request.
-    Result service_rc = manager->CompleteSyncRequest(server_session, *context);
-
-    // Reply to the client.
-    rc = server_session->SendReplyHLE();
-
-    if (rc == ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) {
-        SessionClosed(server_session, manager);
-        return;
-    }
-
-    // TODO: handle other cases
-    ASSERT(rc == ResultSuccess);
-    ASSERT(service_rc == ResultSuccess);
-}
-
-void ServiceThread::Impl::SessionClosed(KServerSession* server_session,
-                                        std::shared_ptr<SessionRequestManager> manager) {
-    {
-        // Lock to get the set.
-        std::scoped_lock lk{m_session_mutex};
-
-        // Erase the session.
-        ASSERT(m_sessions.erase(server_session) == 1);
-    }
-
-    // Close our reference to the server session.
-    server_session->Close();
-}
-
-void ServiceThread::Impl::LoopProcess() {
-    Common::SetCurrentThreadName(m_service_name.c_str());
-
-    kernel.RegisterHostThread(m_thread);
-
-    while (!m_shutdown_requested.load()) {
-        WaitAndProcessImpl();
-    }
-}
-
-void ServiceThread::Impl::RegisterServerSession(KServerSession* server_session,
-                                                std::shared_ptr<SessionRequestManager> manager) {
-    // Open the server session.
-    server_session->Open();
-
-    {
-        // Lock to get the set.
-        std::scoped_lock lk{m_session_mutex};
-
-        // Insert the session and manager.
-        m_sessions[server_session] = manager;
-    }
-
-    // Signal the wakeup event.
-    m_wakeup_event->Signal();
-}
-
-ServiceThread::Impl::~Impl() {
-    // Shut down the processing thread.
-    m_shutdown_requested.store(true);
-    m_wakeup_event->Signal();
-    m_host_thread.join();
-
-    // Close all remaining sessions.
-    for (const auto& [server_session, manager] : m_sessions) {
-        server_session->Close();
-    }
-
-    // Destroy remaining managers.
-    m_sessions.clear();
-
-    // Close event.
-    m_wakeup_event->GetReadableEvent().Close();
-    m_wakeup_event->Close();
-
-    // Close thread.
-    m_thread->Close();
-}
-
-ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
-    : kernel{kernel_}, m_service_name{service_name} {
-    // Initialize event.
-    m_wakeup_event = KEvent::Create(kernel);
-    m_wakeup_event->Initialize(nullptr);
-
-    // Initialize thread.
-    m_thread = KThread::Create(kernel);
-    ASSERT(KThread::InitializeDummyThread(m_thread, nullptr).IsSuccess());
-
-    // Start thread.
-    m_host_thread = std::jthread([this] { LoopProcess(); });
-}
-
-ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name)
-    : impl{std::make_unique<Impl>(kernel, name)} {}
-
-ServiceThread::~ServiceThread() = default;
-
-void ServiceThread::RegisterServerSession(KServerSession* session,
-                                          std::shared_ptr<SessionRequestManager> manager) {
-    impl->RegisterServerSession(session, manager);
-}
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h
deleted file mode 100644
index fb43255317..0000000000
--- a/src/core/hle/kernel/service_thread.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-namespace Kernel {
-
-class HLERequestContext;
-class KernelCore;
-class KSession;
-class SessionRequestManager;
-
-class ServiceThread final {
-public:
-    explicit ServiceThread(KernelCore& kernel, const std::string& name);
-    ~ServiceThread();
-
-    void RegisterServerSession(KServerSession* session,
-                               std::shared_ptr<SessionRequestManager> manager);
-
-private:
-    class Impl;
-    std::unique_ptr<Impl> impl;
-};
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index 58dc475082..cbed4dc8c6 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -126,6 +126,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
             *result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
             return ResultSuccess;
 
+        case InfoType::IsApplication:
+            LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
+            *result = true;
+            return ResultSuccess;
+
         case InfoType::FreeThreadCount:
             *result = process->GetFreeThreadCount();
             return ResultSuccess;
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index 0b5b4ba2b6..78c2a8d171 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -12,56 +12,40 @@
 
 namespace Kernel::Svc {
 
-/// Connect to an OS service given the port name, returns the handle to the port to out
-Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
-    auto& memory = system.Memory();
-    if (!memory.IsValidVirtualAddress(port_name_address)) {
-        LOG_ERROR(Kernel_SVC,
-                  "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
-                  port_name_address);
-        return ResultNotFound;
-    }
+Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) {
+    // Copy the provided name from user memory to kernel memory.
+    auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
 
-    static constexpr std::size_t PortNameMaxLength = 11;
-    // Read 1 char beyond the max allowed port name to detect names that are too long.
-    const std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
-    if (port_name.size() > PortNameMaxLength) {
-        LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
-                  port_name.size());
-        return ResultOutOfRange;
-    }
+    std::array<char, KObjectName::NameLengthMax> name{};
+    std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
 
-    LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
+    // Validate that the name is valid.
+    R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
 
     // Get the current handle table.
-    auto& kernel = system.Kernel();
-    auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
+    auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
 
     // Find the client port.
-    auto port = kernel.CreateNamedServicePort(port_name);
-    if (!port) {
-        LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
-        return ResultNotFound;
-    }
+    auto port = KObjectName::Find<KClientPort>(system.Kernel(), name.data());
+    R_UNLESS(port.IsNotNull(), ResultNotFound);
 
     // Reserve a handle for the port.
     // NOTE: Nintendo really does write directly to the output handle here.
     R_TRY(handle_table.Reserve(out));
-    auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); });
+    ON_RESULT_FAILURE {
+        handle_table.Unreserve(*out);
+    };
 
     // Create a session.
-    KClientSession* session{};
+    KClientSession* session;
     R_TRY(port->CreateSession(std::addressof(session)));
 
-    kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
-
     // Register the session in the table, close the extra reference.
     handle_table.Register(*out, session);
     session->Close();
 
     // We succeeded.
-    handle_guard.Cancel();
-    return ResultSuccess;
+    R_SUCCEED();
 }
 
 Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
@@ -77,9 +61,12 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
 
 Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
                        int32_t max_sessions) {
+    // Copy the provided name from user memory to kernel memory.
+    auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
+
     // Copy the provided name from user memory to kernel memory.
     std::array<char, KObjectName::NameLengthMax> name{};
-    system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
+    std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
 
     // Validate that sessions and name are valid.
     R_UNLESS(max_sessions >= 0, ResultOutOfRange);
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 1241fcdffd..c3e5c4462d 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -25,6 +25,7 @@
 #include "core/hle/service/acc/errors.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/glue/glue_manager.h"
+#include "core/hle/service/server_manager.h"
 #include "core/loader/loader.h"
 
 namespace Service::Account {
@@ -950,18 +951,20 @@ Module::Interface::Interface(std::shared_ptr<Module> module_,
 
 Module::Interface::~Interface() = default;
 
-void InstallInterfaces(Core::System& system) {
+void LoopProcess(Core::System& system) {
     auto module = std::make_shared<Module>();
     auto profile_manager = std::make_shared<ProfileManager>();
+    auto server_manager = std::make_unique<ServerManager>(system);
 
-    std::make_shared<ACC_AA>(module, profile_manager, system)
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<ACC_SU>(module, profile_manager, system)
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<ACC_U0>(module, profile_manager, system)
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<ACC_U1>(module, profile_manager, system)
-        ->InstallAsService(system.ServiceManager());
+    server_manager->RegisterNamedService("acc:aa",
+                                         std::make_shared<ACC_AA>(module, profile_manager, system));
+    server_manager->RegisterNamedService("acc:su",
+                                         std::make_shared<ACC_SU>(module, profile_manager, system));
+    server_manager->RegisterNamedService("acc:u0",
+                                         std::make_shared<ACC_U0>(module, profile_manager, system));
+    server_manager->RegisterNamedService("acc:u1",
+                                         std::make_shared<ACC_U1>(module, profile_manager, system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 9411b0b92d..a2fdafd828 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -67,7 +67,6 @@ public:
     };
 };
 
-/// Registers all ACC services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Account
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9a7316e279..3cd772b83c 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -32,6 +32,7 @@
 #include "core/hle/service/ns/ns.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
 #include "core/hle/service/pm/pm.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/hle/service/vi/vi.h"
 #include "core/memory.h"
@@ -1830,17 +1831,21 @@ void IApplicationFunctions::PrepareForJit(Kernel::HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
-                       Core::System& system) {
+void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system) {
     auto message_queue = std::make_shared<AppletMessageQueue>(system);
     // Needed on game boot
     message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
 
-    std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
-    std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
-    std::make_shared<IdleSys>(system)->InstallAsService(service_manager);
-    std::make_shared<OMM>(system)->InstallAsService(service_manager);
-    std::make_shared<SPSM>(system)->InstallAsService(service_manager);
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService(
+        "appletAE", std::make_shared<AppletAE>(nvflinger, message_queue, system));
+    server_manager->RegisterNamedService(
+        "appletOE", std::make_shared<AppletOE>(nvflinger, message_queue, system));
+    server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
+    server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
+    server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index a0fbfcfc5f..79e2263d73 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -396,8 +396,6 @@ public:
     ~IProcessWindingController() override;
 };
 
-/// Registers all AM services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
-                       Core::System& system);
+void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system);
 
 } // namespace Service::AM
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 1bbf057cbc..fed51cfd69 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -17,6 +17,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/aoc/aoc_u.h"
+#include "core/hle/service/server_manager.h"
 #include "core/loader/loader.h"
 
 namespace Service::AOC {
@@ -314,8 +315,10 @@ void AOC_U::CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ct
     rb.PushIpcInterface<IPurchaseEventManager>(system);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<AOC_U>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+    server_manager->RegisterNamedService("aoc:u", std::make_shared<AOC_U>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::AOC
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 6c1ce601a6..5e7087e509 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -40,7 +40,6 @@ private:
     Kernel::KEvent* aoc_change_event;
 };
 
-/// Registers all AOC services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::AOC
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 44b2927a62..c23ff293d3 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -4,20 +4,24 @@
 #include "core/core.h"
 #include "core/hle/service/apm/apm.h"
 #include "core/hle/service/apm/apm_interface.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::APM {
 
 Module::Module() = default;
 Module::~Module() = default;
 
-void InstallInterfaces(Core::System& system) {
-    auto module_ = std::make_shared<Module>();
-    std::make_shared<APM>(system, module_, system.GetAPMController(), "apm")
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:am")
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<APM_Sys>(system, system.GetAPMController())
-        ->InstallAsService(system.ServiceManager());
+void LoopProcess(Core::System& system) {
+    auto module = std::make_shared<Module>();
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService(
+        "apm", std::make_shared<APM>(system, module, system.GetAPMController(), "apm"));
+    server_manager->RegisterNamedService(
+        "apm:am", std::make_shared<APM>(system, module, system.GetAPMController(), "apm:am"));
+    server_manager->RegisterNamedService(
+        "apm:sys", std::make_shared<APM_Sys>(system, system.GetAPMController()));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::APM
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h
index 0fecc766a0..e188b4e446 100644
--- a/src/core/hle/service/apm/apm.h
+++ b/src/core/hle/service/apm/apm.h
@@ -15,7 +15,6 @@ public:
     ~Module();
 };
 
-/// Registers all AM services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::APM
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 053e8f9dd1..26dec71475 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -203,9 +203,8 @@ private:
 };
 
 AudInU::AudInU(Core::System& system_)
-    : ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew},
-      service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
-                                              system_)} {
+    : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
+      impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &AudInU::ListAudioIns, "ListAudioIns"},
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index ed36e34481..dccd16309f 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -1,6 +1,7 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "core/core.h"
 #include "core/hle/service/audio/audctl.h"
 #include "core/hle/service/audio/audin_u.h"
 #include "core/hle/service/audio/audio.h"
@@ -9,18 +10,22 @@
 #include "core/hle/service/audio/audrec_u.h"
 #include "core/hle/service/audio/audren_u.h"
 #include "core/hle/service/audio/hwopus.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::Audio {
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<AudCtl>(system)->InstallAsService(service_manager);
-    std::make_shared<AudOutU>(system)->InstallAsService(service_manager);
-    std::make_shared<AudInU>(system)->InstallAsService(service_manager);
-    std::make_shared<AudRecA>(system)->InstallAsService(service_manager);
-    std::make_shared<AudRecU>(system)->InstallAsService(service_manager);
-    std::make_shared<AudRenU>(system)->InstallAsService(service_manager);
-    std::make_shared<HwOpus>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system));
+    server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
+    server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
+    server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
+    server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system));
+    server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
+    server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h
index bbb2214e40..d70f022c73 100644
--- a/src/core/hle/service/audio/audio.h
+++ b/src/core/hle/service/audio/audio.h
@@ -13,7 +13,6 @@ class ServiceManager;
 
 namespace Service::Audio {
 
-/// Registers all Audio services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 29751f075a..991e30ba19 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -26,9 +26,8 @@ public:
     explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
                        size_t session_id, const std::string& device_name,
                        const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id)
-        : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew},
-          service_context{system_, "IAudioOut"}, event{service_context.CreateEvent(
-                                                     "AudioOutEvent")},
+        : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
+          event{service_context.CreateEvent("AudioOutEvent")},
           impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
 
         // clang-format off
@@ -221,9 +220,8 @@ private:
 };
 
 AudOutU::AudOutU(Core::System& system_)
-    : ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew},
-      service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>(
-                                               system_)} {
+    : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"},
+      impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 7d730421de..6c12f00a19 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -35,10 +35,9 @@ public:
                             AudioCore::AudioRendererParameterInternal& params,
                             Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
                             u32 process_handle, u64 applet_resource_user_id, s32 session_id)
-        : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew},
-          service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent(
-                                                          "IAudioRendererEvent")},
-          manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
+        : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
+          rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
+          impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
         // clang-format off
         static const FunctionInfo functions[] = {
             {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -243,10 +242,8 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
 public:
     explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
                           u32 device_num)
-        : ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew},
-          service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>(
-                                                        system_, applet_resource_user_id,
-                                                        revision)},
+        : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
+          impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
           event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
         static const FunctionInfo functions[] = {
             {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
@@ -421,7 +418,7 @@ private:
 };
 
 AudRenU::AudRenU(Core::System& system_)
-    : ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew},
+    : ServiceFramework{system_, "audren:u"},
       service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
     // clang-format off
     static const FunctionInfo functions[] = {
diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp
index 6e6fed2275..1db3f026b6 100644
--- a/src/core/hle/service/bcat/bcat_module.cpp
+++ b/src/core/hle/service/bcat/bcat_module.cpp
@@ -15,6 +15,7 @@
 #include "core/hle/service/bcat/bcat.h"
 #include "core/hle/service/bcat/bcat_module.h"
 #include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::BCAT {
 
@@ -585,16 +586,23 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
 
 Module::Interface::~Interface() = default;
 
-void InstallInterfaces(Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
     auto module = std::make_shared<Module>();
-    std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a")
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m")
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u")
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s")
-        ->InstallAsService(system.ServiceManager());
+
+    server_manager->RegisterNamedService(
+        "bcat:a",
+        std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a"));
+    server_manager->RegisterNamedService(
+        "bcat:m",
+        std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m"));
+    server_manager->RegisterNamedService(
+        "bcat:u",
+        std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u"));
+    server_manager->RegisterNamedService(
+        "bcat:s",
+        std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s"));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/bcat_module.h b/src/core/hle/service/bcat/bcat_module.h
index b2fcf9bfbf..0c134d1ff8 100644
--- a/src/core/hle/service/bcat/bcat_module.h
+++ b/src/core/hle/service/bcat/bcat_module.h
@@ -39,8 +39,7 @@ public:
     };
 };
 
-/// Registers all BCAT services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace BCAT
 
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp
index 4661635385..91b15e256c 100644
--- a/src/core/hle/service/bpc/bpc.cpp
+++ b/src/core/hle/service/bpc/bpc.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/bpc/bpc.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::BPC {
 
@@ -54,9 +54,12 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<BPC>(system)->InstallAsService(sm);
-    std::make_shared<BPC_R>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("bpc", std::make_shared<BPC>(system));
+    server_manager->RegisterNamedService("bpc:r", std::make_shared<BPC_R>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::BPC
diff --git a/src/core/hle/service/bpc/bpc.h b/src/core/hle/service/bpc/bpc.h
index 8adc2f9624..524391ddb5 100644
--- a/src/core/hle/service/bpc/bpc.h
+++ b/src/core/hle/service/bpc/bpc.h
@@ -13,6 +13,6 @@ class ServiceManager;
 
 namespace Service::BPC {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::BPC
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index ec7e5320cb..ed020d03fa 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -7,6 +7,7 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/btdrv/btdrv.h"
 #include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
 
@@ -196,9 +197,12 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<BtDrv>(system)->InstallAsService(sm);
-    std::make_shared<Bt>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("btdrv", std::make_shared<BtDrv>(system));
+    server_manager->RegisterNamedService("bt", std::make_shared<Bt>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::BtDrv
diff --git a/src/core/hle/service/btdrv/btdrv.h b/src/core/hle/service/btdrv/btdrv.h
index 9cbe2926fb..42713860e6 100644
--- a/src/core/hle/service/btdrv/btdrv.h
+++ b/src/core/hle/service/btdrv/btdrv.h
@@ -13,7 +13,6 @@ class System;
 
 namespace Service::BtDrv {
 
-/// Registers all BtDrv services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::BtDrv
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 419da36c44..dbd9d6a88f 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -9,6 +9,7 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/btm/btm.h"
 #include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::BTM {
@@ -315,11 +316,14 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<BTM>(system)->InstallAsService(sm);
-    std::make_shared<BTM_DBG>(system)->InstallAsService(sm);
-    std::make_shared<BTM_SYS>(system)->InstallAsService(sm);
-    std::make_shared<BTM_USR>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("btm", std::make_shared<BTM>(system));
+    server_manager->RegisterNamedService("btm:dbg", std::make_shared<BTM_DBG>(system));
+    server_manager->RegisterNamedService("btm:sys", std::make_shared<BTM_SYS>(system));
+    server_manager->RegisterNamedService("btm:u", std::make_shared<BTM_USR>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h
index 9dcda18486..a99b34364f 100644
--- a/src/core/hle/service/btm/btm.h
+++ b/src/core/hle/service/btm/btm.h
@@ -13,6 +13,6 @@ class System;
 
 namespace Service::BTM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::BTM
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index 13940a8c92..610fe99401 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -8,17 +8,21 @@
 #include "core/hle/service/caps/caps_ss.h"
 #include "core/hle/service/caps/caps_su.h"
 #include "core/hle/service/caps/caps_u.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::Capture {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<CAPS_A>(system)->InstallAsService(sm);
-    std::make_shared<CAPS_C>(system)->InstallAsService(sm);
-    std::make_shared<CAPS_U>(system)->InstallAsService(sm);
-    std::make_shared<CAPS_SC>(system)->InstallAsService(sm);
-    std::make_shared<CAPS_SS>(system)->InstallAsService(sm);
-    std::make_shared<CAPS_SU>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("caps:a", std::make_shared<CAPS_A>(system));
+    server_manager->RegisterNamedService("caps:c", std::make_shared<CAPS_C>(system));
+    server_manager->RegisterNamedService("caps:u", std::make_shared<CAPS_U>(system));
+    server_manager->RegisterNamedService("caps:sc", std::make_shared<CAPS_SC>(system));
+    server_manager->RegisterNamedService("caps:ss", std::make_shared<CAPS_SS>(system));
+    server_manager->RegisterNamedService("caps:su", std::make_shared<CAPS_SU>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h
index 3e89c82cb0..15f0ecfaad 100644
--- a/src/core/hle/service/caps/caps.h
+++ b/src/core/hle/service/caps/caps.h
@@ -90,7 +90,6 @@ struct ApplicationAlbumFileEntry {
 static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30,
               "ApplicationAlbumFileEntry has incorrect size.");
 
-/// Registers all Capture services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Capture
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp
index 923c0022a4..3ea862fad3 100644
--- a/src/core/hle/service/erpt/erpt.cpp
+++ b/src/core/hle/service/erpt/erpt.cpp
@@ -4,6 +4,7 @@
 #include <memory>
 
 #include "core/hle/service/erpt/erpt.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
 
@@ -52,9 +53,13 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<ErrorReportContext>(system)->InstallAsService(sm);
-    std::make_shared<ErrorReportSession>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("erpt:c", std::make_shared<ErrorReportContext>(system));
+    server_manager->RegisterNamedService("erpt:r", std::make_shared<ErrorReportSession>(system));
+
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::ERPT
diff --git a/src/core/hle/service/erpt/erpt.h b/src/core/hle/service/erpt/erpt.h
index 507d626ec1..60094f556e 100644
--- a/src/core/hle/service/erpt/erpt.h
+++ b/src/core/hle/service/erpt/erpt.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::ERPT {
 
-/// Registers all ERPT services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::ERPT
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index fb86868596..d9736af4ea 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -4,6 +4,7 @@
 #include "core/crypto/key_manager.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/es/es.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::ES {
@@ -307,8 +308,11 @@ private:
     Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance();
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<ETicket>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("es", std::make_shared<ETicket>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::ES
diff --git a/src/core/hle/service/es/es.h b/src/core/hle/service/es/es.h
index 5305635506..3176806252 100644
--- a/src/core/hle/service/es/es.h
+++ b/src/core/hle/service/es/es.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::ES {
 
-/// Registers all ES services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::ES
diff --git a/src/core/hle/service/eupld/eupld.cpp b/src/core/hle/service/eupld/eupld.cpp
index d1553ace00..3cf27513ae 100644
--- a/src/core/hle/service/eupld/eupld.cpp
+++ b/src/core/hle/service/eupld/eupld.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/eupld/eupld.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::EUPLD {
 
@@ -44,9 +44,12 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<ErrorUploadContext>(system)->InstallAsService(sm);
-    std::make_shared<ErrorUploadRequest>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("eupld:c", std::make_shared<ErrorUploadContext>(system));
+    server_manager->RegisterNamedService("eupld:r", std::make_shared<ErrorUploadRequest>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::EUPLD
diff --git a/src/core/hle/service/eupld/eupld.h b/src/core/hle/service/eupld/eupld.h
index 5de8219bec..8eb0a5b4f2 100644
--- a/src/core/hle/service/eupld/eupld.h
+++ b/src/core/hle/service/eupld/eupld.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::EUPLD {
 
-/// Registers all EUPLD services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::EUPLD
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 2e59193301..3b7b636f33 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -13,6 +13,7 @@
 #include "core/hle/service/fatal/fatal.h"
 #include "core/hle/service/fatal/fatal_p.h"
 #include "core/hle/service/fatal/fatal_u.h"
+#include "core/hle/service/server_manager.h"
 #include "core/reporter.h"
 
 namespace Service::Fatal {
@@ -163,10 +164,13 @@ void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx)
     rb.Push(ResultSuccess);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
     auto module = std::make_shared<Module>();
-    std::make_shared<Fatal_P>(module, system)->InstallAsService(service_manager);
-    std::make_shared<Fatal_U>(module, system)->InstallAsService(service_manager);
+
+    server_manager->RegisterNamedService("fatal:p", std::make_shared<Fatal_P>(module, system));
+    server_manager->RegisterNamedService("fatal:u", std::make_shared<Fatal_U>(module, system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Fatal
diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h
index a7a310f7b1..2e4e4c2f64 100644
--- a/src/core/hle/service/fatal/fatal.h
+++ b/src/core/hle/service/fatal/fatal.h
@@ -28,6 +28,6 @@ public:
     };
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Fatal
diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp
index 7e9fb03852..612491270a 100644
--- a/src/core/hle/service/fgm/fgm.cpp
+++ b/src/core/hle/service/fgm/fgm.cpp
@@ -5,6 +5,7 @@
 
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/fgm/fgm.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
 
@@ -63,11 +64,14 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<FGM>(system, "fgm")->InstallAsService(sm);
-    std::make_shared<FGM>(system, "fgm:0")->InstallAsService(sm);
-    std::make_shared<FGM>(system, "fgm:9")->InstallAsService(sm);
-    std::make_shared<FGM_DBG>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("fgm", std::make_shared<FGM>(system, "fgm"));
+    server_manager->RegisterNamedService("fgm:0", std::make_shared<FGM>(system, "fgm:0"));
+    server_manager->RegisterNamedService("fgm:9", std::make_shared<FGM>(system, "fgm:9"));
+    server_manager->RegisterNamedService("fgm:dbg", std::make_shared<FGM_DBG>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::FGM
diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h
index 077e488120..9d2465c0fb 100644
--- a/src/core/hle/service/fgm/fgm.h
+++ b/src/core/hle/service/fgm/fgm.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::FGM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::FGM
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 177447bc1a..dfcdd3adab 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -23,6 +23,7 @@
 #include "core/hle/service/filesystem/fsp_ldr.h"
 #include "core/hle/service/filesystem/fsp_pr.h"
 #include "core/hle/service/filesystem/fsp_srv.h"
+#include "core/hle/service/server_manager.h"
 #include "core/loader/loader.h"
 
 namespace Service::FileSystem {
@@ -796,10 +797,13 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
     }
 }
 
-void InstallInterfaces(Core::System& system) {
-    std::make_shared<FSP_LDR>(system)->InstallAsService(system.ServiceManager());
-    std::make_shared<FSP_PR>(system)->InstallAsService(system.ServiceManager());
-    std::make_shared<FSP_SRV>(system)->InstallAsService(system.ServiceManager());
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("fsp-ldr", std::make_shared<FSP_LDR>(system));
+    server_manager->RegisterNamedService("fsp:pr", std::make_shared<FSP_PR>(system));
+    server_manager->RegisterNamedService("fsp-srv", std::make_shared<FSP_SRV>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 5b27de9fa5..a5c1c9d3ed 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -139,7 +139,7 @@ private:
     Core::System& system;
 };
 
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 // A class that wraps a VfsDirectory with methods that return ResultVal and Result instead of
 // pointers and booleans. This makes using a VfsDirectory with switch services much easier and
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index e76346ca95..89eddb5107 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -57,8 +57,7 @@ enum class FileSystemType : u8 {
 class IStorage final : public ServiceFramework<IStorage> {
 public:
     explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_)
-        : ServiceFramework{system_, "IStorage", ServiceThreadType::CreateNew},
-          backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
             {0, &IStorage::Read, "Read"},
             {1, nullptr, "Write"},
@@ -116,8 +115,7 @@ private:
 class IFile final : public ServiceFramework<IFile> {
 public:
     explicit IFile(Core::System& system_, FileSys::VirtualFile backend_)
-        : ServiceFramework{system_, "IFile", ServiceThreadType::CreateNew},
-          backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
             {0, &IFile::Read, "Read"},
             {1, &IFile::Write, "Write"},
@@ -254,8 +252,7 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
 class IDirectory final : public ServiceFramework<IDirectory> {
 public:
     explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_)
-        : ServiceFramework{system_, "IDirectory", ServiceThreadType::CreateNew},
-          backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
             {0, &IDirectory::Read, "Read"},
             {1, &IDirectory::GetEntryCount, "GetEntryCount"},
@@ -311,8 +308,8 @@ private:
 class IFileSystem final : public ServiceFramework<IFileSystem> {
 public:
     explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
-        : ServiceFramework{system_, "IFileSystem", ServiceThreadType::CreateNew},
-          backend{std::move(backend_)}, size{std::move(size_)} {
+        : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move(
+                                                                                      size_)} {
         static const FunctionInfo functions[] = {
             {0, &IFileSystem::CreateFile, "CreateFile"},
             {1, &IFileSystem::DeleteFile, "DeleteFile"},
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index fad532115e..fcf10bfeb9 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -11,6 +11,7 @@
 #include "core/hle/service/friend/friend.h"
 #include "core/hle/service/friend/friend_interface.h"
 #include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::Friend {
 
@@ -335,13 +336,22 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
 
 Module::Interface::~Interface() = default;
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
     auto module = std::make_shared<Module>();
-    std::make_shared<Friend>(module, system, "friend:a")->InstallAsService(service_manager);
-    std::make_shared<Friend>(module, system, "friend:m")->InstallAsService(service_manager);
-    std::make_shared<Friend>(module, system, "friend:s")->InstallAsService(service_manager);
-    std::make_shared<Friend>(module, system, "friend:u")->InstallAsService(service_manager);
-    std::make_shared<Friend>(module, system, "friend:v")->InstallAsService(service_manager);
+
+    server_manager->RegisterNamedService("friend:a",
+                                         std::make_shared<Friend>(module, system, "friend:a"));
+    server_manager->RegisterNamedService("friend:m",
+                                         std::make_shared<Friend>(module, system, "friend:m"));
+    server_manager->RegisterNamedService("friend:s",
+                                         std::make_shared<Friend>(module, system, "friend:s"));
+    server_manager->RegisterNamedService("friend:u",
+                                         std::make_shared<Friend>(module, system, "friend:u"));
+    server_manager->RegisterNamedService("friend:v",
+                                         std::make_shared<Friend>(module, system, "friend:v"));
+
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Friend
diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h
index 444da8b359..41be06a4f6 100644
--- a/src/core/hle/service/friend/friend.h
+++ b/src/core/hle/service/friend/friend.h
@@ -27,7 +27,6 @@ public:
     };
 };
 
-/// Registers all Friend services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Friend
diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp
index 717f2562ba..993c3d21da 100644
--- a/src/core/hle/service/glue/glue.cpp
+++ b/src/core/hle/service/glue/glue.cpp
@@ -8,25 +8,30 @@
 #include "core/hle/service/glue/ectx.h"
 #include "core/hle/service/glue/glue.h"
 #include "core/hle/service/glue/notif.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::Glue {
 
-void InstallInterfaces(Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
     // ARP
-    std::make_shared<ARP_R>(system, system.GetARPManager())
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<ARP_W>(system, system.GetARPManager())
-        ->InstallAsService(system.ServiceManager());
+    server_manager->RegisterNamedService("arp:r",
+                                         std::make_shared<ARP_R>(system, system.GetARPManager()));
+    server_manager->RegisterNamedService("arp:w",
+                                         std::make_shared<ARP_W>(system, system.GetARPManager()));
 
     // BackGround Task Controller
-    std::make_shared<BGTC_T>(system)->InstallAsService(system.ServiceManager());
-    std::make_shared<BGTC_SC>(system)->InstallAsService(system.ServiceManager());
+    server_manager->RegisterNamedService("bgtc:t", std::make_shared<BGTC_T>(system));
+    server_manager->RegisterNamedService("bgtc:sc", std::make_shared<BGTC_SC>(system));
 
     // Error Context
-    std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager());
+    server_manager->RegisterNamedService("ectx:aw", std::make_shared<ECTX_AW>(system));
 
     // Notification Services for application
-    std::make_shared<NOTIF_A>(system)->InstallAsService(system.ServiceManager());
+    server_manager->RegisterNamedService("notif:a", std::make_shared<NOTIF_A>(system));
+
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Glue
diff --git a/src/core/hle/service/glue/glue.h b/src/core/hle/service/glue/glue.h
index ae7c6d2354..2a906f5ad6 100644
--- a/src/core/hle/service/glue/glue.h
+++ b/src/core/hle/service/glue/glue.h
@@ -9,7 +9,6 @@ class System;
 
 namespace Service::Glue {
 
-/// Registers all Glue services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Glue
diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp
index 4b684f6d0b..64275da36d 100644
--- a/src/core/hle/service/grc/grc.cpp
+++ b/src/core/hle/service/grc/grc.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/grc/grc.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::GRC {
 
@@ -26,8 +26,11 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<GRC>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("grc:c", std::make_shared<GRC>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::GRC
diff --git a/src/core/hle/service/grc/grc.h b/src/core/hle/service/grc/grc.h
index f8c2f8dab4..a3f8a5b90e 100644
--- a/src/core/hle/service/grc/grc.h
+++ b/src/core/hle/service/grc/grc.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::GRC {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::GRC
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 0da67235fc..4b51304694 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -18,6 +18,7 @@
 #include "core/hle/service/hid/hidbus.h"
 #include "core/hle/service/hid/irs.h"
 #include "core/hle/service/hid/xcd.h"
+#include "core/hle/service/server_manager.h"
 #include "core/memory.h"
 
 #include "core/hle/service/hid/controllers/console_sixaxis.h"
@@ -2739,16 +2740,20 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<Hid>(system)->InstallAsService(service_manager);
-    std::make_shared<HidBus>(system)->InstallAsService(service_manager);
-    std::make_shared<HidDbg>(system)->InstallAsService(service_manager);
-    std::make_shared<HidSys>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
 
-    std::make_shared<Service::IRS::IRS>(system)->InstallAsService(service_manager);
-    std::make_shared<Service::IRS::IRS_SYS>(system)->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("hid", std::make_shared<Hid>(system));
+    server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system));
+    server_manager->RegisterNamedService("hid:dbg", std::make_shared<HidDbg>(system));
+    server_manager->RegisterNamedService("hid:sys", std::make_shared<HidSys>(system));
 
-    std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("irs", std::make_shared<Service::IRS::IRS>(system));
+    server_manager->RegisterNamedService("irs:sys",
+                                         std::make_shared<Service::IRS::IRS_SYS>(system));
+
+    server_manager->RegisterNamedService("xcd:sys", std::make_shared<XCD_SYS>(system));
+    system.RunServer(std::move(server_manager));
 }
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 9ace831299..9563654b6c 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -216,7 +216,6 @@ private:
     KernelHelpers::ServiceContext service_context;
 };
 
-/// Registers all HID services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::HID
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index 47a1277eac..005c212dc3 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -9,6 +9,7 @@
 #include "core/hle/result.h"
 #include "core/hle/service/jit/jit.h"
 #include "core/hle/service/jit/jit_context.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/memory.h"
 
@@ -23,8 +24,8 @@ class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
 public:
     explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
                              CodeRange user_ro)
-        : ServiceFramework{system_, "IJitEnvironment", ServiceThreadType::CreateNew},
-          process{&process_}, context{system_.Memory()} {
+        : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, context{
+                                                                                system_.Memory()} {
         // clang-format off
         static const FunctionInfo functions[] = {
             {0, &IJitEnvironment::GenerateCode, "GenerateCode"},
@@ -397,8 +398,11 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<JITU>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("jit:u", std::make_shared<JITU>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::JIT
diff --git a/src/core/hle/service/jit/jit.h b/src/core/hle/service/jit/jit.h
index af0f5b4f3a..19014c75a4 100644
--- a/src/core/hle/service/jit/jit.h
+++ b/src/core/hle/service/jit/jit.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::JIT {
 
-/// Registers all JIT services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::JIT
diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp
index 42991928e7..a39ce52120 100644
--- a/src/core/hle/service/kernel_helpers.cpp
+++ b/src/core/hle/service/kernel_helpers.cpp
@@ -15,17 +15,24 @@ namespace Service::KernelHelpers {
 
 ServiceContext::ServiceContext(Core::System& system_, std::string name_)
     : kernel(system_.Kernel()) {
+    if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) {
+        return;
+    }
+
     // Create the process.
     process = Kernel::KProcess::Create(kernel);
     ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_),
                                         Kernel::KProcess::ProcessType::KernelInternal,
                                         kernel.GetSystemResourceLimit())
                .IsSuccess());
+    process_created = true;
 }
 
 ServiceContext::~ServiceContext() {
-    process->Close();
-    process = nullptr;
+    if (process_created) {
+        process->Close();
+        process = nullptr;
+    }
 }
 
 Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) {
diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h
index 6415838e56..eca9aefb52 100644
--- a/src/core/hle/service/kernel_helpers.h
+++ b/src/core/hle/service/kernel_helpers.h
@@ -29,6 +29,7 @@ public:
 private:
     Kernel::KernelCore& kernel;
     Kernel::KProcess* process{};
+    bool process_created{false};
 };
 
 } // namespace Service::KernelHelpers
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp
index c8415e0bf9..3f3c68d80d 100644
--- a/src/core/hle/service/lbl/lbl.cpp
+++ b/src/core/hle/service/lbl/lbl.cpp
@@ -7,6 +7,7 @@
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/sm/sm.h"
 
@@ -319,8 +320,11 @@ private:
     bool auto_brightness = false; // TODO(ogniK): Move to system settings
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<LBL>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("lbl", std::make_shared<LBL>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::LBL
diff --git a/src/core/hle/service/lbl/lbl.h b/src/core/hle/service/lbl/lbl.h
index 6484105c24..e47759c01c 100644
--- a/src/core/hle/service/lbl/lbl.h
+++ b/src/core/hle/service/lbl/lbl.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::LBL {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::LBL
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index e5099d61f1..4c2abe7d39 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -8,6 +8,7 @@
 #include "core/hle/service/ldn/ldn.h"
 #include "core/hle/service/ldn/ldn_results.h"
 #include "core/hle/service/ldn/ldn_types.h"
+#include "core/hle/service/server_manager.h"
 #include "core/internal_network/network.h"
 #include "core/internal_network/network_interface.h"
 #include "network/network.h"
@@ -106,7 +107,7 @@ class IUserLocalCommunicationService final
     : public ServiceFramework<IUserLocalCommunicationService> {
 public:
     explicit IUserLocalCommunicationService(Core::System& system_)
-        : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
+        : ServiceFramework{system_, "IUserLocalCommunicationService"},
           service_context{system, "IUserLocalCommunicationService"},
           room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
         // clang-format off
@@ -730,12 +731,15 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<LDNM>(system)->InstallAsService(sm);
-    std::make_shared<LDNS>(system)->InstallAsService(sm);
-    std::make_shared<LDNU>(system)->InstallAsService(sm);
-    std::make_shared<LP2PAPP>(system)->InstallAsService(sm);
-    std::make_shared<LP2PSYS>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system));
+    server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system));
+    server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system));
+    server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system));
+    server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index 6afe2ea6f3..fa869fa891 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -13,13 +13,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::LDN {
 
-/// Registers all LDN services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::LDN
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 2d4d6fe3e7..c82e189f41 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -14,6 +14,7 @@
 #include "core/hle/kernel/svc_results.h"
 #include "core/hle/kernel/svc_types.h"
 #include "core/hle/service/ldr/ldr.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/loader/nro.h"
 #include "core/memory.h"
@@ -159,8 +160,7 @@ public:
 
 class RelocatableObject final : public ServiceFramework<RelocatableObject> {
 public:
-    explicit RelocatableObject(Core::System& system_)
-        : ServiceFramework{system_, "ldr:ro", ServiceThreadType::CreateNew} {
+    explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} {
         // clang-format off
         static const FunctionInfo functions[] = {
             {0, &RelocatableObject::LoadModule, "LoadModule"},
@@ -682,11 +682,15 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<DebugMonitor>(system)->InstallAsService(sm);
-    std::make_shared<ProcessManager>(system)->InstallAsService(sm);
-    std::make_shared<Shell>(system)->InstallAsService(sm);
-    std::make_shared<RelocatableObject>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("ldr:dmnt", std::make_shared<DebugMonitor>(system));
+    server_manager->RegisterNamedService("ldr:pm", std::make_shared<ProcessManager>(system));
+    server_manager->RegisterNamedService("ldr:shel", std::make_shared<Shell>(system));
+    server_manager->RegisterNamedService("ldr:ro", std::make_shared<RelocatableObject>(system));
+
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::LDR
diff --git a/src/core/hle/service/ldr/ldr.h b/src/core/hle/service/ldr/ldr.h
index 25ffd8442c..c9281dbfb2 100644
--- a/src/core/hle/service/ldr/ldr.h
+++ b/src/core/hle/service/ldr/ldr.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::LDR {
 
-/// Registers all LDR services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::LDR
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index ef4b540468..7efd8e0abd 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -10,6 +10,7 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/lm/lm.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::LM {
@@ -351,8 +352,11 @@ private:
     }
 };
 
-void InstallInterfaces(Core::System& system) {
-    std::make_shared<LM>(system)->InstallAsService(system.ServiceManager());
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("lm", std::make_shared<LM>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::LM
diff --git a/src/core/hle/service/lm/lm.h b/src/core/hle/service/lm/lm.h
index 266019c30c..0d7c39cbc3 100644
--- a/src/core/hle/service/lm/lm.h
+++ b/src/core/hle/service/lm/lm.h
@@ -9,7 +9,6 @@ class System;
 
 namespace Service::LM {
 
-/// Registers all LM services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::LM
diff --git a/src/core/hle/service/mig/mig.cpp b/src/core/hle/service/mig/mig.cpp
index b9fe0cecd9..082e470aba 100644
--- a/src/core/hle/service/mig/mig.cpp
+++ b/src/core/hle/service/mig/mig.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/mig/mig.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::Migration {
 
@@ -32,8 +32,11 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<MIG_USR>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("mig:user", std::make_shared<MIG_USR>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Migration
diff --git a/src/core/hle/service/mig/mig.h b/src/core/hle/service/mig/mig.h
index f1641a521b..c8ed732a5b 100644
--- a/src/core/hle/service/mig/mig.h
+++ b/src/core/hle/service/mig/mig.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::Migration {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Migration
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 390514fdcc..50dc0ac641 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -7,8 +7,8 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/mii/mii.h"
 #include "core/hle/service/mii/mii_manager.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::Mii {
 
@@ -310,11 +310,13 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<MiiDBModule>(system, "mii:e")->InstallAsService(sm);
-    std::make_shared<MiiDBModule>(system, "mii:u")->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
 
-    std::make_shared<MiiImg>(system)->InstallAsService(sm);
+    server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e"));
+    server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u"));
+    server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h
index 009d80d587..ed4e3f62b2 100644
--- a/src/core/hle/service/mii/mii.h
+++ b/src/core/hle/service/mii/mii.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::Mii {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Mii
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp
index ba8c0e2305..bee72fa1b8 100644
--- a/src/core/hle/service/mm/mm_u.cpp
+++ b/src/core/hle/service/mm/mm_u.cpp
@@ -4,6 +4,7 @@
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/mm/mm_u.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sm/sm.h"
 
 namespace Service::MM {
@@ -103,8 +104,11 @@ private:
     u32 id{1};
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<MM_U>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("mm:u", std::make_shared<MM_U>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::MM
diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h
index b40941e357..43117c9b1c 100644
--- a/src/core/hle/service/mm/mm_u.h
+++ b/src/core/hle/service/mm/mm_u.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::MM {
 
-/// Registers all MM services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::MM
diff --git a/src/core/hle/service/mnpp/mnpp_app.cpp b/src/core/hle/service/mnpp/mnpp_app.cpp
index c3aad57146..4ce4672b79 100644
--- a/src/core/hle/service/mnpp/mnpp_app.cpp
+++ b/src/core/hle/service/mnpp/mnpp_app.cpp
@@ -4,7 +4,8 @@
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/mnpp/mnpp_app.h"
-#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/server_manager.h"
+#include "core/hle/service/service.h"
 
 namespace Service::MNPP {
 
@@ -37,8 +38,11 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<MNPP_APP>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("mnpp:app", std::make_shared<MNPP_APP>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::MNPP
diff --git a/src/core/hle/service/mnpp/mnpp_app.h b/src/core/hle/service/mnpp/mnpp_app.h
index eec75fe0e9..40d0395bdf 100644
--- a/src/core/hle/service/mnpp/mnpp_app.h
+++ b/src/core/hle/service/mnpp/mnpp_app.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::MNPP {
 
-/// Registers all MNPP services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::MNPP
diff --git a/src/core/hle/service/mutex.cpp b/src/core/hle/service/mutex.cpp
new file mode 100644
index 0000000000..07589a0f0e
--- /dev/null
+++ b/src/core/hle/service/mutex.cpp
@@ -0,0 +1,43 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/service/mutex.h"
+
+namespace Service {
+
+Mutex::Mutex(Core::System& system) : m_system(system) {
+    m_event = Kernel::KEvent::Create(system.Kernel());
+    m_event->Initialize(nullptr);
+
+    ASSERT(R_SUCCEEDED(m_event->Signal()));
+}
+
+Mutex::~Mutex() {
+    m_event->GetReadableEvent().Close();
+    m_event->Close();
+}
+
+void Mutex::lock() {
+    // Infinitely retry until we successfully clear the event.
+    while (R_FAILED(m_event->GetReadableEvent().Reset())) {
+        s32 index;
+        Kernel::KSynchronizationObject* obj = &m_event->GetReadableEvent();
+
+        // The event was already cleared!
+        // Wait for it to become signaled again.
+        ASSERT(R_SUCCEEDED(
+            Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &index, &obj, 1, -1)));
+    }
+
+    // We successfully cleared the event, and now have exclusive ownership.
+}
+
+void Mutex::unlock() {
+    // Unlock.
+    ASSERT(R_SUCCEEDED(m_event->Signal()));
+}
+
+} // namespace Service
diff --git a/src/core/hle/service/mutex.h b/src/core/hle/service/mutex.h
new file mode 100644
index 0000000000..95ac9b117a
--- /dev/null
+++ b/src/core/hle/service/mutex.h
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KEvent;
+}
+
+namespace Service {
+
+class Mutex {
+public:
+    explicit Mutex(Core::System& system);
+    ~Mutex();
+
+    void lock();
+    void unlock();
+
+private:
+    Core::System& m_system;
+    Kernel::KEvent* m_event{};
+};
+
+} // namespace Service
diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp
index 4c66cfeba8..5ab24dc343 100644
--- a/src/core/hle/service/ncm/ncm.cpp
+++ b/src/core/hle/service/ncm/ncm.cpp
@@ -6,8 +6,8 @@
 #include "core/file_sys/romfs_factory.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::NCM {
 
@@ -132,9 +132,12 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<LR>(system)->InstallAsService(sm);
-    std::make_shared<NCM>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("lr", std::make_shared<LR>(system));
+    server_manager->RegisterNamedService("ncm", std::make_shared<NCM>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NCM
diff --git a/src/core/hle/service/ncm/ncm.h b/src/core/hle/service/ncm/ncm.h
index de39714375..b78efdcd79 100644
--- a/src/core/hle/service/ncm/ncm.h
+++ b/src/core/hle/service/ncm/ncm.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NCM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NCM
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index b17b18ab90..34612b9dfe 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -9,8 +9,8 @@
 #include "core/hle/service/nfc/mifare_user.h"
 #include "core/hle/service/nfc/nfc.h"
 #include "core/hle/service/nfc/nfc_user.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::NFC {
 
@@ -154,11 +154,14 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<NFC_AM>(system)->InstallAsService(sm);
-    std::make_shared<NFC_MF_U>(system)->InstallAsService(sm);
-    std::make_shared<NFC_U>(system)->InstallAsService(sm);
-    std::make_shared<NFC_SYS>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("nfc:am", std::make_shared<NFC_AM>(system));
+    server_manager->RegisterNamedService("nfc:mf:u", std::make_shared<NFC_MF_U>(system));
+    server_manager->RegisterNamedService("nfc:user", std::make_shared<NFC_U>(system));
+    server_manager->RegisterNamedService("nfc:sys", std::make_shared<NFC_SYS>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h
index 0107b696cc..d15955b755 100644
--- a/src/core/hle/service/nfc/nfc.h
+++ b/src/core/hle/service/nfc/nfc.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NFC {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NFC
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 0cb55ca49c..1b59aba8e6 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -5,6 +5,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/nfp/nfp.h"
 #include "core/hle/service/nfp/nfp_user.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::NFP {
 
@@ -36,8 +37,11 @@ private:
     std::shared_ptr<IUser> user_interface;
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<IUserManager>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("nfp:user", std::make_shared<IUserManager>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index a25c362b8a..a5aac710b5 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -7,6 +7,6 @@
 
 namespace Service::NFP {
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NFP
diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp
index 8af8a835d7..76897d05c0 100644
--- a/src/core/hle/service/ngct/ngct.cpp
+++ b/src/core/hle/service/ngct/ngct.cpp
@@ -5,6 +5,7 @@
 #include "core/core.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/ngct/ngct.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::NGCT {
@@ -51,8 +52,11 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<IService>(system)->InstallAsService(system.ServiceManager());
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("ngct:u", std::make_shared<IService>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NGCT
diff --git a/src/core/hle/service/ngct/ngct.h b/src/core/hle/service/ngct/ngct.h
index 370bd4a254..27c34dad45 100644
--- a/src/core/hle/service/ngct/ngct.h
+++ b/src/core/hle/service/ngct/ngct.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NGCT {
 
-/// Registers all NGCT services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NGCT
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 5d32adf647..3d176b3c2c 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -6,6 +6,7 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/kernel_helpers.h"
 #include "core/hle/service/nifm/nifm.h"
+#include "core/hle/service/server_manager.h"
 
 namespace {
 
@@ -626,10 +627,16 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<NetworkInterface>("nifm:a", system)->InstallAsService(service_manager);
-    std::make_shared<NetworkInterface>("nifm:s", system)->InstallAsService(service_manager);
-    std::make_shared<NetworkInterface>("nifm:u", system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("nifm:a",
+                                         std::make_shared<NetworkInterface>("nifm:a", system));
+    server_manager->RegisterNamedService("nifm:s",
+                                         std::make_shared<NetworkInterface>("nifm:s", system));
+    server_manager->RegisterNamedService("nifm:u",
+                                         std::make_shared<NetworkInterface>("nifm:u", system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NIFM
diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h
index 48161be28a..b5da7ae129 100644
--- a/src/core/hle/service/nifm/nifm.h
+++ b/src/core/hle/service/nifm/nifm.h
@@ -12,14 +12,9 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NIFM {
 
-/// Registers all NIFM services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 class IGeneralService final : public ServiceFramework<IGeneralService> {
 public:
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 5a8a91e0bd..aff7cc5bd4 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -8,8 +8,8 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/kernel_helpers.h"
 #include "core/hle/service/nim/nim.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::NIM {
 
@@ -418,11 +418,14 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<NIM>(system)->InstallAsService(sm);
-    std::make_shared<NIM_ECA>(system)->InstallAsService(sm);
-    std::make_shared<NIM_SHP>(system)->InstallAsService(sm);
-    std::make_shared<NTC>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("nim", std::make_shared<NIM>(system));
+    server_manager->RegisterNamedService("nim:eca", std::make_shared<NIM_ECA>(system));
+    server_manager->RegisterNamedService("nim:shp", std::make_shared<NIM_SHP>(system));
+    server_manager->RegisterNamedService("ntc", std::make_shared<NTC>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NIM
diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h
index 8f6ff28e83..e7d599908d 100644
--- a/src/core/hle/service/nim/nim.h
+++ b/src/core/hle/service/nim/nim.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NIM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NIM
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp
index 8133711c2b..a162e5c548 100644
--- a/src/core/hle/service/npns/npns.cpp
+++ b/src/core/hle/service/npns/npns.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/npns/npns.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::NPNS {
 
@@ -94,9 +94,12 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<NPNS_S>(system)->InstallAsService(sm);
-    std::make_shared<NPNS_U>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("npns:s", std::make_shared<NPNS_S>(system));
+    server_manager->RegisterNamedService("npns:u", std::make_shared<NPNS_U>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NPNS
diff --git a/src/core/hle/service/npns/npns.h b/src/core/hle/service/npns/npns.h
index 84e6ec4372..0019fca763 100644
--- a/src/core/hle/service/npns/npns.h
+++ b/src/core/hle/service/npns/npns.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::NPNS {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::NPNS
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index e53bdde521..062e96ef99 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -14,6 +14,7 @@
 #include "core/hle/service/ns/language.h"
 #include "core/hle/service/ns/ns.h"
 #include "core/hle/service/ns/pdm_qry.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/set/set.h"
 
 namespace Service::NS {
@@ -785,23 +786,26 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
 
-    std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:ro", system)->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system));
+    server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system));
+    server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system));
+    server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system));
+    server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system));
+    server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system));
 
-    std::make_shared<NS_DEV>(system)->InstallAsService(service_manager);
-    std::make_shared<NS_SU>(system)->InstallAsService(service_manager);
-    std::make_shared<NS_VM>(system)->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system));
+    server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system));
+    server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system));
+    server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system));
 
-    std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager);
-
-    std::make_shared<IPlatformServiceManager>(system, "pl:s")->InstallAsService(service_manager);
-    std::make_shared<IPlatformServiceManager>(system, "pl:u")->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("pl:s",
+                                         std::make_shared<IPlatformServiceManager>(system, "pl:s"));
+    server_manager->RegisterNamedService("pl:u",
+                                         std::make_shared<IPlatformServiceManager>(system, "pl:u"));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::NS
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 9c18e935c5..797e69a137 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -117,8 +117,7 @@ private:
     }
 };
 
-/// Registers all NS services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace NS
 } // namespace Service
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 52d27e7553..a70ea9385a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -24,6 +24,7 @@
 #include "core/hle/service/nvdrv/nvdrv_interface.h"
 #include "core/hle/service/nvdrv/nvmemp.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
+#include "core/hle/service/server_manager.h"
 #include "video_core/gpu.h"
 
 namespace Service::Nvidia {
@@ -41,15 +42,19 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {
     module.service_context.CloseEvent(event);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
-                       Core::System& system) {
-    auto module_ = std::make_shared<Module>(system);
-    std::make_shared<NVDRV>(system, module_, "nvdrv")->InstallAsService(service_manager);
-    std::make_shared<NVDRV>(system, module_, "nvdrv:a")->InstallAsService(service_manager);
-    std::make_shared<NVDRV>(system, module_, "nvdrv:s")->InstallAsService(service_manager);
-    std::make_shared<NVDRV>(system, module_, "nvdrv:t")->InstallAsService(service_manager);
-    std::make_shared<NVMEMP>(system)->InstallAsService(service_manager);
-    nvflinger.SetNVDrvInstance(module_);
+void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+    auto module = std::make_shared<Module>(system);
+    server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv"));
+    server_manager->RegisterNamedService("nvdrv:a",
+                                         std::make_shared<NVDRV>(system, module, "nvdrv:a"));
+    server_manager->RegisterNamedService("nvdrv:s",
+                                         std::make_shared<NVDRV>(system, module, "nvdrv:s"));
+    server_manager->RegisterNamedService("nvdrv:t",
+                                         std::make_shared<NVDRV>(system, module, "nvdrv:t"));
+    server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
+    nvflinger.SetNVDrvInstance(module);
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 Module::Module(Core::System& system)
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index b09b6e5858..b2270cf76d 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -114,8 +114,6 @@ private:
     std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
 };
 
-/// Registers all NVDRV services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
-                       Core::System& system);
+void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system);
 
 } // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index edbdfee43c..396fa7ed5d 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -222,7 +222,7 @@ void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) {
 }
 
 NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name)
-    : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, nvdrv{std::move(nvdrv_)} {
+    : ServiceFramework{system_, name}, nvdrv{std::move(nvdrv_)} {
     static const FunctionInfo functions[] = {
         {0, &NVDRV::Open, "Open"},
         {1, &NVDRV::Ioctl1, "Ioctl"},
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index 530e1be3bd..3493f8272e 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -3,8 +3,8 @@
 
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/olsc/olsc.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::OLSC {
 
@@ -72,8 +72,11 @@ private:
     bool initialized{};
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<OLSC>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/olsc.h b/src/core/hle/service/olsc/olsc.h
index 1522d8d321..620b634fae 100644
--- a/src/core/hle/service/olsc/olsc.h
+++ b/src/core/hle/service/olsc/olsc.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::OLSC {
 
-/// Registers all SSL services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::OLSC
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp
index 79501b9f91..c6da6eb517 100644
--- a/src/core/hle/service/pcie/pcie.cpp
+++ b/src/core/hle/service/pcie/pcie.cpp
@@ -4,8 +4,8 @@
 #include <memory>
 
 #include "core/hle/service/pcie/pcie.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::PCIe {
 
@@ -59,8 +59,11 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<PCIe>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("pcie", std::make_shared<PCIe>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PCIe
diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h
index cebfd9042e..5c2d4b805b 100644
--- a/src/core/hle/service/pcie/pcie.h
+++ b/src/core/hle/service/pcie/pcie.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::PCIe {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PCIe
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 083609b343..a4a12a78c7 100644
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -8,6 +8,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/pctl/pctl.h"
 #include "core/hle/service/pctl/pctl_module.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::PCTL {
 
@@ -393,19 +394,22 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
 
 Module::Interface::~Interface() = default;
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
     auto module = std::make_shared<Module>();
-    std::make_shared<PCTL>(system, module, "pctl",
-                           Capability::Application | Capability::SnsPost | Capability::Status |
-                               Capability::StereoVision)
-        ->InstallAsService(service_manager);
+    server_manager->RegisterNamedService(
+        "pctl", std::make_shared<PCTL>(system, module, "pctl",
+                                       Capability::Application | Capability::SnsPost |
+                                           Capability::Status | Capability::StereoVision));
     // TODO(ogniK): Implement remaining capabilities
-    std::make_shared<PCTL>(system, module, "pctl:a", Capability::None)
-        ->InstallAsService(service_manager);
-    std::make_shared<PCTL>(system, module, "pctl:r", Capability::None)
-        ->InstallAsService(service_manager);
-    std::make_shared<PCTL>(system, module, "pctl:s", Capability::None)
-        ->InstallAsService(service_manager);
+    server_manager->RegisterNamedService(
+        "pctl:a", std::make_shared<PCTL>(system, module, "pctl:a", Capability::None));
+    server_manager->RegisterNamedService(
+        "pctl:r", std::make_shared<PCTL>(system, module, "pctl:r", Capability::None));
+    server_manager->RegisterNamedService(
+        "pctl:s", std::make_shared<PCTL>(system, module, "pctl:s", Capability::None));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_module.h b/src/core/hle/service/pctl/pctl_module.h
index 6f584530d7..4ea77ab212 100644
--- a/src/core/hle/service/pctl/pctl_module.h
+++ b/src/core/hle/service/pctl/pctl_module.h
@@ -42,7 +42,6 @@ public:
     };
 };
 
-/// Registers all PCTL services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PCTL
diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp
index 98037a8d45..be64b94ea5 100644
--- a/src/core/hle/service/pcv/pcv.cpp
+++ b/src/core/hle/service/pcv/pcv.cpp
@@ -5,8 +5,8 @@
 
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/pcv/pcv.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::PCV {
 
@@ -141,11 +141,14 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<PCV>(system)->InstallAsService(sm);
-    std::make_shared<CLKRST>(system, "clkrst")->InstallAsService(sm);
-    std::make_shared<CLKRST>(system, "clkrst:i")->InstallAsService(sm);
-    std::make_shared<CLKRST_A>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("pcv", std::make_shared<PCV>(system));
+    server_manager->RegisterNamedService("clkrst", std::make_shared<CLKRST>(system, "clkrst"));
+    server_manager->RegisterNamedService("clkrst:i", std::make_shared<CLKRST>(system, "clkrst:i"));
+    server_manager->RegisterNamedService("clkrst:a", std::make_shared<CLKRST_A>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PCV
diff --git a/src/core/hle/service/pcv/pcv.h b/src/core/hle/service/pcv/pcv.h
index 6b26b6fa70..bf541e6feb 100644
--- a/src/core/hle/service/pcv/pcv.h
+++ b/src/core/hle/service/pcv/pcv.h
@@ -7,10 +7,6 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::PCV {
 
 enum class DeviceCode : u32 {
@@ -104,6 +100,6 @@ enum class DeviceCode : u32 {
     OscClk = 0x40000080
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PCV
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index b10e86c8fb..02a4ca13b2 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -6,6 +6,7 @@
 #include "core/hle/kernel/k_process.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/service/pm/pm.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
 namespace Service::PM {
@@ -262,12 +263,15 @@ private:
     const Kernel::KernelCore& kernel;
 };
 
-void InstallInterfaces(Core::System& system) {
-    std::make_shared<BootMode>(system)->InstallAsService(system.ServiceManager());
-    std::make_shared<DebugMonitor>(system)->InstallAsService(system.ServiceManager());
-    std::make_shared<Info>(system, system.Kernel().GetProcessList())
-        ->InstallAsService(system.ServiceManager());
-    std::make_shared<Shell>(system)->InstallAsService(system.ServiceManager());
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system));
+    server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system));
+    server_manager->RegisterNamedService(
+        "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList()));
+    server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PM
diff --git a/src/core/hle/service/pm/pm.h b/src/core/hle/service/pm/pm.h
index 0601039289..5d4a1a171c 100644
--- a/src/core/hle/service/pm/pm.h
+++ b/src/core/hle/service/pm/pm.h
@@ -14,7 +14,6 @@ enum class SystemBootMode {
     Maintenance,
 };
 
-/// Registers all PM services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PM
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp
index 90c5f8756e..02af311e8a 100644
--- a/src/core/hle/service/prepo/prepo.cpp
+++ b/src/core/hle/service/prepo/prepo.cpp
@@ -7,6 +7,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/prepo/prepo.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/reporter.h"
 
@@ -183,12 +184,20 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<PlayReport>("prepo:a", system)->InstallAsService(service_manager);
-    std::make_shared<PlayReport>("prepo:a2", system)->InstallAsService(service_manager);
-    std::make_shared<PlayReport>("prepo:m", system)->InstallAsService(service_manager);
-    std::make_shared<PlayReport>("prepo:s", system)->InstallAsService(service_manager);
-    std::make_shared<PlayReport>("prepo:u", system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("prepo:a",
+                                         std::make_shared<PlayReport>("prepo:a", system));
+    server_manager->RegisterNamedService("prepo:a2",
+                                         std::make_shared<PlayReport>("prepo:a2", system));
+    server_manager->RegisterNamedService("prepo:m",
+                                         std::make_shared<PlayReport>("prepo:m", system));
+    server_manager->RegisterNamedService("prepo:s",
+                                         std::make_shared<PlayReport>("prepo:s", system));
+    server_manager->RegisterNamedService("prepo:u",
+                                         std::make_shared<PlayReport>("prepo:u", system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PlayReport
diff --git a/src/core/hle/service/prepo/prepo.h b/src/core/hle/service/prepo/prepo.h
index 37ea5afad2..2c2462f936 100644
--- a/src/core/hle/service/prepo/prepo.h
+++ b/src/core/hle/service/prepo/prepo.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::PlayReport {
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PlayReport
diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp
index 3a9412cf54..1650d2f394 100644
--- a/src/core/hle/service/psc/psc.cpp
+++ b/src/core/hle/service/psc/psc.cpp
@@ -6,8 +6,8 @@
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/service/psc/psc.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::PSC {
 
@@ -71,9 +71,12 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<PSC_C>(system)->InstallAsService(sm);
-    std::make_shared<PSC_M>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("psc:c", std::make_shared<PSC_C>(system));
+    server_manager->RegisterNamedService("psc:m", std::make_shared<PSC_M>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PSC
diff --git a/src/core/hle/service/psc/psc.h b/src/core/hle/service/psc/psc.h
index d248372c27..459137f423 100644
--- a/src/core/hle/service/psc/psc.h
+++ b/src/core/hle/service/psc/psc.h
@@ -13,6 +13,6 @@ class ServiceManager;
 
 namespace Service::PSC {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PSC
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 4bea995c6a..6f0cfe04b8 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -7,12 +7,16 @@
 #include "core/hle/service/ptm/psm.h"
 #include "core/hle/service/ptm/ptm.h"
 #include "core/hle/service/ptm/ts.h"
+#include "core/hle/service/server_manager.h"
 
 namespace Service::PTM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<PSM>(system)->InstallAsService(sm);
-    std::make_shared<TS>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("psm", std::make_shared<PSM>(system));
+    server_manager->RegisterNamedService("ts", std::make_shared<TS>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::PTM
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index 06224a24e6..a0ae03d282 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::PTM {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::PTM
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp
new file mode 100644
index 0000000000..1b3db3caf9
--- /dev/null
+++ b/src/core/hle/service/server_manager.cpp
@@ -0,0 +1,448 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/scope_exit.h"
+
+#include "core/core.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/kernel/k_client_port.h"
+#include "core/hle/kernel/k_client_session.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/kernel/k_object_name.h"
+#include "core/hle/kernel/k_port.h"
+#include "core/hle/kernel/k_server_port.h"
+#include "core/hle/kernel/k_server_session.h"
+#include "core/hle/kernel/k_synchronization_object.h"
+#include "core/hle/kernel/svc_results.h"
+#include "core/hle/service/server_manager.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service {
+
+constexpr size_t MaximumWaitObjects = 0x40;
+
+enum HandleType {
+    Port,
+    Session,
+    DeferEvent,
+    Event,
+};
+
+ServerManager::ServerManager(Core::System& system) : m_system{system}, m_serve_mutex{system} {
+    // Initialize event.
+    m_event = Kernel::KEvent::Create(system.Kernel());
+    m_event->Initialize(nullptr);
+}
+
+ServerManager::~ServerManager() {
+    // Signal stop.
+    m_stop_source.request_stop();
+    m_event->Signal();
+
+    // Wait for processing to stop.
+    m_stopped.wait(false);
+    m_threads.clear();
+
+    // Clean up ports.
+    for (const auto& [port, handler] : m_ports) {
+        port->Close();
+    }
+
+    // Clean up sessions.
+    for (const auto& [session, manager] : m_sessions) {
+        session->Close();
+    }
+
+    for (const auto& request : m_deferrals) {
+        request.session->Close();
+    }
+
+    // Close event.
+    m_event->GetReadableEvent().Close();
+    m_event->Close();
+
+    if (m_deferral_event) {
+        m_deferral_event->GetReadableEvent().Close();
+        // Write event is owned by ServiceManager
+    }
+}
+
+void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) {
+    server_manager->m_system.RunServer(std::move(server_manager));
+}
+
+Result ServerManager::RegisterSession(Kernel::KServerSession* session,
+                                      std::shared_ptr<Kernel::SessionRequestManager> manager) {
+    ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
+
+    // We are taking ownership of the server session, so don't open it.
+    // Begin tracking the server session.
+    {
+        std::scoped_lock ll{m_list_mutex};
+        m_sessions.emplace(session, std::move(manager));
+    }
+
+    // Signal the wakeup event.
+    m_event->Signal();
+
+    R_SUCCEED();
+}
+
+Result ServerManager::RegisterNamedService(const std::string& service_name,
+                                           std::shared_ptr<Kernel::SessionRequestHandler>&& handler,
+                                           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)));
+
+    // Get the registered port.
+    auto port = m_system.ServiceManager().GetServicePort(service_name);
+    ASSERT(port.Succeeded());
+
+    // Open a new reference to the server port.
+    (*port)->GetServerPort().Open();
+
+    // Begin tracking the server port.
+    {
+        std::scoped_lock ll{m_list_mutex};
+        m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler));
+    }
+
+    // Signal the wakeup event.
+    m_event->Signal();
+
+    R_SUCCEED();
+}
+
+Result ServerManager::ManageNamedPort(const std::string& service_name,
+                                      std::shared_ptr<Kernel::SessionRequestHandler>&& handler,
+                                      u32 max_sessions) {
+    ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
+
+    // Create a new port.
+    auto* port = Kernel::KPort::Create(m_system.Kernel());
+    port->Initialize(max_sessions, false, service_name);
+
+    // Register the port.
+    Kernel::KPort::Register(m_system.Kernel(), port);
+
+    // Ensure that our reference to the port is closed if we fail to register it.
+    SCOPE_EXIT({
+        port->GetClientPort().Close();
+        port->GetServerPort().Close();
+    });
+
+    // Register the object name with the kernel.
+    R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()),
+                                           service_name.c_str()));
+
+    // Open a new reference to the server port.
+    port->GetServerPort().Open();
+
+    // Begin tracking the server port.
+    {
+        std::scoped_lock ll{m_list_mutex};
+        m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler));
+    }
+
+    // We succeeded.
+    R_SUCCEED();
+}
+
+Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) {
+    // Create a new event.
+    m_deferral_event = Kernel::KEvent::Create(m_system.Kernel());
+    ASSERT(m_deferral_event != nullptr);
+
+    // Initialize the event.
+    m_deferral_event->Initialize(nullptr);
+
+    // Set the output.
+    *out_event = m_deferral_event;
+
+    // We succeeded.
+    R_SUCCEED();
+}
+
+void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) {
+    for (size_t i = 0; i < num_threads; i++) {
+        auto thread_name = fmt::format("{}:{}", name, i + 1);
+        m_threads.emplace_back(m_system.Kernel().RunOnHostCoreThread(
+            std::move(thread_name), [&] { this->LoopProcessImpl(); }));
+    }
+}
+
+Result ServerManager::LoopProcess() {
+    SCOPE_EXIT({
+        m_stopped.store(true);
+        m_stopped.notify_all();
+    });
+
+    R_RETURN(this->LoopProcessImpl());
+}
+
+Result ServerManager::LoopProcessImpl() {
+    while (!m_stop_source.stop_requested()) {
+        R_TRY(this->WaitAndProcessImpl());
+    }
+
+    R_SUCCEED();
+}
+
+Result ServerManager::WaitAndProcessImpl() {
+    Kernel::KScopedAutoObject<Kernel::KSynchronizationObject> wait_obj;
+    HandleType wait_type{};
+
+    // Ensure we are the only thread waiting for this server.
+    std::unique_lock sl{m_serve_mutex};
+
+    // If we're done, return before we start waiting.
+    R_SUCCEED_IF(m_stop_source.stop_requested());
+
+    // Wait for a tracked object to become signaled.
+    {
+        s32 num_objs{};
+        std::array<HandleType, MaximumWaitObjects> wait_types{};
+        std::array<Kernel::KSynchronizationObject*, MaximumWaitObjects> wait_objs{};
+
+        const auto AddWaiter{
+            [&](Kernel::KSynchronizationObject* synchronization_object, HandleType type) {
+                // Open a new reference to the object.
+                synchronization_object->Open();
+
+                // Insert into the list.
+                wait_types[num_objs] = type;
+                wait_objs[num_objs++] = synchronization_object;
+            }};
+
+        {
+            std::scoped_lock ll{m_list_mutex};
+
+            // Add all of our ports.
+            for (const auto& [port, handler] : m_ports) {
+                AddWaiter(port, HandleType::Port);
+            }
+
+            // Add all of our sessions.
+            for (const auto& [session, manager] : m_sessions) {
+                AddWaiter(session, HandleType::Session);
+            }
+        }
+
+        // Add the deferral wakeup event.
+        if (m_deferral_event != nullptr) {
+            AddWaiter(std::addressof(m_deferral_event->GetReadableEvent()), HandleType::DeferEvent);
+        }
+
+        // Add the wakeup event.
+        AddWaiter(std::addressof(m_event->GetReadableEvent()), HandleType::Event);
+
+        // Clean up extra references on exit.
+        SCOPE_EXIT({
+            for (s32 i = 0; i < num_objs; i++) {
+                wait_objs[i]->Close();
+            }
+        });
+
+        // Wait for a signal.
+        s32 out_index{-1};
+        R_TRY(Kernel::KSynchronizationObject::Wait(m_system.Kernel(), &out_index, wait_objs.data(),
+                                                   num_objs, -1));
+        ASSERT(out_index >= 0 && out_index < num_objs);
+
+        // Set the output index.
+        wait_obj = wait_objs[out_index];
+        wait_type = wait_types[out_index];
+    }
+
+    // Process what we just received, temporarily removing the object so it is
+    // not processed concurrently by another thread.
+    {
+        switch (wait_type) {
+        case HandleType::Port: {
+            // Port signaled.
+            auto* port = wait_obj->DynamicCast<Kernel::KServerPort*>();
+            std::shared_ptr<Kernel::SessionRequestHandler> handler;
+
+            // Remove from tracking.
+            {
+                std::scoped_lock ll{m_list_mutex};
+                ASSERT(m_ports.contains(port));
+                m_ports.at(port).swap(handler);
+                m_ports.erase(port);
+            }
+
+            // Allow other threads to serve.
+            sl.unlock();
+
+            // Finish.
+            R_RETURN(this->OnPortEvent(port, std::move(handler)));
+        }
+        case HandleType::Session: {
+            // Session signaled.
+            auto* session = wait_obj->DynamicCast<Kernel::KServerSession*>();
+            std::shared_ptr<Kernel::SessionRequestManager> manager;
+
+            // Remove from tracking.
+            {
+                std::scoped_lock ll{m_list_mutex};
+                ASSERT(m_sessions.contains(session));
+                m_sessions.at(session).swap(manager);
+                m_sessions.erase(session);
+            }
+
+            // Allow other threads to serve.
+            sl.unlock();
+
+            // Finish.
+            R_RETURN(this->OnSessionEvent(session, std::move(manager)));
+        }
+        case HandleType::DeferEvent: {
+            // Clear event.
+            ASSERT(R_SUCCEEDED(m_deferral_event->Clear()));
+
+            // Drain the list of deferrals while we process.
+            std::list<RequestState> deferrals;
+            {
+                std::scoped_lock ll{m_list_mutex};
+                m_deferrals.swap(deferrals);
+            }
+
+            // Allow other threads to serve.
+            sl.unlock();
+
+            // Finish.
+            R_RETURN(this->OnDeferralEvent(std::move(deferrals)));
+        }
+        case HandleType::Event: {
+            // Clear event and finish.
+            R_RETURN(m_event->Clear());
+        }
+        default: {
+            UNREACHABLE();
+        }
+        }
+    }
+}
+
+Result ServerManager::OnPortEvent(Kernel::KServerPort* port,
+                                  std::shared_ptr<Kernel::SessionRequestHandler>&& handler) {
+    // Accept a new server session.
+    Kernel::KServerSession* session = port->AcceptSession();
+    ASSERT(session != nullptr);
+
+    // Create the session manager and install the handler.
+    auto manager = std::make_shared<Kernel::SessionRequestManager>(m_system.Kernel(), *this);
+    manager->SetSessionHandler(std::shared_ptr(handler));
+
+    // Track the server session.
+    {
+        std::scoped_lock ll{m_list_mutex};
+        m_ports.emplace(port, std::move(handler));
+        m_sessions.emplace(session, std::move(manager));
+    }
+
+    // Signal the wakeup event.
+    m_event->Signal();
+
+    // We succeeded.
+    R_SUCCEED();
+}
+
+Result ServerManager::OnSessionEvent(Kernel::KServerSession* session,
+                                     std::shared_ptr<Kernel::SessionRequestManager>&& manager) {
+    Result rc{ResultSuccess};
+
+    // Try to receive a message.
+    std::shared_ptr<Kernel::HLERequestContext> context;
+    rc = session->ReceiveRequest(&context, manager);
+
+    // If the session has been closed, we're done.
+    if (rc == Kernel::ResultSessionClosed) {
+        // Close the session.
+        session->Close();
+
+        // Finish.
+        R_SUCCEED();
+    }
+    ASSERT(R_SUCCEEDED(rc));
+
+    RequestState request{
+        .session = session,
+        .context = std::move(context),
+        .manager = std::move(manager),
+    };
+
+    // Complete the sync request with deferral handling.
+    R_RETURN(this->CompleteSyncRequest(std::move(request)));
+}
+
+Result ServerManager::CompleteSyncRequest(RequestState&& request) {
+    Result rc{ResultSuccess};
+    Result service_rc{ResultSuccess};
+
+    // Mark the request as not deferred.
+    request.context->SetIsDeferred(false);
+
+    // Complete the request. We have exclusive access to this session.
+    service_rc = request.manager->CompleteSyncRequest(request.session, *request.context);
+
+    // If we've been deferred, we're done.
+    if (request.context->GetIsDeferred()) {
+        // Insert into deferral list.
+        std::scoped_lock ll{m_list_mutex};
+        m_deferrals.emplace_back(std::move(request));
+
+        // Finish.
+        R_SUCCEED();
+    }
+
+    // Send the reply.
+    rc = request.session->SendReplyHLE();
+
+    // If the session has been closed, we're done.
+    if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) {
+        // Close the session.
+        request.session->Close();
+
+        // Finish.
+        R_SUCCEED();
+    }
+
+    ASSERT(R_SUCCEEDED(rc));
+    ASSERT(R_SUCCEEDED(service_rc));
+
+    // Reinsert the session.
+    {
+        std::scoped_lock ll{m_list_mutex};
+        m_sessions.emplace(request.session, std::move(request.manager));
+    }
+
+    // Signal the wakeup event.
+    m_event->Signal();
+
+    // We succeeded.
+    R_SUCCEED();
+}
+
+Result ServerManager::OnDeferralEvent(std::list<RequestState>&& deferrals) {
+    ON_RESULT_FAILURE {
+        std::scoped_lock ll{m_list_mutex};
+        m_deferrals.splice(m_deferrals.end(), deferrals);
+    };
+
+    while (!deferrals.empty()) {
+        RequestState request = deferrals.front();
+        deferrals.pop_front();
+
+        // Try again to complete the request.
+        R_TRY(this->CompleteSyncRequest(std::move(request)));
+    }
+
+    R_SUCCEED();
+}
+
+} // namespace Service
diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h
new file mode 100644
index 0000000000..57b954ae86
--- /dev/null
+++ b/src/core/hle/service/server_manager.h
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <atomic>
+#include <functional>
+#include <list>
+#include <map>
+#include <mutex>
+#include <string_view>
+#include <vector>
+
+#include "common/polyfill_thread.h"
+#include "core/hle/result.h"
+#include "core/hle/service/mutex.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class HLERequestContext;
+class KEvent;
+class KServerPort;
+class KServerSession;
+class KSynchronizationObject;
+class SessionRequestHandler;
+class SessionRequestManager;
+} // namespace Kernel
+
+namespace Service {
+
+class ServerManager {
+public:
+    explicit ServerManager(Core::System& system);
+    ~ServerManager();
+
+    Result RegisterSession(Kernel::KServerSession* session,
+                           std::shared_ptr<Kernel::SessionRequestManager> manager);
+    Result RegisterNamedService(const std::string& service_name,
+                                std::shared_ptr<Kernel::SessionRequestHandler>&& handler,
+                                u32 max_sessions = 64);
+    Result ManageNamedPort(const std::string& service_name,
+                           std::shared_ptr<Kernel::SessionRequestHandler>&& handler,
+                           u32 max_sessions = 64);
+    Result ManageDeferral(Kernel::KEvent** out_event);
+
+    Result LoopProcess();
+    void StartAdditionalHostThreads(const char* name, size_t num_threads);
+
+    static void RunServer(std::unique_ptr<ServerManager>&& server);
+
+private:
+    struct RequestState;
+
+    Result LoopProcessImpl();
+    Result WaitAndProcessImpl();
+    Result OnPortEvent(Kernel::KServerPort* port,
+                       std::shared_ptr<Kernel::SessionRequestHandler>&& handler);
+    Result OnSessionEvent(Kernel::KServerSession* session,
+                          std::shared_ptr<Kernel::SessionRequestManager>&& manager);
+    Result OnDeferralEvent(std::list<RequestState>&& deferrals);
+    Result CompleteSyncRequest(RequestState&& state);
+
+private:
+    Core::System& m_system;
+    Mutex m_serve_mutex;
+    std::mutex m_list_mutex;
+
+    // Guest state tracking
+    std::map<Kernel::KServerPort*, std::shared_ptr<Kernel::SessionRequestHandler>> m_ports{};
+    std::map<Kernel::KServerSession*, std::shared_ptr<Kernel::SessionRequestManager>> m_sessions{};
+    Kernel::KEvent* m_event{};
+    Kernel::KEvent* m_deferral_event{};
+
+    // Deferral tracking
+    struct RequestState {
+        Kernel::KServerSession* session;
+        std::shared_ptr<Kernel::HLERequestContext> context;
+        std::shared_ptr<Kernel::SessionRequestManager> manager;
+    };
+    std::list<RequestState> m_deferrals{};
+
+    // Host state tracking
+    std::atomic<bool> m_stopped{};
+    std::vector<std::jthread> m_threads{};
+    std::stop_source m_stop_source{};
+};
+
+} // namespace Service
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 1ffc1c6948..31021ea03c 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -90,44 +90,13 @@ namespace Service {
 }
 
 ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
-                                           ServiceThreadType thread_type, u32 max_sessions_,
-                                           InvokerFn* handler_invoker_)
-    : SessionRequestHandler(system_.Kernel(), service_name_, thread_type), system{system_},
+                                           u32 max_sessions_, InvokerFn* handler_invoker_)
+    : SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
       service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
 
 ServiceFrameworkBase::~ServiceFrameworkBase() {
     // Wait for other threads to release access before destroying
     const auto guard = LockService();
-
-    if (named_port != nullptr) {
-        named_port->GetClientPort().Close();
-        named_port->GetServerPort().Close();
-        named_port = nullptr;
-    }
-}
-
-void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
-    const auto guard = LockService();
-
-    ASSERT(!service_registered);
-
-    service_manager.RegisterService(service_name, max_sessions, shared_from_this());
-    service_registered = true;
-}
-
-Kernel::KClientPort& ServiceFrameworkBase::CreatePort() {
-    const auto guard = LockService();
-
-    if (named_port == nullptr) {
-        ASSERT(!service_registered);
-
-        named_port = Kernel::KPort::Create(kernel);
-        named_port->Initialize(max_sessions, false, service_name);
-
-        service_registered = true;
-    }
-
-    return named_port->GetClientPort();
 }
 
 void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
@@ -244,67 +213,69 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
     : hos_binder_driver_server{std::make_unique<NVFlinger::HosBinderDriverServer>(system)},
       nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system, *hos_binder_driver_server)} {
 
+    auto& kernel = system.Kernel();
+
     // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
     // here and pass it into the respective InstallInterfaces functions.
-
     system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
 
-    system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory);
-    system.Kernel().RegisterInterfaceForNamedService("sm:", SM::ServiceManager::SessionHandler);
+    // clang-format off
+    kernel.RunOnHostCoreProcess("audio",      [&] { Audio::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("FS",         [&] { FileSystem::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("jit",        [&] { JIT::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("ldn",        [&] { LDN::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("Loader",     [&] { LDR::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach();
+    kernel.RunOnHostCoreProcess("bsdsocket",  [&] { Sockets::LoopProcess(system); }).detach();
+    kernel.RunOnHostCoreProcess("vi",         [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach();
 
-    Account::InstallInterfaces(system);
-    AM::InstallInterfaces(*sm, *nv_flinger, system);
-    AOC::InstallInterfaces(*sm, system);
-    APM::InstallInterfaces(system);
-    Audio::InstallInterfaces(*sm, system);
-    BCAT::InstallInterfaces(system);
-    BPC::InstallInterfaces(*sm, system);
-    BtDrv::InstallInterfaces(*sm, system);
-    BTM::InstallInterfaces(*sm, system);
-    Capture::InstallInterfaces(*sm, system);
-    ERPT::InstallInterfaces(*sm, system);
-    ES::InstallInterfaces(*sm, system);
-    EUPLD::InstallInterfaces(*sm, system);
-    Fatal::InstallInterfaces(*sm, system);
-    FGM::InstallInterfaces(*sm, system);
-    FileSystem::InstallInterfaces(system);
-    Friend::InstallInterfaces(*sm, system);
-    Glue::InstallInterfaces(system);
-    GRC::InstallInterfaces(*sm, system);
-    HID::InstallInterfaces(*sm, system);
-    JIT::InstallInterfaces(*sm, system);
-    LBL::InstallInterfaces(*sm, system);
-    LDN::InstallInterfaces(*sm, system);
-    LDR::InstallInterfaces(*sm, system);
-    LM::InstallInterfaces(system);
-    Migration::InstallInterfaces(*sm, system);
-    Mii::InstallInterfaces(*sm, system);
-    MM::InstallInterfaces(*sm, system);
-    MNPP::InstallInterfaces(*sm, system);
-    NCM::InstallInterfaces(*sm, system);
-    NFC::InstallInterfaces(*sm, system);
-    NFP::InstallInterfaces(*sm, system);
-    NGCT::InstallInterfaces(*sm, system);
-    NIFM::InstallInterfaces(*sm, system);
-    NIM::InstallInterfaces(*sm, system);
-    NPNS::InstallInterfaces(*sm, system);
-    NS::InstallInterfaces(*sm, system);
-    Nvidia::InstallInterfaces(*sm, *nv_flinger, system);
-    OLSC::InstallInterfaces(*sm, system);
-    PCIe::InstallInterfaces(*sm, system);
-    PCTL::InstallInterfaces(*sm, system);
-    PCV::InstallInterfaces(*sm, system);
-    PlayReport::InstallInterfaces(*sm, system);
-    PM::InstallInterfaces(system);
-    PSC::InstallInterfaces(*sm, system);
-    PTM::InstallInterfaces(*sm, system);
-    Set::InstallInterfaces(*sm, system);
-    Sockets::InstallInterfaces(*sm, system);
-    SPL::InstallInterfaces(*sm, system);
-    SSL::InstallInterfaces(*sm, system);
-    Time::InstallInterfaces(system);
-    USB::InstallInterfaces(*sm, system);
-    VI::InstallInterfaces(*sm, system, *nv_flinger, *hos_binder_driver_server);
+    kernel.RunOnGuestCoreProcess("sm",         [&] { SM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("account",    [&] { Account::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("am",         [&] { AM::LoopProcess(*nv_flinger, system); });
+    kernel.RunOnGuestCoreProcess("aoc",        [&] { AOC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("apm",        [&] { APM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("bcat",       [&] { BCAT::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("bpc",        [&] { BPC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("btdrv",      [&] { BtDrv::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("btm",        [&] { BTM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("capsrv",     [&] { Capture::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("erpt",       [&] { ERPT::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("es",         [&] { ES::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("eupld",      [&] { EUPLD::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("fatal",      [&] { Fatal::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("fgm",        [&] { FGM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("friends",    [&] { Friend::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("glue",       [&] { Glue::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("grc",        [&] { GRC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("hid",        [&] { HID::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("lbl",        [&] { LBL::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("mig",        [&] { Migration::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("mii",        [&] { Mii::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("mm",         [&] { MM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("mnpp",       [&] { MNPP::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("NCM",        [&] { NCM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("nfc",        [&] { NFC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("nfp",        [&] { NFP::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("ngct",       [&] { NGCT::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("nifm",       [&] { NIFM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("nim",        [&] { NIM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("npns",       [&] { NPNS::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("ns",         [&] { NS::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("olsc",       [&] { OLSC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("pcie",       [&] { PCIe::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("pctl",       [&] { PCTL::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("pcv",        [&] { PCV::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("prepo",      [&] { PlayReport::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("psc",        [&] { PSC::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("ptm",        [&] { PTM::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("settings",   [&] { Set::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("spl",        [&] { SPL::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("ssl",        [&] { SSL::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("time",       [&] { Time::LoopProcess(system); });
+    kernel.RunOnGuestCoreProcess("usb",        [&] { USB::LoopProcess(system); });
+    // clang-format on
 }
 
 Services::~Services() = default;
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 22e2119d72..db3b313787 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -19,8 +19,6 @@ class System;
 
 namespace Kernel {
 class HLERequestContext;
-class KClientPort;
-class KPort;
 class KServerSession;
 class ServiceThread;
 } // namespace Kernel
@@ -67,18 +65,12 @@ public:
         return max_sessions;
     }
 
-    /// Creates a port pair and registers this service with the given ServiceManager.
-    void InstallAsService(SM::ServiceManager& service_manager);
-
     /// Invokes a service request routine using the HIPC protocol.
     void InvokeRequest(Kernel::HLERequestContext& ctx);
 
     /// Invokes a service request routine using the HIPC protocol.
     void InvokeRequestTipc(Kernel::HLERequestContext& ctx);
 
-    /// Creates a port pair and registers it on the kernel's global port registry.
-    Kernel::KClientPort& CreatePort();
-
     /// Handles a synchronization request for the service.
     Result HandleSyncRequest(Kernel::KServerSession& session,
                              Kernel::HLERequestContext& context) override;
@@ -99,9 +91,6 @@ protected:
     /// Identifier string used to connect to the service.
     std::string service_name;
 
-    /// Port used by ManageNamedPort.
-    Kernel::KPort* named_port{};
-
 private:
     template <typename T>
     friend class ServiceFramework;
@@ -116,8 +105,7 @@ private:
                            Kernel::HLERequestContext& ctx);
 
     explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
-                                  ServiceThreadType thread_type, u32 max_sessions_,
-                                  InvokerFn* handler_invoker_);
+                                  u32 max_sessions_, InvokerFn* handler_invoker_);
     ~ServiceFrameworkBase() override;
 
     void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
@@ -181,15 +169,12 @@ protected:
      *
      * @param system_ The system context to construct this service under.
      * @param service_name_ Name of the service.
-     * @param thread_type Specifies the thread type for this service. If this is set to CreateNew,
-     *                    it creates a new thread for it, otherwise this uses the default thread.
      * @param max_sessions_ Maximum number of sessions that can be connected to this service at the
      * same time.
      */
     explicit ServiceFramework(Core::System& system_, const char* service_name_,
-                              ServiceThreadType thread_type = ServiceThreadType::Default,
                               u32 max_sessions_ = ServerSessionCountMax)
-        : ServiceFrameworkBase(system_, service_name_, thread_type, max_sessions_, Invoker) {}
+        : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
 
     /// Registers handlers in the service.
     template <std::size_t N>
diff --git a/src/core/hle/service/set/settings.cpp b/src/core/hle/service/set/settings.cpp
index 4ebc2a0ec8..c48844f775 100644
--- a/src/core/hle/service/set/settings.cpp
+++ b/src/core/hle/service/set/settings.cpp
@@ -1,20 +1,23 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/set/set.h"
 #include "core/hle/service/set/set_cal.h"
 #include "core/hle/service/set/set_fd.h"
 #include "core/hle/service/set/set_sys.h"
 #include "core/hle/service/set/settings.h"
-#include "core/hle/service/sm/sm.h"
 
 namespace Service::Set {
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<SET>(system)->InstallAsService(service_manager);
-    std::make_shared<SET_CAL>(system)->InstallAsService(service_manager);
-    std::make_shared<SET_FD>(system)->InstallAsService(service_manager);
-    std::make_shared<SET_SYS>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("set", std::make_shared<SET>(system));
+    server_manager->RegisterNamedService("set:cal", std::make_shared<SET_CAL>(system));
+    server_manager->RegisterNamedService("set:fd", std::make_shared<SET_FD>(system));
+    server_manager->RegisterNamedService("set:sys", std::make_shared<SET_SYS>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Set
diff --git a/src/core/hle/service/set/settings.h b/src/core/hle/service/set/settings.h
index 6cd7d634c5..03cd4bb661 100644
--- a/src/core/hle/service/set/settings.h
+++ b/src/core/hle/service/set/settings.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::Set {
 
-/// Registers all Settings services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Set
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 84720094ff..53c877836c 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -12,6 +12,7 @@
 #include "core/hle/kernel/k_scoped_resource_reservation.h"
 #include "core/hle/kernel/k_server_port.h"
 #include "core/hle/result.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/hle/service/sm/sm_controller.h"
 
@@ -22,13 +23,19 @@ constexpr Result ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
 constexpr Result ERR_INVALID_NAME(ErrorModule::SM, 6);
 constexpr Result ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
 
-ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {}
+ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {
+    controller_interface = std::make_unique<Controller>(kernel.System());
+}
 
 ServiceManager::~ServiceManager() {
     for (auto& [name, port] : service_ports) {
         port->GetClientPort().Close();
         port->GetServerPort().Close();
     }
+
+    if (deferral_event) {
+        deferral_event->Close();
+    }
 }
 
 void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
@@ -43,21 +50,12 @@ static Result ValidateServiceName(const std::string& name) {
     return ResultSuccess;
 }
 
-Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) {
-    self.sm_interface = std::make_shared<SM>(self, system);
-    self.controller_interface = std::make_unique<Controller>(system);
-    return self.sm_interface->CreatePort();
-}
-
-void ServiceManager::SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port) {
-    self.sm_interface->AcceptSession(server_port);
-}
-
 Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
                                        Kernel::SessionRequestHandlerPtr handler) {
 
     CASCADE_CODE(ValidateServiceName(name));
 
+    std::scoped_lock lk{lock};
     if (registered_services.find(name) != registered_services.end()) {
         LOG_ERROR(Service_SM, "Service is already registered! service={}", name);
         return ERR_ALREADY_REGISTERED;
@@ -68,6 +66,9 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
 
     service_ports.emplace(name, port);
     registered_services.emplace(name, handler);
+    if (deferral_event) {
+        deferral_event->Signal();
+    }
 
     return ResultSuccess;
 }
@@ -75,6 +76,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
 Result ServiceManager::UnregisterService(const std::string& name) {
     CASCADE_CODE(ValidateServiceName(name));
 
+    std::scoped_lock lk{lock};
     const auto iter = registered_services.find(name);
     if (iter == registered_services.end()) {
         LOG_ERROR(Service_SM, "Server is not registered! service={}", name);
@@ -89,9 +91,11 @@ Result ServiceManager::UnregisterService(const std::string& name) {
 
 ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
     CASCADE_CODE(ValidateServiceName(name));
+
+    std::scoped_lock lk{lock};
     auto it = service_ports.find(name);
     if (it == service_ports.end()) {
-        LOG_ERROR(Service_SM, "Server is not registered! service={}", name);
+        LOG_WARNING(Service_SM, "Server is not registered! service={}", name);
         return ERR_SERVICE_NOT_REGISTERED;
     }
 
@@ -108,7 +112,7 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
 void SM::Initialize(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service_SM, "called");
 
-    is_initialized = true;
+    ctx.GetManager()->SetIsInitializedForSm();
 
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(ResultSuccess);
@@ -116,6 +120,11 @@ void SM::Initialize(Kernel::HLERequestContext& ctx) {
 
 void SM::GetService(Kernel::HLERequestContext& ctx) {
     auto result = GetServiceImpl(ctx);
+    if (ctx.GetIsDeferred()) {
+        // Don't overwrite the command buffer.
+        return;
+    }
+
     if (result.Succeeded()) {
         IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
         rb.Push(result.Code());
@@ -128,6 +137,11 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
 
 void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) {
     auto result = GetServiceImpl(ctx);
+    if (ctx.GetIsDeferred()) {
+        // Don't overwrite the command buffer.
+        return;
+    }
+
     IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
     rb.Push(result.Code());
     rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
@@ -145,7 +159,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) {
 }
 
 ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) {
-    if (!is_initialized) {
+    if (!ctx.GetManager()->GetIsInitializedForSm()) {
         return ERR_NOT_INITIALIZED;
     }
 
@@ -154,10 +168,15 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
 
     // Find the named port.
     auto port_result = service_manager.GetServicePort(name);
-    auto service = service_manager.GetService<Kernel::SessionRequestHandler>(name);
-    if (port_result.Failed() || !service) {
-        LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw);
-        return port_result.Code();
+    if (port_result.Code() == ERR_INVALID_NAME) {
+        LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
+        return ERR_INVALID_NAME;
+    }
+
+    if (port_result.Failed()) {
+        LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
+        ctx.SetIsDeferred();
+        return ERR_SERVICE_NOT_REGISTERED;
     }
     auto& port = port_result.Unwrap();
 
@@ -167,7 +186,6 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
         LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
         return result;
     }
-    service->AcceptSession(&port->GetServerPort());
 
     LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
 
@@ -212,7 +230,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
 }
 
 SM::SM(ServiceManager& service_manager_, Core::System& system_)
-    : ServiceFramework{system_, "sm:", ServiceThreadType::Default, 4},
+    : ServiceFramework{system_, "sm:", 4},
       service_manager{service_manager_}, kernel{system_.Kernel()} {
     RegisterHandlers({
         {0, &SM::Initialize, "Initialize"},
@@ -232,4 +250,16 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_)
 
 SM::~SM() = default;
 
+void LoopProcess(Core::System& system) {
+    auto& service_manager = system.ServiceManager();
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    Kernel::KEvent* deferral_event{};
+    server_manager->ManageDeferral(&deferral_event);
+    service_manager.SetDeferralEvent(deferral_event);
+
+    server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system));
+    ServerManager::RunServer(std::move(server_manager));
+}
+
 } // namespace Service::SM
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 02a5dde9ea..b7eeafdd69 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <memory>
+#include <mutex>
 #include <string>
 #include <unordered_map>
 
@@ -50,9 +51,6 @@ private:
 
 class ServiceManager {
 public:
-    static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system);
-    static void SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port);
-
     explicit ServiceManager(Kernel::KernelCore& kernel_);
     ~ServiceManager();
 
@@ -73,16 +71,25 @@ public:
 
     void InvokeControlRequest(Kernel::HLERequestContext& context);
 
+    void SetDeferralEvent(Kernel::KEvent* deferral_event_) {
+        deferral_event = deferral_event_;
+    }
+
 private:
     std::shared_ptr<SM> sm_interface;
     std::unique_ptr<Controller> controller_interface;
 
     /// Map of registered services, retrieved using GetServicePort.
+    std::mutex lock;
     std::unordered_map<std::string, Kernel::SessionRequestHandlerPtr> registered_services;
     std::unordered_map<std::string, Kernel::KPort*> service_ports;
 
     /// Kernel context
     Kernel::KernelCore& kernel;
+    Kernel::KEvent* deferral_event{};
 };
 
+/// Runs SM services.
+void LoopProcess(Core::System& system);
+
 } // namespace Service::SM
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 1cf9dd1c49..f52522d1d1 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -10,6 +10,7 @@
 #include "core/hle/kernel/k_scoped_resource_reservation.h"
 #include "core/hle/kernel/k_server_session.h"
 #include "core/hle/kernel/k_session.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sm/sm_controller.h"
 
 namespace Service::SM {
@@ -48,9 +49,9 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
     // Commit the session reservation.
     session_reservation.Commit();
 
-    // Register with manager.
-    session_manager->SessionHandler().RegisterSession(&session->GetServerSession(),
-                                                      session_manager);
+    // Register with server manager.
+    session_manager->GetServerManager().RegisterSession(&session->GetServerSession(),
+                                                        session_manager);
 
     // We succeeded.
     IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 330a664090..2789fa1eda 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -881,8 +881,7 @@ void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
 }
 
 BSD::BSD(Core::System& system_, const char* name)
-    : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, room_network{
-                                                                         system_.GetRoomNetwork()} {
+    : ServiceFramework{system_, name}, room_network{system_.GetRoomNetwork()} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &BSD::RegisterClient, "RegisterClient"},
diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp
index b191b5cf5f..676d24e036 100644
--- a/src/core/hle/service/sockets/sockets.cpp
+++ b/src/core/hle/service/sockets/sockets.cpp
@@ -1,6 +1,7 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/sockets/bsd.h"
 #include "core/hle/service/sockets/nsd.h"
 #include "core/hle/service/sockets/sfdnsres.h"
@@ -8,15 +9,17 @@
 
 namespace Service::Sockets {
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<BSD>(system, "bsd:s")->InstallAsService(service_manager);
-    std::make_shared<BSD>(system, "bsd:u")->InstallAsService(service_manager);
-    std::make_shared<BSDCFG>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
 
-    std::make_shared<NSD>(system, "nsd:a")->InstallAsService(service_manager);
-    std::make_shared<NSD>(system, "nsd:u")->InstallAsService(service_manager);
-
-    std::make_shared<SFDNSRES>(system)->InstallAsService(service_manager);
+    server_manager->RegisterNamedService("bsd:s", std::make_shared<BSD>(system, "bsd:s"));
+    server_manager->RegisterNamedService("bsd:u", std::make_shared<BSD>(system, "bsd:u"));
+    server_manager->RegisterNamedService("bsdcfg", std::make_shared<BSDCFG>(system));
+    server_manager->RegisterNamedService("nsd:a", std::make_shared<NSD>(system, "nsd:a"));
+    server_manager->RegisterNamedService("nsd:u", std::make_shared<NSD>(system, "nsd:u"));
+    server_manager->RegisterNamedService("sfdnsres", std::make_shared<SFDNSRES>(system));
+    server_manager->StartAdditionalHostThreads("bsdsocket", 2);
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h
index 9840c11f9e..acd2dae7b0 100644
--- a/src/core/hle/service/sockets/sockets.h
+++ b/src/core/hle/service/sockets/sockets.h
@@ -10,10 +10,6 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::Sockets {
 
 enum class Errno : u32 {
@@ -99,7 +95,6 @@ struct Linger {
     u32 linger;
 };
 
-/// Registers all Sockets services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Sockets
diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp
index 64eae1ebf9..31679e1bb5 100644
--- a/src/core/hle/service/spl/spl_module.cpp
+++ b/src/core/hle/service/spl/spl_module.cpp
@@ -9,6 +9,7 @@
 #include "common/settings.h"
 #include "core/hle/api_version.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/spl/csrng.h"
 #include "core/hle/service/spl/spl.h"
 #include "core/hle/service/spl/spl_module.h"
@@ -158,15 +159,18 @@ ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
     }
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
     auto module = std::make_shared<Module>();
-    std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL_MIG>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL_FS>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL_SSL>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL_ES>(system, module)->InstallAsService(service_manager);
-    std::make_shared<SPL_MANU>(system, module)->InstallAsService(service_manager);
+
+    server_manager->RegisterNamedService("csrng", std::make_shared<CSRNG>(system, module));
+    server_manager->RegisterNamedService("spl", std::make_shared<SPL>(system, module));
+    server_manager->RegisterNamedService("spl:mig", std::make_shared<SPL_MIG>(system, module));
+    server_manager->RegisterNamedService("spl:fs", std::make_shared<SPL_FS>(system, module));
+    server_manager->RegisterNamedService("spl:ssl", std::make_shared<SPL_SSL>(system, module));
+    server_manager->RegisterNamedService("spl:es", std::make_shared<SPL_ES>(system, module));
+    server_manager->RegisterNamedService("spl:manu", std::make_shared<SPL_MANU>(system, module));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::SPL
diff --git a/src/core/hle/service/spl/spl_module.h b/src/core/hle/service/spl/spl_module.h
index 4c9a3c6185..baed9efd71 100644
--- a/src/core/hle/service/spl/spl_module.h
+++ b/src/core/hle/service/spl/spl_module.h
@@ -41,7 +41,6 @@ public:
     };
 };
 
-/// Registers all SPL services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::SPL
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 015208593d..c1fd1a59bd 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -2,8 +2,8 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 #include "core/hle/service/ssl/ssl.h"
 
 namespace Service::SSL {
@@ -183,8 +183,11 @@ private:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
-    std::make_shared<SSL>(system)->InstallAsService(service_manager);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("ssl", std::make_shared<SSL>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::SSL
diff --git a/src/core/hle/service/ssl/ssl.h b/src/core/hle/service/ssl/ssl.h
index 27b38a0032..f6e21bbb3b 100644
--- a/src/core/hle/service/ssl/ssl.h
+++ b/src/core/hle/service/ssl/ssl.h
@@ -7,13 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::SSL {
 
-/// Registers all SSL services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::SSL
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index f77cdbb430..8020e407cb 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -7,6 +7,7 @@
 #include "core/hardware_properties.h"
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/time/time.h"
 #include "core/hle/service/time/time_interface.h"
 #include "core/hle/service/time/time_manager.h"
@@ -397,11 +398,17 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
 
 Module::Interface::~Interface() = default;
 
-void InstallInterfaces(Core::System& system) {
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
     auto module{std::make_shared<Module>()};
-    std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager());
-    std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager());
-    std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager());
+
+    server_manager->RegisterNamedService("time:a",
+                                         std::make_shared<Time>(module, system, "time:a"));
+    server_manager->RegisterNamedService("time:s",
+                                         std::make_shared<Time>(module, system, "time:s"));
+    server_manager->RegisterNamedService("time:u",
+                                         std::make_shared<Time>(module, system, "time:u"));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::Time
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 76a46cfc75..c9936c6451 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -46,7 +46,6 @@ public:
     };
 };
 
-/// Registers all Time services with the specified service manager.
-void InstallInterfaces(Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::Time
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
index ac46a406cb..ddb73f3944 100644
--- a/src/core/hle/service/usb/usb.cpp
+++ b/src/core/hle/service/usb/usb.cpp
@@ -5,8 +5,8 @@
 
 #include "common/logging/log.h"
 #include "core/hle/ipc_helpers.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
-#include "core/hle/service/sm/sm.h"
 #include "core/hle/service/usb/usb.h"
 
 namespace Service::USB {
@@ -218,12 +218,15 @@ public:
     }
 };
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
-    std::make_shared<USB_DS>(system)->InstallAsService(sm);
-    std::make_shared<USB_HS>(system)->InstallAsService(sm);
-    std::make_shared<USB_PD>(system)->InstallAsService(sm);
-    std::make_shared<USB_PD_C>(system)->InstallAsService(sm);
-    std::make_shared<USB_PM>(system)->InstallAsService(sm);
+void LoopProcess(Core::System& system) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService("usb:ds", std::make_shared<USB_DS>(system));
+    server_manager->RegisterNamedService("usb:hs", std::make_shared<USB_HS>(system));
+    server_manager->RegisterNamedService("usb:pd", std::make_shared<USB_PD>(system));
+    server_manager->RegisterNamedService("usb:pd:c", std::make_shared<USB_PD_C>(system));
+    server_manager->RegisterNamedService("usb:pm", std::make_shared<USB_PM>(system));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::USB
diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h
index b41b9684c8..98376ebc0c 100644
--- a/src/core/hle/service/usb/usb.h
+++ b/src/core/hle/service/usb/usb.h
@@ -7,12 +7,8 @@ namespace Core {
 class System;
 }
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::USB {
 
-void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
+void LoopProcess(Core::System& system);
 
 } // namespace Service::USB
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 0915785d25..d9cfebd70f 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -26,6 +26,7 @@
 #include "core/hle/service/nvflinger/hos_binder_driver_server.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
 #include "core/hle/service/nvflinger/parcel.h"
+#include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 #include "core/hle/service/vi/vi.h"
 #include "core/hle/service/vi/vi_m.h"
@@ -73,8 +74,7 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
 class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
 public:
     explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_)
-        : ServiceFramework{system_, "IHOSBinderDriver", ServiceThreadType::CreateNew},
-          server(server_) {
+        : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) {
         static const FunctionInfo functions[] = {
             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
@@ -809,15 +809,17 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System&
     rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger, hos_binder_driver_server);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system,
-                       NVFlinger::NVFlinger& nv_flinger,
-                       NVFlinger::HosBinderDriverServer& hos_binder_driver_server) {
-    std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server)
-        ->InstallAsService(service_manager);
-    std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server)
-        ->InstallAsService(service_manager);
-    std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server)
-        ->InstallAsService(service_manager);
+void LoopProcess(Core::System& system, NVFlinger::NVFlinger& nv_flinger,
+                 NVFlinger::HosBinderDriverServer& hos_binder_driver_server) {
+    auto server_manager = std::make_unique<ServerManager>(system);
+
+    server_manager->RegisterNamedService(
+        "vi:m", std::make_shared<VI_M>(system, nv_flinger, hos_binder_driver_server));
+    server_manager->RegisterNamedService(
+        "vi:s", std::make_shared<VI_S>(system, nv_flinger, hos_binder_driver_server));
+    server_manager->RegisterNamedService(
+        "vi:u", std::make_shared<VI_U>(system, nv_flinger, hos_binder_driver_server));
+    ServerManager::RunServer(std::move(server_manager));
 }
 
 } // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index fc2d717e7f..4ed7aaf2bd 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -18,10 +18,6 @@ class HosBinderDriverServer;
 class NVFlinger;
 } // namespace Service::NVFlinger
 
-namespace Service::SM {
-class ServiceManager;
-}
-
 namespace Service::VI {
 
 enum class DisplayResolution : u32 {
@@ -52,9 +48,7 @@ void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system,
                            Permission permission);
 } // namespace detail
 
-/// Registers all VI services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system,
-                       NVFlinger::NVFlinger& nv_flinger,
-                       NVFlinger::HosBinderDriverServer& hos_binder_driver_server);
+void LoopProcess(Core::System& system, NVFlinger::NVFlinger& nv_flinger,
+                 NVFlinger::HosBinderDriverServer& hos_binder_driver_server);
 
 } // namespace Service::VI
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 44ee39648b..c2d96bbec4 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -47,8 +47,13 @@ void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size)
 }
 
 u64 StandardVmCallbacks::HidKeysDown() {
-    const auto applet_resource =
-        system.ServiceManager().GetService<Service::HID::Hid>("hid")->GetAppletResource();
+    const auto hid = system.ServiceManager().GetService<Service::HID::Hid>("hid");
+    if (hid == nullptr) {
+        LOG_WARNING(CheatEngine, "Attempted to read input state, but hid is not initialized!");
+        return 0;
+    }
+
+    const auto applet_resource = hid->GetAppletResource();
     if (applet_resource == nullptr) {
         LOG_WARNING(CheatEngine,
                     "Attempted to read input state, but applet resource is not initialized!");