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_shared_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_shared_memory.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp new file mode 100644 index 000000000..d465bcbe7 --- /dev/null +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -0,0 +1,106 @@ +// 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_shared_memory.h" +#include "core/hle/kernel/svc.h" + +namespace Kernel::Svc { +namespace { + +constexpr bool IsValidSharedMemoryPermission(MemoryPermission perm) { + switch (perm) { + case MemoryPermission::Read: + case MemoryPermission::ReadWrite: + return true; + default: + return false; + } +} + +[[maybe_unused]] constexpr bool IsValidRemoteSharedMemoryPermission(MemoryPermission perm) { + return IsValidSharedMemoryPermission(perm) || perm == MemoryPermission::DontCare; +} + +} // namespace + +Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size, + Svc::MemoryPermission map_perm) { + LOG_TRACE(Kernel_SVC, + "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", + shmem_handle, address, size, map_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); + + // Validate the permission. + R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); + + // Get the current process. + auto& process = *system.Kernel().CurrentProcess(); + auto& page_table = process.PageTable(); + + // Get the shared memory. + KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); + R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); + + // Verify that the mapping is in range. + R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); + + // Add the shared memory to the process. + R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); + + // Ensure that we clean up the shared memory if we fail to map it. + auto guard = + SCOPE_GUARD({ process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); }); + + // Map the shared memory. + R_TRY(shmem->Map(process, address, size, map_perm)); + + // We succeeded. + guard.Cancel(); + return ResultSuccess; +} + +Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size, + Svc::MemoryPermission map_perm) { + return MapSharedMemory(system, shmem_handle, address, size, map_perm); +} + +Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size) { + // 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); + + // Get the current process. + auto& process = *system.Kernel().CurrentProcess(); + auto& page_table = process.PageTable(); + + // Get the shared memory. + KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); + R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); + + // Verify that the mapping is in range. + R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); + + // Unmap the shared memory. + R_TRY(shmem->Unmap(process, address, size)); + + // Remove the shared memory from the process. + process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + + return ResultSuccess; +} + +Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size) { + return UnmapSharedMemory(system, shmem_handle, address, size); +} + +} // namespace Kernel::Svc |