diff options
| author | Liam <byteslice@airmail.cc> | 2022-10-03 22:52:52 -0400 | 
|---|---|---|
| committer | Liam <byteslice@airmail.cc> | 2022-10-11 18:15:45 -0400 | 
| commit | 9b34afa588c4e4bf312e2812ffe6879e09dafc75 (patch) | |
| tree | 052c8d4c70805dabfa6fc06264bbe53b1911c8ba /src/core/hle | |
| parent | 6bcd676b610773727f446a8c81bcca1c64a95b10 (diff) | |
Add implementation of svcCreateSession
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 90 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 14 | 
2 files changed, 103 insertions, 1 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 27e5a805d..3a89511aa 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -29,6 +29,7 @@  #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_session.h"  #include "core/hle/kernel/k_shared_memory.h"  #include "core/hle/kernel/k_synchronization_object.h"  #include "core/hle/kernel/k_thread.h" @@ -256,6 +257,93 @@ static Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u3      return UnmapMemory(system, dst_addr, src_addr, size);  } +template <typename T> +Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) { +    auto& process = *system.CurrentProcess(); +    auto& handle_table = process.GetHandleTable(); + +    // Declare the session we're going to allocate. +    T* session; + +    // Reserve a new session from the process resource limit. +    // FIXME: LimitableResource_SessionCountMax +    KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); +    if (session_reservation.Succeeded()) { +        session = T::Create(system.Kernel()); +    } else { +        return ResultLimitReached; + +        // // We couldn't reserve a session. Check that we support dynamically expanding the +        // // resource limit. +        // R_UNLESS(process.GetResourceLimit() == +        //          &system.Kernel().GetSystemResourceLimit(), ResultLimitReached); +        // R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), ResultLimitReached()); + +        // // Try to allocate a session from unused slab memory. +        // session = T::CreateFromUnusedSlabMemory(); +        // R_UNLESS(session != nullptr, ResultLimitReached); +        // ON_RESULT_FAILURE { session->Close(); }; + +        // // If we're creating a KSession, we want to add two KSessionRequests to the heap, to +        // // prevent request exhaustion. +        // // NOTE: Nintendo checks if session->DynamicCast<KSession *>() != nullptr, but there's +        // // no reason to not do this statically. +        // if constexpr (std::same_as<T, KSession>) { +        //     for (size_t i = 0; i < 2; i++) { +        //         KSessionRequest* request = KSessionRequest::CreateFromUnusedSlabMemory(); +        //         R_UNLESS(request != nullptr, ResultLimitReached); +        //         request->Close(); +        //     } +        // } + +        // We successfully allocated a session, so add the object we allocated to the resource +        // limit. +        // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1); +    } + +    // Check that we successfully created a session. +    R_UNLESS(session != nullptr, ResultOutOfResource); + +    // Initialize the session. +    session->Initialize(nullptr, fmt::format("{}", name)); + +    // Commit the session reservation. +    session_reservation.Commit(); + +    // Ensure that we clean up the session (and its only references are handle table) on function +    // end. +    SCOPE_EXIT({ +        session->GetClientSession().Close(); +        session->GetServerSession().Close(); +    }); + +    // Register the session. +    T::Register(system.Kernel(), session); + +    // Add the server session to the handle table. +    R_TRY(handle_table.Add(out_server, &session->GetServerSession())); + +    // Add the client session to the handle table. */ +    const auto result = handle_table.Add(out_client, &session->GetClientSession()); + +    if (!R_SUCCEEDED(result)) { +        // Ensure that we maintaing a clean handle state on exit. +        handle_table.Remove(*out_server); +    } + +    return result; +} + +static Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, +                            u32 is_light, u64 name) { +    if (is_light) { +        // return CreateSession<KLightSession>(system, out_server, out_client, name); +        return ResultUnknown; +    } else { +        return CreateSession<KSession>(system, out_server, out_client, name); +    } +} +  /// Connect to an OS service given the port name, returns the handle to the port to out  static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {      auto& memory = system.Memory(); @@ -2860,7 +2948,7 @@ static const FunctionDef SVC_Table_64[] = {      {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},      {0x3E, nullptr, "Unknown3e"},      {0x3F, nullptr, "Unknown3f"}, -    {0x40, nullptr, "CreateSession"}, +    {0x40, SvcWrap64<CreateSession>, "CreateSession"},      {0x41, nullptr, "AcceptSession"},      {0x42, nullptr, "ReplyAndReceiveLight"},      {0x43, nullptr, "ReplyAndReceive"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 4bc49087e..16bf65802 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -346,6 +346,20 @@ void SvcWrap64(Core::System& system) {      FuncReturn(system, retval);  } +// Used by CreateSession +template <Result func(Core::System&, Handle*, Handle*, u32, u64)> +void SvcWrap64(Core::System& system) { +    Handle param_1 = 0; +    Handle param_2 = 0; +    const u32 retval = func(system, ¶m_1, ¶m_2, static_cast<u32>(Param(system, 2)), +                            static_cast<u32>(Param(system, 3))) +                           .raw; + +    system.CurrentArmInterface().SetReg(1, param_1); +    system.CurrentArmInterface().SetReg(2, param_2); +    FuncReturn(system, retval); +} +  // Used by WaitForAddress  template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)>  void SvcWrap64(Core::System& system) {  | 
