diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 6b6415832..f684985d0 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -72,7 +72,7 @@ public:
 
 protected:
     /// Creates the storage for the session data of the service.
-    virtual std::unique_ptr<SessionDataBase> MakeSessionData() const = 0;
+    virtual std::unique_ptr<SessionDataBase> MakeSessionData() = 0;
 
     /// Returns the session data associated with the server session.
     template <typename T>
diff --git a/src/core/hle/service/gsp/gsp.cpp b/src/core/hle/service/gsp/gsp.cpp
index 27a14ff52..4291b9971 100644
--- a/src/core/hle/service/gsp/gsp.cpp
+++ b/src/core/hle/service/gsp/gsp.cpp
@@ -12,12 +12,6 @@ namespace Service::GSP {
 
 static std::weak_ptr<GSP_GPU> gsp_gpu;
 
-FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) {
-    auto gpu = gsp_gpu.lock();
-    ASSERT(gpu != nullptr);
-    return gpu->GetFrameBufferInfo(thread_id, screen_index);
-}
-
 void SignalInterrupt(InterruptId interrupt_id) {
     auto gpu = gsp_gpu.lock();
     ASSERT(gpu != nullptr);
diff --git a/src/core/hle/service/gsp/gsp.h b/src/core/hle/service/gsp/gsp.h
index 2b565bc7e..4cde19e93 100644
--- a/src/core/hle/service/gsp/gsp.h
+++ b/src/core/hle/service/gsp/gsp.h
@@ -16,15 +16,6 @@ class System;
 }
 
 namespace Service::GSP {
-/**
- * Retrieves the framebuffer info stored in the GSP shared memory for the
- * specified screen index and thread id.
- * @param thread_id GSP thread id of the process that accesses the structure that we are requesting.
- * @param screen_index Index of the screen we are requesting (Top = 0, Bottom = 1).
- * @returns FramebufferUpdate Information about the specified framebuffer.
- */
-FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index);
-
 /**
  * Signals that the specified interrupt type has occurred to userland code
  * @param interrupt_id ID of interrupt that is being signalled
diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp
index 129139014..1eb4aae52 100644
--- a/src/core/hle/service/gsp/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp/gsp_gpu.cpp
@@ -50,12 +50,6 @@ constexpr ResultCode ERR_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorM
                                            ErrorSummary::InvalidArgument,
                                            ErrorLevel::Usage); // 0xE0E02BEC
 
-/// Maximum number of threads that can be registered at the same time in the GSP module.
-constexpr u32 MaxGSPThreads = 4;
-
-/// Thread ids currently in use by the sessions connected to the GSPGPU service.
-static std::array<bool, MaxGSPThreads> used_thread_ids = {false, false, false, false};
-
 static PAddr VirtualToPhysicalAddress(VAddr addr) {
     if (addr == 0) {
         return 0;
@@ -79,7 +73,7 @@ static PAddr VirtualToPhysicalAddress(VAddr addr) {
     return addr | 0x80000000;
 }
 
-static u32 GetUnusedThreadId() {
+u32 GSP_GPU::GetUnusedThreadId() {
     for (u32 id = 0; id < MaxGSPThreads; ++id) {
         if (!used_thread_ids[id])
             return id;
@@ -821,17 +815,25 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 2), system
     first_initialization = true;
 };
 
+std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> GSP_GPU::MakeSessionData() {
+    return std::make_unique<SessionData>(this);
+}
+
 SessionData::SessionData() {
+    UNREACHABLE();
+}
+
+SessionData::SessionData(GSP_GPU* gsp) : gsp(gsp) {
     // Assign a new thread id to this session when it connects. Note: In the real GSP service this
     // is done through a real thread (svcCreateThread) but we have to simulate it since our HLE
     // services don't have threads.
-    thread_id = GetUnusedThreadId();
-    used_thread_ids[thread_id] = true;
+    thread_id = gsp->GetUnusedThreadId();
+    gsp->used_thread_ids[thread_id] = true;
 }
 
 SessionData::~SessionData() {
     // Free the thread id slot so that other sessions can use it.
-    used_thread_ids[thread_id] = false;
+    gsp->used_thread_ids[thread_id] = false;
 }
 
 } // namespace Service::GSP
diff --git a/src/core/hle/service/gsp/gsp_gpu.h b/src/core/hle/service/gsp/gsp_gpu.h
index b1ab6807f..1c264837c 100644
--- a/src/core/hle/service/gsp/gsp_gpu.h
+++ b/src/core/hle/service/gsp/gsp_gpu.h
@@ -183,10 +183,15 @@ struct CommandBuffer {
 };
 static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrect size");
 
+class GSP_GPU;
+
 struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {
     SessionData();
+    SessionData(GSP_GPU* gsp);
     ~SessionData();
 
+    GSP_GPU* gsp;
+
     /// Event triggered when GSP interrupt has been signalled
     std::shared_ptr<Kernel::Event> interrupt_event;
     /// Thread index into interrupt relay queue
@@ -404,6 +409,10 @@ private:
     /// Returns the session data for the specified registered thread id, or nullptr if not found.
     SessionData* FindRegisteredThreadData(u32 thread_id);
 
+    u32 GetUnusedThreadId();
+
+    std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> MakeSessionData() override;
+
     Core::System& system;
 
     /// GSP shared memory
@@ -413,6 +422,14 @@ private:
     int active_thread_id = -1;
 
     bool first_initialization = true;
+
+    /// Maximum number of threads that can be registered at the same time in the GSP module.
+    static constexpr u32 MaxGSPThreads = 4;
+
+    /// Thread ids currently in use by the sessions connected to the GSPGPU service.
+    std::array<bool, MaxGSPThreads> used_thread_ids = {false, false, false, false};
+
+    friend class SessionData;
 };
 
 ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 0e8d7222e..1d9e800e2 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -156,7 +156,7 @@ protected:
         RegisterHandlersBase(functions, n);
     }
 
-    std::unique_ptr<SessionDataBase> MakeSessionData() const override {
+    std::unique_ptr<SessionDataBase> MakeSessionData() override {
         return std::make_unique<SessionData>();
     }