2022-10-05 02:15:40 +02:00
|
|
|
// 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.
|
2023-02-13 16:44:41 +01:00
|
|
|
auto& process = GetCurrentProcess(system.Kernel());
|
2022-10-05 02:15:40 +02:00
|
|
|
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.
|
2023-03-07 06:13:05 +01:00
|
|
|
ON_RESULT_FAILURE {
|
|
|
|
process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size);
|
|
|
|
};
|
2022-10-05 02:15:40 +02:00
|
|
|
|
|
|
|
// Map the shared memory.
|
2023-03-07 06:13:05 +01:00
|
|
|
R_RETURN(shmem->Map(process, address, size, map_perm));
|
2022-10-05 02:15:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
2023-02-13 16:44:41 +01:00
|
|
|
auto& process = GetCurrentProcess(system.Kernel());
|
2022-10-05 02:15:40 +02:00
|
|
|
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);
|
|
|
|
|
2023-03-07 06:13:05 +01:00
|
|
|
R_SUCCEED();
|
2022-10-05 02:15:40 +02:00
|
|
|
}
|
|
|
|
|
2023-02-05 20:22:02 +01:00
|
|
|
Result CreateSharedMemory(Core::System& system, Handle* out_handle, uint64_t size,
|
|
|
|
MemoryPermission owner_perm, MemoryPermission remote_perm) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
R_THROW(ResultNotImplemented);
|
|
|
|
}
|
|
|
|
|
|
|
|
Result MapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size,
|
|
|
|
MemoryPermission map_perm) {
|
|
|
|
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
|
|
|
|
}
|
|
|
|
|
|
|
|
Result UnmapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address,
|
|
|
|
uint64_t size) {
|
|
|
|
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
|
|
|
|
}
|
|
|
|
|
|
|
|
Result CreateSharedMemory64(Core::System& system, Handle* out_handle, uint64_t size,
|
|
|
|
MemoryPermission owner_perm, MemoryPermission remote_perm) {
|
|
|
|
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
|
|
|
|
}
|
|
|
|
|
|
|
|
Result MapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
|
|
|
|
uint32_t size, MemoryPermission map_perm) {
|
|
|
|
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
|
|
|
|
}
|
|
|
|
|
|
|
|
Result UnmapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
|
|
|
|
uint32_t size) {
|
|
|
|
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
|
|
|
|
}
|
|
|
|
|
|
|
|
Result CreateSharedMemory64From32(Core::System& system, Handle* out_handle, uint32_t size,
|
|
|
|
MemoryPermission owner_perm, MemoryPermission remote_perm) {
|
|
|
|
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
|
2022-10-05 02:15:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Kernel::Svc
|