diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 615d7901a..7902c2882 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -13,6 +13,7 @@
 
 #include "core/core.h"
 #include "core/core_timing.h"
+#include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
@@ -124,6 +125,8 @@ struct KernelCore::Impl {
 
         timer_callback_handle_table.Clear();
         timer_callback_event_type = nullptr;
+
+        named_ports.clear();
     }
 
     void InitializeResourceLimits(KernelCore& kernel) {
@@ -217,6 +220,10 @@ struct KernelCore::Impl {
     // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
     // allowing us to simply use a pool index or similar.
     Kernel::HandleTable thread_wakeup_callback_handle_table;
+
+    /// Map of named ports managed by the kernel, which can be retrieved using
+    /// the ConnectToPort SVC.
+    NamedPortTable named_ports;
 };
 
 KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {}
@@ -257,6 +264,23 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
     impl->process_list.push_back(std::move(process));
 }
 
+void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
+    impl->named_ports.emplace(std::move(name), std::move(port));
+}
+
+KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) {
+    return impl->named_ports.find(name);
+}
+
+KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort(
+    const std::string& name) const {
+    return impl->named_ports.find(name);
+}
+
+bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
+    return port != impl->named_ports.cend();
+}
+
 u32 KernelCore::CreateNewObjectID() {
     return impl->next_object_id++;
 }
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 089e959ac..ab2e9bffa 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <string>
+#include <unordered_map>
 #include "core/hle/kernel/object.h"
 
 template <typename T>
@@ -15,6 +17,7 @@ struct EventType;
 
 namespace Kernel {
 
+class ClientPort;
 class HandleTable;
 class Process;
 class ResourceLimit;
@@ -25,6 +28,9 @@ enum class ResourceLimitCategory : u8;
 
 /// Represents a single instance of the kernel.
 class KernelCore {
+private:
+    using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>;
+
 public:
     KernelCore();
     ~KernelCore();
@@ -59,6 +65,18 @@ public:
     /// Adds the given shared pointer to an internal list of active processes.
     void AppendNewProcess(SharedPtr<Process> process);
 
+    /// Adds a port to the named port table
+    void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
+
+    /// Finds a port within the named port table with the given name.
+    NamedPortTable::iterator FindNamedPort(const std::string& name);
+
+    /// Finds a port within the named port table with the given name.
+    NamedPortTable::const_iterator FindNamedPort(const std::string& name) const;
+
+    /// Determines whether or not the given port is a valid named port.
+    bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
+
 private:
     friend class Object;
     friend class Process;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 5da71cff0..1c9373ed8 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -68,19 +68,22 @@ static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
 
 /// Connect to an OS service given the port name, returns the handle to the port to out
 static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address) {
-    if (!Memory::IsValidVirtualAddress(port_name_address))
+    if (!Memory::IsValidVirtualAddress(port_name_address)) {
         return ERR_NOT_FOUND;
+    }
 
     static constexpr std::size_t PortNameMaxLength = 11;
     // Read 1 char beyond the max allowed port name to detect names that are too long.
     std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1);
-    if (port_name.size() > PortNameMaxLength)
+    if (port_name.size() > PortNameMaxLength) {
         return ERR_PORT_NAME_TOO_LONG;
+    }
 
     LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
 
-    auto it = Service::g_kernel_named_ports.find(port_name);
-    if (it == Service::g_kernel_named_ports.end()) {
+    auto& kernel = Core::System::GetInstance().Kernel();
+    auto it = kernel.FindNamedPort(port_name);
+    if (!kernel.IsValidNamedPort(it)) {
         LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
         return ERR_NOT_FOUND;
     }
@@ -91,7 +94,6 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
     CASCADE_RESULT(client_session, client_port->Connect());
 
     // Return the client session
-    auto& kernel = Core::System::GetInstance().Kernel();
     CASCADE_RESULT(*out_handle, kernel.HandleTable().Create(client_session));
     return RESULT_SUCCESS;
 }
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 8fb907072..9d804652e 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -12,6 +12,7 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/server_port.h"
 #include "core/hle/kernel/thread.h"
@@ -114,7 +115,7 @@ void ServiceFrameworkBase::InstallAsNamedPort() {
     std::tie(server_port, client_port) =
         ServerPort::CreatePortPair(kernel, max_sessions, service_name);
     server_port->SetHleHandler(shared_from_this());
-    AddNamedPort(service_name, std::move(client_port));
+    kernel.AddNamedPort(service_name, std::move(client_port));
 }
 
 Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
@@ -197,11 +198,6 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Module interface
 
-// TODO(yuriks): Move to kernel
-void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
-    g_kernel_named_ports.emplace(std::move(name), std::move(port));
-}
-
 /// Initialize ServiceManager
 void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) {
     // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
@@ -264,7 +260,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesys
 
 /// Shutdown ServiceManager
 void Shutdown() {
-    g_kernel_named_ports.clear();
     LOG_DEBUG(Service, "shutdown OK");
 }
 } // namespace Service
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index cd9c74f3d..7a051523e 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -6,7 +6,6 @@
 
 #include <cstddef>
 #include <string>
-#include <unordered_map>
 #include <boost/container/flat_map.hpp>
 #include "common/common_types.h"
 #include "core/hle/kernel/hle_ipc.h"
@@ -187,10 +186,4 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm,
 /// Shutdown ServiceManager
 void Shutdown();
 
-/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC.
-extern std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> g_kernel_named_ports;
-
-/// Adds a port to the named port table
-void AddNamedPort(std::string name, Kernel::SharedPtr<Kernel::ClientPort> port);
-
 } // namespace Service