diff options
author | Liam <byteslice@airmail.cc> | 2022-10-05 02:15:40 +0200 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2023-02-05 04:37:43 +0100 |
commit | 92eb091ddb9dfd96e59a75937e185079a63626e3 (patch) | |
tree | be79f36453a4735088d9230e02f426792077eeb4 /src/core/hle/kernel/svc/svc_transfer_memory.cpp | |
parent | Merge pull request #9720 from SoRadGaming/discordPresenceUpdate (diff) | |
download | yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar.gz yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar.bz2 yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar.lz yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar.xz yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.tar.zst yuzu-92eb091ddb9dfd96e59a75937e185079a63626e3.zip |
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/svc/svc_transfer_memory.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp new file mode 100644 index 000000000..b14ae24a1 --- /dev/null +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -0,0 +1,79 @@ +// 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_scoped_resource_reservation.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/svc.h" + +namespace Kernel::Svc { +namespace { + +constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { + switch (perm) { + case MemoryPermission::None: + case MemoryPermission::Read: + case MemoryPermission::ReadWrite: + return true; + default: + return false; + } +} + +} // Anonymous namespace + +/// Creates a TransferMemory object +Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, + MemoryPermission map_perm) { + auto& kernel = system.Kernel(); + + // Validate the 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 permissions. + R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); + + // Get the current process and handle table. + auto& process = *kernel.CurrentProcess(); + auto& handle_table = process.GetHandleTable(); + + // Reserve a new transfer memory from the process resource limit. + KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), + LimitableResource::TransferMemoryCountMax); + R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); + + // Create the transfer memory. + KTransferMemory* trmem = KTransferMemory::Create(kernel); + R_UNLESS(trmem != nullptr, ResultOutOfResource); + + // Ensure the only reference is in the handle table when we're done. + SCOPE_EXIT({ trmem->Close(); }); + + // Ensure that the region is in range. + R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); + + // Initialize the transfer memory. + R_TRY(trmem->Initialize(address, size, map_perm)); + + // Commit the reservation. + trmem_reservation.Commit(); + + // Register the transfer memory. + KTransferMemory::Register(kernel, trmem); + + // Add the transfer memory to the handle table. + R_TRY(handle_table.Add(out, trmem)); + + return ResultSuccess; +} + +Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size, + MemoryPermission map_perm) { + return CreateTransferMemory(system, out, address, size, map_perm); +} +} // namespace Kernel::Svc |