aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs')
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs
new file mode 100644
index 00000000..e082105b
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs
@@ -0,0 +1,156 @@
+using Ryujinx.Common.Collections;
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Memory
+{
+ class KMemoryBlock : IntrusiveRedBlackTreeNode<KMemoryBlock>, IComparable<KMemoryBlock>, IComparable<ulong>
+ {
+ public ulong BaseAddress { get; private set; }
+ public ulong PagesCount { get; private set; }
+
+ public MemoryState State { get; private set; }
+ public KMemoryPermission Permission { get; private set; }
+ public MemoryAttribute Attribute { get; private set; }
+ public KMemoryPermission SourcePermission { get; private set; }
+
+ public int IpcRefCount { get; private set; }
+ public int DeviceRefCount { get; private set; }
+
+ public KMemoryBlock(
+ ulong baseAddress,
+ ulong pagesCount,
+ MemoryState state,
+ KMemoryPermission 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(KMemoryPermission permission, MemoryState state, MemoryAttribute attribute)
+ {
+ Permission = permission;
+ State = state;
+ Attribute &= MemoryAttribute.IpcAndDeviceMapped;
+ Attribute |= attribute;
+ }
+
+ public void SetIpcMappingPermission(KMemoryPermission newPermission)
+ {
+ int oldIpcRefCount = IpcRefCount++;
+
+ if ((ushort)IpcRefCount == 0)
+ {
+ throw new InvalidOperationException("IPC reference count increment overflowed.");
+ }
+
+ if (oldIpcRefCount == 0)
+ {
+ SourcePermission = Permission;
+
+ Permission &= ~KMemoryPermission.ReadAndWrite;
+ Permission |= KMemoryPermission.ReadAndWrite & newPermission;
+ }
+
+ 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 = KMemoryPermission.None;
+
+ Attribute &= ~MemoryAttribute.IpcMapped;
+ }
+ }
+
+ public KMemoryBlock SplitRightAtAddress(ulong address)
+ {
+ ulong leftAddress = BaseAddress;
+
+ ulong leftPagesCount = (address - leftAddress) / KPageTableBase.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 * KPageTableBase.PageSize;
+
+ return new KMemoryInfo(
+ BaseAddress,
+ size,
+ State,
+ Permission,
+ Attribute,
+ SourcePermission,
+ IpcRefCount,
+ DeviceRefCount);
+ }
+
+ public int CompareTo(KMemoryBlock other)
+ {
+ if (BaseAddress < other.BaseAddress)
+ {
+ return -1;
+ }
+ else if (BaseAddress <= other.BaseAddress + other.PagesCount * KPageTableBase.PageSize - 1UL)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ public int CompareTo(ulong address)
+ {
+ if (address < BaseAddress)
+ {
+ return 1;
+ }
+ else if (address <= BaseAddress + PagesCount * KPageTableBase.PageSize - 1UL)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+} \ No newline at end of file