code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

/// Gets system/memory information for the current process
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
               u64 info_sub_id) {
    LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}",
              info_id_type, info_sub_id, handle);

    u32 info_id = static_cast<u32>(info_id_type);

    switch (info_id_type) {
    case InfoType::CoreMask:
    case InfoType::PriorityMask:
    case InfoType::AliasRegionAddress:
    case InfoType::AliasRegionSize:
    case InfoType::HeapRegionAddress:
    case InfoType::HeapRegionSize:
    case InfoType::AslrRegionAddress:
    case InfoType::AslrRegionSize:
    case InfoType::StackRegionAddress:
    case InfoType::StackRegionSize:
    case InfoType::TotalMemorySize:
    case InfoType::UsedMemorySize:
    case InfoType::SystemResourceSizeTotal:
    case InfoType::SystemResourceSizeUsed:
    case InfoType::ProgramId:
    case InfoType::UserExceptionContextAddress:
    case InfoType::TotalNonSystemMemorySize:
    case InfoType::UsedNonSystemMemorySize:
    case InfoType::IsApplication:
    case InfoType::FreeThreadCount: {
        R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue);

        const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
        KScopedAutoObject process = handle_table.GetObject<KProcess>(handle);
        R_UNLESS(process.IsNotNull(), ResultInvalidHandle);

        switch (info_id_type) {
        case InfoType::CoreMask:
            *result = process->GetCoreMask();
            R_SUCCEED();

        case InfoType::PriorityMask:
            *result = process->GetPriorityMask();
            R_SUCCEED();

        case InfoType::AliasRegionAddress:
            *result = GetInteger(process->GetPageTable().GetAliasRegionStart());
            R_SUCCEED();

        case InfoType::AliasRegionSize:
            *result = process->GetPageTable().GetAliasRegionSize();
            R_SUCCEED();

        case InfoType::HeapRegionAddress:
            *result = GetInteger(process->GetPageTable().GetHeapRegionStart());
            R_SUCCEED();

        case InfoType::HeapRegionSize:
            *result = process->GetPageTable().GetHeapRegionSize();
            R_SUCCEED();

        case InfoType::AslrRegionAddress:
            *result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
            R_SUCCEED();

        case InfoType::AslrRegionSize:
            *result = process->GetPageTable().GetAliasCodeRegionSize();
            R_SUCCEED();

        case InfoType::StackRegionAddress:
            *result = GetInteger(process->GetPageTable().GetStackRegionStart());
            R_SUCCEED();

        case InfoType::StackRegionSize:
            *result = process->GetPageTable().GetStackRegionSize();
            R_SUCCEED();

        case InfoType::TotalMemorySize:
            *result = process->GetTotalUserPhysicalMemorySize();
            R_SUCCEED();

        case InfoType::UsedMemorySize:
            *result = process->GetUsedUserPhysicalMemorySize();
            R_SUCCEED();

        case InfoType::SystemResourceSizeTotal:
            *result = process->GetTotalSystemResourceSize();
            R_SUCCEED();

        case InfoType::SystemResourceSizeUsed:
            *result = process->GetUsedSystemResourceSize();
            R_SUCCEED();

        case InfoType::ProgramId:
            *result = process->GetProgramId();
            R_SUCCEED();

        case InfoType::UserExceptionContextAddress:
            *result = GetInteger(process->GetProcessLocalRegionAddress());
            R_SUCCEED();

        case InfoType::TotalNonSystemMemorySize:
            *result = process->GetTotalNonSystemUserPhysicalMemorySize();
            R_SUCCEED();

        case InfoType::UsedNonSystemMemorySize:
            *result = process->GetUsedNonSystemUserPhysicalMemorySize();
            R_SUCCEED();

        case InfoType::IsApplication:
            *result = process->IsApplication();
            R_SUCCEED();

        case InfoType::FreeThreadCount:
            if (KResourceLimit* resource_limit = process->GetResourceLimit();
                resource_limit != nullptr) {
                const auto current_value =
                    resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
                const auto limit_value =
                    resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
                *result = limit_value - current_value;
            } else {
                *result = 0;
            }
            R_SUCCEED();

        default:
            break;
        }

        LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
        R_THROW(ResultInvalidEnumValue);
    }

    case InfoType::DebuggerAttached:
        *result = 0;
        R_SUCCEED();

    case InfoType::ResourceLimit: {
        R_UNLESS(handle == 0, ResultInvalidHandle);
        R_UNLESS(info_sub_id == 0, ResultInvalidCombination);

        KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
        KHandleTable& handle_table = current_process->GetHandleTable();
        const auto resource_limit = current_process->GetResourceLimit();
        if (!resource_limit) {
            *result = Svc::InvalidHandle;
            // Yes, the kernel considers this a successful operation.
            R_SUCCEED();
        }

        Handle resource_handle{};
        R_TRY(handle_table.Add(std::addressof(resource_handle), resource_limit));

        *result = resource_handle;
        R_SUCCEED();
    }

    case InfoType::RandomEntropy:
        R_UNLESS(handle == 0, ResultInvalidHandle);
        R_UNLESS(info_sub_id < 4, ResultInvalidCombination);

        *result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
        R_SUCCEED();

    case InfoType::InitialProcessIdRange:
        LOG_WARNING(Kernel_SVC,
                    "(STUBBED) Attempted to query privileged process id bounds, returned 0");
        *result = 0;
        R_SUCCEED();

    case InfoType::ThreadTickCount: {
        constexpr u64 num_cpus = 4;
        if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
            LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
                      info_sub_id);
            R_THROW(ResultInvalidCombination);
        }

        KScopedAutoObject thread = GetCurrentProcess(system.Kernel())
                                       .GetHandleTable()
                                       .GetObject<KThread>(static_cast<Handle>(handle));
        if (thread.IsNull()) {
            LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
                      static_cast<Handle>(handle));
            R_THROW(ResultInvalidHandle);
        }

        const auto& core_timing = system.CoreTiming();
        const auto& scheduler = *system.Kernel().CurrentScheduler();
        const auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
        const bool same_thread = current_thread == thread.GetPointerUnsafe();

        const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTime();
        u64 out_ticks = 0;
        if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
            const u64 thread_ticks = current_thread->GetCpuTime();

            out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
        } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
            out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
        }

        *result = out_ticks;
        R_SUCCEED();
    }
    case InfoType::IdleTickCount: {
        // Verify the input handle is invalid.
        R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);

        // Verify the requested core is valid.
        const bool core_valid =
            (info_sub_id == 0xFFFFFFFFFFFFFFFF) ||
            (info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex()));
        R_UNLESS(core_valid, ResultInvalidCombination);

        // Get the idle tick count.
        *result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
        R_SUCCEED();
    }
    case InfoType::MesosphereCurrentProcess: {
        // Verify the input handle is invalid.
        R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);

        // Verify the sub-type is valid.
        R_UNLESS(info_sub_id == 0, ResultInvalidCombination);

        // Get the handle table.
        KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
        KHandleTable& handle_table = current_process->GetHandleTable();

        // Get a new handle for the current process.
        Handle tmp;
        R_TRY(handle_table.Add(std::addressof(tmp), current_process));

        // Set the output.
        *result = tmp;

        // We succeeded.
        R_SUCCEED();
    }
    default:
        LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
        R_THROW(ResultInvalidEnumValue);
    }
}

Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
                     uint64_t info_subtype) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
                 uint64_t info_subtype) {
    R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}

Result GetSystemInfo64(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
                       uint64_t info_subtype) {
    R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}

Result GetInfo64From32(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
                       uint64_t info_subtype) {
    R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}

Result GetSystemInfo64From32(Core::System& system, uint64_t* out, SystemInfoType info_type,
                             Handle handle, uint64_t info_subtype) {
    R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result MapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(MapInsecureMemory(system, address, size));
}

Result UnmapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(UnmapInsecureMemory(system, address, size));
}

Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(MapInsecureMemory(system, address, size));
}

Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(UnmapInsecureMemory(system, address, size));
}

} // namespace Kernel::Svc

repo_name: litucks/torzu

license: mit


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

Result CreateInterruptEvent(Core::System& system, Handle* out, int32_t interrupt_id,
                            InterruptType type) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id,
                              InterruptType interrupt_type) {
    R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}

Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle,
                                    int32_t interrupt_id, InterruptType interrupt_type) {
    R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

Result CreateIoPool(Core::System& system, Handle* out, IoPoolType pool_type) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result CreateIoRegion(Core::System& system, Handle* out, Handle io_pool_handle, uint64_t phys_addr,
                      uint64_t size, MemoryMapping mapping, MemoryPermission perm) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result MapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address, uint64_t size,
                   MemoryPermission map_perm) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result UnmapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address,
                     uint64_t size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result CreateIoPool64(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
    R_RETURN(CreateIoPool(system, out_handle, pool_type));
}

Result CreateIoRegion64(Core::System& system, Handle* out_handle, Handle io_pool,
                        uint64_t physical_address, uint64_t size, MemoryMapping mapping,
                        MemoryPermission perm) {
    R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}

Result MapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size,
                     MemoryPermission perm) {
    R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}

Result UnmapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size) {
    R_RETURN(UnmapIoRegion(system, io_region, address, size));
}

Result CreateIoPool64From32(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
    R_RETURN(CreateIoPool(system, out_handle, pool_type));
}

Result CreateIoRegion64From32(Core::System& system, Handle* out_handle, Handle io_pool,
                              uint64_t physical_address, uint32_t size, MemoryMapping mapping,
                              MemoryPermission perm) {
    R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}

Result MapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size,
                           MemoryPermission perm) {
    R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}

Result UnmapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address,
                             uint32_t size) {
    R_RETURN(UnmapIoRegion(system, io_region, address, size));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/scope_exit.h"
#include "common/scratch_buffer.h"
#include "core/core.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_process.h"
#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/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

namespace {

Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size,
                           Handle session_handle) {
    // Get the client session.
    KScopedAutoObject session =
        GetCurrentProcess(kernel).GetHandleTable().GetObject<KClientSession>(session_handle);
    R_UNLESS(session.IsNotNull(), ResultInvalidHandle);

    // Get the parent, and persist a reference to it until we're done.
    KScopedAutoObject parent = session->GetParent();
    ASSERT(parent.IsNotNull());

    // Send the request.
    R_RETURN(session->SendSyncRequest(message, buffer_size));
}

Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message,
                           size_t buffer_size, KPhysicalAddress message_paddr,
                           KSynchronizationObject** objs, int32_t num_objects, Handle reply_target,
                           int64_t timeout_ns) {
    // Reply to the target, if one is specified.
    if (reply_target != InvalidHandle) {
        KScopedAutoObject session =
            GetCurrentProcess(kernel).GetHandleTable().GetObject<KServerSession>(reply_target);
        R_UNLESS(session.IsNotNull(), ResultInvalidHandle);

        // If we fail to reply, we want to set the output index to -1.
        ON_RESULT_FAILURE {
            *out_index = -1;
        };

        // Send the reply.
        R_TRY(session->SendReply(message, buffer_size, message_paddr));
    }

    // Receive a message.
    {
        // Convert the timeout from nanoseconds to ticks.
        // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
        s64 timeout;
        if (timeout_ns > 0) {
            const s64 offset_tick(timeout_ns);
            if (offset_tick > 0) {
                timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
                if (timeout <= 0) {
                    timeout = std::numeric_limits<s64>::max();
                }
            } else {
                timeout = std::numeric_limits<s64>::max();
            }
        } else {
            timeout = timeout_ns;
        }

        // Wait for a message.
        while (true) {
            // Wait for an object.
            s32 index;
            Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs,
                                                         num_objects, timeout);
            if (ResultTimedOut == result) {
                R_THROW(result);
            }

            // Receive the request.
            if (R_SUCCEEDED(result)) {
                KServerSession* session = objs[index]->DynamicCast<KServerSession*>();
                if (session != nullptr) {
                    result = session->ReceiveRequest(message, buffer_size, message_paddr);
                    if (ResultNotFound == result) {
                        continue;
                    }
                }
            }

            *out_index = index;
            R_RETURN(result);
        }
    }
}

Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message,
                           size_t buffer_size, KPhysicalAddress message_paddr,
                           KProcessAddress user_handles, int32_t num_handles, Handle reply_target,
                           int64_t timeout_ns) {
    // Ensure number of handles is valid.
    R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);

    // Get the synchronization context.
    auto& process = GetCurrentProcess(kernel);
    auto& thread = GetCurrentThread(kernel);
    auto& handle_table = process.GetHandleTable();
    KSynchronizationObject** objs = thread.GetSynchronizationObjectBuffer().data();
    Handle* handles = thread.GetHandleBuffer().data();

    // Copy user handles.
    if (num_handles > 0) {
        // Ensure that we can try to get the handles.
        R_UNLESS(process.GetPageTable().Contains(user_handles, num_handles * sizeof(Handle)),
                 ResultInvalidPointer);

        // Get the handles
        R_UNLESS(
            GetCurrentMemory(kernel).ReadBlock(user_handles, handles, sizeof(Handle) * num_handles),
            ResultInvalidPointer);

        // Convert the handles to objects.
        R_UNLESS(
            handle_table.GetMultipleObjects<KSynchronizationObject>(objs, handles, num_handles),
            ResultInvalidHandle);
    }

    // Ensure handles are closed when we're done.
    SCOPE_EXIT {
        for (auto i = 0; i < num_handles; ++i) {
            objs[i]->Close();
        }
    };

    R_RETURN(ReplyAndReceiveImpl(kernel, out_index, message, buffer_size, message_paddr, objs,
                                 num_handles, reply_target, timeout_ns));
}

} // namespace

/// Makes a blocking IPC call to a service.
Result SendSyncRequest(Core::System& system, Handle session_handle) {
    R_RETURN(SendSyncRequestImpl(system.Kernel(), 0, 0, session_handle));
}

Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message, uint64_t buffer_size,
                                     Handle session_handle) {
    auto& kernel = system.Kernel();

    // Validate that the message buffer is page aligned and does not overflow.
    R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress);
    R_UNLESS(buffer_size > 0, ResultInvalidSize);
    R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize);
    R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory);

    // Get the process page table.
    auto& page_table = GetCurrentProcess(kernel).GetPageTable();

    // Lock the message buffer.
    R_TRY(page_table.LockForIpcUserBuffer(nullptr, message, buffer_size));

    {
        // If we fail to send the message, unlock the message buffer.
        ON_RESULT_FAILURE {
            page_table.UnlockForIpcUserBuffer(message, buffer_size);
        };

        // Send the request.
        ASSERT(message != 0);
        R_TRY(SendSyncRequestImpl(kernel, message, buffer_size, session_handle));
    }

    // We successfully processed, so try to unlock the message buffer.
    R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size));
}

Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle,
                                      uint64_t message, uint64_t buffer_size,
                                      Handle session_handle) {
    // Get the process and handle table.
    auto& process = GetCurrentProcess(system.Kernel());
    auto& handle_table = process.GetHandleTable();

    // Reserve a new event from the process resource limit.
    KScopedResourceReservation event_reservation(std::addressof(process),
                                                 Svc::LimitableResource::EventCountMax);
    R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);

    // Get the client session.
    KScopedAutoObject session = process.GetHandleTable().GetObject<KClientSession>(session_handle);
    R_UNLESS(session.IsNotNull(), ResultInvalidHandle);

    // Get the parent, and persist a reference to it until we're done.
    KScopedAutoObject parent = session->GetParent();
    ASSERT(parent.IsNotNull());

    // Create a new event.
    KEvent* event = KEvent::Create(system.Kernel());
    R_UNLESS(event != nullptr, ResultOutOfResource);

    // Initialize the event.
    event->Initialize(std::addressof(process));

    // Commit our reservation.
    event_reservation.Commit();

    // At end of scope, kill the standing references to the sub events.
    SCOPE_EXIT {
        event->GetReadableEvent().Close();
        event->Close();
    };

    // Register the event.
    KEvent::Register(system.Kernel(), event);

    // Add the readable event to the handle table.
    R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent())));

    // Ensure that if we fail to send the request, we close the readable handle.
    ON_RESULT_FAILURE {
        handle_table.Remove(*out_event_handle);
    };

    // Send the async request.
    R_RETURN(session->SendAsyncRequest(event, message, buffer_size));
}

Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles,
                       Handle reply_target, s64 timeout_ns) {
    R_RETURN(ReplyAndReceiveImpl(system.Kernel(), out_index, 0, 0, 0, handles, num_handles,
                                 reply_target, timeout_ns));
}

Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, uint64_t message,
                                     uint64_t buffer_size, uint64_t handles, int32_t num_handles,
                                     Handle reply_target, int64_t timeout_ns) {
    // Validate that the message buffer is page aligned and does not overflow.
    R_UNLESS(Common::IsAligned(message, PageSize), ResultInvalidAddress);
    R_UNLESS(buffer_size > 0, ResultInvalidSize);
    R_UNLESS(Common::IsAligned(buffer_size, PageSize), ResultInvalidSize);
    R_UNLESS(message < message + buffer_size, ResultInvalidCurrentMemory);

    // Get the process page table.
    auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();

    // Lock the message buffer, getting its physical address.
    KPhysicalAddress message_paddr;
    R_TRY(page_table.LockForIpcUserBuffer(std::addressof(message_paddr), message, buffer_size));

    {
        // If we fail to send the message, unlock the message buffer.
        ON_RESULT_FAILURE {
            page_table.UnlockForIpcUserBuffer(message, buffer_size);
        };

        // Reply/Receive the request.
        ASSERT(message != 0);
        R_TRY(ReplyAndReceiveImpl(system.Kernel(), out_index, message, buffer_size, message_paddr,
                                  handles, num_handles, reply_target, timeout_ns));
    }

    // We successfully processed, so try to unlock the message buffer.
    R_RETURN(page_table.UnlockForIpcUserBuffer(message, buffer_size));
}

Result SendSyncRequest64(Core::System& system, Handle session_handle) {
    R_RETURN(SendSyncRequest(system, session_handle));
}

Result SendSyncRequestWithUserBuffer64(Core::System& system, uint64_t message_buffer,
                                       uint64_t message_buffer_size, Handle session_handle) {
    R_RETURN(
        SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}

Result SendAsyncRequestWithUserBuffer64(Core::System& system, Handle* out_event_handle,
                                        uint64_t message_buffer, uint64_t message_buffer_size,
                                        Handle session_handle) {
    R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
                                            message_buffer_size, session_handle));
}

Result ReplyAndReceive64(Core::System& system, int32_t* out_index, uint64_t handles,
                         int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
    R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}

Result ReplyAndReceiveWithUserBuffer64(Core::System& system, int32_t* out_index,
                                       uint64_t message_buffer, uint64_t message_buffer_size,
                                       uint64_t handles, int32_t num_handles, Handle reply_target,
                                       int64_t timeout_ns) {
    R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
                                           handles, num_handles, reply_target, timeout_ns));
}

Result SendSyncRequest64From32(Core::System& system, Handle session_handle) {
    R_RETURN(SendSyncRequest(system, session_handle));
}

Result SendSyncRequestWithUserBuffer64From32(Core::System& system, uint32_t message_buffer,
                                             uint32_t message_buffer_size, Handle session_handle) {
    R_RETURN(
        SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}

Result SendAsyncRequestWithUserBuffer64From32(Core::System& system, Handle* out_event_handle,
                                              uint32_t message_buffer, uint32_t message_buffer_size,
                                              Handle session_handle) {
    R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
                                            message_buffer_size, session_handle));
}

Result ReplyAndReceive64From32(Core::System& system, int32_t* out_index, uint32_t handles,
                               int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
    R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}

Result ReplyAndReceiveWithUserBuffer64From32(Core::System& system, int32_t* out_index,
                                             uint32_t message_buffer, uint32_t message_buffer_size,
                                             uint32_t handles, int32_t num_handles,
                                             Handle reply_target, int64_t timeout_ns) {
    R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
                                           handles, num_handles, reply_target, timeout_ns));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

void KernelDebug(Core::System& system, KernelDebugType kernel_debug_type, u64 arg0, u64 arg1,
                 u64 arg2) {
    // Intentionally do nothing, as this does nothing in released kernel binaries.
}

void ChangeKernelTraceState(Core::System& system, KernelTraceState trace_state) {
    // Intentionally do nothing, as this does nothing in released kernel binaries.
}

void KernelDebug64(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
                   uint64_t arg1, uint64_t arg2) {
    KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}

void ChangeKernelTraceState64(Core::System& system, KernelTraceState kern_trace_state) {
    ChangeKernelTraceState(system, kern_trace_state);
}

void KernelDebug64From32(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
                         uint64_t arg1, uint64_t arg2) {
    KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}

void ChangeKernelTraceState64From32(Core::System& system, KernelTraceState kern_trace_state) {
    ChangeKernelTraceState(system, kern_trace_state);
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_light_client_session.h"
#include "core/hle/kernel/k_light_server_session.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) {
    // Get the light client session from its handle.
    KScopedAutoObject session = GetCurrentProcess(system.Kernel())
                                    .GetHandleTable()
                                    .GetObject<KLightClientSession>(session_handle);
    R_UNLESS(session.IsNotNull(), ResultInvalidHandle);

    // Send the request.
    R_TRY(session->SendSyncRequest(args));

    R_SUCCEED();
}

Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) {
    // Get the light server session from its handle.
    KScopedAutoObject session = GetCurrentProcess(system.Kernel())
                                    .GetHandleTable()
                                    .GetObject<KLightServerSession>(session_handle);
    R_UNLESS(session.IsNotNull(), ResultInvalidHandle);

    // Handle the request.
    R_TRY(session->ReplyAndReceive(args));

    R_SUCCEED();
}

Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) {
    R_RETURN(SendSyncRequestLight(system, session_handle, args));
}

Result ReplyAndReceiveLight64(Core::System& system, Handle session_handle, u32* args) {
    R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}

Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, u32* args) {
    R_RETURN(SendSyncRequestLight(system, session_handle, args));
}

Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle, u32* args) {
    R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}

// Custom ABI implementation for light IPC.

template <typename F>
static void SvcWrap_LightIpc(Core::System& system, std::span<uint64_t, 8> args, F&& cb) {
    std::array<u32, 7> ipc_args{};

    Handle session_handle = static_cast<Handle>(args[0]);
    for (int i = 0; i < 7; i++) {
        ipc_args[i] = static_cast<u32>(args[i + 1]);
    }

    Result ret = cb(system, session_handle, ipc_args.data());

    args[0] = ret.raw;
    for (int i = 0; i < 7; i++) {
        args[i + 1] = ipc_args[i];
    }
}

void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args) {
    SvcWrap_LightIpc(system, args, SendSyncRequestLight64);
}

void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args) {
    SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64);
}

void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
    SvcWrap_LightIpc(system, args, SendSyncRequestLight64From32);
}

void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
    SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64From32);
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

/// Attempts to locks a mutex
Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u32 tag) {
    LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}",
              thread_handle, address, tag);

    // Validate the input address.
    R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
    R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress);

    R_RETURN(KConditionVariable::WaitForAddress(system.Kernel(), thread_handle, address, tag));
}

/// Unlock a mutex
Result ArbitrateUnlock(Core::System& system, u64 address) {
    LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);

    // Validate the input address.
    R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
    R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress);

    R_RETURN(KConditionVariable::SignalToAddress(system.Kernel(), address));
}

Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) {
    R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}

Result ArbitrateUnlock64(Core::System& system, uint64_t address) {
    R_RETURN(ArbitrateUnlock(system, address));
}

Result ArbitrateLock64From32(Core::System& system, Handle thread_handle, uint32_t address,
                             uint32_t tag) {
    R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}

Result ArbitrateUnlock64From32(Core::System& system, uint32_t address) {
    R_RETURN(ArbitrateUnlock(system, address));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {
namespace {

constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
    switch (perm) {
    case MemoryPermission::None:
    case MemoryPermission::Read:
    case MemoryPermission::ReadWrite:
        return true;
    default:
        return false;
    }
}

// Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
constexpr bool IsValidAddressRange(u64 address, u64 size) {
    return address + size > address;
}

// Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order.
Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr, u64 src_addr,
                                  u64 size) {
    if (!Common::Is4KBAligned(dst_addr)) {
        LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
        R_THROW(ResultInvalidAddress);
    }

    if (!Common::Is4KBAligned(src_addr)) {
        LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, 0x{:016X}", src_addr);
        R_THROW(ResultInvalidSize);
    }

    if (size == 0) {
        LOG_ERROR(Kernel_SVC, "Size is 0");
        R_THROW(ResultInvalidSize);
    }

    if (!Common::Is4KBAligned(size)) {
        LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
        R_THROW(ResultInvalidSize);
    }

    if (!IsValidAddressRange(dst_addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Destination is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
                  dst_addr, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    if (!IsValidAddressRange(src_addr, size)) {
        LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
                  src_addr, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    if (!manager.Contains(src_addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
                  src_addr, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    R_SUCCEED();
}

} // namespace

Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPermission perm) {
    LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X}", address, size,
              perm);

    // Validate address / size.
    R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
    R_UNLESS(size > 0, ResultInvalidSize);
    R_UNLESS((address < address + size), ResultInvalidCurrentMemory);

    // Validate the permission.
    R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);

    // Validate that the region is in range for the current process.
    auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);

    // Set the memory attribute.
    R_RETURN(page_table.SetMemoryPermission(address, size, perm));
}

Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, u32 attr) {
    LOG_DEBUG(Kernel_SVC,
              "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
              size, mask, attr);

    // Validate address / size.
    R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
    R_UNLESS(size > 0, ResultInvalidSize);
    R_UNLESS((address < address + size), ResultInvalidCurrentMemory);

    // Validate the attribute and mask.
    constexpr u32 SupportedMask =
        static_cast<u32>(MemoryAttribute::Uncached | MemoryAttribute::PermissionLocked);
    R_UNLESS((mask | attr) == mask, ResultInvalidCombination);
    R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);

    // Check that permission locked is either being set or not masked.
    R_UNLESS((static_cast<Svc::MemoryAttribute>(mask) & Svc::MemoryAttribute::PermissionLocked) ==
                 (static_cast<Svc::MemoryAttribute>(attr) & Svc::MemoryAttribute::PermissionLocked),
             ResultInvalidCombination);

    // Validate that the region is in range for the current process.
    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);

    // Set the memory attribute.
    R_RETURN(page_table.SetMemoryAttribute(address, size, static_cast<KMemoryAttribute>(mask),
                                           static_cast<KMemoryAttribute>(attr)));
}

/// Maps a memory range into a different range.
Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
    LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
              src_addr, size);

    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};

    if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
        result.IsError()) {
        return result;
    }

    R_RETURN(page_table.MapMemory(dst_addr, src_addr, size));
}

/// Unmaps a region that was previously mapped with svcMapMemory
Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
    LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
              src_addr, size);

    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};

    if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
        result.IsError()) {
        return result;
    }

    R_RETURN(page_table.UnmapMemory(dst_addr, src_addr, size));
}

Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size,
                             MemoryPermission perm) {
    R_RETURN(SetMemoryPermission(system, address, size, perm));
}

Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask,
                            uint32_t attr) {
    R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}

Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
                   uint64_t size) {
    R_RETURN(MapMemory(system, dst_address, src_address, size));
}

Result UnmapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
                     uint64_t size) {
    R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}

Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size,
                                   MemoryPermission perm) {
    R_RETURN(SetMemoryPermission(system, address, size, perm));
}

Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size,
                                  uint32_t mask, uint32_t attr) {
    R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}

Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
                         uint32_t size) {
    R_RETURN(MapMemory(system, dst_address, src_address, size));
}

Result UnmapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
                           uint32_t size) {
    R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

/// Set the process heap to a given Size. It can both extend and shrink the heap.
Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
    LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);

    // Validate size.
    R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
    R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);

    // Set the heap size.
    KProcessAddress address{};
    R_TRY(GetCurrentProcess(system.Kernel())
              .GetPageTable()
              .SetHeapSize(std::addressof(address), size));

    // We succeeded.
    *out_address = GetInteger(address);
    R_SUCCEED();
}

/// Maps memory at a desired address
Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
    LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);

    if (!Common::Is4KBAligned(addr)) {
        LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
        R_THROW(ResultInvalidAddress);
    }

    if (!Common::Is4KBAligned(size)) {
        LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
        R_THROW(ResultInvalidSize);
    }

    if (size == 0) {
        LOG_ERROR(Kernel_SVC, "Size is zero");
        R_THROW(ResultInvalidSize);
    }

    if (!(addr < addr + size)) {
        LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
        R_THROW(ResultInvalidMemoryRegion);
    }

    KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
    auto& page_table{current_process->GetPageTable()};

    if (current_process->GetTotalSystemResourceSize() == 0) {
        LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
        R_THROW(ResultInvalidState);
    }

    if (!page_table.Contains(addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
                  size);
        R_THROW(ResultInvalidMemoryRegion);
    }

    if (!page_table.IsInAliasRegion(addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
                  size);
        R_THROW(ResultInvalidMemoryRegion);
    }

    R_RETURN(page_table.MapPhysicalMemory(addr, size));
}

/// Unmaps memory previously mapped via MapPhysicalMemory
Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
    LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);

    if (!Common::Is4KBAligned(addr)) {
        LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
        R_THROW(ResultInvalidAddress);
    }

    if (!Common::Is4KBAligned(size)) {
        LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
        R_THROW(ResultInvalidSize);
    }

    if (size == 0) {
        LOG_ERROR(Kernel_SVC, "Size is zero");
        R_THROW(ResultInvalidSize);
    }

    if (!(addr < addr + size)) {
        LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
        R_THROW(ResultInvalidMemoryRegion);
    }

    KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
    auto& page_table{current_process->GetPageTable()};

    if (current_process->GetTotalSystemResourceSize() == 0) {
        LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
        R_THROW(ResultInvalidState);
    }

    if (!page_table.Contains(addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
                  size);
        R_THROW(ResultInvalidMemoryRegion);
    }

    if (!page_table.IsInAliasRegion(addr, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
                  size);
        R_THROW(ResultInvalidMemoryRegion);
    }

    R_RETURN(page_table.UnmapPhysicalMemory(addr, size));
}

Result MapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result UnmapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result SetUnsafeLimit(Core::System& system, uint64_t limit) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result SetHeapSize64(Core::System& system, uint64_t* out_address, uint64_t size) {
    R_RETURN(SetHeapSize(system, out_address, size));
}

Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(MapPhysicalMemory(system, address, size));
}

Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(UnmapPhysicalMemory(system, address, size));
}

Result MapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}

Result UnmapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
    R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}

Result SetUnsafeLimit64(Core::System& system, uint64_t limit) {
    R_RETURN(SetUnsafeLimit(system, limit));
}

Result SetHeapSize64From32(Core::System& system, uint64_t* out_address, uint32_t size) {
    R_RETURN(SetHeapSize(system, out_address, size));
}

Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(MapPhysicalMemory(system, address, size));
}

Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(UnmapPhysicalMemory(system, address, size));
}

Result MapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}

Result UnmapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
    R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}

Result SetUnsafeLimit64From32(Core::System& system, uint32_t limit) {
    R_RETURN(SetUnsafeLimit(system, limit));
}

} // namespace Kernel::Svc


code:
// 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/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_light_client_session.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) {
    // Copy the provided name from user memory to kernel memory.
    auto string_name =
        GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);

    std::array<char, KObjectName::NameLengthMax> name{};
    std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);

    // Validate that the name is valid.
    R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);

    // Get the current handle table.
    auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();

    // Find the client port.
    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));
    ON_RESULT_FAILURE {
        handle_table.Unreserve(*out);
    };

    // Create a session.
    KClientSession* session;
    R_TRY(port->CreateSession(std::addressof(session)));

    // Register the session in the table, close the extra reference.
    handle_table.Register(*out, session);
    session->Close();

    // We succeeded.
    R_SUCCEED();
}

Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
                  int32_t max_sessions, bool is_light, uint64_t name) {
    auto& kernel = system.Kernel();

    // Ensure max sessions is valid.
    R_UNLESS(max_sessions > 0, ResultOutOfRange);

    // Get the current handle table.
    auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();

    // Create a new port.
    KPort* port = KPort::Create(kernel);
    R_UNLESS(port != nullptr, ResultOutOfResource);

    // Initialize the port.
    port->Initialize(max_sessions, is_light, name);

    // Ensure that we clean up the port (and its only references are handle table) on function end.
    SCOPE_EXIT {
        port->GetServerPort().Close();
        port->GetClientPort().Close();
    };

    // Register the port.
    KPort::Register(kernel, port);

    // Add the client to the handle table.
    R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort())));

    // Ensure that we maintain a clean handle state on exit.
    ON_RESULT_FAILURE {
        handle_table.Remove(*out_client);
    };

    // Add the server to the handle table.
    R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort())));
}

Result ConnectToPort(Core::System& system, Handle* out, Handle port) {
    // Get the current handle table.
    auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();

    // Get the client port.
    KScopedAutoObject client_port = handle_table.GetObject<KClientPort>(port);
    R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle);

    // Reserve a handle for the port.
    // NOTE: Nintendo really does write directly to the output handle here.
    R_TRY(handle_table.Reserve(out));
    ON_RESULT_FAILURE {
        handle_table.Unreserve(*out);
    };

    // Create the session.
    KAutoObject* session;
    if (client_port->IsLight()) {
        R_TRY(client_port->CreateLightSession(
            reinterpret_cast<KLightClientSession**>(std::addressof(session))));
    } else {
        R_TRY(client_port->CreateSession(
            reinterpret_cast<KClientSession**>(std::addressof(session))));
    }

    // Register the session.
    handle_table.Register(*out, session);
    session->Close();

    // We succeeded.
    R_SUCCEED();
}

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 =
        GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);

    // Copy the provided name from user memory to kernel memory.
    std::array<char, KObjectName::NameLengthMax> 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);
    R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);

    if (max_sessions > 0) {
        // Get the current handle table.
        auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();

        // Create a new port.
        KPort* port = KPort::Create(system.Kernel());
        R_UNLESS(port != nullptr, ResultOutOfResource);

        // Initialize the new port.
        port->Initialize(max_sessions, false, 0);

        // Register the port.
        KPort::Register(system.Kernel(), port);

        // Ensure that our only reference to the port is in the handle table when we're done.
        SCOPE_EXIT {
            port->GetClientPort().Close();
            port->GetServerPort().Close();
        };

        // Register the handle in the table.
        R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
        ON_RESULT_FAILURE {
            handle_table.Remove(*out_server_handle);
        };

        // Create a new object name.
        R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
                                       name.data()));
    } else /* if (max_sessions == 0) */ {
        // Ensure that this else case is correct.
        ASSERT(max_sessions == 0);

        // If we're closing, there's no server handle.
        *out_server_handle = InvalidHandle;

        // Delete the object.
        R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
    }

    R_SUCCEED();
}

Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {
    R_RETURN(ConnectToNamedPort(system, out_handle, name));
}

Result CreatePort64(Core::System& system, Handle* out_server_handle, Handle* out_client_handle,
                    int32_t max_sessions, bool is_light, uint64_t name) {
    R_RETURN(
        CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}

Result ManageNamedPort64(Core::System& system, Handle* out_server_handle, uint64_t name,
                         int32_t max_sessions) {
    R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}

Result ConnectToPort64(Core::System& system, Handle* out_handle, Handle port) {
    R_RETURN(ConnectToPort(system, out_handle, port));
}

Result ConnectToNamedPort64From32(Core::System& system, Handle* out_handle, uint32_t name) {
    R_RETURN(ConnectToNamedPort(system, out_handle, name));
}

Result CreatePort64From32(Core::System& system, Handle* out_server_handle,
                          Handle* out_client_handle, int32_t max_sessions, bool is_light,
                          uint32_t name) {
    R_RETURN(
        CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}

Result ManageNamedPort64From32(Core::System& system, Handle* out_server_handle, uint32_t name,
                               int32_t max_sessions) {
    R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}

Result ConnectToPort64From32(Core::System& system, Handle* out_handle, Handle port) {
    R_RETURN(ConnectToPort(system, out_handle, port));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

void SleepSystem(Core::System& system) {
    UNIMPLEMENTED();
}

void SleepSystem64(Core::System& system) {
    return SleepSystem(system);
}

void SleepSystem64From32(Core::System& system) {
    return SleepSystem(system);
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

/// Exits the current process
void ExitProcess(Core::System& system) {
    auto* current_process = GetCurrentProcessPointer(system.Kernel());

    LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessId());
    ASSERT_MSG(current_process->GetState() == KProcess::State::Running,
               "Process has already exited");

    system.Exit();
}

/// Gets the ID of the specified process or a specified thread's owning process.
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
    LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);

    // Get the object from the handle table.
    KScopedAutoObject obj = GetCurrentProcess(system.Kernel())
                                .GetHandleTable()
                                .GetObject<KAutoObject>(static_cast<Handle>(handle));
    R_UNLESS(obj.IsNotNull(), ResultInvalidHandle);

    // Get the process from the object.
    KProcess* process = nullptr;
    if (KProcess* p = obj->DynamicCast<KProcess*>(); p != nullptr) {
        // The object is a process, so we can use it directly.
        process = p;
    } else if (KThread* t = obj->DynamicCast<KThread*>(); t != nullptr) {
        // The object is a thread, so we want to use its parent.
        process = reinterpret_cast<KThread*>(obj.GetPointerUnsafe())->GetOwnerProcess();
    } else {
        // TODO(bunnei): This should also handle debug objects before returning.
        UNIMPLEMENTED_MSG("Debug objects not implemented");
    }

    // Make sure the target process exists.
    R_UNLESS(process != nullptr, ResultInvalidHandle);

    // Get the process id.
    *out_process_id = process->GetId();

    R_SUCCEED();
}

Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_process_ids,
                      int32_t out_process_ids_size) {
    LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
              out_process_ids, out_process_ids_size);

    // If the supplied size is negative or greater than INT32_MAX / sizeof(u64), bail.
    if ((out_process_ids_size & 0xF0000000) != 0) {
        LOG_ERROR(Kernel_SVC,
                  "Supplied size outside [0, 0x0FFFFFFF] range. out_process_ids_size={}",
                  out_process_ids_size);
        R_THROW(ResultOutOfRange);
    }

    auto& kernel = system.Kernel();
    const auto total_copy_size = out_process_ids_size * sizeof(u64);

    if (out_process_ids_size > 0 &&
        !GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) {
        LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
                  out_process_ids, out_process_ids + total_copy_size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    auto& memory = GetCurrentMemory(kernel);
    auto process_list = kernel.GetProcessList();
    auto it = process_list.begin();

    const auto num_processes = process_list.size();
    const auto copy_amount =
        std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);

    for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) {
        memory.Write64(out_process_ids, (*it)->GetProcessId());
        out_process_ids += sizeof(u64);
    }

    *out_num_processes = static_cast<u32>(num_processes);
    R_SUCCEED();
}

Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
                      ProcessInfoType info_type) {
    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, info_type);

    const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
    KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
    if (process.IsNull()) {
        LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
                  process_handle);
        R_THROW(ResultInvalidHandle);
    }

    if (info_type != ProcessInfoType::ProcessState) {
        LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead",
                  info_type);
        R_THROW(ResultInvalidEnumValue);
    }

    *out = static_cast<s64>(process->GetState());
    R_SUCCEED();
}

Result CreateProcess(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
                     int32_t num_caps) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result StartProcess(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id,
                    uint64_t main_thread_stack_size) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result TerminateProcess(Core::System& system, Handle process_handle) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

void ExitProcess64(Core::System& system) {
    ExitProcess(system);
}

Result GetProcessId64(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
    R_RETURN(GetProcessId(system, out_process_id, process_handle));
}

Result GetProcessList64(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids,
                        int32_t max_out_count) {
    R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}

Result CreateProcess64(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
                       int32_t num_caps) {
    R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}

Result StartProcess64(Core::System& system, Handle process_handle, int32_t priority,
                      int32_t core_id, uint64_t main_thread_stack_size) {
    R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}

Result TerminateProcess64(Core::System& system, Handle process_handle) {
    R_RETURN(TerminateProcess(system, process_handle));
}

Result GetProcessInfo64(Core::System& system, int64_t* out_info, Handle process_handle,
                        ProcessInfoType info_type) {
    R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}

void ExitProcess64From32(Core::System& system) {
    ExitProcess(system);
}

Result GetProcessId64From32(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
    R_RETURN(GetProcessId(system, out_process_id, process_handle));
}

Result GetProcessList64From32(Core::System& system, int32_t* out_num_processes,
                              uint32_t out_process_ids, int32_t max_out_count) {
    R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}

Result CreateProcess64From32(Core::System& system, Handle* out_handle, uint32_t parameters,
                             uint32_t caps, int32_t num_caps) {
    R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}

Result StartProcess64From32(Core::System& system, Handle process_handle, int32_t priority,
                            int32_t core_id, uint64_t main_thread_stack_size) {
    R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}

Result TerminateProcess64From32(Core::System& system, Handle process_handle) {
    R_RETURN(TerminateProcess(system, process_handle));
}

Result GetProcessInfo64From32(Core::System& system, int64_t* out_info, Handle process_handle,
                              ProcessInfoType info_type) {
    R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {
namespace {

constexpr bool IsValidAddressRange(u64 address, u64 size) {
    return address + size > address;
}

constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
    switch (perm) {
    case Svc::MemoryPermission::None:
    case Svc::MemoryPermission::Read:
    case Svc::MemoryPermission::ReadWrite:
    case Svc::MemoryPermission::ReadExecute:
        return true;
    default:
        return false;
    }
}

} // namespace

Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u64 address,
                                  u64 size, Svc::MemoryPermission perm) {
    LOG_TRACE(Kernel_SVC,
              "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
              process_handle, address, size, perm);

    // Validate the address/size.
    R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
    R_UNLESS(size > 0, ResultInvalidSize);
    R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
    R_UNLESS(address == static_cast<uint64_t>(address), ResultInvalidCurrentMemory);
    R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory);

    // Validate the memory permission.
    R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission);

    // Get the process from its handle.
    KScopedAutoObject process =
        GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);

    // Validate that the address is in range.
    auto& page_table = process->GetPageTable();
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);

    // Set the memory permission.
    R_RETURN(page_table.SetProcessMemoryPermission(address, size, perm));
}

Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
                        u64 src_address, u64 size) {
    LOG_TRACE(Kernel_SVC,
              "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
              dst_address, process_handle, src_address, size);

    // Validate the address/size.
    R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
    R_UNLESS(size > 0, ResultInvalidSize);
    R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory);
    R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);

    // Get the processes.
    KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
    KScopedAutoObject src_process =
        dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
    R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);

    // Get the page tables.
    auto& dst_pt = dst_process->GetPageTable();
    auto& src_pt = src_process->GetPageTable();

    // Validate that the mapping is in range.
    R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
    R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode),
             ResultInvalidMemoryRegion);

    // Create a new page group.
    KPageGroup pg{system.Kernel(), dst_pt.GetBlockInfoManager()};
    R_TRY(src_pt.MakeAndOpenPageGroup(
        std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess,
        KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None,
        KMemoryAttribute::All, KMemoryAttribute::None));

    // Map the group.
    R_RETURN(dst_pt.MapPageGroup(dst_address, pg, KMemoryState::SharedCode,
                                 KMemoryPermission::UserReadWrite));
}

Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
                          u64 src_address, u64 size) {
    LOG_TRACE(Kernel_SVC,
              "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
              dst_address, process_handle, src_address, size);

    // Validate the address/size.
    R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress);
    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
    R_UNLESS(size > 0, ResultInvalidSize);
    R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory);
    R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);

    // Get the processes.
    KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
    KScopedAutoObject src_process =
        dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
    R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);

    // Get the page tables.
    auto& dst_pt = dst_process->GetPageTable();
    auto& src_pt = src_process->GetPageTable();

    // Validate that the mapping is in range.
    R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
    R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode),
             ResultInvalidMemoryRegion);

    // Unmap the memory.
    R_RETURN(dst_pt.UnmapProcessMemory(dst_address, size, src_pt, src_address));
}

Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
                            u64 src_address, u64 size) {
    LOG_DEBUG(Kernel_SVC,
              "called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
              "src_address=0x{:016X}, size=0x{:016X}",
              process_handle, dst_address, src_address, size);

    if (!Common::Is4KBAligned(src_address)) {
        LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
                  src_address);
        R_THROW(ResultInvalidAddress);
    }

    if (!Common::Is4KBAligned(dst_address)) {
        LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
                  dst_address);
        R_THROW(ResultInvalidAddress);
    }

    if (size == 0 || !Common::Is4KBAligned(size)) {
        LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
        R_THROW(ResultInvalidSize);
    }

    if (!IsValidAddressRange(dst_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Destination address range overflows the address space (dst_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  dst_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    if (!IsValidAddressRange(src_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Source address range overflows the address space (src_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  src_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
    KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
    if (process.IsNull()) {
        LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
                  process_handle);
        R_THROW(ResultInvalidHandle);
    }

    auto& page_table = process->GetPageTable();
    if (!page_table.Contains(src_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Source address range is not within the address space (src_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  src_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size));
}

Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
                              u64 src_address, u64 size) {
    LOG_DEBUG(Kernel_SVC,
              "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
              "size=0x{:016X}",
              process_handle, dst_address, src_address, size);

    if (!Common::Is4KBAligned(dst_address)) {
        LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
                  dst_address);
        R_THROW(ResultInvalidAddress);
    }

    if (!Common::Is4KBAligned(src_address)) {
        LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
                  src_address);
        R_THROW(ResultInvalidAddress);
    }

    if (size == 0 || !Common::Is4KBAligned(size)) {
        LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
        R_THROW(ResultInvalidSize);
    }

    if (!IsValidAddressRange(dst_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Destination address range overflows the address space (dst_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  dst_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    if (!IsValidAddressRange(src_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Source address range overflows the address space (src_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  src_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
    KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
    if (process.IsNull()) {
        LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
                  process_handle);
        R_THROW(ResultInvalidHandle);
    }

    auto& page_table = process->GetPageTable();
    if (!page_table.Contains(src_address, size)) {
        LOG_ERROR(Kernel_SVC,
                  "Source address range is not within the address space (src_address=0x{:016X}, "
                  "size=0x{:016X}).",
                  src_address, size);
        R_THROW(ResultInvalidCurrentMemory);
    }

    R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size));
}

Result SetProcessMemoryPermission64(Core::System& system, Handle process_handle, uint64_t address,
                                    uint64_t size, MemoryPermission perm) {
    R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}

Result MapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
                          uint64_t src_address, uint64_t size) {
    R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}

Result UnmapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
                            uint64_t src_address, uint64_t size) {
    R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}

Result MapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
                              uint64_t src_address, uint64_t size) {
    R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}

Result UnmapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
                                uint64_t src_address, uint64_t size) {
    R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}

Result SetProcessMemoryPermission64From32(Core::System& system, Handle process_handle,
                                          uint64_t address, uint64_t size, MemoryPermission perm) {
    R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}

Result MapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
                                uint64_t src_address, uint32_t size) {
    R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}

Result UnmapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
                                  uint64_t src_address, uint32_t size) {
    R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}

Result MapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
                                    uint64_t dst_address, uint64_t src_address, uint64_t size) {
    R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}

Result UnmapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
                                      uint64_t dst_address, uint64_t src_address, uint64_t size) {
    R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

/// Get which CPU core is executing the current thread
int32_t GetCurrentProcessorNumber(Core::System& system) {
    LOG_TRACE(Kernel_SVC, "called");
    return static_cast<int32_t>(system.CurrentPhysicalCore().CoreIndex());
}

int32_t GetCurrentProcessorNumber64(Core::System& system) {
    return GetCurrentProcessorNumber(system);
}

int32_t GetCurrentProcessorNumber64From32(Core::System& system) {
    return GetCurrentProcessorNumber(system);
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
                   u64 query_address) {
    LOG_TRACE(Kernel_SVC,
              "called, out_memory_info=0x{:016X}, "
              "query_address=0x{:016X}",
              out_memory_info, query_address);

    // Query memory is just QueryProcessMemory on the current process.
    R_RETURN(
        QueryProcessMemory(system, out_memory_info, out_page_info, CurrentProcess, query_address));
}

Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
                          Handle process_handle, uint64_t address) {
    LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
    const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
    KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
    if (process.IsNull()) {
        LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
                  process_handle);
        R_THROW(ResultInvalidHandle);
    }

    auto& current_memory{GetCurrentMemory(system.Kernel())};

    KMemoryInfo mem_info;
    R_TRY(process->GetPageTable().QueryInfo(std::addressof(mem_info), out_page_info, address));

    const auto svc_mem_info = mem_info.GetSvcMemoryInfo();
    current_memory.WriteBlock(out_memory_info, std::addressof(svc_mem_info), sizeof(svc_mem_info));

    R_SUCCEED();
}

Result QueryMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
                     uint64_t address) {
    R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}

Result QueryProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
                            Handle process_handle, uint64_t address) {
    R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}

Result QueryMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info,
                           uint32_t address) {
    R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}

Result QueryProcessMemory64From32(Core::System& system, uint32_t out_memory_info,
                                  PageInfo* out_page_info, Handle process_handle,
                                  uint64_t address) {
    R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"

namespace Kernel::Svc {

Result ReadWriteRegister(Core::System& system, uint32_t* out, uint64_t address, uint32_t mask,
                         uint32_t value) {
    *out = 0;

    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result ReadWriteRegister64(Core::System& system, uint32_t* out_value, uint64_t address,
                           uint32_t mask, uint32_t value) {
    R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}

Result ReadWriteRegister64From32(Core::System& system, uint32_t* out_value, uint64_t address,
                                 uint32_t mask, uint32_t value) {
    R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}

} // namespace Kernel::Svc


code:
// 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/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
    LOG_DEBUG(Kernel_SVC, "called");

    // Create a new resource limit.
    auto& kernel = system.Kernel();
    KResourceLimit* resource_limit = KResourceLimit::Create(kernel);
    R_UNLESS(resource_limit != nullptr, ResultOutOfResource);

    // Ensure we don't leak a reference to the limit.
    SCOPE_EXIT {
        resource_limit->Close();
    };

    // Initialize the resource limit.
    resource_limit->Initialize();

    // Register the limit.
    KResourceLimit::Register(kernel, resource_limit);

    // Add the limit to the handle table.
    R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit));
}

Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value,
                                  Handle resource_limit_handle, LimitableResource which) {
    LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
              which);

    // Validate the resource.
    R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);

    // Get the resource limit.
    KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
                                           .GetHandleTable()
                                           .GetObject<KResourceLimit>(resource_limit_handle);
    R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);

    // Get the limit value.
    *out_limit_value = resource_limit->GetLimitValue(which);

    R_SUCCEED();
}

Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value,
                                    Handle resource_limit_handle, LimitableResource which) {
    LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
              which);

    // Validate the resource.
    R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);

    // Get the resource limit.
    KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
                                           .GetHandleTable()
                                           .GetObject<KResourceLimit>(resource_limit_handle);
    R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);

    // Get the current value.
    *out_current_value = resource_limit->GetCurrentValue(which);

    R_SUCCEED();
}

Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
                                  LimitableResource which, s64 limit_value) {
    LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}",
              resource_limit_handle, which, limit_value);

    // Validate the resource.
    R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);

    // Get the resource limit.
    KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
                                           .GetHandleTable()
                                           .GetObject<KResourceLimit>(resource_limit_handle);
    R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);

    // Set the limit value.
    R_RETURN(resource_limit->SetLimitValue(which, limit_value));
}

Result GetResourceLimitPeakValue(Core::System& system, int64_t* out_peak_value,
                                 Handle resource_limit_handle, LimitableResource which) {
    UNIMPLEMENTED();
    R_THROW(ResultNotImplemented);
}

Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value,
                                    Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}

Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value,
                                      Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}

Result GetResourceLimitPeakValue64(Core::System& system, int64_t* out_peak_value,
                                   Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}

Result CreateResourceLimit64(Core::System& system, Handle* out_handle) {
    R_RETURN(CreateResourceLimit(system, out_handle));
}

Result SetResourceLimitLimitValue64(Core::System& system, Handle resource_limit_handle,
                                    LimitableResource which, int64_t limit_value) {
    R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}

Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value,
                                          Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}

Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value,
                                            Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}

Result GetResourceLimitPeakValue64From32(Core::System& system, int64_t* out_peak_value,
                                         Handle resource_limit_handle, LimitableResource which) {
    R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}

Result CreateResourceLimit64From32(Core::System& system, Handle* out_handle) {
    R_RETURN(CreateResourceLimit(system, out_handle));
}

Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_limit_handle,
                                          LimitableResource which, int64_t limit_value) {
    R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}

} // namespace Kernel::Svc


code:
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "core/core.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {

void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args) {
    UNIMPLEMENTED();
}

void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args) {
    CallSecureMonitor(system, args);
}

void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args) {
    // CallSecureMonitor64From32 is not supported.
    UNIMPLEMENTED_MSG("CallSecureMonitor64From32");
}

// Custom ABI for CallSecureMonitor.

void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args) {
    lp64::SecureMonitorArguments smc_args{};
    for (int i = 0; i < 8; i++) {
        smc_args.r[i] = args[i];
    }

    CallSecureMonitor64(system, std::addressof(smc_args));

    for (int i = 0; i < 8; i++) {
        args[i] = smc_args.r[i];
    }
}

void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args) {
    ilp32::SecureMonitorArguments smc_args{};
    for (int i = 0; i < 8; i++) {
        smc_args.r[i] = static_cast<u32>(args[i]);
    }

    CallSecureMonitor64From32(system, std::addressof(smc_args));

    for (int i = 0; i < 8; i++) {
        args[i] = smc_args.r[i];
    }
}

} // namespace Kernel::Svc


code:
// 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/kernel/k_light_session.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_server_port.h"
#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/svc.h"

namespace Kernel::Svc {
namespace {

template <typename T>
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, uint64_t name) {
    auto& process = GetCurrentProcess(system.Kernel());
    auto& handle_table = process.GetHandleTable();

    // Declare the session we're going to allocate.
    T* session;

    // Reserve a new session from the process resource limit.
    // TODO: Dynamic resource limits
    KScopedResourceReservation session_reservation(std::addressof(process),
                                                   LimitableResource::SessionCountMax);
    if (session_reservation.Succeeded()) {
        session = T::Create(system.Kernel());
    } else {
        R_THROW(ResultLimitReached);

        // // We couldn't reserve a session. Check that we support dynamically expanding the
        // // resource limit.
        // R_UNLESS(process.GetResourceLimit() ==
        //          std::addressof(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::SessionCountMax, 1);
    }

    // Check that we successfully created a session.
    R_UNLESS(session != nullptr, ResultOutOfResource);

    // Initialize the session.
    session->Initialize(nullptr, 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, std::addressof(session->GetServerSession())));

    // Ensure that we maintain a clean handle state on exit.
    ON_RESULT_FAILURE {
        handle_table.Remove(*out_server);
    };

    // Add the client session to the handle table.
    R_RETURN(handle_table.Add(out_client, std::addressof(session->GetClientSession())));
}

} // namespace

Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
                     u64 name) {
    if (is_light) {
        R_RETURN(CreateSession<KLightSession>(system, out_server, out_client, name));
    } else {
        R_RETURN(CreateSession<KSession>(system, out_server, out_client, name));
    }
}

Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) {
    // Get the current handle table.
    auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();

    // Get the server port.
    KScopedAutoObject port = handle_table.GetObject<KServerPort>(port_handle);
    R_UNLESS(port.IsNotNull(), ResultInvalidHandle);

    // Reserve an entry for the new session.
    R_TRY(handle_table.Reserve(out));
    ON_RESULT_FAILURE {
        handle_table.Unreserve(*out);
    };

    // Accept the session.
    KAutoObject* session;
    if (port->IsLight()) {
        session = port->AcceptLightSession();
    } else {
        session = port->AcceptSession();
    }

    // Ensure we accepted successfully.
    R_UNLESS(session != nullptr, ResultNotFound);

    // Register the session.
    handle_table.Register(*out, session);
    session->Close();

    R_SUCCEED();
}

Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
                       Handle* out_client_session_handle, bool is_light, uint64_t name) {
    R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
                           name));
}

Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port) {
    R_RETURN(AcceptSession(system, out_handle, port));
}

Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle,
                             Handle* out_client_session_handle, bool is_light, uint32_t name) {
    R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
                           name));
}

Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port) {
    R_RETURN(AcceptSession(system, out_handle, port));
}

} // namespace Kernel::Svc