using System; namespace Ryujinx.HLE.HOS.Kernel.Memory { class KMemoryBlock { public ulong BaseAddress { get; private set; } public ulong PagesCount { get; private set; } public MemoryState State { get; private set; } public MemoryPermission Permission { get; private set; } public MemoryAttribute Attribute { get; private set; } public MemoryPermission SourcePermission { get; private set; } public int IpcRefCount { get; private set; } public int DeviceRefCount { get; private set; } public KMemoryBlock( ulong baseAddress, ulong pagesCount, MemoryState state, MemoryPermission permission, MemoryAttribute attribute, int ipcRefCount = 0, int deviceRefCount = 0) { BaseAddress = baseAddress; PagesCount = pagesCount; State = state; Attribute = attribute; Permission = permission; IpcRefCount = ipcRefCount; DeviceRefCount = deviceRefCount; } public void SetState(MemoryPermission permission, MemoryState state, MemoryAttribute attribute) { Permission = permission; State = state; Attribute &= MemoryAttribute.IpcAndDeviceMapped; Attribute |= attribute; } public void SetIpcMappingPermission(MemoryPermission permission) { int oldIpcRefCount = IpcRefCount++; if ((ushort)IpcRefCount == 0) { throw new InvalidOperationException("IPC reference count increment overflowed."); } if (oldIpcRefCount == 0) { SourcePermission = permission; Permission &= ~MemoryPermission.ReadAndWrite; Permission |= MemoryPermission.ReadAndWrite & permission; } Attribute |= MemoryAttribute.IpcMapped; } public void RestoreIpcMappingPermission() { int oldIpcRefCount = IpcRefCount--; if (oldIpcRefCount == 0) { throw new InvalidOperationException("IPC reference count decrement underflowed."); } if (oldIpcRefCount == 1) { Permission = SourcePermission; SourcePermission = MemoryPermission.None; Attribute &= ~MemoryAttribute.IpcMapped; } } public KMemoryBlock SplitRightAtAddress(ulong address) { ulong leftAddress = BaseAddress; ulong leftPagesCount = (address - leftAddress) / KMemoryManager.PageSize; BaseAddress = address; PagesCount -= leftPagesCount; return new KMemoryBlock( leftAddress, leftPagesCount, State, Permission, Attribute, IpcRefCount, DeviceRefCount); } public void AddPages(ulong pagesCount) { PagesCount += pagesCount; } public KMemoryInfo GetInfo() { ulong size = PagesCount * KMemoryManager.PageSize; return new KMemoryInfo( BaseAddress, size, State, Permission, Attribute, SourcePermission, IpcRefCount, DeviceRefCount); } } }