Change SvcGetInfo 5 to return actual heap size, remove AMemoryAlloc since it is no longer needed with direct memory access, move some memory management logic out of AMemoryMgr, change default virtual filesystem path to AppData
This commit is contained in:
parent
708761963e
commit
f876bd2a80
17 changed files with 251 additions and 337 deletions
|
@ -41,9 +41,9 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private byte* RamPtr;
|
||||
|
||||
public AMemory(IntPtr Ram, AMemoryAlloc Allocator)
|
||||
public AMemory(IntPtr Ram)
|
||||
{
|
||||
Manager = new AMemoryMgr(Allocator);
|
||||
Manager = new AMemoryMgr();
|
||||
|
||||
Monitors = new Dictionary<int, ExMonitor>();
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
using ChocolArm64.Exceptions;
|
||||
|
||||
namespace ChocolArm64.Memory
|
||||
{
|
||||
public class AMemoryAlloc
|
||||
{
|
||||
private long PhysPos;
|
||||
|
||||
public long Alloc(long Size)
|
||||
{
|
||||
long Position = PhysPos;
|
||||
|
||||
Size = AMemoryHelper.PageRoundUp(Size);
|
||||
|
||||
PhysPos += Size;
|
||||
|
||||
if (PhysPos > AMemoryMgr.RamSize || PhysPos < 0)
|
||||
{
|
||||
throw new VmmOutOfMemoryException(Size);
|
||||
}
|
||||
|
||||
return Position;
|
||||
}
|
||||
|
||||
public void Free(long Position)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public long GetFreeMem()
|
||||
{
|
||||
return AMemoryMgr.RamSize - PhysPos;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
namespace ChocolArm64.Memory
|
||||
{
|
||||
public struct AMemoryMapInfo
|
||||
public class AMemoryMapInfo
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
public long Size { get; private set; }
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.Memory
|
||||
{
|
||||
public class AMemoryMgr
|
||||
|
@ -5,22 +7,20 @@ namespace ChocolArm64.Memory
|
|||
public const long AddrSize = RamSize;
|
||||
public const long RamSize = 4L * 1024 * 1024 * 1024;
|
||||
|
||||
private const int PTLvl0Bits = 11;
|
||||
private const int PTLvl1Bits = 13;
|
||||
private const int PTPageBits = 12;
|
||||
private const int PTLvl0Bits = 10;
|
||||
private const int PTLvl1Bits = 10;
|
||||
private const int PTPageBits = 12;
|
||||
|
||||
private const int PTLvl0Size = 1 << PTLvl0Bits;
|
||||
private const int PTLvl1Size = 1 << PTLvl1Bits;
|
||||
public const int PageSize = 1 << PTPageBits;
|
||||
private const int PTLvl0Size = 1 << PTLvl0Bits;
|
||||
private const int PTLvl1Size = 1 << PTLvl1Bits;
|
||||
public const int PageSize = 1 << PTPageBits;
|
||||
|
||||
private const int PTLvl0Mask = PTLvl0Size - 1;
|
||||
private const int PTLvl1Mask = PTLvl1Size - 1;
|
||||
public const int PageMask = PageSize - 1;
|
||||
private const int PTLvl0Mask = PTLvl0Size - 1;
|
||||
private const int PTLvl1Mask = PTLvl1Size - 1;
|
||||
public const int PageMask = PageSize - 1;
|
||||
|
||||
private const int PTLvl0Bit = PTPageBits + PTLvl0Bits;
|
||||
private const int PTLvl1Bit = PTPageBits;
|
||||
|
||||
private AMemoryAlloc Allocator;
|
||||
private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
|
||||
private const int PTLvl1Bit = PTPageBits;
|
||||
|
||||
private enum PTMap
|
||||
{
|
||||
|
@ -47,132 +47,24 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private PTEntry[][] PageTable;
|
||||
|
||||
private bool IsHeapInitialized;
|
||||
|
||||
public long HeapAddr { get; private set; }
|
||||
public long HeapSize { get; private set; }
|
||||
|
||||
public AMemoryMgr(AMemoryAlloc Allocator)
|
||||
public AMemoryMgr()
|
||||
{
|
||||
this.Allocator = Allocator;
|
||||
|
||||
PageTable = new PTEntry[PTLvl0Size][];
|
||||
}
|
||||
|
||||
public long GetTotalMemorySize()
|
||||
public void Map(long Position, long Size, int Type, AMemoryPerm Perm)
|
||||
{
|
||||
return Allocator.GetFreeMem() + GetUsedMemorySize();
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0));
|
||||
}
|
||||
|
||||
public long GetUsedMemorySize()
|
||||
public void Unmap(long Position, long Size)
|
||||
{
|
||||
long Size = 0;
|
||||
|
||||
for (int L0 = 0; L0 < PageTable.Length; L0++)
|
||||
{
|
||||
if (PageTable[L0] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int L1 = 0; L1 < PageTable[L0].Length; L1++)
|
||||
{
|
||||
Size += PageTable[L0][L1].Map != PTMap.Unmapped ? PageSize : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Size;
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0));
|
||||
}
|
||||
|
||||
public bool SetHeapAddr(long Position)
|
||||
public void Unmap(long Position, long Size, int Type)
|
||||
{
|
||||
if (!IsHeapInitialized)
|
||||
{
|
||||
HeapAddr = Position;
|
||||
|
||||
IsHeapInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetHeapSize(long Size, int Type)
|
||||
{
|
||||
//TODO: Return error when theres no enough space to allocate heap.
|
||||
Size = AMemoryHelper.PageRoundUp(Size);
|
||||
|
||||
long Position = HeapAddr;
|
||||
|
||||
if ((ulong)Size < (ulong)HeapSize)
|
||||
{
|
||||
//Try to free now free area if size is smaller than old size.
|
||||
Position += Size;
|
||||
|
||||
while ((ulong)Size < (ulong)HeapSize)
|
||||
{
|
||||
Allocator.Free(Position);
|
||||
|
||||
Position += PageSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Allocate extra needed size.
|
||||
Position += HeapSize;
|
||||
Size -= HeapSize;
|
||||
|
||||
MapPhys(Position, Size, Type, AMemoryPerm.RW);
|
||||
}
|
||||
|
||||
HeapSize = Size;
|
||||
}
|
||||
|
||||
public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
|
||||
{
|
||||
while (Size > 0)
|
||||
{
|
||||
if (!IsMapped(Position))
|
||||
{
|
||||
SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
|
||||
}
|
||||
|
||||
long CPgSize = PageSize - (Position & PageMask);
|
||||
|
||||
Position += CPgSize;
|
||||
Size -= CPgSize;
|
||||
}
|
||||
}
|
||||
|
||||
public void MapMirror(long Src, long Dst, long Size, int Type)
|
||||
{
|
||||
Src = AMemoryHelper.PageRoundDown(Src);
|
||||
Dst = AMemoryHelper.PageRoundDown(Dst);
|
||||
|
||||
Size = AMemoryHelper.PageRoundUp(Size);
|
||||
|
||||
long PagesCount = Size / PageSize;
|
||||
|
||||
while (PagesCount-- > 0)
|
||||
{
|
||||
PTEntry SrcEntry = GetPTEntry(Src);
|
||||
PTEntry DstEntry = GetPTEntry(Dst);
|
||||
|
||||
DstEntry.Map = PTMap.Mapped;
|
||||
DstEntry.Type = Type;
|
||||
DstEntry.Perm = SrcEntry.Perm;
|
||||
|
||||
SrcEntry.Perm = AMemoryPerm.None;
|
||||
|
||||
SrcEntry.Attr |= 1;
|
||||
|
||||
SetPTEntry(Src, SrcEntry);
|
||||
SetPTEntry(Dst, DstEntry);
|
||||
|
||||
Src += PageSize;
|
||||
Dst += PageSize;
|
||||
}
|
||||
SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0));
|
||||
}
|
||||
|
||||
public void Reprotect(long Position, long Size, AMemoryPerm Perm)
|
||||
|
@ -197,12 +89,22 @@ namespace ChocolArm64.Memory
|
|||
|
||||
public AMemoryMapInfo GetMapInfo(long Position)
|
||||
{
|
||||
if (!IsValidPosition(Position))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Position = AMemoryHelper.PageRoundDown(Position);
|
||||
|
||||
PTEntry BaseEntry = GetPTEntry(Position);
|
||||
|
||||
bool IsSameSegment(long Pos)
|
||||
{
|
||||
if (!IsValidPosition(Pos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PTEntry Entry = GetPTEntry(Pos);
|
||||
|
||||
return Entry.Map == BaseEntry.Map &&
|
||||
|
@ -269,6 +171,16 @@ namespace ChocolArm64.Memory
|
|||
return GetPTEntry(Position).Perm.HasFlag(Perm);
|
||||
}
|
||||
|
||||
public bool IsValidPosition(long Position)
|
||||
{
|
||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsMapped(long Position)
|
||||
{
|
||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||
|
@ -300,8 +212,38 @@ namespace ChocolArm64.Memory
|
|||
return PageTable[L0][L1];
|
||||
}
|
||||
|
||||
private void SetPTEntry(long Position, long Size, PTEntry Entry)
|
||||
{
|
||||
while (Size > 0)
|
||||
{
|
||||
SetPTEntry(Position, Entry);
|
||||
|
||||
Position += PageSize;
|
||||
Size -= PageSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPTEntry(long Position, long Size, int Type, PTEntry Entry)
|
||||
{
|
||||
while (Size > 0)
|
||||
{
|
||||
if (GetPTEntry(Position).Type == Type)
|
||||
{
|
||||
SetPTEntry(Position, Entry);
|
||||
}
|
||||
|
||||
Position += PageSize;
|
||||
Size -= PageSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPTEntry(long Position, PTEntry Entry)
|
||||
{
|
||||
if (!IsValidPosition(Position))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Position));
|
||||
}
|
||||
|
||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||
long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace Ryujinx.Core.Loaders
|
|||
MemoryType Type,
|
||||
AMemoryPerm Perm)
|
||||
{
|
||||
Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
||||
Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
||||
|
||||
for (int Index = 0; Index < Data.Count; Index++)
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ namespace Ryujinx.Core.Loaders
|
|||
|
||||
private void MapBss(long Position, long Size)
|
||||
{
|
||||
Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
Memory.Manager.Map(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
}
|
||||
|
||||
private ElfRel GetRelocation(long Position)
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
|||
public EventHandler<EventArgs> MemoryMapped;
|
||||
public EventHandler<EventArgs> MemoryUnmapped;
|
||||
|
||||
public HSharedMem(long PhysPos)
|
||||
public HSharedMem()
|
||||
{
|
||||
Positions = new List<long>();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle
|
|||
//http://switchbrew.org/index.php?title=Homebrew_ABI
|
||||
public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle)
|
||||
{
|
||||
Memory.Manager.MapPhys(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
Memory.Manager.Map(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
|
||||
//MainThreadHandle
|
||||
WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.Loaders.Executables;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
using Ryujinx.Core.OsHle.Utilities;
|
||||
|
@ -16,9 +15,6 @@ namespace Ryujinx.Core.OsHle
|
|||
internal int HidHandle { get; private set; }
|
||||
internal int FontHandle { get; private set; }
|
||||
|
||||
public long HidOffset { get; private set; }
|
||||
public long FontOffset { get; private set; }
|
||||
|
||||
internal IdPool IdGen { get; private set; }
|
||||
internal IdPool NvMapIds { get; private set; }
|
||||
|
||||
|
@ -33,8 +29,6 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
private HSharedMem HidSharedMem;
|
||||
|
||||
private AMemoryAlloc Allocator;
|
||||
|
||||
private Switch Ns;
|
||||
|
||||
public Horizon(Switch Ns)
|
||||
|
@ -53,18 +47,13 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
Processes = new ConcurrentDictionary<int, Process>();
|
||||
|
||||
Allocator = new AMemoryAlloc();
|
||||
|
||||
HidOffset = Allocator.Alloc(HidSize);
|
||||
FontOffset = Allocator.Alloc(FontSize);
|
||||
|
||||
HidSharedMem = new HSharedMem(HidOffset);
|
||||
HidSharedMem = new HSharedMem();
|
||||
|
||||
HidSharedMem.MemoryMapped += HidInit;
|
||||
|
||||
HidHandle = Handles.GenerateId(HidSharedMem);
|
||||
|
||||
FontHandle = Handles.GenerateId(new HSharedMem(FontOffset));
|
||||
FontHandle = Handles.GenerateId(new HSharedMem());
|
||||
}
|
||||
|
||||
public void LoadCart(string ExeFsDir, string RomFsFile = null)
|
||||
|
@ -76,7 +65,7 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
int ProcessId = IdGen.GenerateId();
|
||||
|
||||
Process MainProcess = new Process(Ns, Allocator, ProcessId);
|
||||
Process MainProcess = new Process(Ns, ProcessId);
|
||||
|
||||
void LoadNso(string FileName)
|
||||
{
|
||||
|
@ -106,7 +95,6 @@ namespace Ryujinx.Core.OsHle
|
|||
LoadNso("subsdk*");
|
||||
LoadNso("sdk");
|
||||
|
||||
MainProcess.InitializeHeap();
|
||||
MainProcess.Run();
|
||||
|
||||
Processes.TryAdd(ProcessId, MainProcess);
|
||||
|
@ -118,7 +106,7 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
int ProcessId = IdGen.GenerateId();
|
||||
|
||||
Process MainProcess = new Process(Ns, Allocator, ProcessId);
|
||||
Process MainProcess = new Process(Ns, ProcessId);
|
||||
|
||||
using (FileStream Input = new FileStream(FileName, FileMode.Open))
|
||||
{
|
||||
|
@ -128,7 +116,6 @@ namespace Ryujinx.Core.OsHle
|
|||
}
|
||||
|
||||
MainProcess.SetEmptyArgs();
|
||||
MainProcess.InitializeHeap();
|
||||
MainProcess.Run(IsNro);
|
||||
|
||||
Processes.TryAdd(ProcessId, MainProcess);
|
||||
|
@ -186,7 +173,7 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
if (SharedMem.TryGetLastVirtualPosition(out long Position))
|
||||
{
|
||||
Logging.Info($"HID shared memory successfully mapped to {Position:x16}!");
|
||||
Logging.Info($"HID shared memory successfully mapped to 0x{Position:x16}!");
|
||||
|
||||
Ns.Hid.Init(Position);
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
using ChocolArm64.Memory;
|
||||
|
||||
namespace Ryujinx.Core.OsHle
|
||||
{
|
||||
struct MemoryInfo
|
||||
{
|
||||
public long BaseAddress;
|
||||
public long Size;
|
||||
public int MemType;
|
||||
public int MemAttr;
|
||||
public int MemPerm;
|
||||
public int IpcRefCount;
|
||||
public int DeviceRefCount;
|
||||
public int Padding; //SBZ
|
||||
|
||||
public MemoryInfo(AMemoryMapInfo MapInfo)
|
||||
{
|
||||
BaseAddress = MapInfo.Position;
|
||||
Size = MapInfo.Size;
|
||||
MemType = MapInfo.Type;
|
||||
MemAttr = MapInfo.Attr;
|
||||
MemPerm = (int)MapInfo.Perm;
|
||||
IpcRefCount = 0;
|
||||
DeviceRefCount = 0;
|
||||
Padding = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,28 @@
|
|||
using ChocolArm64.Memory;
|
||||
|
||||
namespace Ryujinx.Core.OsHle
|
||||
{
|
||||
static class MemoryRegions
|
||||
{
|
||||
public const long MapRegionAddress = 0x80000000;
|
||||
public const long AddrSpaceStart = 0x08000000;
|
||||
|
||||
public const long MapRegionAddress = 0x10000000;
|
||||
public const long MapRegionSize = 0x40000000;
|
||||
|
||||
public const long MainStackSize = 0x100000;
|
||||
|
||||
public const long MainStackAddress = AMemoryMgr.AddrSize - MainStackSize;
|
||||
|
||||
public const long TlsPagesSize = 0x4000;
|
||||
|
||||
public const long TlsPagesAddress = MainStackAddress - TlsPagesSize;
|
||||
|
||||
public const long HeapRegionAddress = MapRegionAddress + MapRegionSize;
|
||||
public const long HeapRegionSize = 0x40000000;
|
||||
|
||||
public const long TotalMemoryUsed = HeapRegionAddress + TlsPagesSize + MainStackSize;
|
||||
|
||||
public const long TotalMemoryAvailable = AMemoryMgr.RamSize - AddrSpaceStart;
|
||||
|
||||
public const long AddrSpaceSize = AMemoryMgr.AddrSize - AddrSpaceStart;
|
||||
}
|
||||
}
|
|
@ -15,19 +15,15 @@ namespace Ryujinx.Core.OsHle
|
|||
{
|
||||
public class Process : IDisposable
|
||||
{
|
||||
private const int MaxStackSize = 8 * 1024 * 1024;
|
||||
|
||||
private const int TlsSize = 0x200;
|
||||
private const int TotalTlsSlots = 32;
|
||||
private const int TlsTotalSize = TotalTlsSlots * TlsSize;
|
||||
private const long TlsPageAddr = (AMemoryMgr.AddrSize - TlsTotalSize) & ~AMemoryMgr.PageMask;
|
||||
|
||||
private Switch Ns;
|
||||
|
||||
private ATranslator Translator;
|
||||
|
||||
public int ProcessId { get; private set; }
|
||||
|
||||
private ATranslator Translator;
|
||||
|
||||
public AMemory Memory { get; private set; }
|
||||
|
||||
public KProcessScheduler Scheduler { get; private set; }
|
||||
|
@ -44,12 +40,12 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
private long ImageBase;
|
||||
|
||||
public Process(Switch Ns, AMemoryAlloc Allocator, int ProcessId)
|
||||
public Process(Switch Ns, int ProcessId)
|
||||
{
|
||||
this.Ns = Ns;
|
||||
this.ProcessId = ProcessId;
|
||||
|
||||
Memory = new AMemory(Ns.Ram, Allocator);
|
||||
Memory = new AMemory(Ns.Ram);
|
||||
|
||||
Scheduler = new KProcessScheduler();
|
||||
|
||||
|
@ -61,13 +57,12 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
Executables = new List<Executable>();
|
||||
|
||||
ImageBase = 0x8000000;
|
||||
ImageBase = MemoryRegions.AddrSpaceStart;
|
||||
|
||||
Memory.Manager.MapPhys(
|
||||
TlsPageAddr,
|
||||
TlsTotalSize,
|
||||
(int)MemoryType.ThreadLocal,
|
||||
AMemoryPerm.RW);
|
||||
MapRWMemRegion(
|
||||
MemoryRegions.TlsPagesAddress,
|
||||
MemoryRegions.TlsPagesSize,
|
||||
MemoryType.ThreadLocal);
|
||||
}
|
||||
|
||||
public void LoadProgram(IExecutable Program)
|
||||
|
@ -86,11 +81,6 @@ namespace Ryujinx.Core.OsHle
|
|||
ImageBase += AMemoryMgr.PageSize;
|
||||
}
|
||||
|
||||
public void InitializeHeap()
|
||||
{
|
||||
Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress);
|
||||
}
|
||||
|
||||
public bool Run(bool UseHbAbi = false)
|
||||
{
|
||||
if (Executables.Count == 0)
|
||||
|
@ -98,11 +88,14 @@ namespace Ryujinx.Core.OsHle
|
|||
return false;
|
||||
}
|
||||
|
||||
long StackBot = TlsPageAddr - MaxStackSize;
|
||||
MapRWMemRegion(
|
||||
MemoryRegions.MainStackAddress,
|
||||
MemoryRegions.MainStackSize,
|
||||
MemoryType.Normal);
|
||||
|
||||
Memory.Manager.MapPhys(StackBot, MaxStackSize, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
|
||||
|
||||
int Handle = MakeThread(Executables[0].ImageBase, TlsPageAddr, 0, 0, 0);
|
||||
int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 0, 0);
|
||||
|
||||
if (Handle == -1)
|
||||
{
|
||||
|
@ -113,7 +106,7 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
if (UseHbAbi)
|
||||
{
|
||||
long HbAbiDataPosition = (Executables[0].ImageEnd + 0xfff) & ~0xfff;
|
||||
long HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd);
|
||||
|
||||
Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle);
|
||||
|
||||
|
@ -126,6 +119,11 @@ namespace Ryujinx.Core.OsHle
|
|||
return true;
|
||||
}
|
||||
|
||||
private void MapRWMemRegion(long Position, long Size, MemoryType Type)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW);
|
||||
}
|
||||
|
||||
public void StopAllThreads()
|
||||
{
|
||||
if (MainThread != null)
|
||||
|
@ -188,12 +186,14 @@ namespace Ryujinx.Core.OsHle
|
|||
return -1;
|
||||
}
|
||||
|
||||
long Tpidr = MemoryRegions.TlsPagesAddress + TlsSlot * TlsSize;
|
||||
|
||||
Thread.ThreadState.Break += BreakHandler;
|
||||
Thread.ThreadState.SvcCall += SvcHandler.SvcCall;
|
||||
Thread.ThreadState.Undefined += UndefinedHandler;
|
||||
Thread.ThreadState.ProcessId = ProcessId;
|
||||
Thread.ThreadState.ThreadId = Ns.Os.IdGen.GenerateId();
|
||||
Thread.ThreadState.Tpidr = TlsPageAddr + TlsSlot * TlsSize;
|
||||
Thread.ThreadState.Tpidr = Tpidr;
|
||||
Thread.ThreadState.X0 = (ulong)ArgsPtr;
|
||||
Thread.ThreadState.X1 = (ulong)Handle;
|
||||
Thread.ThreadState.X31 = (ulong)StackTop;
|
||||
|
@ -267,7 +267,7 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
private int GetTlsSlot(long Position)
|
||||
{
|
||||
return (int)((Position - TlsPageAddr) / TlsSize);
|
||||
return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
|
||||
}
|
||||
|
||||
public HThread GetThread(long Tpidr)
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
private static Random Rng;
|
||||
|
||||
private ulong CurrentHeapSize;
|
||||
|
||||
public SvcHandler(Switch Ns, Process Process)
|
||||
{
|
||||
SvcFuncs = new Dictionary<int, SvcFunc>()
|
||||
|
@ -25,6 +27,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
{ 0x01, SvcSetHeapSize },
|
||||
{ 0x03, SvcSetMemoryAttribute },
|
||||
{ 0x04, SvcMapMemory },
|
||||
{ 0x05, SvcUnmapMemory },
|
||||
{ 0x06, SvcQueryMemory },
|
||||
{ 0x07, SvcExitProcess },
|
||||
{ 0x08, SvcCreateThread },
|
||||
|
|
|
@ -10,10 +10,21 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
{
|
||||
uint Size = (uint)ThreadState.X1;
|
||||
|
||||
Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
|
||||
long Position = MemoryRegions.HeapRegionAddress;
|
||||
|
||||
if (Size > CurrentHeapSize)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW);
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory.Manager.Unmap(Position + Size, (long)CurrentHeapSize - Size);
|
||||
}
|
||||
|
||||
CurrentHeapSize = Size;
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
ThreadState.X1 = (ulong)Memory.Manager.HeapAddr;
|
||||
ThreadState.X1 = (ulong)Position;
|
||||
}
|
||||
|
||||
private void SvcSetMemoryAttribute(AThreadState ThreadState)
|
||||
|
@ -42,7 +53,30 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
long Src = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
|
||||
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
|
||||
AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
|
||||
|
||||
Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
|
||||
|
||||
Memory.Manager.Reprotect(Src, Size, AMemoryPerm.None);
|
||||
|
||||
Memory.Manager.SetAttrBit(Src, Size, 0);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private void SvcUnmapMemory(AThreadState ThreadState)
|
||||
{
|
||||
long Dst = (long)ThreadState.X0;
|
||||
long Src = (long)ThreadState.X1;
|
||||
long Size = (long)ThreadState.X2;
|
||||
|
||||
AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
|
||||
|
||||
Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
|
||||
|
||||
Memory.Manager.Reprotect(Src, Size, DstInfo.Perm);
|
||||
|
||||
Memory.Manager.ClearAttrBit(Src, Size, 0);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
@ -54,17 +88,22 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
||||
|
||||
MemoryInfo Info = new MemoryInfo(MapInfo);
|
||||
if (MapInfo == null)
|
||||
{
|
||||
//TODO: Correct error code.
|
||||
ThreadState.X0 = ulong.MaxValue;
|
||||
|
||||
Memory.WriteInt64(InfoPtr + 0x00, Info.BaseAddress);
|
||||
Memory.WriteInt64(InfoPtr + 0x08, Info.Size);
|
||||
Memory.WriteInt32(InfoPtr + 0x10, Info.MemType);
|
||||
Memory.WriteInt32(InfoPtr + 0x14, Info.MemAttr);
|
||||
Memory.WriteInt32(InfoPtr + 0x18, Info.MemPerm);
|
||||
Memory.WriteInt32(InfoPtr + 0x1c, Info.IpcRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x20, Info.DeviceRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x24, Info.Padding);
|
||||
return;
|
||||
}
|
||||
|
||||
Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
|
||||
Memory.WriteInt64(InfoPtr + 0x08, MapInfo.Size);
|
||||
Memory.WriteInt32(InfoPtr + 0x10, MapInfo.Type);
|
||||
Memory.WriteInt32(InfoPtr + 0x14, MapInfo.Attr);
|
||||
Memory.WriteInt32(InfoPtr + 0x18, (int)MapInfo.Perm);
|
||||
Memory.WriteInt32(InfoPtr + 0x1c, 0);
|
||||
Memory.WriteInt32(InfoPtr + 0x20, 0);
|
||||
Memory.WriteInt32(InfoPtr + 0x24, 0);
|
||||
//TODO: X1.
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
|
@ -84,7 +123,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
{
|
||||
SharedMem.AddVirtualPosition(Src);
|
||||
|
||||
Memory.Manager.MapPhys(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||
Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,14 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private void SvcExitProcess(AThreadState ThreadState) => Ns.Os.ExitProcess(ThreadState.ProcessId);
|
||||
private const int AllowedCpuIdBitmask = 0b1111;
|
||||
|
||||
private const bool EnableProcessDebugging = false;
|
||||
|
||||
private void SvcExitProcess(AThreadState ThreadState)
|
||||
{
|
||||
Ns.Os.ExitProcess(ThreadState.ProcessId);
|
||||
}
|
||||
|
||||
private void SvcCloseHandle(AThreadState ThreadState)
|
||||
{
|
||||
|
@ -162,79 +169,62 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
switch (InfoType)
|
||||
{
|
||||
case 0: ThreadState.X1 = AllowedCpuIdBitmask(); break;
|
||||
case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||
case 3: ThreadState.X1 = GetMapRegionSize(); break;
|
||||
case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break;
|
||||
case 5: ThreadState.X1 = GetHeapRegionSize(); break;
|
||||
case 6: ThreadState.X1 = GetTotalMem(); break;
|
||||
case 7: ThreadState.X1 = GetUsedMem(); break;
|
||||
case 8: ThreadState.X1 = IsCurrentProcessBeingDebugged(); break;
|
||||
case 11: ThreadState.X1 = GetRnd64(); break;
|
||||
case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break;
|
||||
case 13: ThreadState.X1 = GetAddrSpaceSize(); break;
|
||||
case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||
case 15: ThreadState.X1 = GetMapRegionSize(); break;
|
||||
case 0:
|
||||
ThreadState.X1 = AllowedCpuIdBitmask;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ThreadState.X1 = MemoryRegions.MapRegionAddress;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ThreadState.X1 = MemoryRegions.MapRegionSize;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ThreadState.X1 = MemoryRegions.HeapRegionAddress;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ThreadState.X1 = CurrentHeapSize;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ThreadState.X1 = MemoryRegions.TotalMemoryAvailable;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
ThreadState.X1 = MemoryRegions.TotalMemoryUsed + CurrentHeapSize;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ThreadState.X1 = EnableProcessDebugging ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ThreadState.X1 = MemoryRegions.AddrSpaceStart;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
ThreadState.X1 = MemoryRegions.AddrSpaceSize;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
ThreadState.X1 = MemoryRegions.MapRegionAddress;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ThreadState.X1 = MemoryRegions.MapRegionSize;
|
||||
break;
|
||||
|
||||
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
||||
}
|
||||
|
||||
ThreadState.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private ulong AllowedCpuIdBitmask()
|
||||
{
|
||||
return 0xF; //Mephisto value.
|
||||
}
|
||||
|
||||
private ulong GetMapRegionBaseAddr()
|
||||
{
|
||||
return MemoryRegions.MapRegionAddress;
|
||||
}
|
||||
|
||||
private ulong GetMapRegionSize()
|
||||
{
|
||||
return MemoryRegions.MapRegionSize;
|
||||
}
|
||||
|
||||
private ulong GetHeapRegionBaseAddr()
|
||||
{
|
||||
return MemoryRegions.HeapRegionAddress;
|
||||
}
|
||||
|
||||
private ulong GetHeapRegionSize()
|
||||
{
|
||||
return MemoryRegions.HeapRegionSize;
|
||||
}
|
||||
|
||||
private ulong GetTotalMem()
|
||||
{
|
||||
return (ulong)Memory.Manager.GetTotalMemorySize();
|
||||
}
|
||||
|
||||
private ulong GetUsedMem()
|
||||
{
|
||||
return (ulong)Memory.Manager.GetUsedMemorySize();
|
||||
}
|
||||
|
||||
private ulong IsCurrentProcessBeingDebugged()
|
||||
{
|
||||
return (ulong)0;
|
||||
}
|
||||
|
||||
private ulong GetRnd64()
|
||||
{
|
||||
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||
}
|
||||
|
||||
private ulong GetAddrSpaceBaseAddr()
|
||||
{
|
||||
return 0x08000000;
|
||||
}
|
||||
|
||||
private ulong GetAddrSpaceSize()
|
||||
{
|
||||
return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ namespace Ryujinx.Core
|
|||
{
|
||||
class VirtualFs : IDisposable
|
||||
{
|
||||
private const string BasePath = "Fs";
|
||||
private const string SavesPath = "Saves";
|
||||
private const string SdCardPath = "SdCard";
|
||||
private const string BasePath = "RyuFs";
|
||||
private const string NandPath = "nand";
|
||||
private const string SdCardPath = "sdmc";
|
||||
|
||||
public Stream RomFs { get; private set; }
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Ryujinx.Core
|
|||
|
||||
public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath);
|
||||
|
||||
public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath);
|
||||
public string GetGameSavesPath() => MakeDirAndGetFullPath(NandPath);
|
||||
|
||||
private string MakeDirAndGetFullPath(string Dir)
|
||||
{
|
||||
|
@ -56,7 +56,9 @@ namespace Ryujinx.Core
|
|||
|
||||
public string GetBasePath()
|
||||
{
|
||||
return Path.Combine(Directory.GetCurrentDirectory(), BasePath);
|
||||
string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
return Path.Combine(AppDataPath, BasePath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu
|
|||
private const int PTLvl1Mask = PTLvl1Size - 1;
|
||||
private const int PageMask = PageSize - 1;
|
||||
|
||||
private const int PTLvl0Bit = PTPageBits + PTLvl0Bits;
|
||||
private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
|
||||
private const int PTLvl1Bit = PTPageBits;
|
||||
|
||||
private const long PteUnmapped = -1;
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace Ryujinx.Tests.Cpu
|
|||
private long EntryPoint;
|
||||
|
||||
private IntPtr Ram;
|
||||
private AMemoryAlloc Allocator;
|
||||
private AMemory Memory;
|
||||
private AThread Thread;
|
||||
|
||||
|
@ -31,9 +30,8 @@ namespace Ryujinx.Tests.Cpu
|
|||
|
||||
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
|
||||
ATranslator Translator = new ATranslator();
|
||||
Allocator = new AMemoryAlloc();
|
||||
Memory = new AMemory(Ram, Allocator);
|
||||
Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
|
||||
Memory = new AMemory(Ram);
|
||||
Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
|
||||
Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint);
|
||||
}
|
||||
|
||||
|
@ -42,7 +40,6 @@ namespace Ryujinx.Tests.Cpu
|
|||
{
|
||||
Thread = null;
|
||||
Memory = null;
|
||||
Allocator = null;
|
||||
Marshal.FreeHGlobal(Ram);
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue