diff options
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs')
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs new file mode 100644 index 00000000..5ec3cd72 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs @@ -0,0 +1,75 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.Horizon.Common; +using Ryujinx.Memory; + +namespace Ryujinx.HLE.HOS.Kernel.Memory +{ + class KSharedMemory : KAutoObject + { + private readonly KPageList _pageList; + + private readonly ulong _ownerPid; + + private readonly KMemoryPermission _ownerPermission; + private readonly KMemoryPermission _userPermission; + + public KSharedMemory( + KernelContext context, + SharedMemoryStorage storage, + ulong ownerPid, + KMemoryPermission ownerPermission, + KMemoryPermission userPermission) : base(context) + { + _pageList = storage.GetPageList(); + _ownerPid = ownerPid; + _ownerPermission = ownerPermission; + _userPermission = userPermission; + } + + public Result MapIntoProcess( + KPageTableBase memoryManager, + ulong address, + ulong size, + KProcess process, + KMemoryPermission permission) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + KMemoryPermission expectedPermission = process.Pid == _ownerPid + ? _ownerPermission + : _userPermission; + + if (permission != expectedPermission) + { + return KernelResult.InvalidPermission; + } + + // On platforms with page size > 4 KB, this can fail due to the address not being page aligned, + // we can return an error to force the application to retry with a different address. + + try + { + return memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission); + } + catch (InvalidMemoryRegionException) + { + return KernelResult.InvalidMemState; + } + } + + public Result UnmapFromProcess(KPageTableBase memoryManager, ulong address, ulong size, KProcess process) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp<ulong>(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + return memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory); + } + } +}
\ No newline at end of file |
