forked from Mirror/Ryujinx
Fixes to memory management
This commit is contained in:
parent
ccc9ce1908
commit
7f4a190665
6 changed files with 51 additions and 72 deletions
|
@ -5,7 +5,7 @@ namespace ChocolArm64.Exceptions
|
||||||
{
|
{
|
||||||
public class VmmAccessViolationException : Exception
|
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() { }
|
public VmmAccessViolationException() { }
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,16 @@ namespace ChocolArm64.Memory
|
||||||
public long Position { get; private set; }
|
public long Position { get; private set; }
|
||||||
public long Size { get; private set; }
|
public long Size { get; private set; }
|
||||||
public int Type { get; private set; }
|
public int Type { get; private set; }
|
||||||
|
public int Attr { get; private set; }
|
||||||
|
|
||||||
public AMemoryPerm Perm { 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.Position = Position;
|
||||||
this.Size = Size;
|
this.Size = Size;
|
||||||
this.Type = Type;
|
this.Type = Type;
|
||||||
|
this.Attr = Attr;
|
||||||
this.Perm = Perm;
|
this.Perm = Perm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Memory
|
namespace ChocolArm64.Memory
|
||||||
{
|
{
|
||||||
public class AMemoryMgr
|
public class AMemoryMgr
|
||||||
|
@ -27,24 +25,23 @@ namespace ChocolArm64.Memory
|
||||||
private enum PTMap
|
private enum PTMap
|
||||||
{
|
{
|
||||||
Unmapped,
|
Unmapped,
|
||||||
Physical,
|
Mapped
|
||||||
Mirror
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PTEntry
|
private struct PTEntry
|
||||||
{
|
{
|
||||||
public long Position;
|
|
||||||
public int Type;
|
|
||||||
|
|
||||||
public PTMap Map;
|
public PTMap Map;
|
||||||
public AMemoryPerm Perm;
|
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.Map = Map;
|
||||||
this.Perm = Perm;
|
this.Perm = Perm;
|
||||||
|
this.Type = Type;
|
||||||
|
this.Attr = Attr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +50,7 @@ namespace ChocolArm64.Memory
|
||||||
private bool IsHeapInitialized;
|
private bool IsHeapInitialized;
|
||||||
|
|
||||||
public long HeapAddr { get; private set; }
|
public long HeapAddr { get; private set; }
|
||||||
public int HeapSize { get; private set; }
|
public long HeapSize { get; private set; }
|
||||||
|
|
||||||
public AMemoryMgr(AMemoryAlloc Allocator)
|
public AMemoryMgr(AMemoryAlloc Allocator)
|
||||||
{
|
{
|
||||||
|
@ -101,10 +98,10 @@ namespace ChocolArm64.Memory
|
||||||
return false;
|
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.
|
//TODO: Return error when theres no enough space to allocate heap.
|
||||||
Size = (int)AMemoryHelper.PageRoundUp(Size);
|
Size = AMemoryHelper.PageRoundUp(Size);
|
||||||
|
|
||||||
long Position = HeapAddr;
|
long Position = HeapAddr;
|
||||||
|
|
||||||
|
@ -132,40 +129,13 @@ namespace ChocolArm64.Memory
|
||||||
HeapSize = Size;
|
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)
|
public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
while (Size > 0)
|
while (Size > 0)
|
||||||
{
|
{
|
||||||
if (!IsMapped(Position))
|
if (!IsMapped(Position))
|
||||||
{
|
{
|
||||||
long PhysPos = Allocator.Alloc(PageSize);
|
SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
|
||||||
|
|
||||||
SetPTEntry(Position, new PTEntry(PhysPos, Type, PTMap.Physical, Perm));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long CPgSize = PageSize - (Position & PageMask);
|
long CPgSize = PageSize - (Position & PageMask);
|
||||||
|
@ -186,13 +156,19 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
while (PagesCount-- > 0)
|
while (PagesCount-- > 0)
|
||||||
{
|
{
|
||||||
PTEntry Entry = GetPTEntry(Src);
|
PTEntry SrcEntry = GetPTEntry(Src);
|
||||||
|
PTEntry DstEntry = GetPTEntry(Dst);
|
||||||
|
|
||||||
Entry.Type = Type;
|
DstEntry.Map = PTMap.Mapped;
|
||||||
Entry.Map = PTMap.Mirror;
|
DstEntry.Type = Type;
|
||||||
Entry.Position = Dst;
|
DstEntry.Perm = SrcEntry.Perm;
|
||||||
|
|
||||||
SetPTEntry(Src, Entry);
|
SrcEntry.Perm = AMemoryPerm.None;
|
||||||
|
|
||||||
|
SrcEntry.Attr |= 1;
|
||||||
|
|
||||||
|
SetPTEntry(Src, SrcEntry);
|
||||||
|
SetPTEntry(Dst, DstEntry);
|
||||||
|
|
||||||
Src += PageSize;
|
Src += PageSize;
|
||||||
Dst += PageSize;
|
Dst += PageSize;
|
||||||
|
@ -229,9 +205,10 @@ namespace ChocolArm64.Memory
|
||||||
{
|
{
|
||||||
PTEntry Entry = GetPTEntry(Pos);
|
PTEntry Entry = GetPTEntry(Pos);
|
||||||
|
|
||||||
return Entry.Type == BaseEntry.Type &&
|
return Entry.Map == BaseEntry.Map &&
|
||||||
Entry.Map == BaseEntry.Map &&
|
Entry.Perm == BaseEntry.Perm &&
|
||||||
Entry.Perm == BaseEntry.Perm;
|
Entry.Type == BaseEntry.Type &&
|
||||||
|
Entry.Attr == BaseEntry.Attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
long Start = Position;
|
long Start = Position;
|
||||||
|
@ -249,7 +226,12 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
long Size = End - Start;
|
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)
|
public bool HasPermission(long Position, AMemoryPerm Perm)
|
||||||
|
@ -257,7 +239,6 @@ namespace ChocolArm64.Memory
|
||||||
return GetPTEntry(Position).Perm.HasFlag(Perm);
|
return GetPTEntry(Position).Perm.HasFlag(Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool IsMapped(long Position)
|
public bool IsMapped(long Position)
|
||||||
{
|
{
|
||||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||||
|
@ -276,7 +257,6 @@ namespace ChocolArm64.Memory
|
||||||
return PageTable[L0][L1].Map != PTMap.Unmapped;
|
return PageTable[L0][L1].Map != PTMap.Unmapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private PTEntry GetPTEntry(long Position)
|
private PTEntry GetPTEntry(long Position)
|
||||||
{
|
{
|
||||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||||
|
@ -290,7 +270,6 @@ namespace ChocolArm64.Memory
|
||||||
return PageTable[L0][L1];
|
return PageTable[L0][L1];
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void SetPTEntry(long Position, PTEntry Entry)
|
private void SetPTEntry(long Position, PTEntry Entry)
|
||||||
{
|
{
|
||||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Gpu
|
namespace Ryujinx.Gpu
|
||||||
{
|
{
|
||||||
class NsGpuMemoryMgr
|
class NsGpuMemoryMgr
|
||||||
|
@ -107,6 +105,11 @@ namespace Ryujinx.Gpu
|
||||||
long Position = 0;
|
long Position = 0;
|
||||||
long FreeSize = 0;
|
long FreeSize = 0;
|
||||||
|
|
||||||
|
if (Align < 1)
|
||||||
|
{
|
||||||
|
Align = 1;
|
||||||
|
}
|
||||||
|
|
||||||
Align = (Align + PageMask) & ~PageMask;
|
Align = (Align + PageMask) & ~PageMask;
|
||||||
|
|
||||||
while (Position + FreeSize < AddrSize)
|
while (Position + FreeSize < AddrSize)
|
||||||
|
@ -149,7 +152,6 @@ namespace Ryujinx.Gpu
|
||||||
return BasePos + (Position & PageMask);
|
return BasePos + (Position & PageMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private bool HasPTAddr(long Position)
|
private bool HasPTAddr(long Position)
|
||||||
{
|
{
|
||||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||||
|
@ -168,7 +170,6 @@ namespace Ryujinx.Gpu
|
||||||
return PageTable[L0][L1] != PteUnmapped;
|
return PageTable[L0][L1] != PteUnmapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private long GetPTAddr(long Position)
|
private long GetPTAddr(long Position)
|
||||||
{
|
{
|
||||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||||
|
@ -182,7 +183,6 @@ namespace Ryujinx.Gpu
|
||||||
return PageTable[L0][L1];
|
return PageTable[L0][L1];
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void SetPTAddr(long Position, long TgtAddr)
|
private void SetPTAddr(long Position, long TgtAddr)
|
||||||
{
|
{
|
||||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Ryujinx.OsHle
|
||||||
BaseAddress = MapInfo.Position;
|
BaseAddress = MapInfo.Position;
|
||||||
Size = MapInfo.Size;
|
Size = MapInfo.Size;
|
||||||
MemType = MapInfo.Type;
|
MemType = MapInfo.Type;
|
||||||
MemAttr = 0;
|
MemAttr = MapInfo.Attr;
|
||||||
MemPerm = (int)MapInfo.Perm;
|
MemPerm = (int)MapInfo.Perm;
|
||||||
IpcRefCount = 0;
|
IpcRefCount = 0;
|
||||||
DeviceRefCount = 0;
|
DeviceRefCount = 0;
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.OsHle.Svc
|
||||||
{
|
{
|
||||||
private static void SvcSetHeapSize(Switch Ns, ARegisters Registers, AMemory Memory)
|
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);
|
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)
|
private static void SvcMapMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||||
{
|
{
|
||||||
long Src = (long)Registers.X0;
|
long Dst = (long)Registers.X0;
|
||||||
long Dst = (long)Registers.X1;
|
long Src = (long)Registers.X1;
|
||||||
long Size = (long)Registers.X2;
|
long Size = (long)Registers.X2;
|
||||||
|
|
||||||
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
|
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
|
||||||
|
@ -79,12 +79,10 @@ namespace Ryujinx.OsHle.Svc
|
||||||
|
|
||||||
HndData.VirtPos = Src;
|
HndData.VirtPos = Src;
|
||||||
|
|
||||||
if (Memory.Manager.MapPhys(Src, Dst, Size,
|
Memory.Manager.MapPhys(Position, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||||
(int)MemoryType.SharedMemory, (AMemoryPerm)Perm))
|
|
||||||
{
|
|
||||||
Registers.X0 = (int)SvcResult.Success;
|
Registers.X0 = (int)SvcResult.Success;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Error codes.
|
//TODO: Error codes.
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue