Add implementation of svcCreateSession

This commit is contained in:
Liam 2022-10-03 22:52:52 -04:00
parent 6bcd676b61
commit 9b34afa588
2 changed files with 103 additions and 1 deletions

View file

@ -29,6 +29,7 @@
#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_resource_reservation.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_shared_memory.h"
#include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_thread.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); 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 /// 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) { static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
auto& memory = system.Memory(); auto& memory = system.Memory();
@ -2860,7 +2948,7 @@ static const FunctionDef SVC_Table_64[] = {
{0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"}, {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
{0x3E, nullptr, "Unknown3e"}, {0x3E, nullptr, "Unknown3e"},
{0x3F, nullptr, "Unknown3f"}, {0x3F, nullptr, "Unknown3f"},
{0x40, nullptr, "CreateSession"}, {0x40, SvcWrap64<CreateSession>, "CreateSession"},
{0x41, nullptr, "AcceptSession"}, {0x41, nullptr, "AcceptSession"},
{0x42, nullptr, "ReplyAndReceiveLight"}, {0x42, nullptr, "ReplyAndReceiveLight"},
{0x43, nullptr, "ReplyAndReceive"}, {0x43, nullptr, "ReplyAndReceive"},

View file

@ -346,6 +346,20 @@ void SvcWrap64(Core::System& system) {
FuncReturn(system, retval); 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, &param_1, &param_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 // Used by WaitForAddress
template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)> template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)>
void SvcWrap64(Core::System& system) { void SvcWrap64(Core::System& system) {