0
0
Fork 0
mirror of https://github.com/ryujinx-mirror/ryujinx.git synced 2024-12-22 23:05:46 +00:00

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:
gdkchan 2018-02-27 20:45:07 -03:00
parent 708761963e
commit f876bd2a80
17 changed files with 251 additions and 337 deletions

View file

@ -41,9 +41,9 @@ namespace ChocolArm64.Memory
private byte* RamPtr; 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>(); Monitors = new Dictionary<int, ExMonitor>();

View file

@ -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;
}
}
}

View file

@ -1,6 +1,6 @@
namespace ChocolArm64.Memory namespace ChocolArm64.Memory
{ {
public struct AMemoryMapInfo public class AMemoryMapInfo
{ {
public long Position { get; private set; } public long Position { get; private set; }
public long Size { get; private set; } public long Size { get; private set; }

View file

@ -1,3 +1,5 @@
using System;
namespace ChocolArm64.Memory namespace ChocolArm64.Memory
{ {
public class AMemoryMgr public class AMemoryMgr
@ -5,22 +7,20 @@ namespace ChocolArm64.Memory
public const long AddrSize = RamSize; public const long AddrSize = RamSize;
public const long RamSize = 4L * 1024 * 1024 * 1024; public const long RamSize = 4L * 1024 * 1024 * 1024;
private const int PTLvl0Bits = 11; private const int PTLvl0Bits = 10;
private const int PTLvl1Bits = 13; private const int PTLvl1Bits = 10;
private const int PTPageBits = 12; private const int PTPageBits = 12;
private const int PTLvl0Size = 1 << PTLvl0Bits; private const int PTLvl0Size = 1 << PTLvl0Bits;
private const int PTLvl1Size = 1 << PTLvl1Bits; private const int PTLvl1Size = 1 << PTLvl1Bits;
public const int PageSize = 1 << PTPageBits; public const int PageSize = 1 << PTPageBits;
private const int PTLvl0Mask = PTLvl0Size - 1; private const int PTLvl0Mask = PTLvl0Size - 1;
private const int PTLvl1Mask = PTLvl1Size - 1; private const int PTLvl1Mask = PTLvl1Size - 1;
public const int PageMask = PageSize - 1; public const int PageMask = PageSize - 1;
private const int PTLvl0Bit = PTPageBits + PTLvl0Bits; private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
private const int PTLvl1Bit = PTPageBits; private const int PTLvl1Bit = PTPageBits;
private AMemoryAlloc Allocator;
private enum PTMap private enum PTMap
{ {
@ -47,132 +47,24 @@ namespace ChocolArm64.Memory
private PTEntry[][] PageTable; private PTEntry[][] PageTable;
private bool IsHeapInitialized; public AMemoryMgr()
public long HeapAddr { get; private set; }
public long HeapSize { get; private set; }
public AMemoryMgr(AMemoryAlloc Allocator)
{ {
this.Allocator = Allocator;
PageTable = new PTEntry[PTLvl0Size][]; 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; SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 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;
} }
public bool SetHeapAddr(long Position) public void Unmap(long Position, long Size, int Type)
{ {
if (!IsHeapInitialized) SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0));
{
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;
}
} }
public void Reprotect(long Position, long Size, AMemoryPerm Perm) public void Reprotect(long Position, long Size, AMemoryPerm Perm)
@ -197,12 +89,22 @@ namespace ChocolArm64.Memory
public AMemoryMapInfo GetMapInfo(long Position) public AMemoryMapInfo GetMapInfo(long Position)
{ {
if (!IsValidPosition(Position))
{
return null;
}
Position = AMemoryHelper.PageRoundDown(Position); Position = AMemoryHelper.PageRoundDown(Position);
PTEntry BaseEntry = GetPTEntry(Position); PTEntry BaseEntry = GetPTEntry(Position);
bool IsSameSegment(long Pos) bool IsSameSegment(long Pos)
{ {
if (!IsValidPosition(Pos))
{
return false;
}
PTEntry Entry = GetPTEntry(Pos); PTEntry Entry = GetPTEntry(Pos);
return Entry.Map == BaseEntry.Map && return Entry.Map == BaseEntry.Map &&
@ -269,6 +171,16 @@ namespace ChocolArm64.Memory
return GetPTEntry(Position).Perm.HasFlag(Perm); 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) public bool IsMapped(long Position)
{ {
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@ -300,8 +212,38 @@ namespace ChocolArm64.Memory
return PageTable[L0][L1]; 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) private void SetPTEntry(long Position, PTEntry Entry)
{ {
if (!IsValidPosition(Position))
{
throw new ArgumentOutOfRangeException(nameof(Position));
}
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;

View file

@ -96,7 +96,7 @@ namespace Ryujinx.Core.Loaders
MemoryType Type, MemoryType Type,
AMemoryPerm Perm) 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++) for (int Index = 0; Index < Data.Count; Index++)
{ {
@ -108,7 +108,7 @@ namespace Ryujinx.Core.Loaders
private void MapBss(long Position, long Size) 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) private ElfRel GetRelocation(long Position)

View file

@ -12,7 +12,7 @@ namespace Ryujinx.Core.OsHle.Handles
public EventHandler<EventArgs> MemoryMapped; public EventHandler<EventArgs> MemoryMapped;
public EventHandler<EventArgs> MemoryUnmapped; public EventHandler<EventArgs> MemoryUnmapped;
public HSharedMem(long PhysPos) public HSharedMem()
{ {
Positions = new List<long>(); Positions = new List<long>();
} }

View file

@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle
//http://switchbrew.org/index.php?title=Homebrew_ABI //http://switchbrew.org/index.php?title=Homebrew_ABI
public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle) 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 //MainThreadHandle
WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle); WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle);

View file

@ -1,4 +1,3 @@
using ChocolArm64.Memory;
using Ryujinx.Core.Loaders.Executables; using Ryujinx.Core.Loaders.Executables;
using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Utilities; using Ryujinx.Core.OsHle.Utilities;
@ -16,9 +15,6 @@ namespace Ryujinx.Core.OsHle
internal int HidHandle { get; private set; } internal int HidHandle { get; private set; }
internal int FontHandle { 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 IdGen { get; private set; }
internal IdPool NvMapIds { get; private set; } internal IdPool NvMapIds { get; private set; }
@ -33,8 +29,6 @@ namespace Ryujinx.Core.OsHle
private HSharedMem HidSharedMem; private HSharedMem HidSharedMem;
private AMemoryAlloc Allocator;
private Switch Ns; private Switch Ns;
public Horizon(Switch Ns) public Horizon(Switch Ns)
@ -53,18 +47,13 @@ namespace Ryujinx.Core.OsHle
Processes = new ConcurrentDictionary<int, Process>(); Processes = new ConcurrentDictionary<int, Process>();
Allocator = new AMemoryAlloc(); HidSharedMem = new HSharedMem();
HidOffset = Allocator.Alloc(HidSize);
FontOffset = Allocator.Alloc(FontSize);
HidSharedMem = new HSharedMem(HidOffset);
HidSharedMem.MemoryMapped += HidInit; HidSharedMem.MemoryMapped += HidInit;
HidHandle = Handles.GenerateId(HidSharedMem); HidHandle = Handles.GenerateId(HidSharedMem);
FontHandle = Handles.GenerateId(new HSharedMem(FontOffset)); FontHandle = Handles.GenerateId(new HSharedMem());
} }
public void LoadCart(string ExeFsDir, string RomFsFile = null) public void LoadCart(string ExeFsDir, string RomFsFile = null)
@ -76,7 +65,7 @@ namespace Ryujinx.Core.OsHle
int ProcessId = IdGen.GenerateId(); int ProcessId = IdGen.GenerateId();
Process MainProcess = new Process(Ns, Allocator, ProcessId); Process MainProcess = new Process(Ns, ProcessId);
void LoadNso(string FileName) void LoadNso(string FileName)
{ {
@ -106,7 +95,6 @@ namespace Ryujinx.Core.OsHle
LoadNso("subsdk*"); LoadNso("subsdk*");
LoadNso("sdk"); LoadNso("sdk");
MainProcess.InitializeHeap();
MainProcess.Run(); MainProcess.Run();
Processes.TryAdd(ProcessId, MainProcess); Processes.TryAdd(ProcessId, MainProcess);
@ -118,7 +106,7 @@ namespace Ryujinx.Core.OsHle
int ProcessId = IdGen.GenerateId(); 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)) using (FileStream Input = new FileStream(FileName, FileMode.Open))
{ {
@ -128,7 +116,6 @@ namespace Ryujinx.Core.OsHle
} }
MainProcess.SetEmptyArgs(); MainProcess.SetEmptyArgs();
MainProcess.InitializeHeap();
MainProcess.Run(IsNro); MainProcess.Run(IsNro);
Processes.TryAdd(ProcessId, MainProcess); Processes.TryAdd(ProcessId, MainProcess);
@ -186,7 +173,7 @@ namespace Ryujinx.Core.OsHle
if (SharedMem.TryGetLastVirtualPosition(out long Position)) 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); Ns.Hid.Init(Position);
} }

View file

@ -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;
}
}
}

View file

@ -1,11 +1,28 @@
using ChocolArm64.Memory;
namespace Ryujinx.Core.OsHle namespace Ryujinx.Core.OsHle
{ {
static class MemoryRegions 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 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 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;
} }
} }

View file

@ -15,19 +15,15 @@ namespace Ryujinx.Core.OsHle
{ {
public class Process : IDisposable public class Process : IDisposable
{ {
private const int MaxStackSize = 8 * 1024 * 1024;
private const int TlsSize = 0x200; private const int TlsSize = 0x200;
private const int TotalTlsSlots = 32; private const int TotalTlsSlots = 32;
private const int TlsTotalSize = TotalTlsSlots * TlsSize;
private const long TlsPageAddr = (AMemoryMgr.AddrSize - TlsTotalSize) & ~AMemoryMgr.PageMask;
private Switch Ns; private Switch Ns;
private ATranslator Translator;
public int ProcessId { get; private set; } public int ProcessId { get; private set; }
private ATranslator Translator;
public AMemory Memory { get; private set; } public AMemory Memory { get; private set; }
public KProcessScheduler Scheduler { get; private set; } public KProcessScheduler Scheduler { get; private set; }
@ -44,12 +40,12 @@ namespace Ryujinx.Core.OsHle
private long ImageBase; private long ImageBase;
public Process(Switch Ns, AMemoryAlloc Allocator, int ProcessId) public Process(Switch Ns, int ProcessId)
{ {
this.Ns = Ns; this.Ns = Ns;
this.ProcessId = ProcessId; this.ProcessId = ProcessId;
Memory = new AMemory(Ns.Ram, Allocator); Memory = new AMemory(Ns.Ram);
Scheduler = new KProcessScheduler(); Scheduler = new KProcessScheduler();
@ -61,13 +57,12 @@ namespace Ryujinx.Core.OsHle
Executables = new List<Executable>(); Executables = new List<Executable>();
ImageBase = 0x8000000; ImageBase = MemoryRegions.AddrSpaceStart;
Memory.Manager.MapPhys( MapRWMemRegion(
TlsPageAddr, MemoryRegions.TlsPagesAddress,
TlsTotalSize, MemoryRegions.TlsPagesSize,
(int)MemoryType.ThreadLocal, MemoryType.ThreadLocal);
AMemoryPerm.RW);
} }
public void LoadProgram(IExecutable Program) public void LoadProgram(IExecutable Program)
@ -86,11 +81,6 @@ namespace Ryujinx.Core.OsHle
ImageBase += AMemoryMgr.PageSize; ImageBase += AMemoryMgr.PageSize;
} }
public void InitializeHeap()
{
Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress);
}
public bool Run(bool UseHbAbi = false) public bool Run(bool UseHbAbi = false)
{ {
if (Executables.Count == 0) if (Executables.Count == 0)
@ -98,11 +88,14 @@ namespace Ryujinx.Core.OsHle
return false; return false;
} }
long StackBot = TlsPageAddr - MaxStackSize; MapRWMemRegion(
MemoryRegions.MainStackAddress,
MemoryRegions.MainStackSize,
MemoryType.Normal);
long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
Memory.Manager.MapPhys(StackBot, MaxStackSize, (int)MemoryType.Normal, AMemoryPerm.RW); int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 0, 0);
int Handle = MakeThread(Executables[0].ImageBase, TlsPageAddr, 0, 0, 0);
if (Handle == -1) if (Handle == -1)
{ {
@ -113,7 +106,7 @@ namespace Ryujinx.Core.OsHle
if (UseHbAbi) if (UseHbAbi)
{ {
long HbAbiDataPosition = (Executables[0].ImageEnd + 0xfff) & ~0xfff; long HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd);
Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle); Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle);
@ -126,6 +119,11 @@ namespace Ryujinx.Core.OsHle
return true; return true;
} }
private void MapRWMemRegion(long Position, long Size, MemoryType Type)
{
Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW);
}
public void StopAllThreads() public void StopAllThreads()
{ {
if (MainThread != null) if (MainThread != null)
@ -188,12 +186,14 @@ namespace Ryujinx.Core.OsHle
return -1; return -1;
} }
long Tpidr = MemoryRegions.TlsPagesAddress + TlsSlot * TlsSize;
Thread.ThreadState.Break += BreakHandler; Thread.ThreadState.Break += BreakHandler;
Thread.ThreadState.SvcCall += SvcHandler.SvcCall; Thread.ThreadState.SvcCall += SvcHandler.SvcCall;
Thread.ThreadState.Undefined += UndefinedHandler; Thread.ThreadState.Undefined += UndefinedHandler;
Thread.ThreadState.ProcessId = ProcessId; Thread.ThreadState.ProcessId = ProcessId;
Thread.ThreadState.ThreadId = Ns.Os.IdGen.GenerateId(); Thread.ThreadState.ThreadId = Ns.Os.IdGen.GenerateId();
Thread.ThreadState.Tpidr = TlsPageAddr + TlsSlot * TlsSize; Thread.ThreadState.Tpidr = Tpidr;
Thread.ThreadState.X0 = (ulong)ArgsPtr; Thread.ThreadState.X0 = (ulong)ArgsPtr;
Thread.ThreadState.X1 = (ulong)Handle; Thread.ThreadState.X1 = (ulong)Handle;
Thread.ThreadState.X31 = (ulong)StackTop; Thread.ThreadState.X31 = (ulong)StackTop;
@ -267,7 +267,7 @@ namespace Ryujinx.Core.OsHle
private int GetTlsSlot(long Position) private int GetTlsSlot(long Position)
{ {
return (int)((Position - TlsPageAddr) / TlsSize); return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
} }
public HThread GetThread(long Tpidr) public HThread GetThread(long Tpidr)

View file

@ -17,6 +17,8 @@ namespace Ryujinx.Core.OsHle.Svc
private AMemory Memory; private AMemory Memory;
private static Random Rng; private static Random Rng;
private ulong CurrentHeapSize;
public SvcHandler(Switch Ns, Process Process) public SvcHandler(Switch Ns, Process Process)
{ {
@ -25,6 +27,7 @@ namespace Ryujinx.Core.OsHle.Svc
{ 0x01, SvcSetHeapSize }, { 0x01, SvcSetHeapSize },
{ 0x03, SvcSetMemoryAttribute }, { 0x03, SvcSetMemoryAttribute },
{ 0x04, SvcMapMemory }, { 0x04, SvcMapMemory },
{ 0x05, SvcUnmapMemory },
{ 0x06, SvcQueryMemory }, { 0x06, SvcQueryMemory },
{ 0x07, SvcExitProcess }, { 0x07, SvcExitProcess },
{ 0x08, SvcCreateThread }, { 0x08, SvcCreateThread },

View file

@ -10,10 +10,21 @@ namespace Ryujinx.Core.OsHle.Svc
{ {
uint Size = (uint)ThreadState.X1; 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.X0 = (int)SvcResult.Success;
ThreadState.X1 = (ulong)Memory.Manager.HeapAddr; ThreadState.X1 = (ulong)Position;
} }
private void SvcSetMemoryAttribute(AThreadState ThreadState) private void SvcSetMemoryAttribute(AThreadState ThreadState)
@ -42,7 +53,30 @@ namespace Ryujinx.Core.OsHle.Svc
long Src = (long)ThreadState.X1; long Src = (long)ThreadState.X1;
long Size = (long)ThreadState.X2; 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; ThreadState.X0 = (int)SvcResult.Success;
} }
@ -54,17 +88,22 @@ namespace Ryujinx.Core.OsHle.Svc
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position); 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); return;
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);
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. //TODO: X1.
ThreadState.X0 = (int)SvcResult.Success; ThreadState.X0 = (int)SvcResult.Success;
@ -84,7 +123,7 @@ namespace Ryujinx.Core.OsHle.Svc
{ {
SharedMem.AddVirtualPosition(Src); 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; ThreadState.X0 = (int)SvcResult.Success;
} }

View file

@ -11,7 +11,14 @@ namespace Ryujinx.Core.OsHle.Svc
{ {
partial class SvcHandler 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) private void SvcCloseHandle(AThreadState ThreadState)
{ {
@ -162,79 +169,62 @@ namespace Ryujinx.Core.OsHle.Svc
switch (InfoType) switch (InfoType)
{ {
case 0: ThreadState.X1 = AllowedCpuIdBitmask(); break; case 0:
case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break; ThreadState.X1 = AllowedCpuIdBitmask;
case 3: ThreadState.X1 = GetMapRegionSize(); break; break;
case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break;
case 5: ThreadState.X1 = GetHeapRegionSize(); break; case 2:
case 6: ThreadState.X1 = GetTotalMem(); break; ThreadState.X1 = MemoryRegions.MapRegionAddress;
case 7: ThreadState.X1 = GetUsedMem(); break; break;
case 8: ThreadState.X1 = IsCurrentProcessBeingDebugged(); break;
case 11: ThreadState.X1 = GetRnd64(); break; case 3:
case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break; ThreadState.X1 = MemoryRegions.MapRegionSize;
case 13: ThreadState.X1 = GetAddrSpaceSize(); break; break;
case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break;
case 15: ThreadState.X1 = GetMapRegionSize(); 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}"); default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
} }
ThreadState.X0 = (int)SvcResult.Success; 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();
}
} }
} }

View file

@ -5,9 +5,9 @@ namespace Ryujinx.Core
{ {
class VirtualFs : IDisposable class VirtualFs : IDisposable
{ {
private const string BasePath = "Fs"; private const string BasePath = "RyuFs";
private const string SavesPath = "Saves"; private const string NandPath = "nand";
private const string SdCardPath = "SdCard"; private const string SdCardPath = "sdmc";
public Stream RomFs { get; private set; } public Stream RomFs { get; private set; }
@ -35,7 +35,7 @@ namespace Ryujinx.Core
public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath); public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath);
public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath); public string GetGameSavesPath() => MakeDirAndGetFullPath(NandPath);
private string MakeDirAndGetFullPath(string Dir) private string MakeDirAndGetFullPath(string Dir)
{ {
@ -56,7 +56,9 @@ namespace Ryujinx.Core
public string GetBasePath() public string GetBasePath()
{ {
return Path.Combine(Directory.GetCurrentDirectory(), BasePath); string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
return Path.Combine(AppDataPath, BasePath);
} }
public void Dispose() public void Dispose()

View file

@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu
private const int PTLvl1Mask = PTLvl1Size - 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 PTLvl0Bit = PTPageBits + PTLvl1Bits;
private const int PTLvl1Bit = PTPageBits; private const int PTLvl1Bit = PTPageBits;
private const long PteUnmapped = -1; private const long PteUnmapped = -1;

View file

@ -17,7 +17,6 @@ namespace Ryujinx.Tests.Cpu
private long EntryPoint; private long EntryPoint;
private IntPtr Ram; private IntPtr Ram;
private AMemoryAlloc Allocator;
private AMemory Memory; private AMemory Memory;
private AThread Thread; private AThread Thread;
@ -31,9 +30,8 @@ namespace Ryujinx.Tests.Cpu
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize); Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
ATranslator Translator = new ATranslator(); ATranslator Translator = new ATranslator();
Allocator = new AMemoryAlloc(); Memory = new AMemory(Ram);
Memory = new AMemory(Ram, Allocator); Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint); Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint);
} }
@ -42,7 +40,6 @@ namespace Ryujinx.Tests.Cpu
{ {
Thread = null; Thread = null;
Memory = null; Memory = null;
Allocator = null;
Marshal.FreeHGlobal(Ram); Marshal.FreeHGlobal(Ram);
} }