From 7f4a190665bca6f432b09d97ada3e7018612274c Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Fri, 9 Feb 2018 21:13:18 -0300
Subject: [PATCH] Fixes to memory management

---
 .../Exceptions/VmmAccessViolationException.cs |  2 +-
 Ryujinx/Cpu/Memory/AMemoryMapInfo.cs          |  4 +-
 Ryujinx/Cpu/Memory/AMemoryMgr.cs              | 89 +++++++------------
 Ryujinx/Gpu/NsGpuMemoryMgr.cs                 | 12 +--
 Ryujinx/OsHle/MemoryInfo.cs                   |  2 +-
 Ryujinx/OsHle/Svc/SvcMemory.cs                | 14 ++-
 6 files changed, 51 insertions(+), 72 deletions(-)

diff --git a/Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs b/Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs
index dd9d7a646..a557502e5 100644
--- a/Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs
+++ b/Ryujinx/Cpu/Exceptions/VmmAccessViolationException.cs
@@ -5,7 +5,7 @@ namespace ChocolArm64.Exceptions
 {
     public class VmmAccessViolationException : Exception
     {
-        private const string ExMsg = "Value at address 0x{0:x16} could not be \"{1}\"!";
+        private const string ExMsg = "Address 0x{0:x16} does not have \"{1}\" permission!";
 
         public VmmAccessViolationException() { }
 
diff --git a/Ryujinx/Cpu/Memory/AMemoryMapInfo.cs b/Ryujinx/Cpu/Memory/AMemoryMapInfo.cs
index 8ba6c25e6..44b2cc079 100644
--- a/Ryujinx/Cpu/Memory/AMemoryMapInfo.cs
+++ b/Ryujinx/Cpu/Memory/AMemoryMapInfo.cs
@@ -5,14 +5,16 @@ namespace ChocolArm64.Memory
         public long Position { get; private set; }
         public long Size     { get; private set; }
         public int  Type     { get; private set; }
+        public int  Attr     { get; private set; }
 
         public AMemoryPerm Perm { get; private set; }
 
-        public AMemoryMapInfo(long Position, long Size, int Type, AMemoryPerm Perm)
+        public AMemoryMapInfo(long Position, long Size, int Type, int Attr, AMemoryPerm Perm)
         {
             this.Position = Position;
             this.Size     = Size;
             this.Type     = Type;
+            this.Attr     = Attr;
             this.Perm     = Perm;
         }
     }
diff --git a/Ryujinx/Cpu/Memory/AMemoryMgr.cs b/Ryujinx/Cpu/Memory/AMemoryMgr.cs
index 544e51302..05284059e 100644
--- a/Ryujinx/Cpu/Memory/AMemoryMgr.cs
+++ b/Ryujinx/Cpu/Memory/AMemoryMgr.cs
@@ -1,5 +1,3 @@
-using System.Runtime.CompilerServices;
-
 namespace ChocolArm64.Memory
 {
     public class AMemoryMgr
@@ -27,24 +25,23 @@ namespace ChocolArm64.Memory
         private enum PTMap
         {
             Unmapped,
-            Physical,
-            Mirror
+            Mapped
         }
 
         private struct PTEntry
         {
-            public long Position;
-            public int  Type;
-
             public PTMap       Map;
             public AMemoryPerm Perm;
 
-            public PTEntry(long Position, int Type, PTMap Map, AMemoryPerm Perm)
+            public int Type;
+            public int Attr;
+
+            public PTEntry(PTMap Map, AMemoryPerm Perm, int Type, int Attr)
             {
-                this.Position = Position;
-                this.Type     = Type;
-                this.Map      = Map;
-                this.Perm     = Perm;
+                this.Map  = Map;
+                this.Perm = Perm;
+                this.Type = Type;
+                this.Attr = Attr;
             }
         }
 
@@ -53,7 +50,7 @@ namespace ChocolArm64.Memory
         private bool IsHeapInitialized;
 
         public long HeapAddr { get; private set; }
-        public int  HeapSize { get; private set; }
+        public long HeapSize { get; private set; }
 
         public AMemoryMgr(AMemoryAlloc Allocator)
         {
@@ -101,10 +98,10 @@ namespace ChocolArm64.Memory
             return false;
         }
 
-        public void SetHeapSize(int Size, int Type)
+        public void SetHeapSize(long Size, int Type)
         {
             //TODO: Return error when theres no enough space to allocate heap.
-            Size = (int)AMemoryHelper.PageRoundUp(Size);
+            Size = AMemoryHelper.PageRoundUp(Size);
 
             long Position = HeapAddr;
 
@@ -132,40 +129,13 @@ namespace ChocolArm64.Memory
             HeapSize = Size;
         }
 
-        public bool MapPhys(long Src, long Dst, long Size, int Type, AMemoryPerm Perm)
-        {
-            Src = AMemoryHelper.PageRoundDown(Src);
-            Dst = AMemoryHelper.PageRoundDown(Dst);
-
-            Size = AMemoryHelper.PageRoundUp(Size);
-
-            if (Dst < 0 || Dst + Size >= RamSize)
-            {
-                return false;
-            }
-
-            long PagesCount = Size / PageSize;
-
-            while (PagesCount-- > 0)
-            {
-                SetPTEntry(Src, new PTEntry(Dst, Type, PTMap.Physical, Perm));
-
-                Src += PageSize;
-                Dst += PageSize;
-            }
-
-            return true;
-        }
-
         public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
         {
             while (Size > 0)
             {
                 if (!IsMapped(Position))
                 {
-                    long PhysPos = Allocator.Alloc(PageSize);                   
-
-                    SetPTEntry(Position, new PTEntry(PhysPos, Type, PTMap.Physical, Perm));
+                    SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
                 }
 
                 long CPgSize = PageSize - (Position & PageMask);
@@ -186,13 +156,19 @@ namespace ChocolArm64.Memory
 
             while (PagesCount-- > 0)
             {
-                PTEntry Entry = GetPTEntry(Src);
+                PTEntry SrcEntry = GetPTEntry(Src);
+                PTEntry DstEntry = GetPTEntry(Dst);
 
-                Entry.Type     = Type;
-                Entry.Map      = PTMap.Mirror;
-                Entry.Position = Dst;
+                DstEntry.Map  = PTMap.Mapped;
+                DstEntry.Type = Type;
+                DstEntry.Perm = SrcEntry.Perm;
 
-                SetPTEntry(Src, Entry);
+                SrcEntry.Perm = AMemoryPerm.None;
+
+                SrcEntry.Attr |= 1;
+
+                SetPTEntry(Src, SrcEntry);
+                SetPTEntry(Dst, DstEntry);
 
                 Src += PageSize;
                 Dst += PageSize;
@@ -229,9 +205,10 @@ namespace ChocolArm64.Memory
             {
                 PTEntry Entry = GetPTEntry(Pos);
 
-                return Entry.Type == BaseEntry.Type &&
-                       Entry.Map  == BaseEntry.Map  &&
-                       Entry.Perm == BaseEntry.Perm;
+                return Entry.Map  == BaseEntry.Map  &&
+                       Entry.Perm == BaseEntry.Perm &&
+                       Entry.Type == BaseEntry.Type &&
+                       Entry.Attr == BaseEntry.Attr;
             }
 
             long Start = Position;
@@ -249,7 +226,12 @@ namespace ChocolArm64.Memory
 
             long Size = End - Start;
 
-            return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm);
+            return new AMemoryMapInfo(
+                Start,
+                Size,
+                BaseEntry.Type,
+                BaseEntry.Attr,
+                BaseEntry.Perm);
         }
 
         public bool HasPermission(long Position, AMemoryPerm Perm)
@@ -257,7 +239,6 @@ namespace ChocolArm64.Memory
             return GetPTEntry(Position).Perm.HasFlag(Perm);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsMapped(long Position)
         {
             if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@@ -276,7 +257,6 @@ namespace ChocolArm64.Memory
             return PageTable[L0][L1].Map != PTMap.Unmapped;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private PTEntry GetPTEntry(long Position)
         {
             long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
@@ -290,7 +270,6 @@ namespace ChocolArm64.Memory
             return PageTable[L0][L1];
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private void SetPTEntry(long Position, PTEntry Entry)
         {
             long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
diff --git a/Ryujinx/Gpu/NsGpuMemoryMgr.cs b/Ryujinx/Gpu/NsGpuMemoryMgr.cs
index e555f2af3..563a5c099 100644
--- a/Ryujinx/Gpu/NsGpuMemoryMgr.cs
+++ b/Ryujinx/Gpu/NsGpuMemoryMgr.cs
@@ -1,5 +1,3 @@
-using System.Runtime.CompilerServices;
-
 namespace Ryujinx.Gpu
 {
     class NsGpuMemoryMgr
@@ -16,7 +14,7 @@ namespace Ryujinx.Gpu
 
         private const int  PTLvl0Mask = PTLvl0Size - 1;
         private const int  PTLvl1Mask = PTLvl1Size - 1;
-        private const int  PageMask   = PageSize - 1;
+        private const int  PageMask   = PageSize   - 1;
 
         private const int  PTLvl0Bit  = PTPageBits + PTLvl0Bits;
         private const int  PTLvl1Bit  = PTPageBits;
@@ -107,6 +105,11 @@ namespace Ryujinx.Gpu
             long Position = 0;
             long FreeSize = 0;
 
+            if (Align < 1)
+            {
+                Align = 1;
+            }
+
             Align = (Align + PageMask) & ~PageMask;
 
             while (Position + FreeSize < AddrSize)
@@ -149,7 +152,6 @@ namespace Ryujinx.Gpu
             return BasePos + (Position & PageMask);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private bool HasPTAddr(long Position)
         {
             if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@@ -168,7 +170,6 @@ namespace Ryujinx.Gpu
             return PageTable[L0][L1] != PteUnmapped;
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private long GetPTAddr(long Position)
         {
             long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
@@ -182,7 +183,6 @@ namespace Ryujinx.Gpu
             return PageTable[L0][L1];
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private void SetPTAddr(long Position, long TgtAddr)
         {
             long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
diff --git a/Ryujinx/OsHle/MemoryInfo.cs b/Ryujinx/OsHle/MemoryInfo.cs
index adf863b27..395ccf73e 100644
--- a/Ryujinx/OsHle/MemoryInfo.cs
+++ b/Ryujinx/OsHle/MemoryInfo.cs
@@ -18,7 +18,7 @@ namespace Ryujinx.OsHle
             BaseAddress    = MapInfo.Position;
             Size           = MapInfo.Size;
             MemType        = MapInfo.Type;
-            MemAttr        = 0;
+            MemAttr        = MapInfo.Attr;
             MemPerm        = (int)MapInfo.Perm;
             IpcRefCount    = 0;
             DeviceRefCount = 0;
diff --git a/Ryujinx/OsHle/Svc/SvcMemory.cs b/Ryujinx/OsHle/Svc/SvcMemory.cs
index 70988eb0b..185cac892 100644
--- a/Ryujinx/OsHle/Svc/SvcMemory.cs
+++ b/Ryujinx/OsHle/Svc/SvcMemory.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.OsHle.Svc
     {
         private static void SvcSetHeapSize(Switch Ns, ARegisters Registers, AMemory Memory)
         {
-            int Size = (int)Registers.X1;
+            uint Size = (uint)Registers.X1;
 
             Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
 
@@ -30,8 +30,8 @@ namespace Ryujinx.OsHle.Svc
 
         private static void SvcMapMemory(Switch Ns, ARegisters Registers, AMemory Memory)
         {
-            long Src  = (long)Registers.X0;
-            long Dst  = (long)Registers.X1;
+            long Dst  = (long)Registers.X0;
+            long Src  = (long)Registers.X1;
             long Size = (long)Registers.X2;
 
             Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
@@ -79,11 +79,9 @@ namespace Ryujinx.OsHle.Svc
 
                 HndData.VirtPos = Src;
 
-                if (Memory.Manager.MapPhys(Src, Dst, Size,
-                    (int)MemoryType.SharedMemory, (AMemoryPerm)Perm))
-                {
-                    Registers.X0 = (int)SvcResult.Success;
-                }
+                Memory.Manager.MapPhys(Position, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
+
+                Registers.X0 = (int)SvcResult.Success;
             }
 
             //TODO: Error codes.